<?php namespace Rapsys\AirBundle\Form\Extension\Type; use Doctrine\Persistence\ManagerRegistry; use Symfony\Component\Form\DataTransformerInterface; use Symfony\Component\Form\Exception\TransformationFailedException; use Symfony\Component\Form\Extension\Core\Type\HiddenType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\OptionsResolver\Options; use Symfony\Component\OptionsResolver\OptionsResolver; /** * Hidden Entity Type class definition * * @see https://symfony.com/doc/current/form/create_custom_field_type.html */ class HiddenEntityType extends HiddenType implements DataTransformerInterface { /** * @var ManagerRegistry $dm */ private $dm; /** * @var string $class */ private $class; /** * Constructor * * @param ManagerRegistry $doctrine */ public function __construct(ManagerRegistry $doctrine) { $this->dm = $doctrine; } /** * Configure options * * {@inheritdoc} */ public function configureOptions(OptionsResolver $resolver): void { //Call parent parent::configureOptions($resolver); //Derive "data_class" option from passed "data" object $class = function (Options $options) { return isset($options['data']) && \is_object($options['data']) ? \get_class($options['data']) : null; }; $resolver->setDefaults([ #'data_class' => null, 'class' => $class ]); } /** * Build form * * {@inheritdoc} */ public function buildForm(FormBuilderInterface $builder, array $options): void { //Set class from options['class'] $this->class = $options['class']; //Without class if (empty($this->class)) { //Set class from namespace and field name $this->class = str_replace('Form\\Extension\\Type', 'Entity\\' ,__NAMESPACE__).ucfirst($builder->getName()); //With bundle named entity } elseif ( ($pos = strpos($this->class, ':')) !== false && !empty($entity = substr($this->class, $pos + 1)) ) { //Set class from namespace and entity name $this->class = str_replace('Form\\Extension\\Type', 'Entity\\' ,__NAMESPACE__).$entity; } //Set this as model transformer //XXX: clone the model transformer to allow multiple hiddenentitytype field with different class $builder->addModelTransformer(clone $this); } /** * Transform data to string * * @param mixed $data The data object * @return string The object id */ public function transform($data): string { //Modified from comments to use instanceof so that base classes or interfaces can be specified if ($data === null || !$data instanceof $this->class) { return ''; } $res = $data->getId(); return $res; } /** * Reverse transformation from string to data object * * @param mixed $value The object id * @return mixed The data object */ public function reverseTransform(mixed $value): mixed { if (!$value) { return null; } $res = null; try { $rep = $this->dm->getRepository($this->class); $res = $rep->findOneById($value); } catch (\Exception $e) { throw new TransformationFailedException($e->getMessage()); } if ($res === null) { throw new TransformationFailedException(sprintf('A %s with id %s does not exist!', $this->class, $value)); } return $res; } }