Jump to content

Create Pages (with File-Upload Field) via API


MatthewSchenker

Recommended Posts

Greetings Everyone,

*************************************************
*************************************************
EDIT NOTE: This post started as a work-in-progress discussion as I was working out the elements of a successful form. After contributions from participants in this discussion, the code below has been tested and works well.

You can use the code as shown below in your ProcessWire templates!

Feel free to follow up with additional quesations/comments!
*************************************************
*************************************************

I have successfully built front-end forms with ProcessWire to add pages via the API. It works great -- until I had to include image uploads along with the "regular" form fields.  Then it temporarily got a bit complicated.

In this discussion, I show how to handle front-end submissions in ProcessWire with the goal of allowing us to create pages from custom forms.  I then go a step further and show how to use the same form to upload files (images and other files).

I'm hoping this discussion can illustrate the whole process. I know a lot of people are interested in using ProcessWire to do front-end submissions, and my goal for this discussion is to benefit others as well as myself!

First, here's my original contact form (no file uploads):

<form action="/customer-service/contact/contact-success/" method="post">
<p><label for="contactname">Name:</label></p>
<p><input type="text" name="contactname"></p>
<p><label for="email">E-Mail:</label></p>
<p><input type="email" name="email"></p>
<p><label for="comments">Comments:</label></p>
<p><textarea name="comments" cols="25" rows="6"></textarea></p>
<button type="submit">Submit</button></form>

And here's the "contact-success" page that picks up the form entry to create ProcessWire pages:

<?php // First, confirm that a submission has been made
if ($input->post->contactname) {

// Save in the ProcessWire page tree; map submission to the template fields
$np = new Page(); // create new page object
$np->template = $templates->get("contact_submission"); 
$np->parent = $pages->get("/customer-service/contact-us/contact-submission-listing/");

// Send all form submissions through ProcessWire sanitization
$title = $sanitizer->text($input->post->contactname);
$name = $sanitizer->text($input->post->contactname);
$contactname = $sanitizer->text($input->post->contactname);
$email = $sanitizer->email($input->post->email);
$comments = $sanitizer->textarea($input->post->comments);

// Match up the sanitized inputs we just got with the template fields
$np->of(false);
$np->title = $contactname;
$np->name = $contactname;
$np->contactname = $contactname;
$np->email = $email;
$np->comments = $comments;

// Save/create the page
$np->save();							    										    		

} ?>

This works great! After submitting the form, we go to the "Success" page, and new submissions show up in the ProcessWire page tree right away. Excellent!

Now I need to add a photo field. I altered the above form so it looks like this:

<form action="/customer-service/contact/contact-success/" method="post" enctype="multipart/form-data">
<p><label for="contactname">Name:</label></p>
<p><input type="text" name="contactname"></p>
<p><label for="email">E-Mail:</label></p>
<p><input type="email" name="email"></p>
<p><label for="comments">Comments:</label></p>
<p><textarea name="comments" cols="25" rows="6"></textarea></p>
<p>Click the "Select Files" button below to upload your photo.</p>
<input type="file" name="contact_photo" />
<button type="submit">Submit</button>
</form>

And here's the updated "contact-success" page:

<?php // First, confirm that a submission has been made
if($input->post->contactname) {

// Set a temporary upload location where the submitted files are stored during form processing
$upload_path = $config->paths->assets . "files/contact_files/";

// New wire upload
$contact_photo = new WireUpload('contact_photo'); // References the name of the field in the HTML form that uploads the photo
$contact_photo->setMaxFiles(5);
$contact_photo->setOverwrite(false);
$contact_photo->setDestinationPath($upload_path);
$contact_photo->setValidExtensions(array('jpg', 'jpeg', 'png', 'gif'));

// execute upload and check for errors
$files = $contact_photo->execute();

// Run a count($files) test to make sure there are actually files; if so, proceed; if not, generate getErrors()
if(!count($files)) {
$contact_photo->error("Sorry, but you need to add a photo!");
return false;
}

// Do an initial save in the ProcessWire page tree; set the necessary information (template, parent, title, and name)
$np = new Page(); // create new page object
$np->template = $templates->get("contact_submission"); // set the template that applies to pages created from form submissions
$np->parent = $pages->get("/customer-service/contact-us/contact-submission-listing/"); // set the parent for the page being created here

// Send all the form's $_POST submissions through ProcessWire's sanitization and/or map to a variable with the same name as the template fields we'll be populating
$np->title = $sanitizer->text($input->post->contactname);
$np->name = $np->title;
$np->contactname = $sanitizer->text($input->post->contactname);
$np->email = $sanitizer->email($input->post->email);
$np->comments = $sanitizer->textarea($input->post->comments);
$np->save();

// Run photo upload
foreach($files as $filename) {
$pathname = $upload_path . $filename;
$np->contact_photo->add($pathname);
$np->message("Added file: $filename");
unlink($pathname);
}

// Save page again
$np->save(); ?>

<p>Thank you for your contact information.</p>

<?php return true;
}

else { ?>
<p> Sorry, your photo upload was not successful...</P>
<?php } ?>


Replace the field references with your own field names, make sure to change the various paths to match yours, and change the various messages to be what you need for your project.

Read the entire discussion to see how we worked through getting to the solution shown above.

Thanks,
Matthew

  • Like 10
Link to comment
Share on other sites

Hey Wanze,

Yes, that shows you have a good eye for sure!

Unfortunately, that was just an error from me transferring the text to the forum... I edited the forms in my first post and fixed that word.

In other words, it still doesn't work.

Any other ideas?

Thanks,

Matthew

Link to comment
Share on other sites

Hey renobird,

Late here too, but difficult to sleep when working on a ProcessWire site!

You are correct... I was missing that piece!  Definitely, that should be there.

I added it, and holding my breath I tried the form again.  But it still doesn't work.  Same result: no errors, and we see the "success" page, but the new page does not appear in the page tree.

Other suggestions or ideas?

Thanks,

Matthew

PS: I've edited my post above to keep track of changes.  That way, when this discussion is done, there will be a complete example for others to reference.

  • Like 1
Link to comment
Share on other sites

$upload_path = "/site/assets/files/temp/";

I think the path is not correct, it's more an "url".

The complete path usually starts with the folder your site's in (public_html/www).

Try this:

$upload_path = $config->paths->assets . 'files/temp/';

And have you debug mode turned on to see any errors?

Cheers

Link to comment
Share on other sites

Greetings,

To renobird: Yes, I am basing my work on Soma's code.  But because I have more fields than just a file upload, I have to re-work the original code.  In my code above, you can see that what I have looks like Soma's code, but with the other fields included.

$upload_path = "/site/assets/files/temp/";

I think the path is not correct, it's more an "url".

The complete path usually starts with the folder your site's in (public_html/www).

Try this:

$upload_path = $config->paths->assets . 'files/temp/';

And have you debug mode turned on to see any errors?

I fixed the path reference (updated my post above).  But still no luck.  The page is not being created.  And no errors are being reported.

Based on a comment from Ryan in a related discussion, I wonder if I am simply saving the page at the wrong stage?

Here's the related discussion: http://processwire.com/talk/topic/2997-uploading-a-new-photo-to-a-member-profile-avatar-field/#entry30621

I really want to have a full, public example of how to put file uploads in a form with other fields, so I am hoping this discussion can become a live working out of the details.

Thanks,

Matthew

Link to comment
Share on other sites

Not the ideal way to debug like this code in a forum. Nothing against anyone personally. Now the code lost intendation and no way to go through it.

Please post code to some snippet site like Gist or bitbucket.

In general, we should provide some more practice and best ways HOW TO DEBUG YOUR CODE. Good coding is learning how to debug. There's simple steps you can go through to test all vars and parts of code to see where the problem lays. Sometimes it's simple sometimes it can get hard, as you when you don't have errors.

Ok.

What I spotted too is the last bit, where is the $u->getErrors() coming from?

Also as you say the page isn't created at all? I would start there and get that right first and work you way up.

Thanks,

Soma

  • Like 2
Link to comment
Share on other sites

Hey Soma,

I know what you're saying, but I wanted to use the forum as a way to work out what the general idea should be.  Ideally, it would be great to have things like this all in Github, but I think we often need to use a forum this way.  It's a more direct way -- in the end -- to have code that everyone here can use for their sites.

I think having a full working example of a form with various fields as well as file-uploads would be great for the forum.

Good catch on the $u->getErrors()... Yes, that should be $contest_photo->getErrors()

However... It still doesn't work.

I'm sure we'll solve this!

Thanks,

Matthew

Link to comment
Share on other sites

Matthew,

have you debug mode enabled to see PHP errors/warnings?

Also can you do a print_r($_FILES); to check if the PHP $_FILES array isn't empty?

Maybe the file isn't sent at all to the server.

Link to comment
Share on other sites

I also know what you're saying, but I have to strongly disagree. I could've write this in any other similar thread.

The problem is the code posted in a wysiwyg is "horrible" to read and even copy it.

Then after this is working (as with 1000 other code here in the forum), there comes the next who takes this code but need another feature.. then the game start again with same story same code but different bugs issues.

What I would like to do is helping how to code and debug, not have 1 million snippets that are sometimes very bad coded and not complete best practice or not even working spooking around the forum. It already happened many times and it will get worse by time. I know what you're wanting to do and I understand, but in the long run what we are practicing here since 2 years is very bad for newcomers. We better this energy and time to help with little tutorials and snippets that are good to start with in a dedicated site/place.

  • Like 4
Link to comment
Share on other sites

Hey Soma,

I get you!  I really do...  As someone who is attempting to document how to do things, it is difficult when there are pieces here and there for larger routines.  For example, with file-uploads and front-end forms in general, there are isolated chunks throughout the forum, and putting it all together as a single file can be difficult.  My goal with this discussion is to consolidate a whole routine in one coherent file.

For sure, your points about better ways to discuss such code is worthy of a larger discussion!  And yet, forums like this often have bits of code (many times, they are more than just "bits").  In fact, if you remove the code from a forum like this, what's left to discuss?

If I were to move this to GitHub, would it be as valuable to the ProcessWire community?

Thanks,

Matthew

Link to comment
Share on other sites

Greetings,

OK, Soma, here's my gist for this subject: https://gist.github.com/MatthewSchenker/5205927

I hope this can make it easier and more productive to work this out -- and better for everyone to use.

Also, maybe this can be a spark that gets more of us to Github to work out our code?

Thanks,

Matthew

  • Like 1
Link to comment
Share on other sites

Much better... and just now I spoted (starting from top)  an error

if ($input->get->contactname){

Your form is method post and not get!

So you would have easily spoted this already if you add an pseudo echo "Hello" after the if() to see it gets to after the check. As I said it's really simple if you go step by step and output vars to test and see if it really get's there. 

Link to comment
Share on other sites

Dont want to be mean but have to say that I already built multiple working front end form examples that work. The one Reno linked would be what you do. So this is not so much about making a working example but to help you debug your code you messed up. :-P #hides behind stone#

Of course yours has some more fields, but there's no validation happen on those, which I think should be the lesson here. To make it easy on this subject I would suggest looking at my other front end forms using PW forms and field that will make it more streamlined and easy. Its also in my gists examples.

Link to comment
Share on other sites

Hey Soma,

Yes, I admit the code I posted has problems.  I just can't seem to pinpoint the problem because building these kinds of forms gets into a lot of PW-specific steps.  I haven't seen any examples to follow for forms with image-upload fields along with "regular" fields.

I actually based my code above on your very helpful gist for uploading images to newly created pages (https://gist.github.com/somatonic/4150974).  But somewhere in the process of mixing in "regular" fields with the image upload requirements, something is off.

I realize I must be doing something wrong, but I can't tell what.

I'm hoping in the end we'll have a working example of how to do this that can be beneficial to others, since I know other need (or will need) to do this.

Thanks,

Matthew

Link to comment
Share on other sites

Hi Matthew,

have you tried my debugging steps? =)

Matthew,


have you debug mode enabled to see PHP errors/warnings?


Also can you do a print_r($_FILES); to check if the PHP $_FILES array isn't empty?


Maybe the file isn't sent at all to the server at all.

Link to comment
Share on other sites

Greetings Wanze,

Sorry, I meant to respond to that earlier.

Yes, I am seeing a result from that.  For example, I uploaded a photo called "cloudphoto.jpg.  Here's the message I'm seeing:

Array ( [contact_photo] => Array ( [name] => cloudphoto.jpg [type] => image/jpeg [tmp_name] => /tmp/phpdRhJLN [error] => 0 [size] => 1864092 ) ) 

Thanks,

Matthew

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
  • Similar Content

    • By quickjeff
      Hi Everyone, 
      As many of you know, iPhone photos save in .heic unless the user changes the settings in their phone. 
      We have built a web app on top of processwire in which a user can save images from their phone. 
      The issue we are having is that there seems to be an error when uploading and saving. 
      The .heic files won't save and processwire throws an error. The environment is LAMP (Bitnami and all libraries have been installed to support this.) 
      Checking to see if someone has also encountered this here and how they solved it.
      Thanks. 
    • By Saleena Jhon
      Hello There, I have saw a post that was covering event-calendar with php, ajax and js. That was showing a monthly overview when I click on a "month" button or when I switch the month. And show the events on one particular date when I pick a day. Also, most events are kind of exhibitions and so they have a start date and an end date much later, and occur on each day in-between as well. So on the template I put two date picking fileds date_start and date_end. Is there an elegant way to select the events using the API? If yes, kindly help me out.
      Thanks in Advance
      Regards: 
       
    • By opalepatrick
      I am working on my first Process Module. I am creating forms. Fairly straightforward. However, I really can't work out how to create multiple fieldsets?
      $fieldset = $this->modules->get('InputfieldFieldset'); $fieldset->label = 'Customer Source'; $field = $this->modules->get('InputfieldPage'); $field->inputfield = 'InputfieldSelect'; $field->findPagesSelector = 'parent_id=1449, include=hidden'; $field->labelFieldName = 'yff-lead'; $field->name = 'yfflead'; $field->columnWidth = 16; $fieldset->add($field); $field = $this->modules->get('InputfieldPage'); $field->inputfield = 'InputfieldSelect'; $field->findPagesSelector = 'parent_id=1452, include=hidden'; $field->labelFieldName = 'customer-type'; $field->name = 'customertype'; $field->columnWidth = 16; $fieldset->add($field); //Rinse and Repeat $fieldset->label = 'Contacts'; $field = $this->modules->get('InputfieldPage'); $field->inputfield = 'InputfieldSelect'; $field->findPagesSelector = 'parent_id=1538, include=hidden'; $field->labelFieldName = 'salutation'; $field->name = 'salutation'; $field->columnWidth = 16; $fieldset->add($field); I can create the first fieldset (Customer Source) but then get into trouble as the second fieldset overwrites the first. I understand why, but trying to use the open and close fieldset routine has flummoxed me. Any help appreciated.
    • By VeiJari
      Hello forum, we're trying to use Processwire as our REST-API. We are having problems with our API login to Processwire from frontend. It gives us 403 error.
      We have installed ProcessWire to subdirectory (/api/*) and our frontend is static JS files at root ( / ). Apache access logs gives 404 to our POST-request, but browser devtools shows 403 for our POST /api/login request. 
      Processwire backend panel works. We also have a GET endpoint for the API that returns 200 with correct payload.  So we're wondering why does our GET works but POST doesn't?
      Does this have something to do with Processwire .htaccess, or is this because of our webhost? What should we check first? Any help would be appreciated.
    • By rjgamer
      Hi,
      is there a hook after the current (active) page got created? Or which method got called in the Page class after the Constructor of the current page got initialized?
      Thanks.
       
×
×
  • Create New...