diff options
Diffstat (limited to 'vendor/symfony/form/Symfony/Component/Form/Extension/Core/EventListener/MergeCollectionListener.php')
-rw-r--r-- | vendor/symfony/form/Symfony/Component/Form/Extension/Core/EventListener/MergeCollectionListener.php | 137 |
1 files changed, 137 insertions, 0 deletions
diff --git a/vendor/symfony/form/Symfony/Component/Form/Extension/Core/EventListener/MergeCollectionListener.php b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/EventListener/MergeCollectionListener.php new file mode 100644 index 00000000..4d0bdfaa --- /dev/null +++ b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/EventListener/MergeCollectionListener.php | |||
@@ -0,0 +1,137 @@ | |||
1 | <?php | ||
2 | |||
3 | /* | ||
4 | * This file is part of the Symfony package. | ||
5 | * | ||
6 | * (c) Fabien Potencier <fabien@symfony.com> | ||
7 | * | ||
8 | * For the full copyright and license information, please view the LICENSE | ||
9 | * file that was distributed with this source code. | ||
10 | */ | ||
11 | |||
12 | namespace Symfony\Component\Form\Extension\Core\EventListener; | ||
13 | |||
14 | use Symfony\Component\EventDispatcher\EventSubscriberInterface; | ||
15 | use Symfony\Component\Form\FormEvents; | ||
16 | use Symfony\Component\Form\FormEvent; | ||
17 | use Symfony\Component\Form\Exception\UnexpectedTypeException; | ||
18 | |||
19 | /** | ||
20 | * @author Bernhard Schussek <bschussek@gmail.com> | ||
21 | */ | ||
22 | class MergeCollectionListener implements EventSubscriberInterface | ||
23 | { | ||
24 | /** | ||
25 | * Whether elements may be added to the collection | ||
26 | * @var Boolean | ||
27 | */ | ||
28 | private $allowAdd; | ||
29 | |||
30 | /** | ||
31 | * Whether elements may be removed from the collection | ||
32 | * @var Boolean | ||
33 | */ | ||
34 | private $allowDelete; | ||
35 | |||
36 | /** | ||
37 | * Creates a new listener. | ||
38 | * | ||
39 | * @param Boolean $allowAdd Whether values might be added to the | ||
40 | * collection. | ||
41 | * @param Boolean $allowDelete Whether values might be removed from the | ||
42 | * collection. | ||
43 | */ | ||
44 | public function __construct($allowAdd = false, $allowDelete = false) | ||
45 | { | ||
46 | $this->allowAdd = $allowAdd; | ||
47 | $this->allowDelete = $allowDelete; | ||
48 | } | ||
49 | |||
50 | public static function getSubscribedEvents() | ||
51 | { | ||
52 | return array( | ||
53 | FormEvents::SUBMIT => 'onSubmit', | ||
54 | ); | ||
55 | } | ||
56 | |||
57 | public function onSubmit(FormEvent $event) | ||
58 | { | ||
59 | $dataToMergeInto = $event->getForm()->getNormData(); | ||
60 | $data = $event->getData(); | ||
61 | |||
62 | if (null === $data) { | ||
63 | $data = array(); | ||
64 | } | ||
65 | |||
66 | if (!is_array($data) && !($data instanceof \Traversable && $data instanceof \ArrayAccess)) { | ||
67 | throw new UnexpectedTypeException($data, 'array or (\Traversable and \ArrayAccess)'); | ||
68 | } | ||
69 | |||
70 | if (null !== $dataToMergeInto && !is_array($dataToMergeInto) && !($dataToMergeInto instanceof \Traversable && $dataToMergeInto instanceof \ArrayAccess)) { | ||
71 | throw new UnexpectedTypeException($dataToMergeInto, 'array or (\Traversable and \ArrayAccess)'); | ||
72 | } | ||
73 | |||
74 | // If we are not allowed to change anything, return immediately | ||
75 | if ((!$this->allowAdd && !$this->allowDelete) || $data === $dataToMergeInto) { | ||
76 | $event->setData($dataToMergeInto); | ||
77 | |||
78 | return; | ||
79 | } | ||
80 | |||
81 | if (!$dataToMergeInto) { | ||
82 | // No original data was set. Set it if allowed | ||
83 | if ($this->allowAdd) { | ||
84 | $dataToMergeInto = $data; | ||
85 | } | ||
86 | } else { | ||
87 | // Calculate delta | ||
88 | $itemsToAdd = is_object($data) ? clone $data : $data; | ||
89 | $itemsToDelete = array(); | ||
90 | |||
91 | foreach ($dataToMergeInto as $beforeKey => $beforeItem) { | ||
92 | foreach ($data as $afterKey => $afterItem) { | ||
93 | if ($afterItem === $beforeItem) { | ||
94 | // Item found, next original item | ||
95 | unset($itemsToAdd[$afterKey]); | ||
96 | continue 2; | ||
97 | } | ||
98 | } | ||
99 | |||
100 | // Item not found, remember for deletion | ||
101 | $itemsToDelete[] = $beforeKey; | ||
102 | } | ||
103 | |||
104 | // Remove deleted items before adding to free keys that are to be | ||
105 | // replaced | ||
106 | if ($this->allowDelete) { | ||
107 | foreach ($itemsToDelete as $key) { | ||
108 | unset($dataToMergeInto[$key]); | ||
109 | } | ||
110 | } | ||
111 | |||
112 | // Add remaining items | ||
113 | if ($this->allowAdd) { | ||
114 | foreach ($itemsToAdd as $key => $item) { | ||
115 | if (!isset($dataToMergeInto[$key])) { | ||
116 | $dataToMergeInto[$key] = $item; | ||
117 | } else { | ||
118 | $dataToMergeInto[] = $item; | ||
119 | } | ||
120 | } | ||
121 | } | ||
122 | } | ||
123 | |||
124 | $event->setData($dataToMergeInto); | ||
125 | } | ||
126 | |||
127 | /** | ||
128 | * Alias of {@link onSubmit()}. | ||
129 | * | ||
130 | * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use | ||
131 | * {@link onSubmit()} instead. | ||
132 | */ | ||
133 | public function onBind(FormEvent $event) | ||
134 | { | ||
135 | $this->onSubmit($event); | ||
136 | } | ||
137 | } | ||