FriendsOfCake / cakephp-upload

CakePHP: Handle file uploading sans ridiculous automagic
https://cakephp-upload.readthedocs.io/
MIT License
551 stars 255 forks source link

Empty field does not update and clean the record value #490

Closed sirhaplo closed 6 years ago

sirhaplo commented 6 years ago

Hi, i have a field that contain a pdf module.

$this->addBehavior('Josegonzalez/Upload.Upload', [
            'modulo1' => [
                'path' => 'webroot{DS}files{DS}{field-value:mail}{DS}'
            ]
]);

When i save the module there are no problems. Then in edit i show a link to the file and a delete button. Once i press delete i remove the link and add a the file field. If I post the file field empty, beacause i want to clean the value, nothing happen. Cakephp doesnt see the field and update only the 'modified' field.

I dont want to delete the old file ( i saw about dinamic paths ) only to clean up the value How should i clean a file managed by your Plugin ?

davidyell commented 6 years ago

I would think you need to write an empty value into the modulo1 property of the Entity before you save it. I'd try an empty string '' personally, or allow the column to be nullable in the database, and write a null.

There is an example of deleting files in the documentation you might find helpful to understand the process, and adapt to your needs.

sirhaplo commented 6 years ago

I've tried one moment ago without success :

$provider = $this->Providers->patchEntity($provider, $data); 
if ((isset($data['modulo1'])) && (!$data['modulo1']['tmp_name'])) {
                $provider->modulo1  = ''; 
                $provider->setDirty('modulo1', true);
            }

If i receive the empty field i reset the field ( tried both '' and null ) After the patch entity, else it would fail the validation ( is expectign an array ). Now the entity is ready to be saved :

object(Cake\ORM\Entity) {
    'id' => (int) 301,
         ... etc etc ...    
        'modulo1' => '',    
         ... etc etc ...
    'created' => object(Cake\I18n\FrozenTime) {

        'time' => '2018-01-24T00:00:00+00:00',
        'timezone' => 'UTC',
        'fixedNowTime' => false

    },
    'modified' => object(Cake\I18n\FrozenTime) {

        'time' => '2018-06-07T09:38:03+00:00',
        'timezone' => 'UTC',
        'fixedNowTime' => false

    },
         ... etc etc ...
    '[new]' => false,
         ... etc etc ...
    '[dirty]' => [      
        'modulo1' => true
    ],
    '[original]' => [
        'modulo1' => 'Import2.xlsx'
    ],
        ... etc etc ...
}

But cake still not save it :

UPDATE 
  providers 
SET 
  modified = '2018-06-07 09:39:33' 
WHERE 
  id = 301

I think the behaviour intercepts in some way the field and deny the save, its possible ?

davidyell commented 6 years ago

Perhaps try setting an array with an error set?

You could use UPLOAD_ERR_NO_FILE http://php.net/manual/en/features.file-upload.errors.php

sirhaplo commented 6 years ago

I found a solution. Here ( https://github.com/FriendsOfCake/cakephp-upload/blob/dd91ff86321e87d1fb5af9cd03d78022d214f319/src/Model/Behavior/UploadBehavior.php#L91 ) you search for 'restoreValueOnFailure' and set the default to true. So in any case the field is invalid you reset back to original value.

The solution is the combination between set the field to null and force restoreValueOnFailure = false.

In table initialize

$this->addBehavior('Josegonzalez/Upload.Upload', [
            'modulo1' => [
                'path' => 'webroot{DS}files{DS}{field-value:mail}{DS}',
                'restoreValueOnFailure' => false
            ]
]);

and in the Controller edit

$provider = $this->Providers->patchEntity($provider, $data); 
if ((isset($data['modulo1'])) && (!$data['modulo1']['tmp_name'])) {
                $provider->modulo1  = null; 
                $provider->setDirty('modulo1', true);
            }

Hope this will be usefull to others

davidyell commented 6 years ago

Great, glad you found a solution.