Jump to content

Mass create pages OR mass upload images and thus create pages


a-ok
 Share

Recommended Posts

Hi folks,

This might be more a DB/mySQL question, perhaps, but thought I'd put it to the forum for discussion.

I have a lot of pages to add to a certain section of my PW site.

Portraits

> Portrait 1

> Portrait 2

...

> Portrait 100

Each page has one image only.

I am wondering if it is possible, if the image filenames and the titles of each 'page' are the same, if I can somehow mass upload these images to create pages from? Either through the backend or via the DB? So, for example:

julian.jpg > Julian (page created with this image)

kate.jpg > Kate (page created)

...

mat.jpg > Mat (page created)

This, of course, is only to save time... but wondered what you all thought? Or, even still, is it possible to mass create pages much like you can do with templates?

Thanks for your time.

Link to comment
Share on other sites

class ImageBatcher extends WireData implements Module {

    /**
     * getModuleInfo is a module required by all modules to tell ProcessWire about them
     *
     * @return array
     *
     */
    public static function getModuleInfo() {

        return array(

            'title' => 'Image Batcher', 
            'version' => 1, 
            'summary' => 'Do some additional actions after uploading an image',
            'singular' => true, 
            'autoload' => true,  
            );
    }

    /**
     * Initialize the module
     * 
     */
    public function init() {
        // do additional action after upload
        $this->addHookAfter('InputfieldImage::fileAdded', $this, 'createPageFromImage');
    }

    /**
     * create Page from uploaded Image
     *
     */
    public function createPageFromImage($event) {

        $file = $event->arguments(0);
        $parent = wire('pages')->get('/batcher'); // didn't know how to get the current page dynamically 

        // create new page
        $np = new Page();
        $np->parent = $parent;
        $np->template = 'portrait';
        $np->title = $file->name;
        $np->save(); // page has to be saved before adding images

        // add image
        $np->image->add($file->filename);
        $np->save();
    }

}

played a little around... something like this? :)

i didn't know how to get the current page dynamically... and i didn't manage to clear the added files from the "batcher" page because i got some errors i can't explore in detail right now.

this thread should also give you useful information: https://processwire.com/talk/topic/8698-creating-page-for-every-image-uploaded/

edit: i think hooking the method fileAdded should keep you save from timeouts though other things may get more complicated as it are all ajax requests (like the error i got when trying to remove all uploaded images from the batcher page)

edit2: of course you would have to check if the file was added to a "batcher" page. otherwise all your image uploads will create new pages. or you could bind the module to a specific imagefield only.

  • Like 1
Link to comment
Share on other sites

you would have to name this file ImageBatcher.module and place it in your modules folder /site/modules

then go to modules > install > new and maybe refresh, then install

but this is no working and bulletproof code! use a dev-installation to test everything!

here are lots of informations:

https://processwire.com/api/modules/

https://processwire.com/api/hooks/

Link to comment
Share on other sites

Thanks, BernhardB. I'm thinking a PHP query that writes each image from a folder into the DB, as it is a one-off scenario, and uses a similar structure to what you suggested.

All the filenames have the year and title of the page, so for example:

2006_ALI.jpg should equal a page created called Ali, under the parent of 1026 and the date field should have the 2006

parent id in the DB for each page is 1026

title field in the DB is field_title (eg. Ali)
date field in DB is field_works_date (eg. 2007)
image field in the DB is field_works_image (eg. ocean_liner.jpg)

What do you think? Possible?

Link to comment
Share on other sites

sure possible

why do you want to write directly to the DB? if you create pages you have all the benefits of processwire like page editing, pagination, file handling and so on.

just use my example and replace:

$parent = wire('pages')->get(1026); // your given id of the new parent

$np->title = your part of the image filename that represents the title (see php string functions)

$np->date (you have to create this field) = part of the filename that represents the date (year)

Link to comment
Share on other sites

UNTESTED, probably have some typos + poorly formatted code (I gotta run...)

You want to add this to your template file....Wrap it around code that ensures only Superuser can load the code...

//absolute path to a directory called 'tmp' within the site folder where we have our images
$dir = $config->paths->site . 'tmp';

$addAndPublish = false;//true if you want to publish on save
//prepare some variables we'll need later
$a = 0;//for photo pages count
$failed = array();

$parent =$pages->get('/portraits/');
$t = wire('templates')->get('your-portrait-template-name');

//if we found the directory (here we use Standard PHP Library (SPL))
if (is_dir($dir)) {

    $directory = new RecursiveDirectoryIterator($dir, FilesystemIterator::SKIP_DOTS); 

    //iterate through each file in this directory
    foreach ($directory as $path ) {            

       set_time_limit(30);//we try to avoid timing out

       //Remove and delete invalid file types
       $validImagesExts = array('jpg', 'png', 'gif', 'jpeg');
       if($path->isFile() && !in_array($path->getExtension(), $validImagesExts)) {
        unlink($path);//we delete the invalid file
        continue;
    }

     //if valid image file we create a page named after it and later save it to the page
     if($path->isFile()) {

     //we are ready to start creating pages...
     $p = new Page();
    $p->parent =$parent;
    $p->template = $t;
    $title = $path->getBasename('.' . $path->getExtension());
    $p->title = $this->sanitizer->text($title);
    if (!$p->title) continue;//skip to next if no title found (just in case)
   $p->name = $this->sanitizer->pageName($p->title);//sanitize and convert to a URL friendly page name

    //check if name already taken
    if($p->parent->child("name={$p->name}, include=all")->id) {

        //if the same name already exists, add it to the $failed array [to display to user in error later] and skip to next title
        if ($path->isFile()) {
          $failed [] = $path->getFilename();
        }

        continue;
     }

     //if add and publish is false, we save new page unpublished
     if (!$addAndPublish) $p->addStatus(Page::statusUnpublished);
     $p->save();

      //add image to the page and save again
      $p->images_field->add($dir . '/' . $path->getFilename());
      $p->save();

      $a++;
      unlink($path);//we delete the temp file

    }

}//end foreach

     //delete the tmp directory
     wireRmdir($dir, $recursive = true);

    //create a string of "failed" category titles to add to error message
    $failedTitles = implode(', ', $failed);

    //give the user some feedback...
    if($a > 0) echo 'Added' . $a . 'Portraits<br>';
    if($failedTitles) echo 'Some Portraits not added because names already in use. These are:' . $failedTitles;

}//end if (is_dir($dir)))

else echo 'No Such Directory Found!';
Edited by kongondo
  • Like 7
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

×
×
  • Create New...