]> git.immae.eu Git - github/wallabag/wallabag.git/blob - vendor/symfony/form/Symfony/Component/Form/Tests/Extension/Validator/ViolationMapper/ViolationMapperTest.php
twig implementation
[github/wallabag/wallabag.git] / vendor / symfony / form / Symfony / Component / Form / Tests / Extension / Validator / ViolationMapper / ViolationMapperTest.php
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\Tests\Extension\Validator\ViolationMapper;
13
14 use Symfony\Component\Form\Extension\Validator\ViolationMapper\ViolationMapper;
15 use Symfony\Component\Form\Exception\TransformationFailedException;
16 use Symfony\Component\Form\CallbackTransformer;
17 use Symfony\Component\Form\Form;
18 use Symfony\Component\Form\FormConfigBuilder;
19 use Symfony\Component\Form\FormError;
20 use Symfony\Component\PropertyAccess\PropertyPath;
21 use Symfony\Component\Validator\ConstraintViolation;
22
23 /**
24 * @author Bernhard Schussek <bschussek@gmail.com>
25 */
26 class ViolationMapperTest extends \PHPUnit_Framework_TestCase
27 {
28 const LEVEL_0 = 0;
29
30 const LEVEL_1 = 1;
31
32 const LEVEL_1B = 2;
33
34 const LEVEL_2 = 3;
35
36 /**
37 * @var \PHPUnit_Framework_MockObject_MockObject
38 */
39 private $dispatcher;
40
41 /**
42 * @var ViolationMapper
43 */
44 private $mapper;
45
46 /**
47 * @var string
48 */
49 private $message;
50
51 /**
52 * @var string
53 */
54 private $messageTemplate;
55
56 /**
57 * @var array
58 */
59 private $params;
60
61 protected function setUp()
62 {
63 if (!class_exists('Symfony\Component\EventDispatcher\Event')) {
64 $this->markTestSkipped('The "EventDispatcher" component is not available');
65 }
66
67 $this->dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface');
68 $this->mapper = new ViolationMapper();
69 $this->message = 'Message';
70 $this->messageTemplate = 'Message template';
71 $this->params = array('foo' => 'bar');
72 }
73
74 protected function getForm($name = 'name', $propertyPath = null, $dataClass = null, $errorMapping = array(), $inheritData = false, $synchronized = true)
75 {
76 $config = new FormConfigBuilder($name, $dataClass, $this->dispatcher, array(
77 'error_mapping' => $errorMapping,
78 ));
79 $config->setMapped(true);
80 $config->setInheritData($inheritData);
81 $config->setPropertyPath($propertyPath);
82 $config->setCompound(true);
83 $config->setDataMapper($this->getDataMapper());
84
85 if (!$synchronized) {
86 $config->addViewTransformer(new CallbackTransformer(
87 function ($normData) { return $normData; },
88 function () { throw new TransformationFailedException(); }
89 ));
90 }
91
92 return new Form($config);
93 }
94
95 /**
96 * @return \PHPUnit_Framework_MockObject_MockObject
97 */
98 private function getDataMapper()
99 {
100 return $this->getMock('Symfony\Component\Form\DataMapperInterface');
101 }
102
103 /**
104 * @param $propertyPath
105 *
106 * @return ConstraintViolation
107 */
108 protected function getConstraintViolation($propertyPath)
109 {
110 return new ConstraintViolation($this->message, $this->messageTemplate, $this->params, null, $propertyPath, null);
111 }
112
113 /**
114 * @return FormError
115 */
116 protected function getFormError()
117 {
118 return new FormError($this->message, $this->messageTemplate, $this->params);
119 }
120
121 public function testMapToFormInheritingParentDataIfDataDoesNotMatch()
122 {
123 $violation = $this->getConstraintViolation('children[address].data.foo');
124 $parent = $this->getForm('parent');
125 $child = $this->getForm('address', 'address', null, array(), true);
126 $grandChild = $this->getForm('street');
127
128 $parent->add($child);
129 $child->add($grandChild);
130
131 $this->mapper->mapViolation($violation, $parent);
132
133 $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one');
134 $this->assertEquals(array($this->getFormError()), $child->getErrors(), $child->getName().' should have an error, but has none');
135 $this->assertCount(0, $grandChild->getErrors(), $grandChild->getName().' should not have an error, but has one');
136 }
137
138 public function testFollowDotRules()
139 {
140 $violation = $this->getConstraintViolation('data.foo');
141 $parent = $this->getForm('parent', null, null, array(
142 'foo' => 'address',
143 ));
144 $child = $this->getForm('address', null, null, array(
145 '.' => 'street',
146 ));
147 $grandChild = $this->getForm('street', null, null, array(
148 '.' => 'name',
149 ));
150 $grandGrandChild = $this->getForm('name');
151
152 $parent->add($child);
153 $child->add($grandChild);
154 $grandChild->add($grandGrandChild);
155
156 $this->mapper->mapViolation($violation, $parent);
157
158 $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one');
159 $this->assertCount(0, $child->getErrors(), $child->getName().' should not have an error, but has one');
160 $this->assertCount(0, $grandChild->getErrors(), $grandChild->getName().' should not have an error, but has one');
161 $this->assertEquals(array($this->getFormError()), $grandGrandChild->getErrors(), $grandGrandChild->getName().' should have an error, but has none');
162 }
163
164 public function testAbortMappingIfNotSynchronized()
165 {
166 $violation = $this->getConstraintViolation('children[address].data.street');
167 $parent = $this->getForm('parent');
168 $child = $this->getForm('address', 'address', null, array(), false, false);
169 // even though "street" is synchronized, it should not have any errors
170 // due to its parent not being synchronized
171 $grandChild = $this->getForm('street' , 'street');
172
173 $parent->add($child);
174 $child->add($grandChild);
175
176 // submit to invoke the transformer and mark the form unsynchronized
177 $parent->submit(array());
178
179 $this->mapper->mapViolation($violation, $parent);
180
181 $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one');
182 $this->assertCount(0, $child->getErrors(), $child->getName().' should not have an error, but has one');
183 $this->assertCount(0, $grandChild->getErrors(), $grandChild->getName().' should not have an error, but has one');
184 }
185
186 public function testAbortDotRuleMappingIfNotSynchronized()
187 {
188 $violation = $this->getConstraintViolation('data.address');
189 $parent = $this->getForm('parent');
190 $child = $this->getForm('address', 'address', null, array(
191 '.' => 'street',
192 ), false, false);
193 // even though "street" is synchronized, it should not have any errors
194 // due to its parent not being synchronized
195 $grandChild = $this->getForm('street');
196
197 $parent->add($child);
198 $child->add($grandChild);
199
200 // submit to invoke the transformer and mark the form unsynchronized
201 $parent->submit(array());
202
203 $this->mapper->mapViolation($violation, $parent);
204
205 $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one');
206 $this->assertCount(0, $child->getErrors(), $child->getName().' should not have an error, but has one');
207 $this->assertCount(0, $grandChild->getErrors(), $grandChild->getName().' should not have an error, but has one');
208 }
209
210 public function provideDefaultTests()
211 {
212 // The mapping must be deterministic! If a child has the property path "[street]",
213 // "data[street]" should be mapped, but "data.street" should not!
214 return array(
215 // mapping target, child name, its property path, grand child name, its property path, violation path
216 array(self::LEVEL_0, 'address', 'address', 'street', 'street', ''),
217 array(self::LEVEL_0, 'address', 'address', 'street', 'street', 'data'),
218
219 array(self::LEVEL_2, 'address', 'address', 'street', 'street', 'children[address].children[street].data'),
220 array(self::LEVEL_2, 'address', 'address', 'street', 'street', 'children[address].children[street].data.prop'),
221 array(self::LEVEL_1, 'address', 'address', 'street', 'street', 'children[address].data'),
222 array(self::LEVEL_2, 'address', 'address', 'street', 'street', 'children[address].data.street'),
223 array(self::LEVEL_2, 'address', 'address', 'street', 'street', 'children[address].data.street.prop'),
224 array(self::LEVEL_1, 'address', 'address', 'street', 'street', 'children[address].data[street]'),
225 array(self::LEVEL_1, 'address', 'address', 'street', 'street', 'children[address].data[street].prop'),
226 array(self::LEVEL_2, 'address', 'address', 'street', 'street', 'data.address.street'),
227 array(self::LEVEL_2, 'address', 'address', 'street', 'street', 'data.address.street.prop'),
228 array(self::LEVEL_1, 'address', 'address', 'street', 'street', 'data.address[street]'),
229 array(self::LEVEL_1, 'address', 'address', 'street', 'street', 'data.address[street].prop'),
230 array(self::LEVEL_0, 'address', 'address', 'street', 'street', 'data[address].street'),
231 array(self::LEVEL_0, 'address', 'address', 'street', 'street', 'data[address].street.prop'),
232 array(self::LEVEL_0, 'address', 'address', 'street', 'street', 'data[address][street]'),
233 array(self::LEVEL_0, 'address', 'address', 'street', 'street', 'data[address][street].prop'),
234
235 array(self::LEVEL_2, 'address', 'address', 'street', '[street]', 'children[address].children[street].data'),
236 array(self::LEVEL_2, 'address', 'address', 'street', '[street]', 'children[address].children[street].data.prop'),
237 array(self::LEVEL_1, 'address', 'address', 'street', '[street]', 'children[address].data'),
238 array(self::LEVEL_1, 'address', 'address', 'street', '[street]', 'children[address].data.street'),
239 array(self::LEVEL_1, 'address', 'address', 'street', '[street]', 'children[address].data.street.prop'),
240 array(self::LEVEL_2, 'address', 'address', 'street', '[street]', 'children[address].data[street]'),
241 array(self::LEVEL_2, 'address', 'address', 'street', '[street]', 'children[address].data[street].prop'),
242 array(self::LEVEL_1, 'address', 'address', 'street', '[street]', 'data.address.street'),
243 array(self::LEVEL_1, 'address', 'address', 'street', '[street]', 'data.address.street.prop'),
244 array(self::LEVEL_2, 'address', 'address', 'street', '[street]', 'data.address[street]'),
245 array(self::LEVEL_2, 'address', 'address', 'street', '[street]', 'data.address[street].prop'),
246 array(self::LEVEL_0, 'address', 'address', 'street', '[street]', 'data[address].street'),
247 array(self::LEVEL_0, 'address', 'address', 'street', '[street]', 'data[address].street.prop'),
248 array(self::LEVEL_0, 'address', 'address', 'street', '[street]', 'data[address][street]'),
249 array(self::LEVEL_0, 'address', 'address', 'street', '[street]', 'data[address][street].prop'),
250
251 array(self::LEVEL_2, 'address', '[address]', 'street', 'street', 'children[address].children[street].data'),
252 array(self::LEVEL_2, 'address', '[address]', 'street', 'street', 'children[address].children[street].data.prop'),
253 array(self::LEVEL_1, 'address', '[address]', 'street', 'street', 'children[address].data'),
254 array(self::LEVEL_2, 'address', '[address]', 'street', 'street', 'children[address].data.street'),
255 array(self::LEVEL_2, 'address', '[address]', 'street', 'street', 'children[address].data.street.prop'),
256 array(self::LEVEL_1, 'address', '[address]', 'street', 'street', 'children[address].data[street]'),
257 array(self::LEVEL_1, 'address', '[address]', 'street', 'street', 'children[address].data[street].prop'),
258 array(self::LEVEL_0, 'address', '[address]', 'street', 'street', 'data.address.street'),
259 array(self::LEVEL_0, 'address', '[address]', 'street', 'street', 'data.address.street.prop'),
260 array(self::LEVEL_0, 'address', '[address]', 'street', 'street', 'data.address[street]'),
261 array(self::LEVEL_0, 'address', '[address]', 'street', 'street', 'data.address[street].prop'),
262 array(self::LEVEL_2, 'address', '[address]', 'street', 'street', 'data[address].street'),
263 array(self::LEVEL_2, 'address', '[address]', 'street', 'street', 'data[address].street.prop'),
264 array(self::LEVEL_1, 'address', '[address]', 'street', 'street', 'data[address][street]'),
265 array(self::LEVEL_1, 'address', '[address]', 'street', 'street', 'data[address][street].prop'),
266
267 array(self::LEVEL_2, 'address', '[address]', 'street', '[street]', 'children[address].children[street].data'),
268 array(self::LEVEL_2, 'address', '[address]', 'street', '[street]', 'children[address].children[street].data.prop'),
269 array(self::LEVEL_1, 'address', '[address]', 'street', '[street]', 'children[address].data'),
270 array(self::LEVEL_1, 'address', '[address]', 'street', '[street]', 'children[address].data.street'),
271 array(self::LEVEL_1, 'address', '[address]', 'street', '[street]', 'children[address].data.street.prop'),
272 array(self::LEVEL_2, 'address', '[address]', 'street', '[street]', 'children[address].data[street]'),
273 array(self::LEVEL_2, 'address', '[address]', 'street', '[street]', 'children[address].data[street].prop'),
274 array(self::LEVEL_0, 'address', '[address]', 'street', '[street]', 'data.address.street'),
275 array(self::LEVEL_0, 'address', '[address]', 'street', '[street]', 'data.address.street.prop'),
276 array(self::LEVEL_0, 'address', '[address]', 'street', '[street]', 'data.address[street]'),
277 array(self::LEVEL_0, 'address', '[address]', 'street', '[street]', 'data.address[street].prop'),
278 array(self::LEVEL_1, 'address', '[address]', 'street', '[street]', 'data[address].street'),
279 array(self::LEVEL_1, 'address', '[address]', 'street', '[street]', 'data[address].street.prop'),
280 array(self::LEVEL_2, 'address', '[address]', 'street', '[street]', 'data[address][street]'),
281 array(self::LEVEL_2, 'address', '[address]', 'street', '[street]', 'data[address][street].prop'),
282
283 array(self::LEVEL_2, 'address', 'person.address', 'street', 'street', 'children[address].children[street].data'),
284 array(self::LEVEL_2, 'address', 'person.address', 'street', 'street', 'children[address].children[street].data.prop'),
285 array(self::LEVEL_1, 'address', 'person.address', 'street', 'street', 'children[address].data'),
286 array(self::LEVEL_2, 'address', 'person.address', 'street', 'street', 'children[address].data.street'),
287 array(self::LEVEL_2, 'address', 'person.address', 'street', 'street', 'children[address].data.street.prop'),
288 array(self::LEVEL_1, 'address', 'person.address', 'street', 'street', 'children[address].data[street]'),
289 array(self::LEVEL_1, 'address', 'person.address', 'street', 'street', 'children[address].data[street].prop'),
290 array(self::LEVEL_2, 'address', 'person.address', 'street', 'street', 'data.person.address.street'),
291 array(self::LEVEL_2, 'address', 'person.address', 'street', 'street', 'data.person.address.street.prop'),
292 array(self::LEVEL_1, 'address', 'person.address', 'street', 'street', 'data.person.address[street]'),
293 array(self::LEVEL_1, 'address', 'person.address', 'street', 'street', 'data.person.address[street].prop'),
294 array(self::LEVEL_0, 'address', 'person.address', 'street', 'street', 'data.person[address].street'),
295 array(self::LEVEL_0, 'address', 'person.address', 'street', 'street', 'data.person[address].street.prop'),
296 array(self::LEVEL_0, 'address', 'person.address', 'street', 'street', 'data.person[address][street]'),
297 array(self::LEVEL_0, 'address', 'person.address', 'street', 'street', 'data.person[address][street].prop'),
298 array(self::LEVEL_0, 'address', 'person.address', 'street', 'street', 'data[person].address.street'),
299 array(self::LEVEL_0, 'address', 'person.address', 'street', 'street', 'data[person].address.street.prop'),
300 array(self::LEVEL_0, 'address', 'person.address', 'street', 'street', 'data[person].address[street]'),
301 array(self::LEVEL_0, 'address', 'person.address', 'street', 'street', 'data[person].address[street].prop'),
302 array(self::LEVEL_0, 'address', 'person.address', 'street', 'street', 'data[person][address].street'),
303 array(self::LEVEL_0, 'address', 'person.address', 'street', 'street', 'data[person][address].street.prop'),
304 array(self::LEVEL_0, 'address', 'person.address', 'street', 'street', 'data[person][address][street]'),
305 array(self::LEVEL_0, 'address', 'person.address', 'street', 'street', 'data[person][address][street].prop'),
306
307 array(self::LEVEL_2, 'address', 'person.address', 'street', '[street]', 'children[address].children[street].data'),
308 array(self::LEVEL_2, 'address', 'person.address', 'street', '[street]', 'children[address].children[street].data.prop'),
309 array(self::LEVEL_1, 'address', 'person.address', 'street', '[street]', 'children[address].data'),
310 array(self::LEVEL_1, 'address', 'person.address', 'street', '[street]', 'children[address].data.street'),
311 array(self::LEVEL_1, 'address', 'person.address', 'street', '[street]', 'children[address].data.street.prop'),
312 array(self::LEVEL_2, 'address', 'person.address', 'street', '[street]', 'children[address].data[street]'),
313 array(self::LEVEL_2, 'address', 'person.address', 'street', '[street]', 'children[address].data[street].prop'),
314 array(self::LEVEL_1, 'address', 'person.address', 'street', '[street]', 'data.person.address.street'),
315 array(self::LEVEL_1, 'address', 'person.address', 'street', '[street]', 'data.person.address.street.prop'),
316 array(self::LEVEL_2, 'address', 'person.address', 'street', '[street]', 'data.person.address[street]'),
317 array(self::LEVEL_2, 'address', 'person.address', 'street', '[street]', 'data.person.address[street].prop'),
318 array(self::LEVEL_0, 'address', 'person.address', 'street', '[street]', 'data.person[address].street'),
319 array(self::LEVEL_0, 'address', 'person.address', 'street', '[street]', 'data.person[address].street.prop'),
320 array(self::LEVEL_0, 'address', 'person.address', 'street', '[street]', 'data.person[address][street]'),
321 array(self::LEVEL_0, 'address', 'person.address', 'street', '[street]', 'data.person[address][street].prop'),
322 array(self::LEVEL_0, 'address', 'person.address', 'street', '[street]', 'data[person].address.street'),
323 array(self::LEVEL_0, 'address', 'person.address', 'street', '[street]', 'data[person].address.street.prop'),
324 array(self::LEVEL_0, 'address', 'person.address', 'street', '[street]', 'data[person].address[street]'),
325 array(self::LEVEL_0, 'address', 'person.address', 'street', '[street]', 'data[person].address[street].prop'),
326 array(self::LEVEL_0, 'address', 'person.address', 'street', '[street]', 'data[person][address].street'),
327 array(self::LEVEL_0, 'address', 'person.address', 'street', '[street]', 'data[person][address].street.prop'),
328 array(self::LEVEL_0, 'address', 'person.address', 'street', '[street]', 'data[person][address][street]'),
329 array(self::LEVEL_0, 'address', 'person.address', 'street', '[street]', 'data[person][address][street].prop'),
330
331 array(self::LEVEL_2, 'address', 'person[address]', 'street', 'street', 'children[address].children[street].data'),
332 array(self::LEVEL_2, 'address', 'person[address]', 'street', 'street', 'children[address].children[street].data.prop'),
333 array(self::LEVEL_1, 'address', 'person[address]', 'street', 'street', 'children[address].data'),
334 array(self::LEVEL_2, 'address', 'person[address]', 'street', 'street', 'children[address].data.street'),
335 array(self::LEVEL_2, 'address', 'person[address]', 'street', 'street', 'children[address].data.street.prop'),
336 array(self::LEVEL_1, 'address', 'person[address]', 'street', 'street', 'children[address].data[street]'),
337 array(self::LEVEL_1, 'address', 'person[address]', 'street', 'street', 'children[address].data[street].prop'),
338 array(self::LEVEL_0, 'address', 'person[address]', 'street', 'street', 'data.person.address.street'),
339 array(self::LEVEL_0, 'address', 'person[address]', 'street', 'street', 'data.person.address.street.prop'),
340 array(self::LEVEL_0, 'address', 'person[address]', 'street', 'street', 'data.person.address[street]'),
341 array(self::LEVEL_0, 'address', 'person[address]', 'street', 'street', 'data.person.address[street].prop'),
342 array(self::LEVEL_2, 'address', 'person[address]', 'street', 'street', 'data.person[address].street'),
343 array(self::LEVEL_2, 'address', 'person[address]', 'street', 'street', 'data.person[address].street.prop'),
344 array(self::LEVEL_1, 'address', 'person[address]', 'street', 'street', 'data.person[address][street]'),
345 array(self::LEVEL_1, 'address', 'person[address]', 'street', 'street', 'data.person[address][street].prop'),
346 array(self::LEVEL_0, 'address', 'person[address]', 'street', 'street', 'data[person].address.street'),
347 array(self::LEVEL_0, 'address', 'person[address]', 'street', 'street', 'data[person].address.street.prop'),
348 array(self::LEVEL_0, 'address', 'person[address]', 'street', 'street', 'data[person].address[street]'),
349 array(self::LEVEL_0, 'address', 'person[address]', 'street', 'street', 'data[person].address[street].prop'),
350 array(self::LEVEL_0, 'address', 'person[address]', 'street', 'street', 'data[person][address].street'),
351 array(self::LEVEL_0, 'address', 'person[address]', 'street', 'street', 'data[person][address].street.prop'),
352 array(self::LEVEL_0, 'address', 'person[address]', 'street', 'street', 'data[person][address][street]'),
353 array(self::LEVEL_0, 'address', 'person[address]', 'street', 'street', 'data[person][address][street].prop'),
354
355 array(self::LEVEL_2, 'address', 'person[address]', 'street', '[street]', 'children[address].children[street].data'),
356 array(self::LEVEL_2, 'address', 'person[address]', 'street', '[street]', 'children[address].children[street].data.prop'),
357 array(self::LEVEL_1, 'address', 'person[address]', 'street', '[street]', 'children[address].data'),
358 array(self::LEVEL_1, 'address', 'person[address]', 'street', '[street]', 'children[address].data.street'),
359 array(self::LEVEL_1, 'address', 'person[address]', 'street', '[street]', 'children[address].data.street.prop'),
360 array(self::LEVEL_2, 'address', 'person[address]', 'street', '[street]', 'children[address].data[street]'),
361 array(self::LEVEL_2, 'address', 'person[address]', 'street', '[street]', 'children[address].data[street].prop'),
362 array(self::LEVEL_0, 'address', 'person[address]', 'street', '[street]', 'data.person.address.street'),
363 array(self::LEVEL_0, 'address', 'person[address]', 'street', '[street]', 'data.person.address.street.prop'),
364 array(self::LEVEL_0, 'address', 'person[address]', 'street', '[street]', 'data.person.address[street]'),
365 array(self::LEVEL_0, 'address', 'person[address]', 'street', '[street]', 'data.person.address[street].prop'),
366 array(self::LEVEL_1, 'address', 'person[address]', 'street', '[street]', 'data.person[address].street'),
367 array(self::LEVEL_1, 'address', 'person[address]', 'street', '[street]', 'data.person[address].street.prop'),
368 array(self::LEVEL_2, 'address', 'person[address]', 'street', '[street]', 'data.person[address][street]'),
369 array(self::LEVEL_2, 'address', 'person[address]', 'street', '[street]', 'data.person[address][street].prop'),
370 array(self::LEVEL_0, 'address', 'person[address]', 'street', '[street]', 'data[person].address.street'),
371 array(self::LEVEL_0, 'address', 'person[address]', 'street', '[street]', 'data[person].address.street.prop'),
372 array(self::LEVEL_0, 'address', 'person[address]', 'street', '[street]', 'data[person].address[street]'),
373 array(self::LEVEL_0, 'address', 'person[address]', 'street', '[street]', 'data[person].address[street].prop'),
374 array(self::LEVEL_0, 'address', 'person[address]', 'street', '[street]', 'data[person][address].street'),
375 array(self::LEVEL_0, 'address', 'person[address]', 'street', '[street]', 'data[person][address].street.prop'),
376 array(self::LEVEL_0, 'address', 'person[address]', 'street', '[street]', 'data[person][address][street]'),
377 array(self::LEVEL_0, 'address', 'person[address]', 'street', '[street]', 'data[person][address][street].prop'),
378
379 array(self::LEVEL_2, 'address', '[person].address', 'street', 'street', 'children[address].children[street].data'),
380 array(self::LEVEL_2, 'address', '[person].address', 'street', 'street', 'children[address].children[street].data.prop'),
381 array(self::LEVEL_1, 'address', '[person].address', 'street', 'street', 'children[address].data'),
382 array(self::LEVEL_2, 'address', '[person].address', 'street', 'street', 'children[address].data.street'),
383 array(self::LEVEL_2, 'address', '[person].address', 'street', 'street', 'children[address].data.street.prop'),
384 array(self::LEVEL_1, 'address', '[person].address', 'street', 'street', 'children[address].data[street]'),
385 array(self::LEVEL_1, 'address', '[person].address', 'street', 'street', 'children[address].data[street].prop'),
386 array(self::LEVEL_0, 'address', '[person].address', 'street', 'street', 'data.person.address.street'),
387 array(self::LEVEL_0, 'address', '[person].address', 'street', 'street', 'data.person.address.street.prop'),
388 array(self::LEVEL_0, 'address', '[person].address', 'street', 'street', 'data.person.address[street]'),
389 array(self::LEVEL_0, 'address', '[person].address', 'street', 'street', 'data.person.address[street].prop'),
390 array(self::LEVEL_0, 'address', '[person].address', 'street', 'street', 'data.person[address].street'),
391 array(self::LEVEL_0, 'address', '[person].address', 'street', 'street', 'data.person[address].street.prop'),
392 array(self::LEVEL_0, 'address', '[person].address', 'street', 'street', 'data.person[address][street]'),
393 array(self::LEVEL_0, 'address', '[person].address', 'street', 'street', 'data.person[address][street].prop'),
394 array(self::LEVEL_2, 'address', '[person].address', 'street', 'street', 'data[person].address.street'),
395 array(self::LEVEL_2, 'address', '[person].address', 'street', 'street', 'data[person].address.street.prop'),
396 array(self::LEVEL_1, 'address', '[person].address', 'street', 'street', 'data[person].address[street]'),
397 array(self::LEVEL_1, 'address', '[person].address', 'street', 'street', 'data[person].address[street].prop'),
398 array(self::LEVEL_0, 'address', '[person].address', 'street', 'street', 'data[person][address].street'),
399 array(self::LEVEL_0, 'address', '[person].address', 'street', 'street', 'data[person][address].street.prop'),
400 array(self::LEVEL_0, 'address', '[person].address', 'street', 'street', 'data[person][address][street]'),
401 array(self::LEVEL_0, 'address', '[person].address', 'street', 'street', 'data[person][address][street].prop'),
402
403 array(self::LEVEL_2, 'address', '[person].address', 'street', '[street]', 'children[address].children[street].data'),
404 array(self::LEVEL_2, 'address', '[person].address', 'street', '[street]', 'children[address].children[street].data.prop'),
405 array(self::LEVEL_1, 'address', '[person].address', 'street', '[street]', 'children[address].data'),
406 array(self::LEVEL_1, 'address', '[person].address', 'street', '[street]', 'children[address].data.street'),
407 array(self::LEVEL_1, 'address', '[person].address', 'street', '[street]', 'children[address].data.street.prop'),
408 array(self::LEVEL_2, 'address', '[person].address', 'street', '[street]', 'children[address].data[street]'),
409 array(self::LEVEL_2, 'address', '[person].address', 'street', '[street]', 'children[address].data[street].prop'),
410 array(self::LEVEL_0, 'address', '[person].address', 'street', '[street]', 'data.person.address.street'),
411 array(self::LEVEL_0, 'address', '[person].address', 'street', '[street]', 'data.person.address.street.prop'),
412 array(self::LEVEL_0, 'address', '[person].address', 'street', '[street]', 'data.person.address[street]'),
413 array(self::LEVEL_0, 'address', '[person].address', 'street', '[street]', 'data.person.address[street].prop'),
414 array(self::LEVEL_0, 'address', '[person].address', 'street', '[street]', 'data.person[address].street'),
415 array(self::LEVEL_0, 'address', '[person].address', 'street', '[street]', 'data.person[address].street.prop'),
416 array(self::LEVEL_0, 'address', '[person].address', 'street', '[street]', 'data.person[address][street]'),
417 array(self::LEVEL_0, 'address', '[person].address', 'street', '[street]', 'data.person[address][street].prop'),
418 array(self::LEVEL_1, 'address', '[person].address', 'street', '[street]', 'data[person].address.street'),
419 array(self::LEVEL_1, 'address', '[person].address', 'street', '[street]', 'data[person].address.street.prop'),
420 array(self::LEVEL_2, 'address', '[person].address', 'street', '[street]', 'data[person].address[street]'),
421 array(self::LEVEL_2, 'address', '[person].address', 'street', '[street]', 'data[person].address[street].prop'),
422 array(self::LEVEL_0, 'address', '[person].address', 'street', '[street]', 'data[person][address].street'),
423 array(self::LEVEL_0, 'address', '[person].address', 'street', '[street]', 'data[person][address].street.prop'),
424 array(self::LEVEL_0, 'address', '[person].address', 'street', '[street]', 'data[person][address][street]'),
425 array(self::LEVEL_0, 'address', '[person].address', 'street', '[street]', 'data[person][address][street].prop'),
426
427 array(self::LEVEL_2, 'address', '[person][address]', 'street', 'street', 'children[address].children[street].data'),
428 array(self::LEVEL_2, 'address', '[person][address]', 'street', 'street', 'children[address].children[street].data.prop'),
429 array(self::LEVEL_1, 'address', '[person][address]', 'street', 'street', 'children[address]'),
430 array(self::LEVEL_1, 'address', '[person][address]', 'street', 'street', 'children[address].data'),
431 array(self::LEVEL_2, 'address', '[person][address]', 'street', 'street', 'children[address].data.street'),
432 array(self::LEVEL_2, 'address', '[person][address]', 'street', 'street', 'children[address].data.street.prop'),
433 array(self::LEVEL_1, 'address', '[person][address]', 'street', 'street', 'children[address].data[street]'),
434 array(self::LEVEL_1, 'address', '[person][address]', 'street', 'street', 'children[address].data[street].prop'),
435 array(self::LEVEL_0, 'address', '[person][address]', 'street', 'street', 'data.person.address.street'),
436 array(self::LEVEL_0, 'address', '[person][address]', 'street', 'street', 'data.person.address.street.prop'),
437 array(self::LEVEL_0, 'address', '[person][address]', 'street', 'street', 'data.person.address[street]'),
438 array(self::LEVEL_0, 'address', '[person][address]', 'street', 'street', 'data.person.address[street].prop'),
439 array(self::LEVEL_0, 'address', '[person][address]', 'street', 'street', 'data.person[address].street'),
440 array(self::LEVEL_0, 'address', '[person][address]', 'street', 'street', 'data.person[address].street.prop'),
441 array(self::LEVEL_0, 'address', '[person][address]', 'street', 'street', 'data.person[address][street]'),
442 array(self::LEVEL_0, 'address', '[person][address]', 'street', 'street', 'data.person[address][street].prop'),
443 array(self::LEVEL_0, 'address', '[person][address]', 'street', 'street', 'data[person].address.street'),
444 array(self::LEVEL_0, 'address', '[person][address]', 'street', 'street', 'data[person].address.street.prop'),
445 array(self::LEVEL_0, 'address', '[person][address]', 'street', 'street', 'data[person].address[street]'),
446 array(self::LEVEL_0, 'address', '[person][address]', 'street', 'street', 'data[person].address[street].prop'),
447 array(self::LEVEL_2, 'address', '[person][address]', 'street', 'street', 'data[person][address].street'),
448 array(self::LEVEL_2, 'address', '[person][address]', 'street', 'street', 'data[person][address].street.prop'),
449 array(self::LEVEL_1, 'address', '[person][address]', 'street', 'street', 'data[person][address][street]'),
450 array(self::LEVEL_1, 'address', '[person][address]', 'street', 'street', 'data[person][address][street].prop'),
451
452 array(self::LEVEL_2, 'address', '[person][address]', 'street', '[street]', 'children[address].children[street].data'),
453 array(self::LEVEL_2, 'address', '[person][address]', 'street', '[street]', 'children[address].children[street].data.prop'),
454 array(self::LEVEL_1, 'address', '[person][address]', 'street', '[street]', 'children[address].data'),
455 array(self::LEVEL_1, 'address', '[person][address]', 'street', '[street]', 'children[address].data.street'),
456 array(self::LEVEL_1, 'address', '[person][address]', 'street', '[street]', 'children[address].data.street.prop'),
457 array(self::LEVEL_2, 'address', '[person][address]', 'street', '[street]', 'children[address].data[street]'),
458 array(self::LEVEL_2, 'address', '[person][address]', 'street', '[street]', 'children[address].data[street].prop'),
459 array(self::LEVEL_0, 'address', '[person][address]', 'street', '[street]', 'data.person.address.street'),
460 array(self::LEVEL_0, 'address', '[person][address]', 'street', '[street]', 'data.person.address.street.prop'),
461 array(self::LEVEL_0, 'address', '[person][address]', 'street', '[street]', 'data.person.address[street]'),
462 array(self::LEVEL_0, 'address', '[person][address]', 'street', '[street]', 'data.person.address[street].prop'),
463 array(self::LEVEL_0, 'address', '[person][address]', 'street', '[street]', 'data.person[address].street'),
464 array(self::LEVEL_0, 'address', '[person][address]', 'street', '[street]', 'data.person[address].street.prop'),
465 array(self::LEVEL_0, 'address', '[person][address]', 'street', '[street]', 'data.person[address][street]'),
466 array(self::LEVEL_0, 'address', '[person][address]', 'street', '[street]', 'data.person[address][street].prop'),
467 array(self::LEVEL_0, 'address', '[person][address]', 'street', '[street]', 'data[person].address.street'),
468 array(self::LEVEL_0, 'address', '[person][address]', 'street', '[street]', 'data[person].address.street.prop'),
469 array(self::LEVEL_0, 'address', '[person][address]', 'street', '[street]', 'data[person].address[street]'),
470 array(self::LEVEL_0, 'address', '[person][address]', 'street', '[street]', 'data[person].address[street].prop'),
471 array(self::LEVEL_1, 'address', '[person][address]', 'street', '[street]', 'data[person][address].street'),
472 array(self::LEVEL_1, 'address', '[person][address]', 'street', '[street]', 'data[person][address].street.prop'),
473 array(self::LEVEL_2, 'address', '[person][address]', 'street', '[street]', 'data[person][address][street]'),
474 array(self::LEVEL_2, 'address', '[person][address]', 'street', '[street]', 'data[person][address][street].prop'),
475
476 array(self::LEVEL_2, 'address', 'address', 'street', 'office.street', 'children[address].children[street].data'),
477 array(self::LEVEL_2, 'address', 'address', 'street', 'office.street', 'children[address].children[street].data.prop'),
478 array(self::LEVEL_1, 'address', 'address', 'street', 'office.street', 'children[address].data'),
479 array(self::LEVEL_1, 'address', 'address', 'street', 'office.street', 'children[address].data.office'),
480 array(self::LEVEL_2, 'address', 'address', 'street', 'office.street', 'children[address].data.office.street'),
481 array(self::LEVEL_2, 'address', 'address', 'street', 'office.street', 'children[address].data.office.street.prop'),
482 array(self::LEVEL_1, 'address', 'address', 'street', 'office.street', 'children[address].data.office[street]'),
483 array(self::LEVEL_1, 'address', 'address', 'street', 'office.street', 'children[address].data.office[street].prop'),
484 array(self::LEVEL_1, 'address', 'address', 'street', 'office.street', 'children[address].data[office]'),
485 array(self::LEVEL_1, 'address', 'address', 'street', 'office.street', 'children[address].data[office].street'),
486 array(self::LEVEL_1, 'address', 'address', 'street', 'office.street', 'children[address].data[office].street.prop'),
487 array(self::LEVEL_1, 'address', 'address', 'street', 'office.street', 'children[address].data[office][street]'),
488 array(self::LEVEL_1, 'address', 'address', 'street', 'office.street', 'children[address].data[office][street].prop'),
489 array(self::LEVEL_2, 'address', 'address', 'street', 'office.street', 'data.address.office.street'),
490 array(self::LEVEL_2, 'address', 'address', 'street', 'office.street', 'data.address.office.street.prop'),
491 array(self::LEVEL_1, 'address', 'address', 'street', 'office.street', 'data.address.office[street]'),
492 array(self::LEVEL_1, 'address', 'address', 'street', 'office.street', 'data.address.office[street].prop'),
493 array(self::LEVEL_1, 'address', 'address', 'street', 'office.street', 'data.address[office].street'),
494 array(self::LEVEL_1, 'address', 'address', 'street', 'office.street', 'data.address[office].street.prop'),
495 array(self::LEVEL_1, 'address', 'address', 'street', 'office.street', 'data.address[office][street]'),
496 array(self::LEVEL_1, 'address', 'address', 'street', 'office.street', 'data.address[office][street].prop'),
497 array(self::LEVEL_0, 'address', 'address', 'street', 'office.street', 'data[address].office.street'),
498 array(self::LEVEL_0, 'address', 'address', 'street', 'office.street', 'data[address].office.street.prop'),
499 array(self::LEVEL_0, 'address', 'address', 'street', 'office.street', 'data[address].office[street]'),
500 array(self::LEVEL_0, 'address', 'address', 'street', 'office.street', 'data[address].office[street].prop'),
501 array(self::LEVEL_0, 'address', 'address', 'street', 'office.street', 'data[address][office].street'),
502 array(self::LEVEL_0, 'address', 'address', 'street', 'office.street', 'data[address][office].street.prop'),
503 array(self::LEVEL_0, 'address', 'address', 'street', 'office.street', 'data[address][office][street]'),
504 array(self::LEVEL_0, 'address', 'address', 'street', 'office.street', 'data[address][office][street].prop'),
505
506 array(self::LEVEL_2, 'address', '[address]', 'street', 'office.street', 'children[address].children[street].data'),
507 array(self::LEVEL_2, 'address', '[address]', 'street', 'office.street', 'children[address].children[street].data.prop'),
508 array(self::LEVEL_1, 'address', '[address]', 'street', 'office.street', 'children[address].data'),
509 array(self::LEVEL_1, 'address', '[address]', 'street', 'office.street', 'children[address].data.office'),
510 array(self::LEVEL_2, 'address', '[address]', 'street', 'office.street', 'children[address].data.office.street'),
511 array(self::LEVEL_2, 'address', '[address]', 'street', 'office.street', 'children[address].data.office.street.prop'),
512 array(self::LEVEL_1, 'address', '[address]', 'street', 'office.street', 'children[address].data.office[street]'),
513 array(self::LEVEL_1, 'address', '[address]', 'street', 'office.street', 'children[address].data.office[street].prop'),
514 array(self::LEVEL_1, 'address', '[address]', 'street', 'office.street', 'children[address].data[office]'),
515 array(self::LEVEL_1, 'address', '[address]', 'street', 'office.street', 'children[address].data[office].street'),
516 array(self::LEVEL_1, 'address', '[address]', 'street', 'office.street', 'children[address].data[office].street.prop'),
517 array(self::LEVEL_1, 'address', '[address]', 'street', 'office.street', 'children[address].data[office][street]'),
518 array(self::LEVEL_1, 'address', '[address]', 'street', 'office.street', 'children[address].data[office][street].prop'),
519 array(self::LEVEL_0, 'address', '[address]', 'street', 'office.street', 'data.address.office.street'),
520 array(self::LEVEL_0, 'address', '[address]', 'street', 'office.street', 'data.address.office.street.prop'),
521 array(self::LEVEL_0, 'address', '[address]', 'street', 'office.street', 'data.address.office[street]'),
522 array(self::LEVEL_0, 'address', '[address]', 'street', 'office.street', 'data.address.office[street].prop'),
523 array(self::LEVEL_0, 'address', '[address]', 'street', 'office.street', 'data.address[office].street'),
524 array(self::LEVEL_0, 'address', '[address]', 'street', 'office.street', 'data.address[office].street.prop'),
525 array(self::LEVEL_0, 'address', '[address]', 'street', 'office.street', 'data.address[office][street]'),
526 array(self::LEVEL_0, 'address', '[address]', 'street', 'office.street', 'data.address[office][street].prop'),
527 array(self::LEVEL_2, 'address', '[address]', 'street', 'office.street', 'data[address].office.street'),
528 array(self::LEVEL_2, 'address', '[address]', 'street', 'office.street', 'data[address].office.street.prop'),
529 array(self::LEVEL_1, 'address', '[address]', 'street', 'office.street', 'data[address].office[street]'),
530 array(self::LEVEL_1, 'address', '[address]', 'street', 'office.street', 'data[address].office[street].prop'),
531 array(self::LEVEL_1, 'address', '[address]', 'street', 'office.street', 'data[address][office].street'),
532 array(self::LEVEL_1, 'address', '[address]', 'street', 'office.street', 'data[address][office].street.prop'),
533 array(self::LEVEL_1, 'address', '[address]', 'street', 'office.street', 'data[address][office][street]'),
534 array(self::LEVEL_1, 'address', '[address]', 'street', 'office.street', 'data[address][office][street].prop'),
535
536 array(self::LEVEL_2, 'address', 'address', 'street', 'office[street]', 'children[address].children[street].data'),
537 array(self::LEVEL_2, 'address', 'address', 'street', 'office[street]', 'children[address].children[street].data.prop'),
538 array(self::LEVEL_1, 'address', 'address', 'street', 'office[street]', 'children[address].data'),
539 array(self::LEVEL_1, 'address', 'address', 'street', 'office[street]', 'children[address].data.office'),
540 array(self::LEVEL_1, 'address', 'address', 'street', 'office[street]', 'children[address].data.office.street'),
541 array(self::LEVEL_1, 'address', 'address', 'street', 'office[street]', 'children[address].data.office.street.prop'),
542 array(self::LEVEL_2, 'address', 'address', 'street', 'office[street]', 'children[address].data.office[street]'),
543 array(self::LEVEL_2, 'address', 'address', 'street', 'office[street]', 'children[address].data.office[street].prop'),
544 array(self::LEVEL_1, 'address', 'address', 'street', 'office[street]', 'children[address].data[office]'),
545 array(self::LEVEL_1, 'address', 'address', 'street', 'office[street]', 'children[address].data[office].street'),
546 array(self::LEVEL_1, 'address', 'address', 'street', 'office[street]', 'children[address].data[office].street.prop'),
547 array(self::LEVEL_1, 'address', 'address', 'street', 'office[street]', 'children[address].data[office][street]'),
548 array(self::LEVEL_1, 'address', 'address', 'street', 'office[street]', 'children[address].data[office][street].prop'),
549 array(self::LEVEL_1, 'address', 'address', 'street', 'office[street]', 'data.address.office.street'),
550 array(self::LEVEL_1, 'address', 'address', 'street', 'office[street]', 'data.address.office.street.prop'),
551 array(self::LEVEL_2, 'address', 'address', 'street', 'office[street]', 'data.address.office[street]'),
552 array(self::LEVEL_2, 'address', 'address', 'street', 'office[street]', 'data.address.office[street].prop'),
553 array(self::LEVEL_1, 'address', 'address', 'street', 'office[street]', 'data.address[office].street'),
554 array(self::LEVEL_1, 'address', 'address', 'street', 'office[street]', 'data.address[office].street.prop'),
555 array(self::LEVEL_1, 'address', 'address', 'street', 'office[street]', 'data.address[office][street]'),
556 array(self::LEVEL_1, 'address', 'address', 'street', 'office[street]', 'data.address[office][street].prop'),
557 array(self::LEVEL_0, 'address', 'address', 'street', 'office[street]', 'data[address].office.street'),
558 array(self::LEVEL_0, 'address', 'address', 'street', 'office[street]', 'data[address].office.street.prop'),
559 array(self::LEVEL_0, 'address', 'address', 'street', 'office[street]', 'data[address].office[street]'),
560 array(self::LEVEL_0, 'address', 'address', 'street', 'office[street]', 'data[address].office[street].prop'),
561 array(self::LEVEL_0, 'address', 'address', 'street', 'office[street]', 'data[address][office].street'),
562 array(self::LEVEL_0, 'address', 'address', 'street', 'office[street]', 'data[address][office].street.prop'),
563 array(self::LEVEL_0, 'address', 'address', 'street', 'office[street]', 'data[address][office][street]'),
564 array(self::LEVEL_0, 'address', 'address', 'street', 'office[street]', 'data[address][office][street].prop'),
565
566 array(self::LEVEL_2, 'address', '[address]', 'street', 'office[street]', 'children[address].children[street].data'),
567 array(self::LEVEL_2, 'address', '[address]', 'street', 'office[street]', 'children[address].children[street].data.prop'),
568 array(self::LEVEL_1, 'address', '[address]', 'street', 'office[street]', 'children[address].data.office.street'),
569 array(self::LEVEL_1, 'address', '[address]', 'street', 'office[street]', 'children[address].data.office.street.prop'),
570 array(self::LEVEL_2, 'address', '[address]', 'street', 'office[street]', 'children[address].data.office[street]'),
571 array(self::LEVEL_2, 'address', '[address]', 'street', 'office[street]', 'children[address].data.office[street].prop'),
572 array(self::LEVEL_1, 'address', '[address]', 'street', 'office[street]', 'children[address].data[office]'),
573 array(self::LEVEL_1, 'address', '[address]', 'street', 'office[street]', 'children[address].data[office].street'),
574 array(self::LEVEL_1, 'address', '[address]', 'street', 'office[street]', 'children[address].data[office].street.prop'),
575 array(self::LEVEL_1, 'address', '[address]', 'street', 'office[street]', 'children[address].data[office][street]'),
576 array(self::LEVEL_1, 'address', '[address]', 'street', 'office[street]', 'children[address].data[office][street].prop'),
577 array(self::LEVEL_0, 'address', '[address]', 'street', 'office[street]', 'data.address.office.street'),
578 array(self::LEVEL_0, 'address', '[address]', 'street', 'office[street]', 'data.address.office.street.prop'),
579 array(self::LEVEL_0, 'address', '[address]', 'street', 'office[street]', 'data.address.office[street]'),
580 array(self::LEVEL_0, 'address', '[address]', 'street', 'office[street]', 'data.address.office[street].prop'),
581 array(self::LEVEL_0, 'address', '[address]', 'street', 'office[street]', 'data.address[office].street'),
582 array(self::LEVEL_0, 'address', '[address]', 'street', 'office[street]', 'data.address[office].street.prop'),
583 array(self::LEVEL_0, 'address', '[address]', 'street', 'office[street]', 'data.address[office][street]'),
584 array(self::LEVEL_0, 'address', '[address]', 'street', 'office[street]', 'data.address[office][street].prop'),
585 array(self::LEVEL_1, 'address', '[address]', 'street', 'office[street]', 'data[address].office.street'),
586 array(self::LEVEL_1, 'address', '[address]', 'street', 'office[street]', 'data[address].office.street.prop'),
587 array(self::LEVEL_2, 'address', '[address]', 'street', 'office[street]', 'data[address].office[street]'),
588 array(self::LEVEL_2, 'address', '[address]', 'street', 'office[street]', 'data[address].office[street].prop'),
589 array(self::LEVEL_1, 'address', '[address]', 'street', 'office[street]', 'data[address][office].street'),
590 array(self::LEVEL_1, 'address', '[address]', 'street', 'office[street]', 'data[address][office].street.prop'),
591 array(self::LEVEL_1, 'address', '[address]', 'street', 'office[street]', 'data[address][office][street]'),
592 array(self::LEVEL_1, 'address', '[address]', 'street', 'office[street]', 'data[address][office][street].prop'),
593
594 array(self::LEVEL_2, 'address', 'address', 'street', '[office].street', 'children[address].children[street].data'),
595 array(self::LEVEL_2, 'address', 'address', 'street', '[office].street', 'children[address].children[street].data.prop'),
596 array(self::LEVEL_1, 'address', 'address', 'street', '[office].street', 'children[address].data'),
597 array(self::LEVEL_1, 'address', 'address', 'street', '[office].street', 'children[address].data.office'),
598 array(self::LEVEL_1, 'address', 'address', 'street', '[office].street', 'children[address].data.office.street'),
599 array(self::LEVEL_1, 'address', 'address', 'street', '[office].street', 'children[address].data.office.street.prop'),
600 array(self::LEVEL_1, 'address', 'address', 'street', '[office].street', 'children[address].data.office[street]'),
601 array(self::LEVEL_1, 'address', 'address', 'street', '[office].street', 'children[address].data.office[street].prop'),
602 array(self::LEVEL_1, 'address', 'address', 'street', '[office].street', 'children[address].data[office]'),
603 array(self::LEVEL_2, 'address', 'address', 'street', '[office].street', 'children[address].data[office].street'),
604 array(self::LEVEL_2, 'address', 'address', 'street', '[office].street', 'children[address].data[office].street.prop'),
605 array(self::LEVEL_1, 'address', 'address', 'street', '[office].street', 'children[address].data[office][street]'),
606 array(self::LEVEL_1, 'address', 'address', 'street', '[office].street', 'children[address].data[office][street].prop'),
607 array(self::LEVEL_1, 'address', 'address', 'street', '[office].street', 'data.address.office.street'),
608 array(self::LEVEL_1, 'address', 'address', 'street', '[office].street', 'data.address.office.street.prop'),
609 array(self::LEVEL_1, 'address', 'address', 'street', '[office].street', 'data.address.office[street]'),
610 array(self::LEVEL_1, 'address', 'address', 'street', '[office].street', 'data.address.office[street].prop'),
611 array(self::LEVEL_2, 'address', 'address', 'street', '[office].street', 'data.address[office].street'),
612 array(self::LEVEL_2, 'address', 'address', 'street', '[office].street', 'data.address[office].street.prop'),
613 array(self::LEVEL_1, 'address', 'address', 'street', '[office].street', 'data.address[office][street]'),
614 array(self::LEVEL_1, 'address', 'address', 'street', '[office].street', 'data.address[office][street].prop'),
615 array(self::LEVEL_0, 'address', 'address', 'street', '[office].street', 'data[address].office.street'),
616 array(self::LEVEL_0, 'address', 'address', 'street', '[office].street', 'data[address].office.street.prop'),
617 array(self::LEVEL_0, 'address', 'address', 'street', '[office].street', 'data[address].office[street]'),
618 array(self::LEVEL_0, 'address', 'address', 'street', '[office].street', 'data[address].office[street].prop'),
619 array(self::LEVEL_0, 'address', 'address', 'street', '[office].street', 'data[address][office].street'),
620 array(self::LEVEL_0, 'address', 'address', 'street', '[office].street', 'data[address][office].street.prop'),
621 array(self::LEVEL_0, 'address', 'address', 'street', '[office].street', 'data[address][office][street]'),
622 array(self::LEVEL_0, 'address', 'address', 'street', '[office].street', 'data[address][office][street].prop'),
623
624 array(self::LEVEL_2, 'address', '[address]', 'street', '[office].street', 'children[address].children[street].data'),
625 array(self::LEVEL_2, 'address', '[address]', 'street', '[office].street', 'children[address].children[street].data.prop'),
626 array(self::LEVEL_1, 'address', '[address]', 'street', '[office].street', 'children[address].data'),
627 array(self::LEVEL_1, 'address', '[address]', 'street', '[office].street', 'children[address].data.office'),
628 array(self::LEVEL_1, 'address', '[address]', 'street', '[office].street', 'children[address].data.office.street'),
629 array(self::LEVEL_1, 'address', '[address]', 'street', '[office].street', 'children[address].data.office.street.prop'),
630 array(self::LEVEL_1, 'address', '[address]', 'street', '[office].street', 'children[address].data.office[street]'),
631 array(self::LEVEL_1, 'address', '[address]', 'street', '[office].street', 'children[address].data.office[street].prop'),
632 array(self::LEVEL_1, 'address', '[address]', 'street', '[office].street', 'children[address].data[office]'),
633 array(self::LEVEL_2, 'address', '[address]', 'street', '[office].street', 'children[address].data[office].street'),
634 array(self::LEVEL_2, 'address', '[address]', 'street', '[office].street', 'children[address].data[office].street.prop'),
635 array(self::LEVEL_1, 'address', '[address]', 'street', '[office].street', 'children[address].data[office][street]'),
636 array(self::LEVEL_1, 'address', '[address]', 'street', '[office].street', 'children[address].data[office][street].prop'),
637 array(self::LEVEL_0, 'address', '[address]', 'street', '[office].street', 'data.address.office.street'),
638 array(self::LEVEL_0, 'address', '[address]', 'street', '[office].street', 'data.address.office.street.prop'),
639 array(self::LEVEL_0, 'address', '[address]', 'street', '[office].street', 'data.address.office[street]'),
640 array(self::LEVEL_0, 'address', '[address]', 'street', '[office].street', 'data.address.office[street].prop'),
641 array(self::LEVEL_0, 'address', '[address]', 'street', '[office].street', 'data.address[office].street'),
642 array(self::LEVEL_0, 'address', '[address]', 'street', '[office].street', 'data.address[office].street.prop'),
643 array(self::LEVEL_0, 'address', '[address]', 'street', '[office].street', 'data.address[office][street]'),
644 array(self::LEVEL_0, 'address', '[address]', 'street', '[office].street', 'data.address[office][street].prop'),
645 array(self::LEVEL_1, 'address', '[address]', 'street', '[office].street', 'data[address].office.street'),
646 array(self::LEVEL_1, 'address', '[address]', 'street', '[office].street', 'data[address].office.street.prop'),
647 array(self::LEVEL_1, 'address', '[address]', 'street', '[office].street', 'data[address].office[street]'),
648 array(self::LEVEL_1, 'address', '[address]', 'street', '[office].street', 'data[address].office[street].prop'),
649 array(self::LEVEL_2, 'address', '[address]', 'street', '[office].street', 'data[address][office].street'),
650 array(self::LEVEL_2, 'address', '[address]', 'street', '[office].street', 'data[address][office].street.prop'),
651 array(self::LEVEL_1, 'address', '[address]', 'street', '[office].street', 'data[address][office][street]'),
652 array(self::LEVEL_1, 'address', '[address]', 'street', '[office].street', 'data[address][office][street].prop'),
653
654 array(self::LEVEL_2, 'address', 'address', 'street', '[office][street]', 'children[address].children[street].data'),
655 array(self::LEVEL_2, 'address', 'address', 'street', '[office][street]', 'children[address].children[street].data.prop'),
656 array(self::LEVEL_1, 'address', 'address', 'street', '[office][street]', 'children[address].data'),
657 array(self::LEVEL_1, 'address', 'address', 'street', '[office][street]', 'children[address].data.office'),
658 array(self::LEVEL_1, 'address', 'address', 'street', '[office][street]', 'children[address].data.office.street'),
659 array(self::LEVEL_1, 'address', 'address', 'street', '[office][street]', 'children[address].data.office.street.prop'),
660 array(self::LEVEL_1, 'address', 'address', 'street', '[office][street]', 'children[address].data.office[street]'),
661 array(self::LEVEL_1, 'address', 'address', 'street', '[office][street]', 'children[address].data.office[street].prop'),
662 array(self::LEVEL_1, 'address', 'address', 'street', '[office][street]', 'children[address].data[office]'),
663 array(self::LEVEL_1, 'address', 'address', 'street', '[office][street]', 'children[address].data[office].street'),
664 array(self::LEVEL_1, 'address', 'address', 'street', '[office][street]', 'children[address].data[office].street.prop'),
665 array(self::LEVEL_2, 'address', 'address', 'street', '[office][street]', 'children[address].data[office][street]'),
666 array(self::LEVEL_2, 'address', 'address', 'street', '[office][street]', 'children[address].data[office][street].prop'),
667 array(self::LEVEL_1, 'address', 'address', 'street', '[office][street]', 'data.address.office.street'),
668 array(self::LEVEL_1, 'address', 'address', 'street', '[office][street]', 'data.address.office.street.prop'),
669 array(self::LEVEL_1, 'address', 'address', 'street', '[office][street]', 'data.address.office[street]'),
670 array(self::LEVEL_1, 'address', 'address', 'street', '[office][street]', 'data.address.office[street].prop'),
671 array(self::LEVEL_1, 'address', 'address', 'street', '[office][street]', 'data.address[office].street'),
672 array(self::LEVEL_1, 'address', 'address', 'street', '[office][street]', 'data.address[office].street.prop'),
673 array(self::LEVEL_2, 'address', 'address', 'street', '[office][street]', 'data.address[office][street]'),
674 array(self::LEVEL_2, 'address', 'address', 'street', '[office][street]', 'data.address[office][street].prop'),
675 array(self::LEVEL_0, 'address', 'address', 'street', '[office][street]', 'data[address].office.street'),
676 array(self::LEVEL_0, 'address', 'address', 'street', '[office][street]', 'data[address].office.street.prop'),
677 array(self::LEVEL_0, 'address', 'address', 'street', '[office][street]', 'data[address].office[street]'),
678 array(self::LEVEL_0, 'address', 'address', 'street', '[office][street]', 'data[address].office[street].prop'),
679 array(self::LEVEL_0, 'address', 'address', 'street', '[office][street]', 'data[address][office].street'),
680 array(self::LEVEL_0, 'address', 'address', 'street', '[office][street]', 'data[address][office].street.prop'),
681 array(self::LEVEL_0, 'address', 'address', 'street', '[office][street]', 'data[address][office][street]'),
682 array(self::LEVEL_0, 'address', 'address', 'street', '[office][street]', 'data[address][office][street].prop'),
683
684 array(self::LEVEL_2, 'address', '[address]', 'street', '[office][street]', 'children[address].children[street].data'),
685 array(self::LEVEL_2, 'address', '[address]', 'street', '[office][street]', 'children[address].children[street].data.prop'),
686 array(self::LEVEL_1, 'address', '[address]', 'street', '[office][street]', 'children[address].data'),
687 array(self::LEVEL_1, 'address', '[address]', 'street', '[office][street]', 'children[address].data.office'),
688 array(self::LEVEL_1, 'address', '[address]', 'street', '[office][street]', 'children[address].data.office.street'),
689 array(self::LEVEL_1, 'address', '[address]', 'street', '[office][street]', 'children[address].data.office.street.prop'),
690 array(self::LEVEL_1, 'address', '[address]', 'street', '[office][street]', 'children[address].data.office[street]'),
691 array(self::LEVEL_1, 'address', '[address]', 'street', '[office][street]', 'children[address].data.office[street].prop'),
692 array(self::LEVEL_1, 'address', '[address]', 'street', '[office][street]', 'children[address].data[office]'),
693 array(self::LEVEL_1, 'address', '[address]', 'street', '[office][street]', 'children[address].data[office].street'),
694 array(self::LEVEL_1, 'address', '[address]', 'street', '[office][street]', 'children[address].data[office].street.prop'),
695 array(self::LEVEL_2, 'address', '[address]', 'street', '[office][street]', 'children[address].data[office][street]'),
696 array(self::LEVEL_2, 'address', '[address]', 'street', '[office][street]', 'children[address].data[office][street].prop'),
697 array(self::LEVEL_0, 'address', '[address]', 'street', '[office][street]', 'data.address.office.street'),
698 array(self::LEVEL_0, 'address', '[address]', 'street', '[office][street]', 'data.address.office.street.prop'),
699 array(self::LEVEL_0, 'address', '[address]', 'street', '[office][street]', 'data.address.office[street]'),
700 array(self::LEVEL_0, 'address', '[address]', 'street', '[office][street]', 'data.address.office[street].prop'),
701 array(self::LEVEL_0, 'address', '[address]', 'street', '[office][street]', 'data.address[office].street'),
702 array(self::LEVEL_0, 'address', '[address]', 'street', '[office][street]', 'data.address[office].street.prop'),
703 array(self::LEVEL_0, 'address', '[address]', 'street', '[office][street]', 'data.address[office][street]'),
704 array(self::LEVEL_0, 'address', '[address]', 'street', '[office][street]', 'data.address[office][street].prop'),
705 array(self::LEVEL_1, 'address', '[address]', 'street', '[office][street]', 'data[address].office.street'),
706 array(self::LEVEL_1, 'address', '[address]', 'street', '[office][street]', 'data[address].office.street.prop'),
707 array(self::LEVEL_1, 'address', '[address]', 'street', '[office][street]', 'data[address].office[street]'),
708 array(self::LEVEL_1, 'address', '[address]', 'street', '[office][street]', 'data[address].office[street].prop'),
709 array(self::LEVEL_1, 'address', '[address]', 'street', '[office][street]', 'data[address][office].street'),
710 array(self::LEVEL_1, 'address', '[address]', 'street', '[office][street]', 'data[address][office].street.prop'),
711 array(self::LEVEL_2, 'address', '[address]', 'street', '[office][street]', 'data[address][office][street]'),
712 array(self::LEVEL_2, 'address', '[address]', 'street', '[office][street]', 'data[address][office][street].prop'),
713
714 // Edge cases which must not occur
715 array(self::LEVEL_1, 'address', 'address', 'street', 'street', 'children[address][street]'),
716 array(self::LEVEL_1, 'address', 'address', 'street', 'street', 'children[address][street].prop'),
717 array(self::LEVEL_1, 'address', 'address', 'street', '[street]', 'children[address][street]'),
718 array(self::LEVEL_1, 'address', 'address', 'street', '[street]', 'children[address][street].prop'),
719 array(self::LEVEL_1, 'address', '[address]', 'street', 'street', 'children[address][street]'),
720 array(self::LEVEL_1, 'address', '[address]', 'street', 'street', 'children[address][street].prop'),
721 array(self::LEVEL_1, 'address', '[address]', 'street', '[street]', 'children[address][street]'),
722 array(self::LEVEL_1, 'address', '[address]', 'street', '[street]', 'children[address][street].prop'),
723
724 array(self::LEVEL_0, 'address', 'person.address', 'street', 'street', 'children[person].children[address].children[street]'),
725 array(self::LEVEL_0, 'address', 'person.address', 'street', 'street', 'children[person].children[address].data.street'),
726 array(self::LEVEL_0, 'address', 'person.address', 'street', 'street', 'children[person].data.address.street'),
727 array(self::LEVEL_0, 'address', 'person.address', 'street', 'street', 'data.address.street'),
728
729 array(self::LEVEL_1, 'address', 'address', 'street', 'office.street', 'children[address].children[office].children[street]'),
730 array(self::LEVEL_1, 'address', 'address', 'street', 'office.street', 'children[address].children[office].data.street'),
731 array(self::LEVEL_1, 'address', 'address', 'street', 'office.street', 'children[address].data.street'),
732 array(self::LEVEL_1, 'address', 'address', 'street', 'office.street', 'data.address.street'),
733 );
734 }
735
736 /**
737 * @dataProvider provideDefaultTests
738 */
739 public function testDefaultErrorMapping($target, $childName, $childPath, $grandChildName, $grandChildPath, $violationPath)
740 {
741 $violation = $this->getConstraintViolation($violationPath);
742 $parent = $this->getForm('parent');
743 $child = $this->getForm($childName, $childPath);
744 $grandChild = $this->getForm($grandChildName, $grandChildPath);
745
746 $parent->add($child);
747 $child->add($grandChild);
748
749 $this->mapper->mapViolation($violation, $parent);
750
751 if (self::LEVEL_0 === $target) {
752 $this->assertEquals(array($this->getFormError()), $parent->getErrors(), $parent->getName().' should have an error, but has none');
753 $this->assertCount(0, $child->getErrors(), $childName.' should not have an error, but has one');
754 $this->assertCount(0, $grandChild->getErrors(), $grandChildName.' should not have an error, but has one');
755 } elseif (self::LEVEL_1 === $target) {
756 $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one');
757 $this->assertEquals(array($this->getFormError()), $child->getErrors(), $childName.' should have an error, but has none');
758 $this->assertCount(0, $grandChild->getErrors(), $grandChildName.' should not have an error, but has one');
759 } else {
760 $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one');
761 $this->assertCount(0, $child->getErrors(), $childName.' should not have an error, but has one');
762 $this->assertEquals(array($this->getFormError()), $grandChild->getErrors(), $grandChildName.' should have an error, but has none');
763 }
764 }
765
766 public function provideCustomDataErrorTests()
767 {
768 return array(
769 // mapping target, error mapping, child name, its property path, grand child name, its property path, violation path
770 array(self::LEVEL_1, 'foo', 'address', 'address', 'address', 'street', 'street', 'data.foo'),
771 array(self::LEVEL_1, 'foo', 'address', 'address', 'address', 'street', 'street', 'data.foo.prop'),
772 array(self::LEVEL_0, 'foo', 'address', 'address', 'address', 'street', 'street', 'data[foo]'),
773 array(self::LEVEL_0, 'foo', 'address', 'address', 'address', 'street', 'street', 'data[foo].prop'),
774
775 array(self::LEVEL_1, 'foo', 'address', 'address', 'address', 'street', 'street', 'data.address'),
776 array(self::LEVEL_1, 'foo', 'address', 'address', 'address', 'street', 'street', 'data.address.prop'),
777 array(self::LEVEL_0, 'foo', 'address', 'address', 'address', 'street', 'street', 'data[address]'),
778 array(self::LEVEL_0, 'foo', 'address', 'address', 'address', 'street', 'street', 'data[address].prop'),
779
780 array(self::LEVEL_1, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data.foo'),
781 array(self::LEVEL_1, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data.foo.prop'),
782 array(self::LEVEL_0, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data[foo]'),
783 array(self::LEVEL_0, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data[foo].prop'),
784
785 array(self::LEVEL_0, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data.address'),
786 array(self::LEVEL_0, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data.address.prop'),
787 array(self::LEVEL_1, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data[address]'),
788 array(self::LEVEL_1, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data[address].prop'),
789
790 array(self::LEVEL_0, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data.foo'),
791 array(self::LEVEL_0, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data.foo.prop'),
792 array(self::LEVEL_1, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data[foo]'),
793 array(self::LEVEL_1, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data[foo].prop'),
794
795 array(self::LEVEL_1, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data.address'),
796 array(self::LEVEL_1, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data.address.prop'),
797 array(self::LEVEL_0, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data[address]'),
798 array(self::LEVEL_0, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data[address].prop'),
799
800 array(self::LEVEL_0, '[foo]', 'address', 'address', '[address]', 'street', 'street', 'data.foo'),
801 array(self::LEVEL_0, '[foo]', 'address', 'address', '[address]', 'street', 'street', 'data.foo.prop'),
802 array(self::LEVEL_1, '[foo]', 'address', 'address', '[address]', 'street', 'street', 'data[foo]'),
803 array(self::LEVEL_1, '[foo]', 'address', 'address', '[address]', 'street', 'street', 'data[foo].prop'),
804
805 array(self::LEVEL_0, '[foo]', 'address', 'address', '[address]', 'street', 'street', 'data.address'),
806 array(self::LEVEL_0, '[foo]', 'address', 'address', '[address]', 'street', 'street', 'data.address.prop'),
807 array(self::LEVEL_1, '[foo]', 'address', 'address', '[address]', 'street', 'street', 'data[address]'),
808 array(self::LEVEL_1, '[foo]', 'address', 'address', '[address]', 'street', 'street', 'data[address].prop'),
809
810 array(self::LEVEL_2, 'foo', 'address', 'address', 'address', 'street', 'street', 'data.foo.street'),
811 array(self::LEVEL_2, 'foo', 'address', 'address', 'address', 'street', 'street', 'data.foo.street.prop'),
812 array(self::LEVEL_1, 'foo', 'address', 'address', 'address', 'street', 'street', 'data.foo[street]'),
813 array(self::LEVEL_1, 'foo', 'address', 'address', 'address', 'street', 'street', 'data.foo[street].prop'),
814 array(self::LEVEL_0, 'foo', 'address', 'address', 'address', 'street', 'street', 'data[foo].street'),
815 array(self::LEVEL_0, 'foo', 'address', 'address', 'address', 'street', 'street', 'data[foo].street.prop'),
816 array(self::LEVEL_0, 'foo', 'address', 'address', 'address', 'street', 'street', 'data[foo][street]'),
817 array(self::LEVEL_0, 'foo', 'address', 'address', 'address', 'street', 'street', 'data[foo][street].prop'),
818
819 array(self::LEVEL_2, 'foo', 'address', 'address', 'address', 'street', 'street', 'data.address.street'),
820 array(self::LEVEL_2, 'foo', 'address', 'address', 'address', 'street', 'street', 'data.address.street.prop'),
821 array(self::LEVEL_1, 'foo', 'address', 'address', 'address', 'street', 'street', 'data.address[street]'),
822 array(self::LEVEL_1, 'foo', 'address', 'address', 'address', 'street', 'street', 'data.address[street].prop'),
823 array(self::LEVEL_0, 'foo', 'address', 'address', 'address', 'street', 'street', 'data[address].street'),
824 array(self::LEVEL_0, 'foo', 'address', 'address', 'address', 'street', 'street', 'data[address].street.prop'),
825 array(self::LEVEL_0, 'foo', 'address', 'address', 'address', 'street', 'street', 'data[address][street]'),
826 array(self::LEVEL_0, 'foo', 'address', 'address', 'address', 'street', 'street', 'data[address][street].prop'),
827
828 array(self::LEVEL_1, 'foo', 'address', 'address', 'address', 'street', '[street]', 'data.foo.street'),
829 array(self::LEVEL_1, 'foo', 'address', 'address', 'address', 'street', '[street]', 'data.foo.street.prop'),
830 array(self::LEVEL_2, 'foo', 'address', 'address', 'address', 'street', '[street]', 'data.foo[street]'),
831 array(self::LEVEL_2, 'foo', 'address', 'address', 'address', 'street', '[street]', 'data.foo[street].prop'),
832 array(self::LEVEL_0, 'foo', 'address', 'address', 'address', 'street', '[street]', 'data[foo].street'),
833 array(self::LEVEL_0, 'foo', 'address', 'address', 'address', 'street', '[street]', 'data[foo].street.prop'),
834 array(self::LEVEL_0, 'foo', 'address', 'address', 'address', 'street', '[street]', 'data[foo][street]'),
835 array(self::LEVEL_0, 'foo', 'address', 'address', 'address', 'street', '[street]', 'data[foo][street].prop'),
836
837 array(self::LEVEL_1, 'foo', 'address', 'address', 'address', 'street', '[street]', 'data.address.street'),
838 array(self::LEVEL_1, 'foo', 'address', 'address', 'address', 'street', '[street]', 'data.address.street.prop'),
839 array(self::LEVEL_2, 'foo', 'address', 'address', 'address', 'street', '[street]', 'data.address[street]'),
840 array(self::LEVEL_2, 'foo', 'address', 'address', 'address', 'street', '[street]', 'data.address[street].prop'),
841 array(self::LEVEL_0, 'foo', 'address', 'address', 'address', 'street', '[street]', 'data[address].street'),
842 array(self::LEVEL_0, 'foo', 'address', 'address', 'address', 'street', '[street]', 'data[address].street.prop'),
843 array(self::LEVEL_0, 'foo', 'address', 'address', 'address', 'street', '[street]', 'data[address][street]'),
844 array(self::LEVEL_0, 'foo', 'address', 'address', 'address', 'street', '[street]', 'data[address][street].prop'),
845
846 array(self::LEVEL_2, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data.foo.street'),
847 array(self::LEVEL_2, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data.foo.street.prop'),
848 array(self::LEVEL_1, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data.foo[street]'),
849 array(self::LEVEL_1, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data.foo[street].prop'),
850 array(self::LEVEL_0, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data[foo].street'),
851 array(self::LEVEL_0, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data[foo].street.prop'),
852 array(self::LEVEL_0, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data[foo][street]'),
853 array(self::LEVEL_0, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data[foo][street].prop'),
854
855 array(self::LEVEL_0, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data.address.street'),
856 array(self::LEVEL_0, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data.address.street.prop'),
857 array(self::LEVEL_0, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data.address[street]'),
858 array(self::LEVEL_0, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data.address[street].prop'),
859 array(self::LEVEL_2, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data[address].street'),
860 array(self::LEVEL_2, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data[address].street.prop'),
861 array(self::LEVEL_1, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data[address][street]'),
862 array(self::LEVEL_1, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data[address][street].prop'),
863
864 array(self::LEVEL_1, 'foo', 'address', 'address', '[address]', 'street', '[street]', 'data.foo.street'),
865 array(self::LEVEL_1, 'foo', 'address', 'address', '[address]', 'street', '[street]', 'data.foo.street.prop'),
866 array(self::LEVEL_2, 'foo', 'address', 'address', '[address]', 'street', '[street]', 'data.foo[street]'),
867 array(self::LEVEL_2, 'foo', 'address', 'address', '[address]', 'street', '[street]', 'data.foo[street].prop'),
868 array(self::LEVEL_0, 'foo', 'address', 'address', '[address]', 'street', '[street]', 'data[foo].street'),
869 array(self::LEVEL_0, 'foo', 'address', 'address', '[address]', 'street', '[street]', 'data[foo].street.prop'),
870 array(self::LEVEL_0, 'foo', 'address', 'address', '[address]', 'street', '[street]', 'data[foo][street]'),
871 array(self::LEVEL_0, 'foo', 'address', 'address', '[address]', 'street', '[street]', 'data[foo][street].prop'),
872
873 array(self::LEVEL_0, 'foo', 'address', 'address', '[address]', 'street', '[street]', 'data.address.street'),
874 array(self::LEVEL_0, 'foo', 'address', 'address', '[address]', 'street', '[street]', 'data.address.street.prop'),
875 array(self::LEVEL_0, 'foo', 'address', 'address', '[address]', 'street', '[street]', 'data.address[street]'),
876 array(self::LEVEL_0, 'foo', 'address', 'address', '[address]', 'street', '[street]', 'data.address[street].prop'),
877 array(self::LEVEL_1, 'foo', 'address', 'address', '[address]', 'street', '[street]', 'data[address].street'),
878 array(self::LEVEL_1, 'foo', 'address', 'address', '[address]', 'street', '[street]', 'data[address].street.prop'),
879 array(self::LEVEL_2, 'foo', 'address', 'address', '[address]', 'street', '[street]', 'data[address][street]'),
880 array(self::LEVEL_2, 'foo', 'address', 'address', '[address]', 'street', '[street]', 'data[address][street].prop'),
881
882 array(self::LEVEL_0, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data.foo.street'),
883 array(self::LEVEL_0, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data.foo.street.prop'),
884 array(self::LEVEL_0, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data.foo[street]'),
885 array(self::LEVEL_0, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data.foo[street].prop'),
886 array(self::LEVEL_2, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data[foo].street'),
887 array(self::LEVEL_2, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data[foo].street.prop'),
888 array(self::LEVEL_1, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data[foo][street]'),
889 array(self::LEVEL_1, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data[foo][street].prop'),
890
891 array(self::LEVEL_2, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data.address.street'),
892 array(self::LEVEL_2, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data.address.street.prop'),
893 array(self::LEVEL_1, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data.address[street]'),
894 array(self::LEVEL_1, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data.address[street].prop'),
895 array(self::LEVEL_0, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data[address].street'),
896 array(self::LEVEL_0, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data[address].street.prop'),
897 array(self::LEVEL_0, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data[address][street]'),
898 array(self::LEVEL_0, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data[address][street].prop'),
899
900 array(self::LEVEL_0, '[foo]', 'address', 'address', 'address', 'street', '[street]', 'data.foo.street'),
901 array(self::LEVEL_0, '[foo]', 'address', 'address', 'address', 'street', '[street]', 'data.foo.street.prop'),
902 array(self::LEVEL_0, '[foo]', 'address', 'address', 'address', 'street', '[street]', 'data.foo[street]'),
903 array(self::LEVEL_0, '[foo]', 'address', 'address', 'address', 'street', '[street]', 'data.foo[street].prop'),
904 array(self::LEVEL_1, '[foo]', 'address', 'address', 'address', 'street', '[street]', 'data[foo].street'),
905 array(self::LEVEL_1, '[foo]', 'address', 'address', 'address', 'street', '[street]', 'data[foo].street.prop'),
906 array(self::LEVEL_2, '[foo]', 'address', 'address', 'address', 'street', '[street]', 'data[foo][street]'),
907 array(self::LEVEL_2, '[foo]', 'address', 'address', 'address', 'street', '[street]', 'data[foo][street].prop'),
908
909 array(self::LEVEL_1, '[foo]', 'address', 'address', 'address', 'street', '[street]', 'data.address.street'),
910 array(self::LEVEL_1, '[foo]', 'address', 'address', 'address', 'street', '[street]', 'data.address.street.prop'),
911 array(self::LEVEL_2, '[foo]', 'address', 'address', 'address', 'street', '[street]', 'data.address[street]'),
912 array(self::LEVEL_2, '[foo]', 'address', 'address', 'address', 'street', '[street]', 'data.address[street].prop'),
913 array(self::LEVEL_0, '[foo]', 'address', 'address', 'address', 'street', '[street]', 'data[address].street'),
914 array(self::LEVEL_0, '[foo]', 'address', 'address', 'address', 'street', '[street]', 'data[address].street.prop'),
915 array(self::LEVEL_0, '[foo]', 'address', 'address', 'address', 'street', '[street]', 'data[address][street]'),
916 array(self::LEVEL_0, '[foo]', 'address', 'address', 'address', 'street', '[street]', 'data[address][street].prop'),
917
918 array(self::LEVEL_0, '[foo]', 'address', 'address', '[address]', 'street', 'street', 'data.foo.street'),
919 array(self::LEVEL_0, '[foo]', 'address', 'address', '[address]', 'street', 'street', 'data.foo.street.prop'),
920 array(self::LEVEL_0, '[foo]', 'address', 'address', '[address]', 'street', 'street', 'data.foo[street]'),
921 array(self::LEVEL_0, '[foo]', 'address', 'address', '[address]', 'street', 'street', 'data.foo[street].prop'),
922 array(self::LEVEL_2, '[foo]', 'address', 'address', '[address]', 'street', 'street', 'data[foo].street'),
923 array(self::LEVEL_2, '[foo]', 'address', 'address', '[address]', 'street', 'street', 'data[foo].street.prop'),
924 array(self::LEVEL_1, '[foo]', 'address', 'address', '[address]', 'street', 'street', 'data[foo][street]'),
925 array(self::LEVEL_1, '[foo]', 'address', 'address', '[address]', 'street', 'street', 'data[foo][street].prop'),
926
927 array(self::LEVEL_0, '[foo]', 'address', 'address', '[address]', 'street', 'street', 'data.address.street'),
928 array(self::LEVEL_0, '[foo]', 'address', 'address', '[address]', 'street', 'street', 'data.address.street.prop'),
929 array(self::LEVEL_0, '[foo]', 'address', 'address', '[address]', 'street', 'street', 'data.address[street]'),
930 array(self::LEVEL_0, '[foo]', 'address', 'address', '[address]', 'street', 'street', 'data.address[street].prop'),
931 array(self::LEVEL_2, '[foo]', 'address', 'address', '[address]', 'street', 'street', 'data[address].street'),
932 array(self::LEVEL_2, '[foo]', 'address', 'address', '[address]', 'street', 'street', 'data[address].street.prop'),
933 array(self::LEVEL_1, '[foo]', 'address', 'address', '[address]', 'street', 'street', 'data[address][street]'),
934 array(self::LEVEL_1, '[foo]', 'address', 'address', '[address]', 'street', 'street', 'data[address][street].prop'),
935
936 array(self::LEVEL_0, '[foo]', 'address', 'address', '[address]', 'street', '[street]', 'data.foo.street'),
937 array(self::LEVEL_0, '[foo]', 'address', 'address', '[address]', 'street', '[street]', 'data.foo.street.prop'),
938 array(self::LEVEL_0, '[foo]', 'address', 'address', '[address]', 'street', '[street]', 'data.foo[street]'),
939 array(self::LEVEL_0, '[foo]', 'address', 'address', '[address]', 'street', '[street]', 'data.foo[street].prop'),
940 array(self::LEVEL_1, '[foo]', 'address', 'address', '[address]', 'street', '[street]', 'data[foo].street'),
941 array(self::LEVEL_1, '[foo]', 'address', 'address', '[address]', 'street', '[street]', 'data[foo].street.prop'),
942 array(self::LEVEL_2, '[foo]', 'address', 'address', '[address]', 'street', '[street]', 'data[foo][street]'),
943 array(self::LEVEL_2, '[foo]', 'address', 'address', '[address]', 'street', '[street]', 'data[foo][street].prop'),
944
945 array(self::LEVEL_0, '[foo]', 'address', 'address', '[address]', 'street', '[street]', 'data.address.street'),
946 array(self::LEVEL_0, '[foo]', 'address', 'address', '[address]', 'street', '[street]', 'data.address.street.prop'),
947 array(self::LEVEL_0, '[foo]', 'address', 'address', '[address]', 'street', '[street]', 'data.address[street]'),
948 array(self::LEVEL_0, '[foo]', 'address', 'address', '[address]', 'street', '[street]', 'data.address[street].prop'),
949 array(self::LEVEL_1, '[foo]', 'address', 'address', '[address]', 'street', '[street]', 'data[address].street'),
950 array(self::LEVEL_1, '[foo]', 'address', 'address', '[address]', 'street', '[street]', 'data[address].street.prop'),
951 array(self::LEVEL_2, '[foo]', 'address', 'address', '[address]', 'street', '[street]', 'data[address][street]'),
952 array(self::LEVEL_2, '[foo]', 'address', 'address', '[address]', 'street', '[street]', 'data[address][street].prop'),
953
954 array(self::LEVEL_1, 'foo.bar', 'address', 'address', 'address', 'street', 'street', 'data.foo.bar'),
955 array(self::LEVEL_1, 'foo.bar', 'address', 'address', 'address', 'street', 'street', 'data.foo.bar.prop'),
956 array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', 'street', 'data.foo[bar]'),
957 array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', 'street', 'data.foo[bar].prop'),
958 array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', 'street', 'data[foo].bar'),
959 array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', 'street', 'data[foo].bar.prop'),
960 array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', 'street', 'data[foo][bar]'),
961 array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', 'street', 'data[foo][bar].prop'),
962
963 array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', 'street', 'data.foo.bar'),
964 array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', 'street', 'data.foo.bar.prop'),
965 array(self::LEVEL_1, 'foo[bar]', 'address', 'address', 'address', 'street', 'street', 'data.foo[bar]'),
966 array(self::LEVEL_1, 'foo[bar]', 'address', 'address', 'address', 'street', 'street', 'data.foo[bar].prop'),
967 array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', 'street', 'data[foo].bar'),
968 array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', 'street', 'data[foo].bar.prop'),
969 array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', 'street', 'data[foo][bar]'),
970 array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', 'street', 'data[foo][bar].prop'),
971
972 array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', 'street', 'data.foo.bar'),
973 array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', 'street', 'data.foo.bar.prop'),
974 array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', 'street', 'data.foo[bar]'),
975 array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', 'street', 'data.foo[bar].prop'),
976 array(self::LEVEL_1, '[foo].bar', 'address', 'address', 'address', 'street', 'street', 'data[foo].bar'),
977 array(self::LEVEL_1, '[foo].bar', 'address', 'address', 'address', 'street', 'street', 'data[foo].bar.prop'),
978 array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', 'street', 'data[foo][bar]'),
979 array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', 'street', 'data[foo][bar].prop'),
980
981 array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', 'street', 'data.foo.bar'),
982 array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', 'street', 'data.foo.bar.prop'),
983 array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', 'street', 'data.foo[bar]'),
984 array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', 'street', 'data.foo[bar].prop'),
985 array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', 'street', 'data[foo].bar'),
986 array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', 'street', 'data[foo].bar.prop'),
987 array(self::LEVEL_1, '[foo][bar]', 'address', 'address', 'address', 'street', 'street', 'data[foo][bar]'),
988 array(self::LEVEL_1, '[foo][bar]', 'address', 'address', 'address', 'street', 'street', 'data[foo][bar].prop'),
989
990 array(self::LEVEL_2, 'foo.bar', 'address', 'address', 'address', 'street', 'street', 'data.foo.bar.street'),
991 array(self::LEVEL_2, 'foo.bar', 'address', 'address', 'address', 'street', 'street', 'data.foo.bar.street.prop'),
992 array(self::LEVEL_1, 'foo.bar', 'address', 'address', 'address', 'street', 'street', 'data.foo.bar[street]'),
993 array(self::LEVEL_1, 'foo.bar', 'address', 'address', 'address', 'street', 'street', 'data.foo.bar[street].prop'),
994 array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', 'street', 'data.foo[bar].street'),
995 array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', 'street', 'data.foo[bar].street.prop'),
996 array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', 'street', 'data.foo[bar][street]'),
997 array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', 'street', 'data.foo[bar][street].prop'),
998 array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', 'street', 'data[foo].bar.street'),
999 array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', 'street', 'data[foo].bar.street.prop'),
1000 array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', 'street', 'data[foo].bar[street]'),
1001 array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', 'street', 'data[foo].bar[street].prop'),
1002 array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', 'street', 'data[foo][bar].street'),
1003 array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', 'street', 'data[foo][bar].street.prop'),
1004 array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', 'street', 'data[foo][bar][street]'),
1005 array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', 'street', 'data[foo][bar][street].prop'),
1006
1007 array(self::LEVEL_1, 'foo.bar', 'address', 'address', 'address', 'street', '[street]', 'data.foo.bar.street'),
1008 array(self::LEVEL_1, 'foo.bar', 'address', 'address', 'address', 'street', '[street]', 'data.foo.bar.street.prop'),
1009 array(self::LEVEL_2, 'foo.bar', 'address', 'address', 'address', 'street', '[street]', 'data.foo.bar[street]'),
1010 array(self::LEVEL_2, 'foo.bar', 'address', 'address', 'address', 'street', '[street]', 'data.foo.bar[street].prop'),
1011 array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', '[street]', 'data.foo[bar].street'),
1012 array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', '[street]', 'data.foo[bar].street.prop'),
1013 array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', '[street]', 'data.foo[bar][street]'),
1014 array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', '[street]', 'data.foo[bar][street].prop'),
1015 array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', '[street]', 'data[foo].bar.street'),
1016 array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', '[street]', 'data[foo].bar.street.prop'),
1017 array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', '[street]', 'data[foo].bar[street]'),
1018 array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', '[street]', 'data[foo].bar[street].prop'),
1019 array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', '[street]', 'data[foo][bar].street'),
1020 array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', '[street]', 'data[foo][bar].street.prop'),
1021 array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', '[street]', 'data[foo][bar][street]'),
1022 array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', '[street]', 'data[foo][bar][street].prop'),
1023
1024 array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', 'street', 'data.foo.bar.street'),
1025 array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', 'street', 'data.foo.bar.street.prop'),
1026 array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', 'street', 'data.foo.bar[street]'),
1027 array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', 'street', 'data.foo.bar[street].prop'),
1028 array(self::LEVEL_2, 'foo[bar]', 'address', 'address', 'address', 'street', 'street', 'data.foo[bar].street'),
1029 array(self::LEVEL_2, 'foo[bar]', 'address', 'address', 'address', 'street', 'street', 'data.foo[bar].street.prop'),
1030 array(self::LEVEL_1, 'foo[bar]', 'address', 'address', 'address', 'street', 'street', 'data.foo[bar][street]'),
1031 array(self::LEVEL_1, 'foo[bar]', 'address', 'address', 'address', 'street', 'street', 'data.foo[bar][street].prop'),
1032 array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', 'street', 'data[foo].bar.street'),
1033 array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', 'street', 'data[foo].bar.street.prop'),
1034 array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', 'street', 'data[foo].bar[street]'),
1035 array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', 'street', 'data[foo].bar[street].prop'),
1036 array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', 'street', 'data[foo][bar].street'),
1037 array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', 'street', 'data[foo][bar].street.prop'),
1038 array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', 'street', 'data[foo][bar][street]'),
1039 array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', 'street', 'data[foo][bar][street].prop'),
1040
1041 array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', '[street]', 'data.foo.bar.street'),
1042 array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', '[street]', 'data.foo.bar.street.prop'),
1043 array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', '[street]', 'data.foo.bar[street]'),
1044 array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', '[street]', 'data.foo.bar[street].prop'),
1045 array(self::LEVEL_1, 'foo[bar]', 'address', 'address', 'address', 'street', '[street]', 'data.foo[bar].street'),
1046 array(self::LEVEL_1, 'foo[bar]', 'address', 'address', 'address', 'street', '[street]', 'data.foo[bar].street.prop'),
1047 array(self::LEVEL_2, 'foo[bar]', 'address', 'address', 'address', 'street', '[street]', 'data.foo[bar][street]'),
1048 array(self::LEVEL_2, 'foo[bar]', 'address', 'address', 'address', 'street', '[street]', 'data.foo[bar][street].prop'),
1049 array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', '[street]', 'data[foo].bar.street'),
1050 array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', '[street]', 'data[foo].bar.street.prop'),
1051 array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', '[street]', 'data[foo].bar[street]'),
1052 array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', '[street]', 'data[foo].bar[street].prop'),
1053 array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', '[street]', 'data[foo][bar].street'),
1054 array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', '[street]', 'data[foo][bar].street.prop'),
1055 array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', '[street]', 'data[foo][bar][street]'),
1056 array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', '[street]', 'data[foo][bar][street].prop'),
1057
1058 array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', 'street', 'data.foo.bar.street'),
1059 array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', 'street', 'data.foo.bar.street.prop'),
1060 array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', 'street', 'data.foo.bar[street]'),
1061 array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', 'street', 'data.foo.bar[street].prop'),
1062 array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', 'street', 'data.foo[bar].street'),
1063 array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', 'street', 'data.foo[bar].street.prop'),
1064 array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', 'street', 'data.foo[bar][street]'),
1065 array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', 'street', 'data.foo[bar][street].prop'),
1066 array(self::LEVEL_2, '[foo].bar', 'address', 'address', 'address', 'street', 'street', 'data[foo].bar.street'),
1067 array(self::LEVEL_2, '[foo].bar', 'address', 'address', 'address', 'street', 'street', 'data[foo].bar.street.prop'),
1068 array(self::LEVEL_1, '[foo].bar', 'address', 'address', 'address', 'street', 'street', 'data[foo].bar[street]'),
1069 array(self::LEVEL_1, '[foo].bar', 'address', 'address', 'address', 'street', 'street', 'data[foo].bar[street].prop'),
1070 array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', 'street', 'data[foo][bar].street'),
1071 array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', 'street', 'data[foo][bar].street.prop'),
1072 array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', 'street', 'data[foo][bar][street]'),
1073 array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', 'street', 'data[foo][bar][street].prop'),
1074
1075 array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', '[street]', 'data.foo.bar.street'),
1076 array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', '[street]', 'data.foo.bar.street.prop'),
1077 array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', '[street]', 'data.foo.bar[street]'),
1078 array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', '[street]', 'data.foo.bar[street].prop'),
1079 array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', '[street]', 'data.foo[bar].street'),
1080 array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', '[street]', 'data.foo[bar].street.prop'),
1081 array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', '[street]', 'data.foo[bar][street]'),
1082 array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', '[street]', 'data.foo[bar][street].prop'),
1083 array(self::LEVEL_1, '[foo].bar', 'address', 'address', 'address', 'street', '[street]', 'data[foo].bar.street'),
1084 array(self::LEVEL_1, '[foo].bar', 'address', 'address', 'address', 'street', '[street]', 'data[foo].bar.street.prop'),
1085 array(self::LEVEL_2, '[foo].bar', 'address', 'address', 'address', 'street', '[street]', 'data[foo].bar[street]'),
1086 array(self::LEVEL_2, '[foo].bar', 'address', 'address', 'address', 'street', '[street]', 'data[foo].bar[street].prop'),
1087 array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', '[street]', 'data[foo][bar].street'),
1088 array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', '[street]', 'data[foo][bar].street.prop'),
1089 array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', '[street]', 'data[foo][bar][street]'),
1090 array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', '[street]', 'data[foo][bar][street].prop'),
1091
1092 array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', 'street', 'data.foo.bar.street'),
1093 array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', 'street', 'data.foo.bar.street.prop'),
1094 array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', 'street', 'data.foo.bar[street]'),
1095 array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', 'street', 'data.foo.bar[street].prop'),
1096 array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', 'street', 'data.foo[bar].street'),
1097 array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', 'street', 'data.foo[bar].street.prop'),
1098 array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', 'street', 'data.foo[bar][street]'),
1099 array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', 'street', 'data.foo[bar][street].prop'),
1100 array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', 'street', 'data[foo].bar.street'),
1101 array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', 'street', 'data[foo].bar.street.prop'),
1102 array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', 'street', 'data[foo].bar[street]'),
1103 array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', 'street', 'data[foo].bar[street].prop'),
1104 array(self::LEVEL_2, '[foo][bar]', 'address', 'address', 'address', 'street', 'street', 'data[foo][bar].street'),
1105 array(self::LEVEL_2, '[foo][bar]', 'address', 'address', 'address', 'street', 'street', 'data[foo][bar].street.prop'),
1106 array(self::LEVEL_1, '[foo][bar]', 'address', 'address', 'address', 'street', 'street', 'data[foo][bar][street]'),
1107 array(self::LEVEL_1, '[foo][bar]', 'address', 'address', 'address', 'street', 'street', 'data[foo][bar][street].prop'),
1108
1109 array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', '[street]', 'data.foo.bar.street'),
1110 array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', '[street]', 'data.foo.bar.street.prop'),
1111 array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', '[street]', 'data.foo.bar[street]'),
1112 array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', '[street]', 'data.foo.bar[street].prop'),
1113 array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', '[street]', 'data.foo[bar].street'),
1114 array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', '[street]', 'data.foo[bar].street.prop'),
1115 array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', '[street]', 'data.foo[bar][street]'),
1116 array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', '[street]', 'data.foo[bar][street].prop'),
1117 array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', '[street]', 'data[foo].bar.street'),
1118 array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', '[street]', 'data[foo].bar.street.prop'),
1119 array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', '[street]', 'data[foo].bar[street]'),
1120 array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', '[street]', 'data[foo].bar[street].prop'),
1121 array(self::LEVEL_1, '[foo][bar]', 'address', 'address', 'address', 'street', '[street]', 'data[foo][bar].street'),
1122 array(self::LEVEL_1, '[foo][bar]', 'address', 'address', 'address', 'street', '[street]', 'data[foo][bar].street.prop'),
1123 array(self::LEVEL_2, '[foo][bar]', 'address', 'address', 'address', 'street', '[street]', 'data[foo][bar][street]'),
1124 array(self::LEVEL_2, '[foo][bar]', 'address', 'address', 'address', 'street', '[street]', 'data[foo][bar][street].prop'),
1125
1126 array(self::LEVEL_2, 'foo', 'address.street', 'address', 'address', 'street', 'street', 'data.foo'),
1127 array(self::LEVEL_2, 'foo', 'address.street', 'address', 'address', 'street', 'street', 'data.foo.prop'),
1128 array(self::LEVEL_2, '[foo]', 'address.street', 'address', 'address', 'street', 'street', 'data[foo]'),
1129 array(self::LEVEL_2, '[foo]', 'address.street', 'address', 'address', 'street', 'street', 'data[foo].prop'),
1130
1131 array(self::LEVEL_2, 'foo', 'address.street', 'address', 'address', 'street', '[street]', 'data.foo'),
1132 array(self::LEVEL_2, 'foo', 'address.street', 'address', 'address', 'street', '[street]', 'data.foo.prop'),
1133 array(self::LEVEL_2, '[foo]', 'address.street', 'address', 'address', 'street', '[street]', 'data[foo]'),
1134 array(self::LEVEL_2, '[foo]', 'address.street', 'address', 'address', 'street', '[street]', 'data[foo].prop'),
1135
1136 array(self::LEVEL_2, 'foo', 'address.street', 'address', '[address]', 'street', 'street', 'data.foo'),
1137 array(self::LEVEL_2, 'foo', 'address.street', 'address', '[address]', 'street', 'street', 'data.foo.prop'),
1138 array(self::LEVEL_2, '[foo]', 'address.street', 'address', '[address]', 'street', 'street', 'data[foo]'),
1139 array(self::LEVEL_2, '[foo]', 'address.street', 'address', '[address]', 'street', 'street', 'data[foo].prop'),
1140
1141 array(self::LEVEL_2, 'foo.bar', 'address.street', 'address', 'address', 'street', 'street', 'data.foo.bar'),
1142 array(self::LEVEL_2, 'foo.bar', 'address.street', 'address', 'address', 'street', 'street', 'data.foo.bar.prop'),
1143 array(self::LEVEL_2, 'foo[bar]', 'address.street', 'address', 'address', 'street', 'street', 'data.foo[bar]'),
1144 array(self::LEVEL_2, 'foo[bar]', 'address.street', 'address', 'address', 'street', 'street', 'data.foo[bar].prop'),
1145 array(self::LEVEL_2, '[foo].bar', 'address.street', 'address', 'address', 'street', 'street', 'data[foo].bar'),
1146 array(self::LEVEL_2, '[foo].bar', 'address.street', 'address', 'address', 'street', 'street', 'data[foo].bar.prop'),
1147 array(self::LEVEL_2, '[foo][bar]', 'address.street', 'address', 'address', 'street', 'street', 'data[foo][bar]'),
1148 array(self::LEVEL_2, '[foo][bar]', 'address.street', 'address', 'address', 'street', 'street', 'data[foo][bar].prop'),
1149
1150 array(self::LEVEL_2, 'foo.bar', 'address.street', 'address', 'address', 'street', '[street]', 'data.foo.bar'),
1151 array(self::LEVEL_2, 'foo.bar', 'address.street', 'address', 'address', 'street', '[street]', 'data.foo.bar.prop'),
1152 array(self::LEVEL_2, 'foo[bar]', 'address.street', 'address', 'address', 'street', '[street]', 'data.foo[bar]'),
1153 array(self::LEVEL_2, 'foo[bar]', 'address.street', 'address', 'address', 'street', '[street]', 'data.foo[bar].prop'),
1154 array(self::LEVEL_2, '[foo].bar', 'address.street', 'address', 'address', 'street', '[street]', 'data[foo].bar'),
1155 array(self::LEVEL_2, '[foo].bar', 'address.street', 'address', 'address', 'street', '[street]', 'data[foo].bar.prop'),
1156 array(self::LEVEL_2, '[foo][bar]', 'address.street', 'address', 'address', 'street', '[street]', 'data[foo][bar]'),
1157 array(self::LEVEL_2, '[foo][bar]', 'address.street', 'address', 'address', 'street', '[street]', 'data[foo][bar].prop'),
1158
1159 array(self::LEVEL_2, 'foo.bar', 'address.street', 'address', '[address]', 'street', 'street', 'data.foo.bar'),
1160 array(self::LEVEL_2, 'foo.bar', 'address.street', 'address', '[address]', 'street', 'street', 'data.foo.bar.prop'),
1161 array(self::LEVEL_2, 'foo[bar]', 'address.street', 'address', '[address]', 'street', 'street', 'data.foo[bar]'),
1162 array(self::LEVEL_2, 'foo[bar]', 'address.street', 'address', '[address]', 'street', 'street', 'data.foo[bar].prop'),
1163 array(self::LEVEL_2, '[foo].bar', 'address.street', 'address', '[address]', 'street', 'street', 'data[foo].bar'),
1164 array(self::LEVEL_2, '[foo].bar', 'address.street', 'address', '[address]', 'street', 'street', 'data[foo].bar.prop'),
1165 array(self::LEVEL_2, '[foo][bar]', 'address.street', 'address', '[address]', 'street', 'street', 'data[foo][bar]'),
1166 array(self::LEVEL_2, '[foo][bar]', 'address.street', 'address', '[address]', 'street', 'street', 'data[foo][bar].prop'),
1167
1168 // Edge cases
1169 array(self::LEVEL_2, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data.foo.street'),
1170 array(self::LEVEL_2, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data.foo.street.prop'),
1171 array(self::LEVEL_1, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data.foo[street]'),
1172 array(self::LEVEL_1, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data.foo[street].prop'),
1173 array(self::LEVEL_0, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data[foo].street'),
1174 array(self::LEVEL_0, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data[foo].street.prop'),
1175 array(self::LEVEL_0, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data[foo][street]'),
1176 array(self::LEVEL_0, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data[foo][street].prop'),
1177
1178 array(self::LEVEL_0, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data.foo.street'),
1179 array(self::LEVEL_0, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data.foo.street.prop'),
1180 array(self::LEVEL_0, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data.foo[street]'),
1181 array(self::LEVEL_0, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data.foo[street].prop'),
1182 array(self::LEVEL_2, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data[foo].street'),
1183 array(self::LEVEL_2, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data[foo].street.prop'),
1184 array(self::LEVEL_1, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data[foo][street]'),
1185 array(self::LEVEL_1, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data[foo][street].prop'),
1186 );
1187 }
1188
1189 /**
1190 * @dataProvider provideCustomDataErrorTests
1191 */
1192 public function testCustomDataErrorMapping($target, $mapFrom, $mapTo, $childName, $childPath, $grandChildName, $grandChildPath, $violationPath)
1193 {
1194 $violation = $this->getConstraintViolation($violationPath);
1195 $parent = $this->getForm('parent', null, null, array($mapFrom => $mapTo));
1196 $child = $this->getForm($childName, $childPath);
1197 $grandChild = $this->getForm($grandChildName, $grandChildPath);
1198
1199 $parent->add($child);
1200 $child->add($grandChild);
1201
1202 // Add a field mapped to the first element of $mapFrom
1203 // to try to distract the algorithm
1204 // Only add it if we expect the error to come up on a different
1205 // level than LEVEL_0, because in this case the error would
1206 // (correctly) be mapped to the distraction field
1207 if ($target !== self::LEVEL_0) {
1208 $mapFromPath = new PropertyPath($mapFrom);
1209 $mapFromPrefix = $mapFromPath->isIndex(0)
1210 ? '['.$mapFromPath->getElement(0).']'
1211 : $mapFromPath->getElement(0);
1212 $distraction = $this->getForm('distraction', $mapFromPrefix);
1213
1214 $parent->add($distraction);
1215 }
1216
1217 $this->mapper->mapViolation($violation, $parent);
1218
1219 if ($target !== self::LEVEL_0) {
1220 $this->assertCount(0, $distraction->getErrors(), 'distraction should not have an error, but has one');
1221 }
1222
1223 if (self::LEVEL_0 === $target) {
1224 $this->assertEquals(array($this->getFormError()), $parent->getErrors(), $parent->getName().' should have an error, but has none');
1225 $this->assertCount(0, $child->getErrors(), $childName.' should not have an error, but has one');
1226 $this->assertCount(0, $grandChild->getErrors(), $grandChildName.' should not have an error, but has one');
1227 } elseif (self::LEVEL_1 === $target) {
1228 $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one');
1229 $this->assertEquals(array($this->getFormError()), $child->getErrors(), $childName.' should have an error, but has none');
1230 $this->assertCount(0, $grandChild->getErrors(), $grandChildName.' should not have an error, but has one');
1231 } else {
1232 $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one');
1233 $this->assertCount(0, $child->getErrors(), $childName.' should not have an error, but has one');
1234 $this->assertEquals(array($this->getFormError()), $grandChild->getErrors(), $grandChildName.' should have an error, but has none');
1235 }
1236 }
1237
1238 public function provideCustomFormErrorTests()
1239 {
1240 // This case is different than the data errors, because here the
1241 // left side of the mapping refers to the property path of the actual
1242 // children. In other words, a child error only works if
1243 // 1) the error actually maps to an existing child and
1244 // 2) the property path of that child (relative to the form providing
1245 // the mapping) matches the left side of the mapping
1246 return array(
1247 // mapping target, map from, map to, child name, its property path, grand child name, its property path, violation path
1248 array(self::LEVEL_1, 'foo', 'address', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[foo].children[street].data'),
1249 array(self::LEVEL_1, 'foo', 'address', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[foo].children[street].data.prop'),
1250 array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[foo].data.street'),
1251 array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[foo].data.street.prop'),
1252 array(self::LEVEL_1, 'foo', 'address', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[foo].data[street]'),
1253 array(self::LEVEL_1, 'foo', 'address', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[foo].data[street].prop'),
1254
1255 array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[address].children[street].data'),
1256 array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[address].children[street].data.prop'),
1257 array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[address].data.street'),
1258 array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[address].data.street.prop'),
1259 array(self::LEVEL_1, 'foo', 'address', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[address].data[street]'),
1260 array(self::LEVEL_1, 'foo', 'address', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[address].data[street].prop'),
1261
1262 // Property path of the erroneous field and mapping must match exactly
1263 array(self::LEVEL_1B, 'foo', 'address', 'foo', '[foo]', 'address', 'address', 'street', 'street', 'children[foo].children[street].data'),
1264 array(self::LEVEL_1B, 'foo', 'address', 'foo', '[foo]', 'address', 'address', 'street', 'street', 'children[foo].children[street].data.prop'),
1265 array(self::LEVEL_1B, 'foo', 'address', 'foo', '[foo]', 'address', 'address', 'street', 'street', 'children[foo].data.street'),
1266 array(self::LEVEL_1B, 'foo', 'address', 'foo', '[foo]', 'address', 'address', 'street', 'street', 'children[foo].data.street.prop'),
1267 array(self::LEVEL_1B, 'foo', 'address', 'foo', '[foo]', 'address', 'address', 'street', 'street', 'children[foo].data[street]'),
1268 array(self::LEVEL_1B, 'foo', 'address', 'foo', '[foo]', 'address', 'address', 'street', 'street', 'children[foo].data[street].prop'),
1269
1270 array(self::LEVEL_1B, '[foo]', 'address', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[foo].children[street].data'),
1271 array(self::LEVEL_1B, '[foo]', 'address', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[foo].children[street].data.prop'),
1272 array(self::LEVEL_1B, '[foo]', 'address', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[foo].data.street'),
1273 array(self::LEVEL_1B, '[foo]', 'address', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[foo].data.street.prop'),
1274 array(self::LEVEL_1B, '[foo]', 'address', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[foo].data[street]'),
1275 array(self::LEVEL_1B, '[foo]', 'address', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[foo].data[street].prop'),
1276
1277 array(self::LEVEL_1, '[foo]', 'address', 'foo', '[foo]', 'address', 'address', 'street', 'street', 'children[foo].children[street].data'),
1278 array(self::LEVEL_1, '[foo]', 'address', 'foo', '[foo]', 'address', 'address', 'street', 'street', 'children[foo].children[street].data.prop'),
1279 array(self::LEVEL_2, '[foo]', 'address', 'foo', '[foo]', 'address', 'address', 'street', 'street', 'children[foo].data.street'),
1280 array(self::LEVEL_2, '[foo]', 'address', 'foo', '[foo]', 'address', 'address', 'street', 'street', 'children[foo].data.street.prop'),
1281 array(self::LEVEL_1, '[foo]', 'address', 'foo', '[foo]', 'address', 'address', 'street', 'street', 'children[foo].data[street]'),
1282 array(self::LEVEL_1, '[foo]', 'address', 'foo', '[foo]', 'address', 'address', 'street', 'street', 'children[foo].data[street].prop'),
1283
1284 array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[foo].children[street].data'),
1285 array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[foo].children[street].data.prop'),
1286 array(self::LEVEL_1, 'foo', 'address', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[foo].data.street'),
1287 array(self::LEVEL_1, 'foo', 'address', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[foo].data.street.prop'),
1288 array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[foo].data[street]'),
1289 array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[foo].data[street].prop'),
1290
1291 array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[address].children[street].data'),
1292 array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[address].children[street].data.prop'),
1293 array(self::LEVEL_1, 'foo', 'address', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[address].data.street'),
1294 array(self::LEVEL_1, 'foo', 'address', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[address].data.street.prop'),
1295 array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[address].data[street]'),
1296 array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[address].data[street].prop'),
1297
1298 array(self::LEVEL_1, 'foo', 'address', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[foo].children[street].data'),
1299 array(self::LEVEL_1, 'foo', 'address', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[foo].children[street].data.prop'),
1300 array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[foo].data.street'),
1301 array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[foo].data.street.prop'),
1302 array(self::LEVEL_1, 'foo', 'address', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[foo].data[street]'),
1303 array(self::LEVEL_1, 'foo', 'address', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[foo].data[street].prop'),
1304
1305 array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[address].children[street].data'),
1306 array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[address].children[street].data.prop'),
1307 array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[address].data.street'),
1308 array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[address].data.street.prop'),
1309 array(self::LEVEL_1, 'foo', 'address', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[address].data[street]'),
1310 array(self::LEVEL_1, 'foo', 'address', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[address].data[street].prop'),
1311
1312 array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[foo].children[street].data'),
1313 array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[foo].children[street].data.prop'),
1314 array(self::LEVEL_1, 'foo', 'address', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[foo].data.street'),
1315 array(self::LEVEL_1, 'foo', 'address', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[foo].data.street.prop'),
1316 array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[foo].data[street]'),
1317 array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[foo].data[street].prop'),
1318
1319 array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[address].children[street].data'),
1320 array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[address].children[street].data.prop'),
1321 array(self::LEVEL_1, 'foo', 'address', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[address].data.street'),
1322 array(self::LEVEL_1, 'foo', 'address', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[address].data.street.prop'),
1323 array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[address].data[street]'),
1324 array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[address].data[street].prop'),
1325
1326 // Map to a nested child
1327 array(self::LEVEL_2, 'foo', 'address.street', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[foo]'),
1328 array(self::LEVEL_2, 'foo', 'address.street', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[foo]'),
1329 array(self::LEVEL_2, 'foo', 'address.street', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[foo]'),
1330 array(self::LEVEL_2, 'foo', 'address.street', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[foo]'),
1331
1332 // Map from a nested child
1333 array(self::LEVEL_1B, 'address.street', 'foo', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[address].children[street]'),
1334 array(self::LEVEL_1B, 'address.street', 'foo', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[address].data.street'),
1335 array(self::LEVEL_1, 'address.street', 'foo', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[address].data[street]'),
1336 array(self::LEVEL_2, 'address.street', 'foo', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[address].children[street]'),
1337 array(self::LEVEL_1B, 'address.street', 'foo', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[address].data.street'),
1338 array(self::LEVEL_2, 'address.street', 'foo', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[address].data[street]'),
1339 array(self::LEVEL_2, 'address.street', 'foo', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[address].children[street]'),
1340 array(self::LEVEL_2, 'address.street', 'foo', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[address].data.street'),
1341 array(self::LEVEL_1, 'address.street', 'foo', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[address].data[street]'),
1342 array(self::LEVEL_2, 'address.street', 'foo', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[address].children[street]'),
1343 array(self::LEVEL_1, 'address.street', 'foo', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[address].data.street'),
1344 array(self::LEVEL_2, 'address.street', 'foo', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[address].data[street]'),
1345
1346 array(self::LEVEL_2, 'address[street]', 'foo', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[address].children[street]'),
1347 array(self::LEVEL_2, 'address[street]', 'foo', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[address].data.street'),
1348 array(self::LEVEL_1B, 'address[street]', 'foo', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[address].data[street]'),
1349 array(self::LEVEL_1B, 'address[street]', 'foo', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[address].children[street]'),
1350 array(self::LEVEL_1, 'address[street]', 'foo', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[address].data.street'),
1351 array(self::LEVEL_1B, 'address[street]', 'foo', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[address].data[street]'),
1352 array(self::LEVEL_2, 'address[street]', 'foo', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[address].children[street]'),
1353 array(self::LEVEL_2, 'address[street]', 'foo', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[address].data.street'),
1354 array(self::LEVEL_1, 'address[street]', 'foo', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[address].data[street]'),
1355 array(self::LEVEL_2, 'address[street]', 'foo', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[address].children[street]'),
1356 array(self::LEVEL_1, 'address[street]', 'foo', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[address].data.street'),
1357 array(self::LEVEL_2, 'address[street]', 'foo', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[address].data[street]'),
1358
1359 array(self::LEVEL_2, '[address].street', 'foo', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[address].children[street]'),
1360 array(self::LEVEL_2, '[address].street', 'foo', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[address].data.street'),
1361 array(self::LEVEL_1, '[address].street', 'foo', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[address].data[street]'),
1362 array(self::LEVEL_2, '[address].street', 'foo', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[address].children[street]'),
1363 array(self::LEVEL_1, '[address].street', 'foo', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[address].data.street'),
1364 array(self::LEVEL_2, '[address].street', 'foo', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[address].data[street]'),
1365 array(self::LEVEL_1B, '[address].street', 'foo', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[address].children[street]'),
1366 array(self::LEVEL_1B, '[address].street', 'foo', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[address].data.street'),
1367 array(self::LEVEL_1, '[address].street', 'foo', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[address].data[street]'),
1368 array(self::LEVEL_2, '[address].street', 'foo', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[address].children[street]'),
1369 array(self::LEVEL_1B, '[address].street', 'foo', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[address].data.street'),
1370 array(self::LEVEL_2, '[address].street', 'foo', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[address].data[street]'),
1371
1372 array(self::LEVEL_2, '[address][street]', 'foo', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[address].children[street]'),
1373 array(self::LEVEL_2, '[address][street]', 'foo', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[address].data.street'),
1374 array(self::LEVEL_1, '[address][street]', 'foo', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[address].data[street]'),
1375 array(self::LEVEL_2, '[address][street]', 'foo', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[address].children[street]'),
1376 array(self::LEVEL_1, '[address][street]', 'foo', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[address].data.street'),
1377 array(self::LEVEL_2, '[address][street]', 'foo', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[address].data[street]'),
1378 array(self::LEVEL_2, '[address][street]', 'foo', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[address].children[street]'),
1379 array(self::LEVEL_2, '[address][street]', 'foo', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[address].data.street'),
1380 array(self::LEVEL_1B, '[address][street]', 'foo', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[address].data[street]'),
1381 array(self::LEVEL_1B, '[address][street]', 'foo', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[address].children[street]'),
1382 array(self::LEVEL_1, '[address][street]', 'foo', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[address].data.street'),
1383 array(self::LEVEL_1B, '[address][street]', 'foo', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[address].data[street]'),
1384 );
1385 }
1386
1387 /**
1388 * @dataProvider provideCustomFormErrorTests
1389 */
1390 public function testCustomFormErrorMapping($target, $mapFrom, $mapTo, $errorName, $errorPath, $childName, $childPath, $grandChildName, $grandChildPath, $violationPath)
1391 {
1392 $violation = $this->getConstraintViolation($violationPath);
1393 $parent = $this->getForm('parent', null, null, array($mapFrom => $mapTo));
1394 $child = $this->getForm($childName, $childPath);
1395 $grandChild = $this->getForm($grandChildName, $grandChildPath);
1396 $errorChild = $this->getForm($errorName, $errorPath);
1397
1398 $parent->add($child);
1399 $parent->add($errorChild);
1400 $child->add($grandChild);
1401
1402 $this->mapper->mapViolation($violation, $parent);
1403
1404 if (self::LEVEL_0 === $target) {
1405 $this->assertCount(0, $errorChild->getErrors(), $errorName.' should not have an error, but has one');
1406 $this->assertEquals(array($this->getFormError()), $parent->getErrors(), $parent->getName().' should have an error, but has none');
1407 $this->assertCount(0, $child->getErrors(), $childName.' should not have an error, but has one');
1408 $this->assertCount(0, $grandChild->getErrors(), $grandChildName.' should not have an error, but has one');
1409 } elseif (self::LEVEL_1 === $target) {
1410 $this->assertCount(0, $errorChild->getErrors(), $errorName.' should not have an error, but has one');
1411 $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one');
1412 $this->assertEquals(array($this->getFormError()), $child->getErrors(), $childName.' should have an error, but has none');
1413 $this->assertCount(0, $grandChild->getErrors(), $grandChildName.' should not have an error, but has one');
1414 } elseif (self::LEVEL_1B === $target) {
1415 $this->assertEquals(array($this->getFormError()), $errorChild->getErrors(), $errorName.' should have an error, but has none');
1416 $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one');
1417 $this->assertCount(0, $child->getErrors(), $childName.' should not have an error, but has one');
1418 $this->assertCount(0, $grandChild->getErrors(), $grandChildName.' should not have an error, but has one');
1419 } else {
1420 $this->assertCount(0, $errorChild->getErrors(), $errorName.' should not have an error, but has one');
1421 $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one');
1422 $this->assertCount(0, $child->getErrors(), $childName.' should not have an error, but has one');
1423 $this->assertEquals(array($this->getFormError()), $grandChild->getErrors(), $grandChildName.' should have an error, but has none');
1424 }
1425 }
1426
1427 public function provideErrorTestsForFormInheritingParentData()
1428 {
1429 return array(
1430 // mapping target, child name, its property path, grand child name, its property path, violation path
1431 array(self::LEVEL_2, 'address', 'address', 'street', 'street', 'children[address].children[street].data'),
1432 array(self::LEVEL_2, 'address', 'address', 'street', 'street', 'children[address].children[street].data.prop'),
1433 array(self::LEVEL_2, 'address', 'address', 'street', 'street', 'children[address].data.street'),
1434 array(self::LEVEL_2, 'address', 'address', 'street', 'street', 'children[address].data.street.prop'),
1435 array(self::LEVEL_1, 'address', 'address', 'street', 'street', 'children[address].data[street]'),
1436 array(self::LEVEL_1, 'address', 'address', 'street', 'street', 'children[address].data[street].prop'),
1437 array(self::LEVEL_2, 'address', 'address', 'street', 'street', 'data.street'),
1438 array(self::LEVEL_2, 'address', 'address', 'street', 'street', 'data.street.prop'),
1439 array(self::LEVEL_0, 'address', 'address', 'street', 'street', 'data[street]'),
1440 array(self::LEVEL_0, 'address', 'address', 'street', 'street', 'data[street].prop'),
1441 array(self::LEVEL_0, 'address', 'address', 'street', 'street', 'data.address.street'),
1442 array(self::LEVEL_0, 'address', 'address', 'street', 'street', 'data.address.street.prop'),
1443 array(self::LEVEL_0, 'address', 'address', 'street', 'street', 'data.address[street]'),
1444 array(self::LEVEL_0, 'address', 'address', 'street', 'street', 'data.address[street].prop'),
1445 array(self::LEVEL_0, 'address', 'address', 'street', 'street', 'data[address].street'),
1446 array(self::LEVEL_0, 'address', 'address', 'street', 'street', 'data[address].street.prop'),
1447 array(self::LEVEL_0, 'address', 'address', 'street', 'street', 'data[address][street]'),
1448 array(self::LEVEL_0, 'address', 'address', 'street', 'street', 'data[address][street].prop'),
1449 );
1450 }
1451
1452 /**
1453 * @dataProvider provideErrorTestsForFormInheritingParentData
1454 */
1455 public function testErrorMappingForFormInheritingParentData($target, $childName, $childPath, $grandChildName, $grandChildPath, $violationPath)
1456 {
1457 $violation = $this->getConstraintViolation($violationPath);
1458 $parent = $this->getForm('parent');
1459 $child = $this->getForm($childName, $childPath, null, array(), true);
1460 $grandChild = $this->getForm($grandChildName, $grandChildPath);
1461
1462 $parent->add($child);
1463 $child->add($grandChild);
1464
1465 $this->mapper->mapViolation($violation, $parent);
1466
1467 if (self::LEVEL_0 === $target) {
1468 $this->assertEquals(array($this->getFormError()), $parent->getErrors(), $parent->getName().' should have an error, but has none');
1469 $this->assertCount(0, $child->getErrors(), $childName.' should not have an error, but has one');
1470 $this->assertCount(0, $grandChild->getErrors(), $grandChildName.' should not have an error, but has one');
1471 } elseif (self::LEVEL_1 === $target) {
1472 $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one');
1473 $this->assertEquals(array($this->getFormError()), $child->getErrors(), $childName.' should have an error, but has none');
1474 $this->assertCount(0, $grandChild->getErrors(), $grandChildName.' should not have an error, but has one');
1475 } else {
1476 $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one');
1477 $this->assertCount(0, $child->getErrors(), $childName.' should not have an error, but has one');
1478 $this->assertEquals(array($this->getFormError()), $grandChild->getErrors(), $grandChildName.' should have an error, but has none');
1479 }
1480 }
1481 }