Jump to content

Hook processInputFile and processInputDeleteFile


cwsoft
 Share

Recommended Posts

Hi,

I added the following hook into site/ready.php to extract the contents of an uploaded ZIP archive to a specific folder (site/assets/files/uploads). The first steps works just fine.

// Hook into input file field to extract zip files into specific target folder.
$wire->addHookAfter('InputfieldFile::processInputFile', function (HookEvent $event) {
    // Limit unzip handler to specific file fields on specific template pages.
    $pageFile = $event->arguments('pagefile');
    $page = $pageFile?->page;
    if (!$page || $page->template->name !== 'XX' || $pageFile->field->name !== 'XX_zip') 
		return $event->return;

    // Build path to specific target folder, where ZIP files gets extracted to.
    $files = $this->wire('files');
    $extractPath = $this->wire('config')->paths->assets . "files/uploads";

    // Ensure destination folder for files to extract exists.
    if (!$files->exists($extractPath, 'dir')) {
        $files->mkdir($extractPath, $recursive = true);
    }

    // Extract ZIP file into specific folder.
    if ($files->exists($extractPath, 'writeable dir')) {
        $items = $files->unzip($pageFile->filename, $extractPath);
    }
    return $event->return;
});

Then I tried to remove the automatically extracted files from the specific folder, once the uploaded ZIP files gets deleted via the backend via the hook below (again in site/ready.php). The code below works standalone, but not in combination with the other hook above.

Issue: Once the code in the delete hook (below) was executed, the code in the processInputFile hook (above) kicks in again, causing the unpacking of the files from the uploaded ZIP archive again. The ZIP file gets deleted during the process, but the unpacked files remain inside /site/assets/files/uploads.

// Hook into file field to remove extracted files from specific folder once ZIP file gets deleted.
$wire->addHookAfter('InputfieldFile::processInputDeleteFile', function (HookEvent $event) {
    // Limit unzip handler to specific file fields on specific template pages.
    $pageFile = $event->arguments('pagefile');
    $page = $pageFile?->page;
    if (!$page || $page->template->name !== 'XX' || $pageFile->field->name !== 'XX_zip') 
		return $event->return;

    // Build path to target folder.
    $files = $this->wire('files');
    $extractPath = $this->wire('config')->paths->assets . "files/uploads";

    // Delete zip folder when ZIP file gets deleted.
    $files->rmdir($extractPath, $recursive = true);

    return $event->return;
});

Also tried to hook to processInputAddFile without success.

Is there any way I can check inside processInputFile, if the hook was triggered by the delete or upload/add action?

Thanks in advance for any hints or comments on this issue.

Edited by cwsoft
Link to comment
Share on other sites

Hi. Added a "workaround" to solve my issue by setting a session variable at the end of the processInputDelete Hook to indicate, that the ZIP file was deleted. Then I check in the processInputHook if this session variable exists and is true to skip the part to extract the content of the ZIP file again. That seems to work.

However I doubt this is the best solution to deal with this issue. Is there a more PW like way achieving the same without the ugly session variable hack? Any hints or tips on this topic are welcome.

Link to comment
Share on other sites

Just curious if there's a less PW-like way of dealing with this issue? Are you unpacking the archive, doing some processing on the extracted files, then deleting the files -- all in sequential order? If so, why not call the other methods from within each method/step of the process? That way you'd only need one hook, the other logic can be separated into standard functions/methods and don't need to rely on proper hook order.

If that's not possible, I haven't checked to see if PW's file methods are non-blocking, but if they are blocking, then perhaps setting a priority order on the hook calls will suffice?

  • Like 1
Link to comment
Share on other sites

@BrendonKozThanks for your suggestion.

Basically an editor can upload a zip file with PDF participation certificates for courses from a page file field in the backend. Once the ZIP file was uploaded, the PDF files should be extracted to a folder inside site/assets/files/upload, which is protected via .htaccess from direct access. At the end of the year the extracted PDF files will be deleted by the course editor, by deleting the corresponding ZIP archive via pressing the trashcan icon of the page file field.

The course attendees can download their PDF certificate after the course is finished from their course page available after frontend login. This is done by clicking a download button, which reads the binary contents of the corresponding PDF file and sends it as PDF file to the browser for download using PHP header functions. So the PDF files are not touched after upload until they get deleted at the end of the year. The PDF files should stay around until the end of the year or a predefined time period before getting deleted.

So I do need two hooks. Upload of the ZIP file triggers the unzip task and the deletion of the ZIP archive should trigger the delete extracted PDF files task. Timing won‘t help, as the delete action should not trigger the unzip process again.

Edited by cwsoft
  • Like 1
Link to comment
Share on other sites

Looking at the code for processInputFile, it does seem to run against any changes to the field, including deletion, so in that regard it makes sense that it also runs when the ZIP archive file is being deleted. You might be able to get an InputfieldFile after hook to work against ProcessInputAddFile, but I think to be successful you'd have to examine the current method to get access to the values you need since the default method only accepts the filename as a parameter, you can't immediately get the pagefile. Maybe that was the issue when you tried to use it as a hook previously?

  • Like 1
Link to comment
Share on other sites

@BrendonKozYes that is exactly the issue. The method processInputFile executes on both upload and deletion using the file input field. The processInputAddFile does not allow easy access to the pagefile and the other infos like page object etc. needed to unzip the files to the designated spots. Thought there might be a PW way of preventing trigger to kick in (e.g. by adding data to return value object) or to detect inside processInputFile if this was triggered from processInputDeleteFile etc.

The easiest method I came up with is to set a PW session variable inside the delete hook and check for it in processInputFile to skip the extraction of the ZIP file. This works fine, but I doubt that this is the ideal way of doing it. 

Edited by cwsoft
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.
×
×
  • Create New...