Friday, August 28, 2009

symfony admin generator upload reloaded

the good old admin_input_file_tag



When you hear that symfony "admin generator system has improved", it usually means
that they got rid of some useful feature (ie. upload/form helpers in generator.yml, validation in yaml etc :)

To "emulate" the deprecated admin_input_file_tag behaviour without fall back to the sfCompat10Plugin (whose features will be deprecated in the next releases of the framework) I did something like this in lib/form/doctrine/BaseFormDoctrine.class.php:



abstract class BaseFormDoctrine extends sfFormDoctrine
{
protected function _getWebUploadDirPath($fieldName)
{
return '/'. basename(sfConfig::get('sf_upload_dir')) .'/files/'.
$this->getModelName() .'/'. $fieldName .'/';
}

protected function _getUploadDirPath($fieldName)
{
return sfConfig::get('sf_upload_dir') .'/files/'. $this->getModelName() .'/'. $fieldName .'/';
}

/**
* Get generator.yml configuration
*/
protected function _getFieldsForm() {
static $generatorYml = null;
if ($generatorYml == null) {
try {
$configClassName = sfContext::getInstance()->getModuleName() . 'GeneratorConfiguration';
$configuration = new $configClassName();
$generatorYml = $configuration->getFieldsForm();
}
catch (sfException $e) {
return array();
}
}
return $generatorYml;
}

public function setup()
{
parent::setup();

foreach ($this->_getFieldsForm() as $fieldName => $config) {
if (isset($config['ntcType']) and $config['ntcType'] == 'image_upload') {
$getterFunction = 'get'. sfInflector::camelize($fieldName);
$this->validatorSchema[$fieldName] = new sfValidatorFile(array(
'required' => FALSE,
'path' => $this->_getUploadDirPath($fieldName),
'mime_types' => 'web_images',
));
$this->validatorSchema[$fieldName .'_delete'] = new sfValidatorBoolean();
$this->widgetSchema[$fieldName] = new sfWidgetFormInputFileEditable(array(
'label' => sfInflector::humanize($fieldName),
'is_image' => TRUE,
'with_delete' => TRUE,
'delete_label' => 'remove current file',
'edit_mode' => !$this->isNew(),
'template' => '%input% %delete% %delete_label% %file%',
'file_src' => $this->_getWebUploadDirPath($fieldName) .
pathinfo($this->getObject()->$getterFunction(), PATHINFO_FILENAME) .'_thumb.jpg',
));
}
}
}

protected function processUploadedFile($field, $filename = null, $values = null)
{
$generatorYml = $this->_getFieldsForm();
$fileName = parent::processUploadedFile($field, $filename, $values);
/*
* create a thumbnail to show in the form
*/
if (isset($generatorYml[$field]['ntcType']) and
$generatorYml[$field]['ntcType'] == 'image_upload')
{
$dirPath = $this->_getUploadDirPath($field);
if (!empty($fileName)) {
$thumbnail = new sfThumbnail(150, 150);
$thumbnail->loadFile($dirPath . $fileName);
$thumbName = pathinfo($fileName, PATHINFO_FILENAME) . '_thumb.jpg';
$thumbnail->save($dirPath . $thumbName, 'image/jpeg');
}
}
return $fileName;
}
}



Then put in generator.yml of your model:


...

form:
fields:
my_image_field: {ntcType: image_upload}



You have to install sfThumbnailPlugin to make this work (or you just can drop the thumbnail generation code)

This will activate a file upload widget for every field configured with type "image_upload".

Thanks to searbe post for the inspiration.

2 comments:

Anonymous said...

not a good idea... base is the base. if you plan to rebuild your model is cleaned up.

gunzip said...

actually, it doesn't (i'm used to rebuild my models pretty often =). it's a special case (indeed it's outside the base directory) so it's safe to use.

Post a Comment