0

I am working with CKFinder 3.4 for PHP and I am looking for a way to change the format of the automatic renaming that takes place when uploading a file which already exists on the server. The standard format is to rename file.ext to file(1).ext. I need to change this to file-1.ext.

It is possible to change the functionality in the source of ckfinder easily enough in:

/core/connector/php/vendor/cksource/ckfinder/src/CKSource/CKFinder/Filesystem/File/File.php

however I would like to avoid changing source files since it makes updating more difficult.

Optimally I would like to solve the problem using a plugin, however the BEFORE_COMMAND_FILE_UPLOAD event does not seem to contain the (auto) renamed filename.

Anyone out there who has worked on a similar problem and found a solution?

1 Answers1

0

I've prepared a small connector plugin that renames files the way you described. Unfortunately, I couldn't achieve this result without a small hack: binding a closure to access a private object property.

To find out more about CKFinder 3 PHP Connector plugins please have a look at plugins docs.

Here's the plugin, I hope you will find it useful:

<?php

namespace CKSource\CKFinder\Plugin\CustomAutorename;

use CKSource\CKFinder\CKFinder;
use CKSource\CKFinder\Event\BeforeCommandEvent;
use CKSource\CKFinder\Event\CKFinderEvent;
use CKSource\CKFinder\Filesystem\Folder\WorkingFolder;
use CKSource\CKFinder\Plugin\PluginInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\File\UploadedFile;

class CustomAutorename implements PluginInterface, EventSubscriberInterface
{
    protected $app;

    public function setContainer(CKFinder $app)
    {
        $this->app = $app;
    }

    public function getDefaultConfig()
    {
        return [];
    }

    public function onBeforeUpload(BeforeCommandEvent $event)
    {
        $request = $event->getRequest();

        /** @var UploadedFile $uploadedFile */
        $uploadedFile = $request->files->get('upload');

        /** @var WorkingFolder $workingFolder */
        $workingFolder = $this->app['working_folder'];

        if ($uploadedFile) {
            $uploadedFileName = $uploadedFile->getClientOriginalName();
            if (!$workingFolder->containsFile($uploadedFileName)) {
                // File with this name doesn't exist, nothing to do here.
                return;
            }

            $basename = pathinfo($uploadedFileName, PATHINFO_FILENAME);
            $extension = pathinfo($uploadedFileName, PATHINFO_EXTENSION);

            $i = 0;

            // Increment the counter until there's no file named like this in current folder.
            while (true) {
                $i++;
                $uploadedFileName = "{$basename}-{$i}.{$extension}";

                if (!$workingFolder->containsFile($uploadedFileName)) {
                    break;
                }
            }

            // And here's the hack to make a private property accessible to set a new file name.
            $setOriginalName = function (UploadedFile $file, $newFileName) {
                $file->originalName = $newFileName;
            };

            $setOriginalName = \Closure::bind($setOriginalName, null, $uploadedFile);

            $setOriginalName($uploadedFile, $uploadedFileName);
        }
    }

    public static function getSubscribedEvents()
    {
        return [CKFinderEvent::BEFORE_COMMAND_FILE_UPLOAD => 'onBeforeUpload'];
    }
}
zaak
  • 745
  • 7
  • 14