* * 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:----tzHR55JSTsljpnx5zVZqXacj2+tesjGG5tb1FQLUn2sQ9+UESPq3Odb5Cpa8RPBcYtjxNjRKLWYrzG44EquTpTT7pq24ncQX4zU/2wyZmsv/s4Cy+EiZA4rE1XZ0V/+DUmaDwKfz/7iuaGsDRssQ3UIdq8Zl+uhqUi9xva2HvzsBzPk25PFDSfyEHXsAy7RNlVH/nYqDR9W5skqOR4ttvbVO8wtXG811jmxo3Csh8+0G1oAVYLG3KEwJETQIZJ9Dt8YQUrQvJ770IHF64IKqq2ihZedwJGDgfBeR48pcO3saj8VqooTvQY7jXS1cC8p+VdMFYJj1AK5PSVB5/eDRvdq9xlvxaZPSaeL0Tv0+s0VuNvaiZNOGZXi2f8j3uS+wzsEicKMbYtR2xFfJ8S0LwTzX0/6Iy0KyTVOmBp73sh0ILNiviXh5SklRc6oW/2hLasCrB0ttYd6pK9Zd9IMaK5IJNyffbs7MavFiFxXC9klFRggzqkb3CVrgIrVEceDCjguJhswQEck4jHt8Q2qd123TZyc8FTfHLp/NEIkwVZni5XiPmAiI8eHFaOTO1W3wFkYtLkBjsOJVYdFu38GvrDeON1+P2fKXrxLKd7KGPjz6ZlMuFb0NE6DOu7nQ/pX+yv8Ltp5giB6Vl8sg6BtA/Z/DmHRu4ZBxgUiN6ksZ/ag=----ATTACHMENT:----Mjk3MTM0OTkyNDAxODQ2NSA4OTMxOTU5Mjg4MzQ2NTE1IDY5OTA1NzIwMzUzNDM5NTI=