I have this model:
Banner:
columns:
filename: string(255)
url: string(255)
position:
type: enum
values: [top, right]
default: right
and this form:
class BannerForm extends BaseBannerForm
{
public function configure()
{
$this->widgetSchema['filename'] = new sfWidgetFormInputFileEditable(array(
'file_src' => $this->getObject()->getThumbURL(),
'is_image' => true,
'edit_mode' => $this->getObject()->exists()
));
$validated_file_class = $this->getObject()->position === 'right' ? 'bannerRightValidatedFile' : 'bannerTopValidatedFile';
$this->validatorSchema['filename'] = new sfValidatorFile(array(
'path' => sfConfig::get('sf_upload_dir'),
'mime_types' => 'web_images',
'validated_file_class' => $validated_file_class',
'required' => $this->getObject()->isNew()
));
}
}
I use different validate classes because inside it i incapsulate thumbnail operations, and the sizes of banners depends on it position field. The problem is that $validated_file_class is always bannerRightValidatedFile class. How i can achieve this thing ?
I can suggest 4 solutions which you can choose from:
Option 1:
You should add a update$fieldNameColumn method to the form class. In your case it should look like this:
// change validated file instance before calling save
protected function updateFilenameColumn($value)
{
if ($value instanceof sfValidatedFile)
{
$class = 'right' == $this->getValue('position') ? 'bannerRightValidatedFile' : 'bannerTopValidatedFile';
// this will not work as I thought at first time
// $this->getValidator('filename')->setOption('validated_file_class', $class);
$this->values['filename'] = new $class(
$value->getOriginalName(),
$value->getType(),
$value->getTempName(),
$value->getSize(),
$value->getPath()
);
return $this->processUploadedFile('filename');
}
return $value;
}
I think it's kind of hacky.
Option 2:
You should add a doctrine hook method to the model:
/**
* @param Doctrine_Event $event
*/
public function postSave($event)
{
$record = $event->getInvoker();
if (array_key_exists('filename', $record->getLastModified()))
{
// get the full path to the file
$file = sfConfig::get('sf_upload_dir') . '/' . $record->getFilename();
if (file_exists($file))
{
// resize the file e.g. with sfImageTransformPlugin
$img = new sfImage($file);
$img
->resize(100, 100)
->save();
}
}
}
This will work when creating records whitout a form e.g. when using fixtures.
Option 3:
Use the admin.save_object
event.
public static function listenToAdminSaveObject(sfEvent $event)
{
$record = $event['object'];
if ($event['object'] instanceof Banner)
{
// use the same code as in the `postSave` example
}
}
Option 4:
Use the sfImageTransformExtraPlugin
It's kind of hard to setup and configure (and it's code is a mess :), but it makes possible to modify the size of the image whithout regenerating all the already resized ones.