5

I'm using Concrete5, and I'm trying to display thumbnails for various uploaded files. While some of these might be images, the majority are PDFs.

I'm currently using:

<?php
$file = File::getByID($fID);
$imageHelper = Core::make('helper/image');
try {
    $imageHelper->outputThumbnail($file, 200, 200);
} catch(InvalidArgumentException $e) { ?>
    <img src='https://placehold.it/200x200'>
<?php } ?>

I'd much prefer to somehow create a smaller thumbnail of PDF files, for example by using ghostscript in the background. In the built-in file manager, at least a PDF icon is displayed. That would be a non-optimal option, but still better than not displaying anything to signify that we're dealing with a PDF..

How can I access the built-in thumbnails? And, more importantly, how can I properly overwrite them for certain file-types when they are uploaded?

EDIT:

I came across $file->getThumbnailURL('type'); and created a type for my own purposes. How would you automatically generate such a thumbnail when a file is uploaded? I can likely figure out how to generate the file with plain PHP, but storing it in Concrete5 is something I'm unsure about.

Joost
  • 4,094
  • 3
  • 27
  • 58
  • I have no idea whether C5 supports this, interesting question. If it doesn't work out, you could consider taking care of the thumbnail generation yourself, generating and storing them in a separate directory. – Pekka May 14 '15 at 12:06
  • @Pekka I did consider that for a bit.. I noticed that there is an `on_file_add` event to hook into. How would you recommend associating thumbnails with files? Create a directory structure based on the file ID? Or can I somehow set the location for custom thumbnail types? Thanks for bringing this up! – Joost May 14 '15 at 12:09

2 Answers2

2

In the end, here's how I did it.

I started off by creating a new thumbnail type in the configure method of my package's controller, as follows:

use Concrete\Core\File\Image\Thumbnail\Type\Type;

...

public function configure($pkg) {
    ...

    $thumbnailType = new Type();
    $thumbnailType->setName(tc('ThumbnailTypeName', 'PDF Thumbnails'));
    $thumbnailType->setHandle('pdfthumbnails');
    $thumbnailType->setWidth(200);
    $thumbnailType->setHeight(200);
    $thumbnailType->save();
}

Then I created a class mypackage/src/document_processing/pdfthumbnails.php with the following contents:

namespace Concrete\Package\Mypackage\Src\DocumentProcessing;

use Core;
use File;
use Concrete\Core\File\Image\Thumbnail\Type\Type;

class Pdfthumbnails {

    public function processPDFThumbnails($fv) {
        $fi = Core::make('helper/file');
        $fvObj = $fv->getFileVersionObject();
        $ext = $fi->getExtension($fvObj->getFilename());
        $file = $fvObj->getFile();
        if ($ext == 'pdf') {
            $type = Type::getByHandle('pdfthumbnails');
            $basetype = $type->getBaseVersion();
            $thumbpath = $basetype->getFilePath($fvObj);

            $fsl = $file->getFileStorageLocationObject()->getFileSystemObject();
            $fre = $fvObj->getFileResource();
            // this requires sufficient permissions..
            // depending on your setup, reconsider 0777
            mkdir('application/files'.dirname($thumbpath), 0777, true);
            exec('gs -o application/files'.escapeshellarg($thumbpath).' -dPDFFitPage -sDEVICE=png16m -g200x200 -dLastPage=1 -f application/files/'.escapeshellarg($fre->getPath()));
        }
    }
}

And then I hooked into the on_file_version_add event in my package's controller:

use Concrete\Package\Mypackage\Src\DocumentProcessing\Pdfthumbnails;

...

    public function on_start() {
        Events::addListener('on_file_version_add', array(new Pdfthumbnails(), 'processPDFThumbnails'));
    }
Joost
  • 4,094
  • 3
  • 27
  • 58
1

This appears to be possible inside C5 after all, using file inspectors:

Any time a file is imported into Concrete5 (which happens through an instance of the File Importer class) it may be run through an optional file Inspector, which is a PHP class that can perform additional operations on files of a certain type when they're uploaded or rescanned

More information and implementation examples on file inspectors can be found in the C5 documentation.

In this Concrete5 forum discussion, someone seems to have used this feature to build exactly what you want to build, a thumbnail generator for PDFs using ImageMagick.

That user's example code does two things. First, it registers a new custom file inspector with the running C5 instance. Then, your custom inspector library is added to the project.

Pekka
  • 442,112
  • 142
  • 972
  • 1,088
  • 1
    Nice, that looks pretty neat! Thanks. I'll try it out and will report back :) – Joost May 14 '15 at 12:16
  • I ended up using this to hook into the file_add_version event, and that works fine. The problem is still with actually _storing_ the generated thumbnail, though. This does not seem to be addressed there. – Joost Jun 06 '15 at 10:30