Jump to content

Creating a new Page (with file upload)


jrtderonde
 Share

Recommended Posts

Hi,

I'm working on a script that allows users to add a new Page to my installation of ProcessWire. I will explain how this script works below.

  • The user enters some information into a simple form
  • ^ This can include an image
  • The form is validated with jQuery
  • When valid, the form triggers a function through a class that handles the process

I will include some of the code below.

Form:

<form id="entry" class="entry" method="post" action="./" name="entry" enctype="multipart/form-data">
    <div class="row">
        <input type="text" name="fullName" id="fullName" placeholder="Naam initiatiefhouder *" data-validation="required" />
    </div>
    <div class="row">
        <input type="text" name="projectName" id="projectName" placeholder="Projectnaam *" data-validation="required" />
    </div>
    <div class="row">
        <input type="email" name="emailAddress" id="emailAddress" placeholder="E-mailadres *" data-validation="required" />
    </div>
    <div class="row">
        <textarea name="projectDescription" id="projectDescription" placeholder="Beschrijf uw initiatief *" data-validation="required"></textarea>
    </div>
    <div class="row">
        <input type="file" id="image" name="image" data-validation="mime size" data-validation-allowing="jpg, jpeg, png, gif" data-validation-max-size="2M" />
    </div>
    <div class="row">
        <input type="submit" name="submitEntry" id="submitEntry" value="Insturen" />
    </div>
</form>

So basically the "image" field is the field that allows the user to add a file (jpg, jpeg, png, gif - max 2mb).

Now, when all the information is valid it will post this form through the following function.

public function pushEntry ($input, $file) {

    // Unset the array
    $this->array = [];

    // If there is any data
    if ($input) {

        // Get some of the variables needed
        $this->name = $this->sanitizer->text($input->fullName);
        $this->email = $this->sanitizer->email($input->emailAddress);
        $this->project = $this->sanitizer->text($input->projectName);
        $this->description = $this->sanitizer->text($input->projectDescription);

        // Get the date
        $this->date = date("d-m-Y H:i:s");

        // Generate the title
        $this->title = "$this->project - $this->name";

        $this->duplicate = $this->pages->find("title=$this->title");

        // Generate the array
        $this->array = [
            "title" => $this->title,
            "fullName" => $this->name,
            "emailAddress" => $this->email,
            "projectName" => $this->project,
            "projectDescription" => $this->description,
            "date" => $this->date
        ];

        // Create the page
        $new = new Page();
        $new->template = $this->templates->get("entry"); 
        $new->parent = $this->pages->get("/entries/");

        foreach ($this->array as $key => $value) {

            // Foreach key and value, create a new page
            $new->$key = $value;

        }

        // Check if there is any duplicates
        if ($this->duplicate->count() == 0) {
            $new->save();
        } else {
            echo "Dit initiatief bestaat al.";
            exit;
        }

        // If there is an image
        if (!empty($file["image"]["name"])) {

            // Some variables
            $this->path = $this->config->paths->assets . "files/$new->id";

            // Set the extensions
            $this->extensions = [
                "jpg",
                "jpeg",
                "png",
                "gif"
            ];

            // Do the Wire
            $this->image = new WireUpload($file["image"]["name"]);
            $this->image->setMaxFiles(1);
            $this->image->setOverwrite(false);
            $this->image->setDestinationPath($this->path);
            $this->image->setValidExtensions($this->extensions);

            // Execute and check for errors
            $files = $this->image->execute();

            // Add the image to the page
            $this->fileName = $file["image"]["name"];
            $this->fullPath = $this->path ."/". $this->fileName;

            // Move the file
            $new->image->add($this->fullPath);

            // Unlink the file
            unlink($this->fullPath);

            // Save the page
            $new->save($new->id);

        }

    }

    // Return the array
    return $this->array;

}

The script adds a page to my installation of ProcessWire perfectly; except for the file upload. I encounter the following errors;

Warning: unlink(C:/wamp/www/gezondsteregio/site/assets/files/1135/dekkleden_header.1919x301.jpg): No such file or directory in C:\wamp\www\gezondsteregio\site\templates\controllers\home.php on line 106

Warning: filemtime(): stat failed for C:/wamp/www/gezondsteregio/site/assets/files/1135/dekkleden_header.1919x301.jpg in C:\wamp\www\gezondsteregio\wire\core\Pagefile.php on line 324

Warning: filemtime(): stat failed for C:/wamp/www/gezondsteregio/site/assets/files/1135/dekkleden_header.1919x301.jpg in C:\wamp\www\gezondsteregio\wire\core\Pagefile.php on line 324

I am really curious if someone can help me with this problem. I have tried this script on both my localhost (regular Apache) and my webhost (Fast CGI).

Regards,

Jim 


Oh, and I use the following script to trigger the function.

$entry = new Entry();

// If there is a post
if ($input->post->submitEntry && !empty($input->post->fullName) && !empty($input->post->emailAddress) && !empty($input->post->projectName) && !empty($input->post->projectDescription)):

    // Push the entry to the controller
    $entry->pushEntry($input->post, $_FILES);

endif;
Link to comment
Share on other sites

Hi @jrtderonde and welcome to the forums.

The first thing I notice is that you are uploading the file directly to the assets/files/page_id/ location. You should upload to a temp directory first, then $new->image->add('full_temp_path'), and then unlink from that temp location.

  • Like 2
Link to comment
Share on other sites

  • 1 month later...

Can I pass a remote file path to WireUpload to have it download it using curl?   Or do they need to always be local?

Maybe you are looking for WireHttp::download() ?

https://processwire.com/blog/posts/august-2014-core-updates-3/#new-download-capabilities-in-wirehttp-class

"...First it attempts to use cURL..."

Never used it though, just guessing. Sorry if ti is not the one you need.

  • Like 1
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
 Share

  • Recently Browsing   0 members

    No registered users viewing this page.

  • Similar Content

    • By joeck
      Hi,
      I'm facing the issue where a customer has only 1GB of RAM on its server available (and doesn't want to upgrade).
      They have a few large files (videos) that they want on the website but when uploading via the processwire backend the progress bar gets stock after some time (assuming because it ran out of RAM).
      I see that files are saved to site/assets/files/1048 and 1048 being the page id. I tried uploading the files via ftp (to avoid the shortage of RAM) to the same folder but the images don't appear in the files field.
      I'm assuming the files field is just an array with the file names that are then searched in site/assets/files/1048 . Is there a way where I can have the field look for other files in that folder and have it automatically added to the array so it appears in the files field of the page?
      My attempt didn't work and I didn't quite understand why:
      $directory = "../../files/1048"; // files uploaded here via ftp $page->of(false); foreach (scandir($directory) as $file) { //go through all files if ($file !== '.' && $file !== '..') { echo $file; $page->file->add($file); } } $page->save(); $page->of(true);  
    • By picarica
      so hello there i have fiel field type i have lots of stuff there, and also an image i can easily get image from that field using
                                                        
      $options = array('quality' => 85, 'upscaling' => true, 'cropping' => 'north', 'sharpening' => 'medium'); $word = ".png"; // Test if string contains the word foreach($childgames->subor_hry as $file) { if(strpos($file, $word) !== false){ /* $imger = $file->size(473, 266, $options); */ echo $file; /* echo $file->url; */ } } so i get the fiel i tried invoking size on it like the commented out part and it doesnt work i get error Oh snizzle… Error:     Exception: Method Pagefile::size does not exist or is not callable in this context (in
      what am i doing wrong? can you guys help me by all logic this should work
    • 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.
       
    • By rjgamer
      Hi guys,
      the field "redirect_last" of type DateTime got not updated. The update on the field "redirect_counter" works and got saved.
      Does anybody know what I did wrong in my code?
      if ($input->urlSegment(1) === 'redirect') { $page->of(false); $page->redirect_last = time(); $page->redirect_counter += 1; if ($page->save('redirect_counter')) { $session->redirect($page->website_url, 302); } } Thanks.
    • By theoretic
      Hi there! And thanks for Processwire!
      I have an interesting task which i cannot fulfill as i want. Maybe someone could help me please?
      Let's imagine a simple page structure of this kind:
      Category 1
      + Item 1.1
      + Item 1.2
      Category 2
      + Item 2.1
      + Item 2.2
      My task is to attach some items to more than one category, at least to show some items on different frontend category pages. With PW, it's a piece of cake. I've just created a field called Items (of type Page Reference) and attrached it to Category template. Since i have lots of items inside each category i preferred to use Page Autocomplete input for my Items field. The pages available for autocomplete are restricted by a very simple selector:
      template=item
      It works like a charm. But later i decided to make this autocomplete even smarter and to exclude current category children items from it. I tried to update my selector this way...
      template=item,parent!=(page)
      ...and oops, this broke my selector. My autocomplete founds nothing. Sorry, i had to replace the square braces by () because of this forum limitations, i swear i'm using square brackets in real-life selector!
      What am i doing wrong? And is there any way to include current page info in autocomplete-related selectors? Thanks in advance!
       
×
×
  • Create New...