ProcessWire - Dateien verarbeiten

Aus Wikizone
Wechseln zu: Navigation, Suche

Dateien sind immer ein recht komplexes Thema. Hier sind einige Basics dazu welche Funktionen und Fieldtypes es gibt, wo Dateien gespeichert werden etc.

Links[Bearbeiten]

https://processwire.com/talk/topic/19876-how-to-hook-file-upload-destination/
https://wiki.stephanschlegel.de/index.php?title=ProcessWire_-_RockPdf_(Module)#Aus_Modul_in_Datei_schreiben

Funktionen für Files und Bilder[Bearbeiten]

https://cheatsheet.processwire.com/#files
https://processwire.com/api/ref/wire-file-tools/

Pagefiles[Bearbeiten]

Pagefiles verwalten Pagefile Objekte und diese werden wiederum in File oder Image Feldern gespeichert.

https://processwire.com/talk/topic/14840-create-pagefile-or-pageimage/
https://processwire.com/api/ref/pagefiles/

File Uploads in Modulen[Bearbeiten]

Uploads funktionieren entweder über WireUpload, wenn man einen bestimmten Pfad angeben will. Oder über eine Pagefile Instanz wenn die Datei mit der Seite zusammen gespeichert wird. Im letzteren Fall erstellt man meistens ein InputfieldFile Feld. Dann muss man nicht mehr viel machen. Vorsicht, wenn man

https://processwire.com/talk/topic/21616-file-upload-inside-custom-module/
https://github.com/ryancramerdesign/ImportPagesCSV/blob/master/ImportPagesCSV.module

Basiswissen zu Dateien ProcessWire[Bearbeiten]

Jede Seite in ProcessWire hat einen eigenen Ordner unterhalb von

site/assets/files/

Wenn Dateien oder Bilder hochgeladen werden (egal ob API oder über ein Feld) muss die Seite gespeichert werden, sonst werden die Dateien gelöscht.

Wichtige Klassen und Methoden[Bearbeiten]

  • Pagefile class - Represents a single file item attached to a page, typically via a File Fieldtype.
  • InputfieldFile class - One or more file uploads (sortable)
  • WireUpload - Saves uploads of single or multiple files, saving them to the destination path. If the destination path does not exist, it will be created.

Snippets[Bearbeiten]

Funktionen um Dateien zu löschen[Bearbeiten]

$page->files->deleteAll();
$page->files->delete($pagefile);

$page->images->removeAll(); // wirearray

$page->save();

Custom Directory für Dateien[Bearbeiten]

https://processwire.com/talk/topic/19876-how-to-hook-file-upload-destination/

Mit dem InputfieldFile werden Dateien nach $page->save() automatisch mit einer Seite gespeichert. Wenn man mit den Seiten etwas spezielles vorhat, z.B. in einem Custom Ordner speichern kommt man mit einem Hook weiter.

You can Hook into InputfieldFile::processInputFile. There are other places in that Class you could also hook into, but I think processInputFile works best.

Throw the code below in ready.php

Please note:

  1. Starter code: not much validation going on other than checking if the field the file was uploaded to is 'course_file'
  2. You will have to implement other logic yourself. For instance, the code copies the file immediately it is uploaded by ProcessWire Ajax. It doesn't check if the page is actually saved. If a page is not saved and the page is reloaded, as you know, files in file fields are deleted from disk. This code does not delete the corresponding file in your custom directory
  3. You might want the Hook to only run if you are in admin. You can add that logic
  4. I've purposefully left in verbose and debugging code in there (Tracy stuff) to help you ( maybe and others) understand what's going on. I suggest you test using Tracy Debugger for a better grasp of the file upload process. Delete the debugging stuff when you've got this working as you want :-).
wire()->addHookAfter("InputfieldFile::processInputFile", function(HookEvent $event)  {
    // @note: here, events are $input, $pagefile, $n @see: the method
    // get event we are hooking into
    
    // get arguments by index {a bit faster, but less-readable}
    /* $input = $event->arguments[0];
    $pagefile = $event->arguments[1];
    $n = $event->arguments[2]; */
    // get arguments by name
    #$input = $event->argumentsByName('input');
    $pagefile = $event->argumentsByName('pagefile');
    #$n = $event->argumentsByName('n');
    
    // $pagefile->field: The Field object that this file is part of.
    // limit to a specific field {course_file}
    if($pagefile->field->name != 'course_files') return;

    # intercept file
    
    // Tracy Debugger calls to see what's going on. Also logs Ajax inputs!
    #bd($input, 'input');
    #bd($n, 'input');
    // @see: http://processwire.com/api/ref/pagefile/
    // pagefile object
    bd($pagefile, 'pagefile');
    // name of the field uploading to {your 'course_file'}
    bd($pagefile->field->name, 'field pagefile is part of');
    // file-sanitized name of the file we've added, e.g. 'checklist_install.pdf'
    bd($pagefile->basename, 'name of added file');
    // full disk path where the file has been uploaded in this page's files folder...
    //... in /site/assets/files/1234 where 1234 is this page's ID
    // ... e.g. "F:/www/mysite/site/assets/files/1234/checklist_install.pdf"
    bd($pagefile->filename, 'full disk path name of added file');
    // $pagefile->page: The Page object that this file is part of
    bd($pagefile->page->id, 'id of the page file added to');

    // full disk path to your custom uploads directory
    $customDirectory = $this->wire('config')->paths->assets . 'custom_directory/';
    bd($customDirectory,'custom directory for files');
    
    # copy file
    // use ProcessWire's $files API
    // @see: http://processwire.com/api/ref/files/
    $files = $this->wire('files');
    // copy the file(s)
    $files->copy($pagefile->filename,$customDirectory . $pagefile->basename);
});

Verwaiste Dateien[Bearbeiten]

https://processwire.com/talk/topic/4437-delete-orphaned-filesimages-from-siteassetsfiles/page/2/
<?php

$keepThumbnails = true;
$keepPimVariations = true;    // Pageimage Manipulator Variations

ini_set('max_execution_time', 60 * 5); // 5 minutes, increase as needed
include("./index.php"); // bootstrap ProcessWire

if($keepPimVariations) {
   if(!wire('modules')->isInstalled('PageImageManipulator')) {
      $keepPimVariations = false;
   } else {
      // PiM is installed, but is it a version that has method getPimVariations() (Ver 0.1.0 +)
      $a = wire('modules')->get('PageImageManipulator')->getModuleInfo();
      $actual = preg_replace('/(\d)(?=\d)/', '$1.', str_pad("{$a['version']}", 3, "0", STR_PAD_LEFT));
      $keepPimVariations = version_compare($actual, '0.1.0', '<') ? false : true;
   }
}

$dir = new DirectoryIterator(wire('config')->paths->files);
foreach ($dir as $file) {
   if ($file->isDot() || !$file->isDir()) {
      continue;
   }
   $id = $file->getFilename();
   if (!ctype_digit("$id")) {
      continue;
   }
   $page = wire('pages')->get((int) $id);
   if (!$page->id) {
      echo "Orphaned directory: " . wire('config')->urls->files . "$id/" . $file->getBasename() . "\n";
      continue;
   }
   // determine which files are valid for the page
   $valid = array();
   foreach ($page->template->fieldgroup as $field) {
      if ($field->type instanceof FieldtypeFile) {
         foreach ($page->get($field->name) as $file) {
            $valid[] = $file->basename;
            if ($field->type instanceof FieldtypeImage) {
               foreach ($file->getVariations() as $f) {
                  $valid[] = $f->basename;
               }
            }
            // keep thumbnails:
            if ($keepThumbnails && $field->type instanceof FieldtypeCropImage) {
               $crops = $field->getArray();
               $crops = $crops['thumbSetting'];
               $crops_a = explode("\n", $crops); // ie. thumbname,200,200 (name,width,height)
               foreach ($crops_a as $crop) {
                  $crop = explode(",", $crop);
                  $prefix = wire('sanitizer')->name($crop[0]);
                  $valid[] = $prefix . "_" . $file->basename;
               }
            }
            // what's about PimVariations ?
            if ($keepPimVariations) {
               if ($field->type instanceof FieldtypeImage) {
                  foreach ($file->pimLoad('x',true)->getPimVariations() as $f) {
                     $valid[] = $f->basename;
                  }
               }
            }
         }
      }
   }
   // now find all the files present on the page
   // identify those that are not part of our $valid array
   $d = new DirectoryIterator($page->filesManager->path);
   foreach ($d as $f) {
      if ($f->isDot() || !$f->isFile()) {
         continue;
      }
      if (!in_array($f->getFilename(), $valid)) {
         echo "Orphaned file: " . wire('config')->urls->files . "$id/" . $f->getBasename() . "\n";
//         #unlink($f->getPathname());
      }
   }
   wire('pages')->uncache($page); // just in case we need the memory
}





<?php
ini_set('max_execution_time', 60 * 5); // 5 minutes, increase as needed
include("./index.php");
$dir = new DirectoryIterator(wire('config')->paths->files);

foreach ($dir as $file) {
    if ($file->isDot() || !$file->isDir()) {
        continue;
    }
    $id = $file->getFilename();
    if (!ctype_digit("$id")) {
        continue;
    }
    $page = wire('pages')->get((int) $id);
    if (!$page->id) {
        echo "Orphaned directory: " . wire('config')->urls->files . "$id/" . $file->getBasename() . "\n";
        continue;
    }
    // determine which files are valid for the page
    $valid = array();
    foreach ($page->template->fieldgroup as $field) {
        if ($field->type instanceof FieldtypeFile) {
            foreach ($page->get($field->name) as $file) {
                $valid[] = $file->basename;
                if ($field->type instanceof FieldtypeImage) {
                    foreach ($file->getVariations() as $f) {
                        //$valid[] = $f->basename;
                    }
                }
                // keep thumbnails:
                /*
                if ($field->type instanceof FieldtypeCropImage) {
                    $crops = $field->getArray();
                    $crops = $crops['thumbSetting'];
                    $crops_a = explode("\n", $crops); // ie. thumbname,200,200 (name,width,height)
                    foreach ($crops_a as $crop) {
                        $crop = explode(",", $crop);
                        $prefix = wire('sanitizer')->name($crop[0]);
                        $valid[] = $prefix . "_" . $file->basename;
                    }
                }*/
            }
        }
    }
    // now find all the files present on the page
    // identify those that are not part of our $valid array
    $d = new DirectoryIterator($page->filesManager->path);
    foreach ($d as $f) {
        if ($f->isDot() || !$f->isFile()) {
            continue;
        }
        if (!in_array($f->getFilename(), $valid)) {
            echo "Orphaned file: " . wire('config')->urls->files . "$id/" . $f->getBasename() . "\n";
//             unlink($f->getPathname());
        }
    }
    wire('pages')->uncache($page); // just in case we need the memory
}