vendor/vich/uploader-bundle/src/Form/Type/VichFileType.php line 27

Open in your IDE?
  1. <?php
  2. namespace Vich\UploaderBundle\Form\Type;
  3. use Symfony\Component\Form\AbstractType;
  4. use Symfony\Component\Form\Extension\Core\Type;
  5. use Symfony\Component\Form\FormBuilderInterface;
  6. use Symfony\Component\Form\FormEvent;
  7. use Symfony\Component\Form\FormEvents;
  8. use Symfony\Component\Form\FormInterface;
  9. use Symfony\Component\Form\FormView;
  10. use Symfony\Component\OptionsResolver\Options;
  11. use Symfony\Component\OptionsResolver\OptionsResolver;
  12. use Symfony\Component\PropertyAccess\PropertyAccess;
  13. use Symfony\Component\PropertyAccess\PropertyAccessorInterface;
  14. use Symfony\Component\PropertyAccess\PropertyPath;
  15. use Vich\UploaderBundle\Form\DataTransformer\FileTransformer;
  16. use Vich\UploaderBundle\Handler\UploadHandler;
  17. use Vich\UploaderBundle\Mapping\PropertyMappingFactory;
  18. use Vich\UploaderBundle\Storage\StorageInterface;
  19. /**
  20.  * @author Kévin Gomez <contact@kevingomez.fr>
  21.  * @author Konstantin Myakshin <koc-dp@yandex.ru>
  22.  * @author Massimiliano Arione <max.arione@gmail.com>
  23.  */
  24. class VichFileType extends AbstractType
  25. {
  26.     /**
  27.      * @var StorageInterface
  28.      */
  29.     protected $storage;
  30.     /**
  31.      * @var UploadHandler
  32.      */
  33.     protected $handler;
  34.     /**
  35.      * @var PropertyMappingFactory
  36.      */
  37.     protected $factory;
  38.     /**
  39.      * @var PropertyAccessorInterface
  40.      */
  41.     protected $propertyAccessor;
  42.     public function __construct(
  43.         StorageInterface $storage,
  44.         UploadHandler $handler,
  45.         PropertyMappingFactory $factory,
  46.         PropertyAccessorInterface $propertyAccessor null
  47.     ) {
  48.         $this->storage $storage;
  49.         $this->handler $handler;
  50.         $this->factory $factory;
  51.         $this->propertyAccessor $propertyAccessor ?: PropertyAccess::createPropertyAccessor();
  52.     }
  53.     public function configureOptions(OptionsResolver $resolver): void
  54.     {
  55.         $resolver->setDefaults([
  56.             'allow_delete' => true,
  57.             'asset_helper' => false,
  58.             'download_link' => null,
  59.             'download_uri' => true,
  60.             //TODO: use 'form.label.download'
  61.             'download_label' => 'download',
  62.             'delete_label' => 'form.label.delete',
  63.             'error_bubbling' => false,
  64.             'translation_domain' => 'VichUploaderBundle',
  65.         ]);
  66.         $resolver->setAllowedTypes('allow_delete''bool');
  67.         $resolver->setAllowedTypes('asset_helper''bool');
  68.         $resolver->setAllowedTypes('download_link', ['null''bool']);
  69.         $resolver->setAllowedTypes('download_uri', ['bool''string''callable']);
  70.         $resolver->setAllowedTypes('download_label', ['bool''string''callable'PropertyPath::class]);
  71.         $resolver->setAllowedTypes('error_bubbling''bool');
  72.         $downloadUriNormalizer = static function (Options $options$downloadUri) {
  73.             if (null !== $options['download_link']) {
  74.                 @\trigger_error('The "download_link" option is deprecated since version 1.6 and will be removed in 2.0. You should use "download_uri" instead.'E_USER_DEPRECATED);
  75.                 return $options['download_link'];
  76.             }
  77.             return $downloadUri;
  78.         };
  79.         $resolver->setNormalizer('download_uri'$downloadUriNormalizer);
  80.     }
  81.     public function buildForm(FormBuilderInterface $builder, array $options): void
  82.     {
  83.         $builder->add('file'Type\FileType::class, [
  84.             'required' => $options['required'],
  85.             'label' => $options['label'],
  86.             'attr' => $options['attr'],
  87.             'translation_domain' => $options['translation_domain'],
  88.         ]);
  89.         $builder->addModelTransformer(new FileTransformer());
  90.         if ($options['allow_delete']) {
  91.             $this->buildDeleteField($builder$options);
  92.         }
  93.     }
  94.     protected function buildDeleteField(FormBuilderInterface $builder, array $options): void
  95.     {
  96.         // add delete only if there is a file
  97.         $builder->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) use ($options): void {
  98.             $form $event->getForm();
  99.             $parent $form->getParent();
  100.             // no object: no delete button
  101.             if (null === $parent) {
  102.                 return;
  103.             }
  104.             $object $parent->getData();
  105.             // no object or no uploaded file: no delete button
  106.             if (null === $object || null === $this->storage->resolveUri($object$form->getName())) {
  107.                 return;
  108.             }
  109.             $form->add('delete'Type\CheckboxType::class, [
  110.                 'label' => $options['delete_label'],
  111.                 'mapped' => false,
  112.                 'translation_domain' => $options['translation_domain'],
  113.                 'required' => false,
  114.             ]);
  115.         });
  116.         // delete file if needed
  117.         $builder->addEventListener(FormEvents::POST_SUBMIT, function (FormEvent $event): void {
  118.             $form $event->getForm();
  119.             $object $form->getParent()->getData();
  120.             $delete $form->has('delete') ? $form->get('delete')->getData() : false;
  121.             if (!$delete) {
  122.                 return;
  123.             }
  124.             $this->handler->remove($object$form->getName());
  125.         });
  126.     }
  127.     public function buildView(FormView $viewFormInterface $form, array $options): void
  128.     {
  129.         $object $form->getParent()->getData();
  130.         $view->vars['object'] = $object;
  131.         $view->vars['download_uri'] = null;
  132.         if ($options['download_uri'] && $object) {
  133.             $view->vars['download_uri'] = $this->resolveUriOption($options['download_uri'], $object$form);
  134.             $view->vars = \array_replace(
  135.                 $view->vars,
  136.                 $this->resolveDownloadLabel($options['download_label'], $object$form)
  137.             );
  138.         }
  139.         $view->vars['asset_helper'] = $options['asset_helper'];
  140.     }
  141.     public function getBlockPrefix(): string
  142.     {
  143.         return 'vich_file';
  144.     }
  145.     protected function resolveUriOption($uriOption$objectFormInterface $form)
  146.     {
  147.         if (true === $uriOption) {
  148.             return $this->storage->resolveUri($object$form->getName());
  149.         }
  150.         if (\is_callable($uriOption)) {
  151.             return $uriOption($object$this->storage->resolveUri($object$form->getName()));
  152.         }
  153.         return $uriOption;
  154.     }
  155.     protected function resolveDownloadLabel($downloadLabel$objectFormInterface $form): array
  156.     {
  157.         if (true === $downloadLabel) {
  158.             $mapping $this->factory->fromField($object$form->getName());
  159.             return ['download_label' => $mapping->readProperty($object'originalName'), 'translation_domain' => false];
  160.         }
  161.         if (\is_callable($downloadLabel)) {
  162.             $result $downloadLabel($object);
  163.             return [
  164.                 'download_label' => $result['download_label'] ?? $result,
  165.                 'translation_domain' => $result['translation_domain'] ?? false,
  166.             ];
  167.         }
  168.         if ($downloadLabel instanceof PropertyPath) {
  169.             return [
  170.                 'download_label' => $this->propertyAccessor->getValue($object$downloadLabel),
  171.                 'translation_domain' => false,
  172.             ];
  173.         }
  174.         return ['download_label' => $downloadLabel];
  175.     }
  176. }