Skip to content
This repository has been archived by the owner on Mar 5, 2022. It is now read-only.

"First arg must be a non empty string!" exception when deleting on cascade #122

Closed
choma opened this issue Feb 21, 2016 · 9 comments
Closed
Assignees
Labels
Milestone

Comments

@choma
Copy link
Contributor

choma commented Feb 21, 2016

I'm having a "First arg must be a non empty string!" exception when trying to delete a post and its associated image on cascade.

I'm using cakephp v3.2.1, with cakephp-file-storage v1.1.4 and cakephp-imagine-plugin v2.1.1

As I understand the problem is here. It is trying to read $event->result['adapter'], but $event->result is equal to true (I'm not sure, but I think that value comes from here)

Here is my current configuration:

// config/file_storage.php
$listener = new BaseListener([
    'imageProcessing' => true, // Required if you want image processing!
    'pathBuilderOptions' => [
        'pathPrefix' => '/files',
        'preserveFilename' => true
    ]
]);
// Attach the BaseListener to the global EventManager
EventManager::instance()->on($listener);
Configure::write('FileStorage', [
    // Configure image versions on a per model base
        // Same as docs example
]);
// This is very important! The hashes are needed to calculate the image versions!
StorageUtils::generateHashes();
// Configure Local adapter instance through the StorageManager
StorageManager::config('Local', [
    'adapterOptions' => [ROOT . DS . 'file_storage', true],
    'adapterClass' => '\Gaufrette\Adapter\Local',
    'class' => '\Gaufrette\Filesystem'
]);
// Set model field
\Cake\Event\EventManager::instance()->on('Model.beforeSave', function (\Cake\Event\Event $event, \Cake\ORM\Entity $entity, ArrayObject $options) {
    $event->subject()->patchEntity($entity, ['model' => $entity->source()]);
});

Table classes:

class PostsTable extends Table
{
    public function initialize(array $config)
    {
        parent::initialize($config);
        $this->hasOne('MainImages', [
            'foreignKey' => 'foreign_key',
            'className' => 'PostImages',
            'conditions' => ['model' => 'MainImages'],
            'dependent' => true,
            'cascadeCallbacks' => true
        ]);
    }
}

and

use Burzum\FileStorage\Model\Table\ImageStorageTable;
class PostImagesTable extends ImageStorageTable
{
    // empty
}

The controllers and templates are baked, and I'm using the posts/delete action to delete posts (and images on cascade).

Here is the full error log message:

2016-02-21 03:16:43 Error: [Burzum\FileStorage\Storage\StorageException] First arg must be a non empty string!
Request URL: /posts/delete/32
Referer URL: http://testupload.v1/posts
Stack Trace:
#0 /home/choma/www/testupload_v1/vendor/burzum/file-storage/src/Storage/Listener/BaseListener.php(81): Burzum\FileStorage\Storage\Listener\AbstractListener->_deleteFile(Object(Cake\Event\Event))
#1 /home/choma/www/testupload_v1/vendor/cakephp/cakephp/src/Event/EventManager.php(391): Burzum\FileStorage\Storage\Listener\BaseListener->afterDelete(Object(Cake\Event\Event), Object(Cake\ORM\Entity), Object(Gaufrette\Filesystem), Object(App\Model\Table\PostImagesTable))
#2 /home/choma/www/testupload_v1/vendor/cakephp/cakephp/src/Event/EventManager.php(355): Cake\Event\EventManager->_callListener(Array, Object(Cake\Event\Event))
#3 /home/choma/www/testupload_v1/vendor/cakephp/cakephp/src/Event/EventDispatcherTrait.php(78): Cake\Event\EventManager->dispatch(Object(Cake\Event\Event))
#4 /home/choma/www/testupload_v1/vendor/burzum/file-storage/src/Model/Table/FileStorageTable.php(243): Cake\ORM\Table->dispatchEvent('ImageStorage.af...', Array, NULL)
#5 /home/choma/www/testupload_v1/vendor/burzum/file-storage/src/Model/Table/ImageStorageTable.php(129): Burzum\FileStorage\Model\Table\FileStorageTable->dispatchEvent('ImageStorage.af...', Array)
#6 /home/choma/www/testupload_v1/vendor/cakephp/cakephp/src/Event/EventManager.php(391): Burzum\FileStorage\Model\Table\ImageStorageTable->afterDelete(Object(Cake\Event\Event), Object(Cake\ORM\Entity), Object(ArrayObject), Object(App\Model\Table\PostImagesTable))
#7 /home/choma/www/testupload_v1/vendor/cakephp/cakephp/src/Event/EventManager.php(355): Cake\Event\EventManager->_callListener(Array, Object(Cake\Event\Event))
#8 /home/choma/www/testupload_v1/vendor/cakephp/cakephp/src/Event/EventDispatcherTrait.php(78): Cake\Event\EventManager->dispatch(Object(Cake\Event\Event))
#9 /home/choma/www/testupload_v1/vendor/burzum/file-storage/src/Model/Table/FileStorageTable.php(243): Cake\ORM\Table->dispatchEvent('Model.afterDele...', Array, NULL)
#10 /home/choma/www/testupload_v1/vendor/cakephp/cakephp/src/ORM/Table.php(1725): Burzum\FileStorage\Model\Table\FileStorageTable->dispatchEvent('Model.afterDele...', Array)
#11 /home/choma/www/testupload_v1/vendor/cakephp/cakephp/src/ORM/Table.php(1647): Cake\ORM\Table->_processDelete(Object(Cake\ORM\Entity), Object(ArrayObject))
#12 /home/choma/www/testupload_v1/vendor/cakephp/cakephp/src/Database/Connection.php(557): Cake\ORM\Table->Cake\ORM\{closure}(Object(Cake\Database\Connection))
#13 /home/choma/www/testupload_v1/vendor/cakephp/cakephp/src/ORM/Table.php(1652): Cake\Database\Connection->transactional(Object(Closure))
#14 /home/choma/www/testupload_v1/vendor/cakephp/cakephp/src/ORM/Association/DependentDeleteTrait.php(48): Cake\ORM\Table->delete(Object(Cake\ORM\Entity), Array)
#15 /home/choma/www/testupload_v1/vendor/cakephp/cakephp/src/ORM/AssociationCollection.php(270): Cake\ORM\Association\HasOne->cascadeDelete(Object(App\Model\Entity\Post), Array)
#16 /home/choma/www/testupload_v1/vendor/cakephp/cakephp/src/ORM/Table.php(1709): Cake\ORM\AssociationCollection->cascadeDelete(Object(App\Model\Entity\Post), Array)
#17 /home/choma/www/testupload_v1/vendor/cakephp/cakephp/src/ORM/Table.php(1647): Cake\ORM\Table->_processDelete(Object(App\Model\Entity\Post), Object(ArrayObject))
#18 /home/choma/www/testupload_v1/vendor/cakephp/cakephp/src/Database/Connection.php(557): Cake\ORM\Table->Cake\ORM\{closure}(Object(Cake\Database\Connection))
#19 /home/choma/www/testupload_v1/vendor/cakephp/cakephp/src/ORM/Table.php(1652): Cake\Database\Connection->transactional(Object(Closure))
#20 /home/choma/www/testupload_v1/src/Controller/PostsController.php(102): Cake\ORM\Table->delete(Object(App\Model\Entity\Post))
#21 [internal function]: App\Controller\PostsController->delete('32')
#22 /home/choma/www/testupload_v1/vendor/cakephp/cakephp/src/Controller/Controller.php(430): call_user_func_array(Array, Array)
#23 /home/choma/www/testupload_v1/vendor/cakephp/cakephp/src/Routing/Dispatcher.php(114): Cake\Controller\Controller->invokeAction()
#24 /home/choma/www/testupload_v1/vendor/cakephp/cakephp/src/Routing/Dispatcher.php(87): Cake\Routing\Dispatcher->_invoke(Object(App\Controller\PostsController))
#25 /home/choma/www/testupload_v1/webroot/index.php(37): Cake\Routing\Dispatcher->dispatch(Object(Cake\Network\Request), Object(Cake\Network\Response))
#26 {main}
@choma
Copy link
Contributor Author

choma commented Feb 23, 2016

Sorry, I was wrong when I tried to guess where the problem was.
I'm not sure of being right again, that's the reason I don't PR, but this change worked for me. I changed this in AbstractListener:

protected function _afterDeleteFile(Event $event) {
        $this->_handleLegacyEvent($event);
        $afterDeleteEvent = new Event('FileStorage.afterDeleteFile', $this, [
            'entity' => $event->result,
            'adapter' => $this->storageAdapter($event->result['adapter'])
        ]);
        EventManager::instance()->dispatch($afterDeleteEvent);
    }

with this:

protected function _afterDeleteFile(Event $event) {
        $this->_handleLegacyEvent($event);
        $afterDeleteEvent = new Event('FileStorage.afterDeleteFile', $this, [
            // use passed entity here...
            'entity' => $event->data['entity'],
            'adapter' => $this->storageAdapter($event->data['entity']->adapter) 
        ]);
        EventManager::instance()->dispatch($afterDeleteEvent);
    }

And now it works for me.

@burzum burzum added the bug label Feb 23, 2016
@burzum burzum added this to the 1.1.0 milestone Feb 23, 2016
@burzum
Copy link
Owner

burzum commented Feb 25, 2016

Hey, sorry for the delay but I'm very busy this week with work and private stuff. I'll review this in detail when I have the time. I understand the problem and see the fix but I need to review it more deeply and see if this doesn't have any side effects.

@burzum burzum self-assigned this Feb 25, 2016
@choma
Copy link
Contributor Author

choma commented Feb 25, 2016

I'm not sure if it is related to this bug, but I've noted that even when the files are deleted correctly, the container folders are not. So I end up with a lot of empty nested folders. Is this the way it is supposed to work?

@burzum
Copy link
Owner

burzum commented Feb 25, 2016

I'm aware of that but never gave it a priority because it doesn't hurt.

The problem is you need to know if the file resides alone on this folder or not to delete the folder without accidentally deleting other files. The default config is that it should use one folder at the end of the nested path for each file which is using the uuid as name. But if you configure it different you can end up with many files in the same folder.

@burzum
Copy link
Owner

burzum commented Feb 28, 2016

@choma please try 1.1-dev I've fixed the code in the 1.1 branch.

@burzum burzum closed this as completed Feb 28, 2016
@choma
Copy link
Contributor Author

choma commented Feb 29, 2016

Nope!
It didn't fixed the issue for me. You still need to change the 390 line, by this:

'adapter' => $this->storageAdapter($event->data['entity']->adapter)

There is where the bug is in fact, sorry if wasn't clear in my previous comments.
I just changed the previous line because I thought it would create other problems.

burzum pushed a commit that referenced this issue Feb 29, 2016
@burzum
Copy link
Owner

burzum commented Feb 29, 2016

No problem, I've made the change.

Any reason you didn't do the change yourself and created a pull request?

@choma
Copy link
Contributor Author

choma commented Feb 29, 2016

I'm sorry I didn't. I'm still trying to understand the code, I'm not sure how the change will affect the rest of it. And I never learned to do php tests, so I'm not sure how to handle them.
But hopefully, with some more time using the plugin I'll be able to give you a hand :)

Thanks for the great plugin!

@burzum
Copy link
Owner

burzum commented Feb 29, 2016

Welcome, I'm glad you like it. Let me know if you need something else.

I can't admit that the plugin isn't the most easy one to use but I think it is the most powerful on with the best architecture. And I keep improving it. 2.0 will drop a lot of legacy code and make things more easy. I'm not happy with the image processing right now, it's still to tight coupled and interwoven with the storage related code.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests

2 participants