Last active
May 24, 2023 18:26
-
-
Save somatonic/5233338 to your computer and use it in GitHub Desktop.
ProcessWire example front-end form with file upload and fields
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
// ------------------------------ FORM Processing --------------------------------------- | |
$errors = null; | |
$success = false; | |
// helper function to format form errors | |
function showError($e){ | |
return "<p class='error'>$e</p>"; | |
} | |
// dump some variables | |
// var_dump($_FILES,$_POST,$_SESSION); | |
/** | |
* Cast and save field values in array $form_fields | |
* this is also done even form not submited to make populating the form later easier. | |
* | |
* Also used for pupulating page when form was valid | |
*/ | |
$required_fields = array(); | |
foreach($form_fields as $key => $f){ | |
if($f['type'] == 'text'){ | |
$form_fields[$key]['value'] = $sanitizer->text($input->post->$key); | |
} | |
if($f['type'] == 'textarea'){ | |
$form_fields[$key]['value'] = $sanitizer->textarea($input->post->$key); | |
} | |
if($f['type'] == 'email'){ | |
$form_fields[$key]['value'] = $sanitizer->email($input->post->$key); | |
} | |
if($f['type'] == 'checkbox'){ | |
$form_fields[$key]['value'] = isset($input->post->$key) ? 1 : 0; | |
} | |
// store required fields in array | |
if($f['required']) $required_fields[] = $key; | |
} | |
/** | |
* form was submitted, start processing the form | |
*/ | |
if($input->post->action == 'send'){ | |
// validate CSRF token first to check if it's a valid request | |
if(!$session->CSRF->hasValidToken()){ | |
$errors['csrf'] = "Form submit was not valid, please try again."; | |
} | |
/** | |
* Ceck for required fields and make sure they have a value | |
*/ | |
foreach($required_fields as $req){ | |
// required upload file field | |
if($form_fields[$req]['type'] == 'file'){ | |
if(empty($_FILES[$req]['name'][0])){ | |
$errors[$req] = "Select files to upload."; | |
} | |
// reqired checkbox fields | |
} else if($form_fields[$req]['type'] == 'checkbox'){ | |
if($form_fields[$req]['value'] == 0){ | |
$errors[$req] = "Field required"; | |
} | |
// reqired text fields | |
} else if($form_fields[$req]['type'] == 'text' | |
|| $form_fields[$req]['type'] == 'textarea' | |
|| $form_fields[$req]['type'] == 'email'){ | |
if(!strlen($form_fields[$req]['value'])){ | |
$errors[$req] = "Field required"; | |
} | |
// reqired email fields | |
if($form_fields[$req]['type'] == 'email'){ | |
if($form_fields[$req]['value'] != $input->post->$req){ | |
$errors[$req] = "Please enter a valid Email address."; | |
} | |
} | |
} | |
} | |
/** | |
* if no required errors found yet continue file upload form processing | |
*/ | |
if(empty($errors)) { | |
// RC: create temp path if it isn't there already | |
if(!is_dir($upload_path)) { | |
if(!wireMkdir($upload_path)) throw new WireException("No upload path!"); | |
} | |
// setup new wire upload | |
$u = new WireUpload($file_field); | |
$u->setMaxFiles($max_files); | |
$u->setMaxFileSize($max_upload_size); | |
$u->setOverwrite($overwrite); | |
$u->setDestinationPath($upload_path); | |
$u->setValidExtensions($file_extensions); | |
// start the upload of the files | |
$files = $u->execute(); | |
// if no errors when uploading files | |
if(!$u->getErrors()){ | |
// create the new page to add field values and uploaded images | |
$uploadpage = new Page(); | |
$uploadpage->template = $template; | |
$uploadpage->parent = $parent; | |
// add title/name and make it unique with time and uniqid | |
$uploadpage->title = date("d-m-Y H:i:s") . " - " . uniqid(); | |
// populate page fields with values using $page_fields array | |
foreach($page_fields as $pf){ | |
if($templates->get($template)->hasField($pf)){ | |
$uploadpage->$pf = $form_fields[$pf]['value']; | |
} else { | |
throw new WireException("Template '$template' has no field: $pf"); | |
} | |
} | |
// RC: for safety, only add user uploaded files to an unpublished page, for later approval | |
// RC: also ensure that using v2.3+, and $config->pagefileSecure=true; in your /site/config.php | |
$uploadpage->addStatus(Page::statusUnpublished); | |
$uploadpage->save(); | |
// Now page is created we can add images upload to the page file field | |
foreach($files as $filename) { | |
$uploadpage->$file_field = $upload_path . $filename; | |
// remove tmp file uploaded | |
unlink($upload_path . $filename); | |
} | |
$uploadpage->save(); | |
// $success_message .= "<p>Page created: <a href='$uploadpage->url'>$uploadpage->title</a></p>"; | |
$success = true; | |
// reset the token so no double posts happen | |
// also prevent submit button to from double clicking is a good pratice | |
$session->CSRF->resetToken(); | |
} else { | |
// errors found | |
$success = false; | |
// remove files uploaded | |
foreach($files as $filename) unlink($upload_path . $filename); | |
// get the errors | |
if(count($u->getErrors()) > 1){ // if multiple error | |
foreach($u->getErrors() as $e) { | |
$errors[$file_field][] = $e; | |
} | |
} else { // if single error | |
$errors[$file_field] = $u->getErrors(); | |
} | |
} | |
} | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* ### Example front-end form template with file upload and fields ### | |
* | |
* - with files (images) upload to page field | |
* - adds new page on the fly and adds uploaded images | |
* - prevents CRSF attacks, this also prevents double post by refresh page after submit | |
* - has required fields with error messages inline | |
* - sanitizing and saving values to a page | |
* - jquery example with disabled submit button on form submit | |
* | |
* Edit add or remove form markup below and configure this section according to what you need. | |
* | |
*/ | |
// ------------------------------ FORM Configuration --------------------------------------- | |
// --- Some default variables --- | |
$success_message = "<p class='message'>Thanks for your message!</p>"; | |
// --- All form fields as nested array --- | |
// using html form field name => template field nam, from the page you're going to create | |
$form_fields = array( | |
'fullname' => array('type' => 'text', 'value' => '', 'required' => true), | |
'email' => array('type' => 'email', 'value' => '', 'required' => true), | |
'message' => array('type' => 'textarea', 'value' => '', 'required' => true), | |
'newsletter_subscribe' => array('type' => 'checkbox', 'value' => 0, 'required' => false), | |
'images' => array('type' => 'file', 'required' => true) | |
); | |
// --- WireUpload settings --- | |
$upload_path = $config->paths->assets . "files/.tmp_uploads/"; // tmp upload folder | |
$file_extensions = array('jpg', 'jpeg', 'gif', 'png'); | |
$max_files = 3; | |
$max_upload_size = 1*1024*1024; // make sure PHP's upload and post max size is also set to a reasonable size | |
$overwrite = false; | |
// --- Page creation settings --- | |
$template = "upload-entry"; // the template used to create the page | |
$parent = $pages->get("/uploads/"); | |
$file_field = "images"; | |
$page_fields = array('fullname','email','message','newsletter_subscribe'); | |
// $page_fields = define the fields (except file) you want to save value to a page | |
// this is for the form process to populate page fields. | |
// Your page template must have the same field names existent | |
// ------------------------------ FORM Processing --------------------------------------- | |
include("./form-process.php"); | |
?> | |
<!-- ========================= FORM HTML markup ================================== --> | |
<?php | |
/** | |
* Some vars used on the form markup for error and population of fields | |
* | |
* $errors[fieldname]; to get errors | |
* $form_fields[fieldname]['value']; | |
* | |
* Some helper function to get error markup | |
* echo showError(string); | |
* | |
* Prevent CSRF attacks by adding hidden field with name and value | |
* you an get by using $session->CSRF | |
* $session->CSRF->getTokenName(); | |
* $session->CSRF->getTokenValue(); | |
* | |
* $errors['csrf']; used to check for CSRF error | |
* | |
*/ | |
?> | |
<div class="content"> | |
<h2>Upload Images to Page Example Form</h2> | |
<?php if(!$success) : ?> | |
<?php if(!empty($errors)) echo showError("Form contains errors"); ?> | |
<?php if(!empty($errors['csrf'])) echo showError($errors['csrf']); ?> | |
<form name="myform" class="myform" id="myform" method="post" action="./" enctype="multipart/form-data"> | |
<input type="hidden" name="<?php echo $session->CSRF->getTokenName(); ?>" value="<?php echo $session->CSRF->getTokenValue(); ?>"/> | |
<div class="row <?php if(isset($errors['fullname'])) echo "error";?>"> | |
<label for="fullname">Name* </label><br/> | |
<input type="text" name="fullname" id="fullname" value="<?php echo $sanitizer->entities($form_fields['fullname']['value']); ?>"/> | |
<?php if(isset($errors['fullname'])) echo showError($errors['fullname']); ?> | |
</div> | |
<div class="row <?php if(isset($errors['email'])) echo "error";?>"> | |
<label for="email">Email* </label><br/> | |
<input type="text" name="email" id="email" value="<?php echo $sanitizer->entities($form_fields['email']['value']); ?>"/> | |
<?php if(isset($errors['email'])) echo showError($errors['email']); ?> | |
</div> | |
<div class="row <?php if(isset($errors['message'])) echo "error";?>"> | |
<label for="message">Message* </label><br/> | |
<textarea type="text" name="message" id="message"><?php echo $sanitizer->entities($form_fields['message']['value']); ?></textarea> | |
<?php if(isset($errors['message'])) echo showError($errors['message']); ?> | |
</div> | |
<div class="row <?php if(isset($errors['newsletter_subscribe'])) echo "error";?>"> | |
<label for="newsletter_subscribe">Newsletter* </label><br/> | |
<input type="checkbox" name="newsletter_subscribe" id="newsletter_subscribe" | |
<?php echo $form_fields['newsletter_subscribe']['value'] ? "checked='checked'" : "" ; ?> | |
/> | |
<?php if(isset($errors['newsletter_subscribe'])) echo showError($errors['newsletter_subscribe']); ?> | |
</div> | |
<div class="row <?php if(isset($errors['images'])) echo "error";?>"> | |
<label for="images">Images* </label><br/> | |
<input type="file" name="images[]" id="images" multiple="multiple" size="40" accept="image/jpg,image/jpeg,image/gif,image/png"/> | |
<?php | |
// show upload errors | |
if(isset($errors['images'])){ | |
// if multiple errors | |
if(is_array($errors['images'])){ | |
foreach($errors['images'] as $e){ | |
echo showError($e); | |
} | |
} else { // if single error | |
echo showError($errors['images']); | |
} | |
} | |
?> | |
</div> | |
<div class="row"> | |
<input type="hidden" name="action" id="action" value="send"/> | |
<input type="submit" name="submit" id="submit" value="Submit"/> | |
</div> | |
</form> | |
<?php else: ?> | |
<p><?php echo $success_message; ?></p> | |
<?php endif; ?> | |
</div> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!-- ========================= FORM Styling ================================== --> | |
<style> | |
/* basic CSS styling */ | |
.content { width: 30em; margin: 0 auto ;} | |
.error { color: red;} | |
.myform { padding: 1.618em 0; margin: 0 0 1em 0; border: 1px solid #bbb;} | |
.myform p.error { margin: 0.5em 0; border: 1px solid red; padding: 2px 5px;} | |
.myform .row { padding: 1.618em 0 0; margin: 0 1.618em 1.618em; border-top: 1px solid #aaa; } | |
.myform input[type="text"] { padding: 0.8em; background-color: #eee; border: none; width: 100%; } | |
.myform textarea { padding: 0.8em; background-color: #eee; border: none; width: 100%; } | |
</style> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!-- ========================= FORM jQuery Script ================================== --> | |
<script src="<?php echo $config->urls->templates . "scripts/jquery-1.7.1.min.js"; ?>"></script> | |
<script> | |
$(function(){ | |
// Avoid double posts by disabling submit button on form submit | |
$('#myform').submit(function(){ | |
$("#submit").attr('disabled','disabled'); | |
return true; | |
}); | |
}); | |
</script> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment