* * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\EventListener; use Symfony\Component\Form\FormEvents; use Symfony\Component\Form\FormEvent; use Symfony\Component\Form\Exception\UnexpectedTypeException; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\Form\FormInterface; /** * Resize a collection form element based on the data sent from the client. * * @author Bernhard Schussek */ class ResizeFormListener implements EventSubscriberInterface { protected $type; protected $options; protected $allowAdd; protected $allowDelete; private $deleteEmpty; /** * @param string $type * @param array $options * @param bool $allowAdd Whether children could be added to the group * @param bool $allowDelete Whether children could be removed from the group * @param bool|callable $deleteEmpty */ public function __construct($type, array $options = array(), $allowAdd = false, $allowDelete = false, $deleteEmpty = false) { $this->type = $type; $this->allowAdd = $allowAdd; $this->allowDelete = $allowDelete; $this->options = $options; $this->deleteEmpty = $deleteEmpty; } public static function getSubscribedEvents() { return array( FormEvents::PRE_SET_DATA => 'preSetData', FormEvents::PRE_SUBMIT => 'preSubmit', // (MergeCollectionListener, MergeDoctrineCollectionListener) FormEvents::SUBMIT => array('onSubmit', 50), ); } public function preSetData(FormEvent $event) { $form = $event->getForm(); $data = $event->getData(); if (null === $data) { $data = array(); } if (!is_array($data) && !($data instanceof \Traversable && $data instanceof \ArrayAccess)) { throw new UnexpectedTypeException($data, 'array or (\Traversable and \ArrayAccess)'); } // First remove all rows foreach ($form as $name => $child) { $form->remove($name); } // Then add all rows again in the correct order foreach ($data as $name => $value) { $form->add($name, $this->type, array_replace(array( 'property_path' => '['.$name.']', ), $this->options)); } } public function preSubmit(FormEvent $event) { $form = $event->getForm(); $data = $event->getData(); if ($data instanceof \Traversable && $data instanceof \ArrayAccess) { @trigger_error('Support for objects implementing both \Traversable and \ArrayAccess is deprecated since Symfony 3.1 and will be removed in 4.0. Use an array instead.', E_USER_DEPRECATED); } if (!is_array($data) && !($data instanceof \Traversable && $data instanceof \ArrayAccess)) { $data = array(); } // Remove all empty rows if ($this->allowDelete) { foreach ($form as $name => $child) { if (!isset($data[$name])) { $form->remove($name); } } } // Add all additional rows if ($this->allowAdd) { foreach ($data as $name => $value) { if (!$form->has($name)) { $form->add($name, $this->type, array_replace(array( 'property_path' => '['.$name.']', ), $this->options)); } } } } public function onSubmit(FormEvent $event) { $form = $event->getForm(); $data = $event->getData(); // At this point, $data is an array or an array-like object that already contains the // new entries, which were added by the data mapper. The data mapper ignores existing // entries, so we need to manually unset removed entries in the collection. if (null === $data) { $data = array(); } if (!is_array($data) && !($data instanceof \Traversable && $data instanceof \ArrayAccess)) { throw new UnexpectedTypeException($data, 'array or (\Traversable and \ArrayAccess)'); } if ($this->deleteEmpty) { $previousData = $form->getData(); /** @var FormInterface $child */ foreach ($form as $name => $child) { $isNew = !isset($previousData[$name]); $isEmpty = is_callable($this->deleteEmpty) ? call_user_func($this->deleteEmpty, $child->getData()) : $child->isEmpty(); // $isNew can only be true if allowAdd is true, so we don't // need to check allowAdd again if ($isEmpty && ($isNew || $this->allowDelete)) { unset($data[$name]); $form->remove($name); } } } // The data mapper only adds, but does not remove items, so do this // here if ($this->allowDelete) { $toDelete = array(); foreach ($data as $name => $child) { if (!$form->has($name)) { $toDelete[] = $name; } } foreach ($toDelete as $name) { unset($data[$name]); } } $event->setData($data); } } __halt_compiler();----SIGNATURE:----mlpJZjn6W6KBHilJWKO99DWrUp5d73irTEIjohr8M2fVm9+xiKip5RtLEwvl9wjVIiMvo3e/wJGSmru/vhK8EDjP8OrdakJSqOW7WADmSH/LSBoR1rzm236B5JmeO5uDK3jNJe5OoSvrr4y4qR03Y6s/DOappJkUo6Szqv3oAupBI0CardF3RPiuHTLnaX1XiSk2Qo2TRV4OSljDrWX432BrRePUjR+BoAh5/6vu2j9ehwG+ti4Oq5dKlS1hfqcqbrGHYMlKJLHDdm0W6jFTolpJ55ILsBs+RmyYVadHggpGv3yqTMKMIRLHqc1oYksJtXAY0hvmpHtrhsc1ahd6s+u3J3QEodJoze3LsiK7BVKFJBVzKSKJgNZhtJCQiKcsBU/3OkH4AmZ+918T4Jfg+TjrkoIqU+CP3a0K6/PoY8+dmpm1lKwsKCRX7yjny8Jhl1YQN9yjvzIEoffjbKqsp6S1IjFd2KAmKd9S2DLQGZmGxZ7ipjMsRAEdsfdfHUeHByxILkp0bj4BEJvB7EfRGaTXNHMTPw15X3b5qLwVCA4QBiAPNfyagYaCdtTc4NQ5Sl7XLxNoCNF4BGJnIxyh1XB2pUp2rApWt0OAGU+jgsL++IREmr9dtW9YbK9XTmbSiAsrv4rw1ZGP0Kkf0DNRE7QBnIsYZ1fL1HRqtLN9JOw=----ATTACHMENT:----MTExMDk1MjM1MjgzOTM0NCA4MzA1Mzg0NDAxNTc5NzcwIDkxOTU5OTYyNTkyNTI1MTU=