Open ksn135 opened 9 years ago
Hi @ksn135
This is probably because you don't go through https://github.com/symfony2admingenerator/FormExtensionsBundle/blob/master/Form/EventListener/CollectionUploadSubscriber.php#L174
I don't have immediately time to check for it. Maybe later today or next week (working on AdminLTE in priority :) ). But if you can find what's wrong and make a PR, that would be great !
Question: do you have the same issue with the "legacy" bundle? I have a sample in some of my codes, I'll try to show it to you ASAP
What is the "legacy" bundle ? You mean AvocodeFormExtensionsBundle ?
Yes... the current one is still unstable and in active development
My bad, production project already running on it Well, very good motivated hands avaiable to work on issues to speed up stabilisation!!! ))
Well, I try to get it fixed by myself
Here is some CollectionUpload I'm using in a production project working well:
$builder->add('medias', 'afe_collection_upload', array(
'primary_key' => 'pathHashed',
'label' => false,
'sortable' => false,
'nameable' => false,
'editable' => $options['with_description'] ? array('description') : array(),
'allow_add' => true,
'allow_delete' => true,
'type' => 'my_project_media',
'uploadRouteName' => 'async_upload',
'autoUpload' => $options['auto_upload'],
'options' => array(
'data_class' => Media::class,
'media_type' => Media::PICTURE,
'for_library' => true,
'with_description' => $options['with_description']
)
));
Could you please show us the generated Form?
Thank you,
Thank you very much for your help! Curently it starts working. I'm testing it. Code changes in CollectionUploadSubscriber.php:
if ($this->allow_add) {
// create file entites for each file
foreach ($this->uploads as $upload) {
$editable = $this->editable; // ADD THIS LINE
if (!is_object($upload) && !is_null($this->storage)) {
// read submitted editable
// $editable = $this->editable[$upload]; // COMMENT OUT THIS ONE
$upload = $this->storage->getFile($upload);
}
And my form class:
<?php
namespace Ksn135\CompanyBundle\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use Symfony\Component\Form\FormBuilderInterface;
use JMS\DiExtraBundle\Annotation\FormType;
/**
* @FormType
*/
class CabinetFileType extends AbstractType
{
/**
* (non-PHPdoc)
* @see \Symfony\Component\Form\AbstractType::buildForm()
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('id', 'hidden')
->add('name', 'text', array( 'label' => 'Название'))
->add('description', 'text', array( 'label' => 'Описание'))
->add('position', 'hidden')
->add('file','file');
}
/**
* (non-PHPdoc)
* @see \Symfony\Component\Form\AbstractType::setDefaultOptions()
*/
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'Ksn135\CompanyBundle\Entity\CabinetFile',
'groups' => array(),
'cascade_validation' => true
));
$resolver->setAllowedTypes(array(
'groups' => 'array',
));
}
/* (non-PHPdoc)
* @see \Symfony\Component\Form\FormTypeInterface::getName()
*/
public function getName()
{
return 'cabinet_file_type';
}
}
This is your CabinetFileType
, could you please show us the generated CabinetType
(I assumed) form.
Regarding your fix, take care that you change a big behavior there... Could you please double check what the type of $this->editable is? (is it an array or something else?)
I assume you are not in a "async" mode, am I right?
So basically, your fix might be wrong in async mode for example (I'm not sure, there is a long time I worked on that part, I could double check what I'm saying if you want). I think the right fix should be something like:
if ($this->allow_add) {
// create file entites for each file
$editable = array(); // Prevent strange behavior... or don't define it and so Exception will be thrown meaning the user mis-configured its form?
foreach ($this->uploads as $index => $upload) {
if (!is_object($upload) && !is_null($this->storage)) {
// read submitted editable
$editable = $this->editable[$upload];
$upload = $this->storage->getFile($upload);
} elseif (array_key_exists($index, $this->editable)) {
$editable = $this->editable[$index];
}
Not sure at all about it. You can also take a look here: https://github.com/sescandell/CollectionUploadSample
My mistake, in my sample project, I'm not using the editable param... I should make an example...
I assume you are not in a "async" mode, am I right?
With my fix it works in both modes.
If you return back my uncommented line you've got undefined index error, because $upload is null when you save already filed form.
My autogenerated form type for CabinetCategory:
<?php
namespace Admingenerated\Ksn135CompanyBundle\Form\BaseCabinet_categoryType;
use Admingenerator\GeneratorBundle\Form\BaseType;
use Admingenerator\GeneratorBundle\Form\BaseOptions;
use Symfony\Component\Form\FormBuilderInterface;
use JMS\SecurityExtraBundle\Security\Authorization\Expression\Expression;
class EditType extends BaseType
{
protected $securityContext;
public function buildForm(FormBuilderInterface $builder, array $options)
{
$this->groups = $options['groups'];
if ($this->isDisplayedTitle()) {
$builder->add('title', $this->getTypeTitle(), $this->getOptionsTitle($options));
}
if ($this->isDisplayedSlug()) {
$builder->add('slug', $this->getTypeSlug(), $this->getOptionsSlug($options));
}
if ($this->isDisplayedFiles()) {
$builder->add('files', $this->getTypeFiles(), $this->getOptionsFiles($options));
}
}
/**
* Get form type for title field.
*
* @return string|FormTypeInterface Field form type.
*/
protected function getTypeTitle()
{
return $this->inject('text');
}
/**
* Get options for title field.
*
* @param array $builderOptions The builder options.
* @return array Field options.
*/
protected function getOptionsTitle(array $builderOptions = array())
{
$optionsClass = 'Ksn135\CompanyBundle\Form\Type\Cabinet_category\Options';
$options = class_exists($optionsClass) ? new $optionsClass() : null;
return $this->resolveOptions('title', array( 'required' => true, 'label' => 'Наименование', 'translation_domain' => 'Admin',), $builderOptions, $options);
}
/**
* Check groups for title field.
*
* @return boolean
*/
protected function isDisplayedTitle()
{
return $this->checkGroups(array());
}
/**
* Get form type for slug field.
*
* @return string|FormTypeInterface Field form type.
*/
protected function getTypeSlug()
{
return $this->inject('text');
}
/**
* Get options for slug field.
*
* @param array $builderOptions The builder options.
* @return array Field options.
*/
protected function getOptionsSlug(array $builderOptions = array())
{
$optionsClass = 'Ksn135\CompanyBundle\Form\Type\Cabinet_category\Options';
$options = class_exists($optionsClass) ? new $optionsClass() : null;
return $this->resolveOptions('slug', array( 'required' => true, 'label' => 'Ссылка', 'translation_domain' => 'Admin',), $builderOptions, $options);
}
/**
* Check groups for slug field.
*
* @return boolean
*/
protected function isDisplayedSlug()
{
return $this->checkGroups(array());
}
/**
* Get form type for files field.
*
* @return string|FormTypeInterface Field form type.
*/
protected function getTypeFiles()
{
return $this->inject('s2a_collection_upload');
}
/**
* Get options for files field.
*
* @param array $builderOptions The builder options.
* @return array Field options.
*/
protected function getOptionsFiles(array $builderOptions = array())
{
$optionsClass = 'Ksn135\CompanyBundle\Form\Type\Cabinet_category\Options';
$options = class_exists($optionsClass) ? new $optionsClass() : null;
return $this->resolveOptions('files', array( 'required' => false, 'primary_key' => 'id', 'nameable' => true, 'nameable_field' => 'name', 'sortable' => true, 'sortable_field' => 'position', 'editable' => array( 0 => 'description', ), 'type' => new \Ksn135\CompanyBundle\Form\Type\CabinetFileType(), 'autoUpload' => true, 'loadImageFileTypes' => '/^image\\/(gif|jpe?g|png)$/i', 'previewMaxWidth' => 100, 'previewMaxHeight' => 100, 'previewAsCanvas' => true, 'prependFiles' => false, 'allow_add' => true, 'allow_delete' => true, 'error_bubbling' => false, 'options' => array( 'data_class' => 'Ksn135\\CompanyBundle\\Entity\\CabinetFile', ), 'label' => 'Загруженные файлы', 'translation_domain' => 'Admin',), $builderOptions, $options);
}
/**
* Check groups for files field.
*
* @return boolean
*/
protected function isDisplayedFiles()
{
return $this->checkGroups(array());
}
public function getName()
{
return 'edit_companybundle_cabinetcategory';
}
}
OK... I'll take a look later, if it works for now for you, it's okay :+1:
No, async mode IS NOT working in my case. It's problem with folder permissions in MAC OS X: http://stackoverflow.com/questions/16378828/result-of-sys-get-temp-dir-not-writable-by-apache-processs-user . Sync mode is worked after my patch, but now I can't delete uploaded file. Form submited and filed back again with just deleted file. Continue investigation... )
Well, javascript just remove uploaded file row from DOM on "delete" button and then on "save" send empty form. CollectionUploadSubscriber can't do anything because it dosen't recieve expected "delete_uploads" key in empty data array. Moving on... May be just piece of Javascript code just dissapers ? Or may be it's again something wrong in my case, don't know /
Did you try the other bundle: https://github.com/symfony2admingenerator/AvocodeFormExtensionsBundle ?
Hi,
I have the same problem with editable :
Undefined variable: editable
Was it fixed ?
Thanks
Hi,
I have the same problem too, with field editable :
Undefined variable: editable
Thanks !
I have encountered the same issue. My fix is as follows (Starting in line 174 in CollectionUploadSubscriber.php):
$editable = array();
if (!is_object($upload) && !is_null($this->storage)) {
// read submitted editable
$editable[] = array_key_exists($upload, $this->editable) ? $this->editable[$upload] : array();
$upload = $this->storage->getFile($upload);
}
I don't know exactly how this works but I assumed that on first upload (synchronous) there are objects in $upload and then the variable §editable will never be set. And when it is set, it has to be an array.
Please fix this soon. I would do this on my own but I'm not quite sure if my solution is best. It works though (at least for me but there is a chance to break async mode with my modifiaction) ;)
In fact $editable has to be a multidimensional array (see foreach call), maybe there is some more work to do to clean it up.
Greetings.
@tknuppe For me your code works with the following changes:
$editable = array_key_exists($upload, $this->editable) ? $this->editable[$upload] : array();
I'm on dev-master. In vendor/symfony2admingenerator/form-extensions-bundle/Admingenerator/FormExtensionsBundle/Form/EventListener/CollectionUploadSubscriber.php at line 192
My config:
My entity (almost the same as from example: https://github.com/symfony2admingenerator/FormExtensionsBundle/blob/master/Resources/doc/collection-upload/overview.md):