Closed bobmulder closed 7 years ago
You could override the PathProcessor to not use the Default File Trait and do whatever you'd like instead. The nameCallback
option is there as an easy way to get things done.
Thanks @josegonzalez, I'll check it out. It's probably worth supporting this by default?
For next users:
<?php
namespace App\Core\Upload;
use Cake\ORM\Entity;
use Cake\ORM\Table;
use Cake\Utility\Hash;
use Josegonzalez\Upload\File\Path\ProcessorInterface;
use Josegonzalez\Upload\File\Path\Basepath\DefaultTrait as BasepathTrait;
class PathProcessor implements ProcessorInterface
{
/**
* Table instance.
*
* @var \Cake\ORM\Table
*/
protected $table;
/**
* Entity instance.
*
* @var \Cake\ORM\Entity
*/
protected $entity;
/**
* Array of uploaded data for this field
*
* @var array
*/
protected $data;
/**
* Name of field
*
* @var string
*/
protected $field;
/**
* Settings for processing a path
*
* @var array
*/
protected $settings;
/**
* Constructor
*
* @param \Cake\ORM\Table $table the instance managing the entity
* @param \Cake\ORM\Entity $entity the entity to construct a path for.
* @param array $data the data being submitted for a save
* @param string $field the field for which data will be saved
* @param array $settings the settings for the current field
*/
public function __construct(Table $table, Entity $entity, $data, $field, $settings)
{
$this->table = $table;
$this->entity = $entity;
$this->data = $data;
$this->field = $field;
$this->settings = $settings;
}
/**
* Returns the filename for the current field/data combination.
* If a `nameCallback` is specified in settings, then that callable
* will be invoked with the current upload data.
*
* @return string
*/
public function filename()
{
$processor = Hash::get($this->settings, 'nameCallback', null);
if (is_callable($processor)) {
return $processor($this->data, $this->settings, $this->entity);
}
return $this->data['name'];
}
use BasepathTrait;
}
And in your config:
$this->addBehavior('Josegonzalez/Upload.Upload', [
'file' => [
'pathProcessor' => PathProcessor::class,
'nameCallback' => function ($data, $settings, $entity) {
// use $entity here
}
]
]);
Want to make a PR to expand it?
As soon I got time for that I will! To make it backwards compatible we should detect if the $entity
is requested by the developer... Or do you prefer another PathProcessor
(which doesn't feel that 'DRY')
We can just cut a minor/major release if need be.
Bumping this as I too would find this very useful. Naming files currently seems rather arbitrary, I can use a hash of the file or whatever the user supplied (which seems like a bad idea), or maybe something else. Renaming file like $entity->full_name
would take care of many use-cases, but it looks like this never made it in to the repo?
You can use {field-value:SOME_FIELD}
to grab some value from the entity.
Thank you for the tip, though that does not seem to be working for me in the path or in the nameCallback. Here is my configuration:
$this->addBehavior('Josegonzalez/Upload.Upload', [
'photo_path' => [
'path' => '{DS}webroot{DS}img{DS}sps{DS}{field-name:first_name}{DS}',
'pathProcessor' => 'Josegonzalez\Upload\File\Path\DefaultProcessor',
'nameCallback' => function($data, $settings) {
return "{field-name:first_name}.jpg";
},
]
]);
When I upload using these settings, I get a file which is literally webroot/img/sps/{field-name:first_name}/{field-name:first_name}.jpg
. I would like to be able to use the nameCallback as above as I am only interested in using the field on file name, not the directory name.
If you can confirm that this is a sensible configuration I will try to figure out what's going wrong, or I can put together a minimal project for you to demonstrate the behavior.
I didn't say {field-name:SOME_FIELD}
, I said {field-value:SOME_FIELD}
. That belongs in your path
option, as specified here: https://cakephp-upload.readthedocs.io/en/latest/configuration.html. That assumes you have that field in the data being posted of course.
Ah yes! What a silly mistake. So then I will use @bobmulder solution to pull a field from the entity in the nameCallback, since {field-value:SOME_FIELD} has no effect there. Thank you for your time!
Hi there,
I want to change my filename based on some entity values. It's able to use entity related values when configuring the path, but I would like to set its filename.
Any hints about how to do this? An addition would be to add the entity as 3rd parameter in the callback...
Greetz,
Bob