This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | |||
3 | declare(strict_types=1); |
||
4 | |||
5 | /* |
||
6 | * This file is part of the Sonata Project package. |
||
7 | * |
||
8 | * (c) Thomas Rabaix <[email protected]> |
||
9 | * |
||
10 | * For the full copyright and license information, please view the LICENSE |
||
11 | * file that was distributed with this source code. |
||
12 | */ |
||
13 | |||
14 | namespace Sonata\AdminBundle\Tests\Datagrid; |
||
15 | |||
16 | use PHPUnit\Framework\TestCase; |
||
17 | use Sonata\AdminBundle\Admin\AbstractAdmin; |
||
18 | use Sonata\AdminBundle\Admin\AdminInterface; |
||
19 | use Sonata\AdminBundle\Admin\BaseFieldDescription; |
||
20 | use Sonata\AdminBundle\Admin\FieldDescriptionCollection; |
||
21 | use Sonata\AdminBundle\Admin\FieldDescriptionInterface; |
||
22 | use Sonata\AdminBundle\Builder\ListBuilderInterface; |
||
23 | use Sonata\AdminBundle\Datagrid\ListMapper; |
||
24 | use Sonata\AdminBundle\Model\ModelManagerInterface; |
||
25 | use Sonata\AdminBundle\Translator\NoopLabelTranslatorStrategy; |
||
26 | |||
27 | /** |
||
28 | * @author Andrej Hudec <[email protected]> |
||
29 | */ |
||
30 | class ListMapperTest extends TestCase |
||
31 | { |
||
32 | private const DEFAULT_GRANTED_ROLE = 'ROLE_ADMIN_BAZ'; |
||
33 | |||
34 | /** |
||
35 | * @var ListMapper |
||
36 | */ |
||
37 | private $listMapper; |
||
38 | |||
39 | /** |
||
40 | * @var FieldDescriptionCollection |
||
41 | */ |
||
42 | private $fieldDescriptionCollection; |
||
43 | |||
44 | /** |
||
45 | * @var AdminInterface |
||
46 | */ |
||
47 | private $admin; |
||
48 | |||
49 | protected function setUp(): void |
||
50 | { |
||
51 | $listBuilder = $this->createMock(ListBuilderInterface::class); |
||
52 | $this->fieldDescriptionCollection = new FieldDescriptionCollection(); |
||
53 | $this->admin = $this->createMock(AbstractAdmin::class); |
||
54 | |||
55 | $listBuilder |
||
56 | ->method('addField') |
||
57 | ->willReturnCallback(static function ( |
||
58 | FieldDescriptionCollection $list, |
||
59 | ?string $type, |
||
60 | BaseFieldDescription $fieldDescription, |
||
61 | AbstractAdmin $admin |
||
62 | ): void { |
||
63 | $fieldDescription->setType($type); |
||
64 | $list->add($fieldDescription); |
||
65 | }); |
||
66 | |||
67 | $modelManager = $this->createMock(ModelManagerInterface::class); |
||
68 | |||
69 | $modelManager |
||
70 | ->method('getNewFieldDescriptionInstance') |
||
71 | ->willReturnCallback(function (?string $class, string $name, array $options = []): BaseFieldDescription { |
||
72 | $fieldDescription = $this->getFieldDescriptionMock(); |
||
73 | $fieldDescription->setName($name); |
||
74 | $fieldDescription->setOptions($options); |
||
75 | |||
76 | return $fieldDescription; |
||
77 | }); |
||
78 | |||
79 | $this->admin |
||
80 | ->method('getModelManager') |
||
81 | ->willReturn($modelManager); |
||
82 | |||
83 | $labelTranslatorStrategy = new NoopLabelTranslatorStrategy(); |
||
84 | |||
85 | $this->admin |
||
86 | ->method('getLabelTranslatorStrategy') |
||
87 | ->willReturn($labelTranslatorStrategy); |
||
88 | |||
89 | $this->admin |
||
90 | ->method('isGranted') |
||
91 | ->willReturnCallback(static function (string $name, ?object $object = null): bool { |
||
92 | return self::DEFAULT_GRANTED_ROLE === $name; |
||
93 | }); |
||
94 | |||
95 | $this->listMapper = new ListMapper($listBuilder, $this->fieldDescriptionCollection, $this->admin); |
||
96 | } |
||
97 | |||
98 | public function testFluidInterface(): void |
||
99 | { |
||
100 | $fieldDescription = $this->getFieldDescriptionMock('fooName', 'fooLabel'); |
||
101 | |||
102 | $this->assertSame($this->listMapper, $this->listMapper->add($fieldDescription)); |
||
103 | $this->assertSame($this->listMapper, $this->listMapper->remove('fooName')); |
||
104 | $this->assertSame($this->listMapper, $this->listMapper->reorder([])); |
||
105 | } |
||
106 | |||
107 | public function testGet(): void |
||
108 | { |
||
109 | $this->assertFalse($this->listMapper->has('fooName')); |
||
110 | |||
111 | $fieldDescription = $this->getFieldDescriptionMock('fooName', 'fooLabel'); |
||
112 | |||
113 | $this->listMapper->add($fieldDescription); |
||
114 | $this->assertSame($fieldDescription, $this->listMapper->get('fooName')); |
||
115 | } |
||
116 | |||
117 | public function testAddIdentifier(): void |
||
118 | { |
||
119 | $this->assertFalse($this->listMapper->has('fooName')); |
||
120 | |||
121 | $fieldDescription = $this->getFieldDescriptionMock('fooName', 'fooLabel'); |
||
122 | |||
123 | $this->listMapper->addIdentifier($fieldDescription); |
||
124 | $this->assertTrue($this->listMapper->has('fooName')); |
||
125 | |||
126 | $fieldDescription = $this->listMapper->get('fooName'); |
||
127 | $this->assertTrue($fieldDescription->getOption('identifier')); |
||
128 | } |
||
129 | |||
130 | public function testAddOptionIdentifier(): void |
||
131 | { |
||
132 | $this->assertFalse($this->listMapper->has('fooName')); |
||
133 | $this->assertFalse($this->listMapper->has('barName')); |
||
134 | $this->assertFalse($this->listMapper->has('bazName')); |
||
135 | |||
136 | $this->listMapper->add('barName'); |
||
137 | $this->assertNull($this->listMapper->get('barName')->getOption('identifier')); |
||
138 | $this->listMapper->add('fooName', null, ['identifier' => true]); |
||
139 | $this->assertTrue($this->listMapper->has('fooName')); |
||
140 | $this->assertTrue($this->listMapper->get('fooName')->getOption('identifier')); |
||
141 | $this->listMapper->add('bazName', null, ['identifier' => false]); |
||
142 | $this->assertTrue($this->listMapper->has('bazName')); |
||
143 | $this->assertFalse($this->listMapper->get('bazName')->getOption('identifier')); |
||
144 | } |
||
145 | |||
146 | /** |
||
147 | * @dataProvider getWrongIdentifierOptions |
||
148 | */ |
||
149 | public function testAddOptionIdentifierWithWrongValue(bool $expected, $value): void |
||
150 | { |
||
151 | $this->assertFalse($this->listMapper->has('fooName')); |
||
152 | |||
153 | $this->expectException(\InvalidArgumentException::class); |
||
154 | $this->expectExceptionMessageMatches('/^Value for "identifier" option must be boolean, .+ given.$/'); |
||
155 | |||
156 | $this->listMapper->add('fooName', null, ['identifier' => $value]); |
||
157 | } |
||
158 | |||
159 | public function getWrongIdentifierOptions(): iterable |
||
160 | { |
||
161 | return [ |
||
162 | [true, 1], |
||
163 | [true, 'string'], |
||
164 | [true, new \stdClass()], |
||
165 | [true, [null]], |
||
166 | [false, 0], |
||
167 | [false, null], |
||
168 | [false, ''], |
||
169 | [false, '0'], |
||
170 | [false, []], |
||
171 | ]; |
||
172 | } |
||
173 | |||
174 | public function testAdd(): void |
||
175 | { |
||
176 | $this->listMapper->add('fooName'); |
||
177 | $this->listMapper->add('fooNameLabelBar', null, ['label' => 'Foo Bar']); |
||
178 | $this->listMapper->add('fooNameLabelEmpty', null, ['label' => '']); |
||
179 | |||
180 | $this->assertTrue($this->listMapper->has('fooName')); |
||
181 | |||
182 | $fieldDescription = $this->listMapper->get('fooName'); |
||
183 | $fieldLabelBar = $this->listMapper->get('fooNameLabelBar'); |
||
184 | $fieldLabelFalse = $this->listMapper->get('fooNameLabelEmpty'); |
||
185 | |||
186 | $this->assertInstanceOf(FieldDescriptionInterface::class, $fieldDescription); |
||
187 | $this->assertSame('fooName', $fieldDescription->getName()); |
||
188 | $this->assertSame('fooName', $fieldDescription->getOption('label')); |
||
189 | $this->assertSame('Foo Bar', $fieldLabelBar->getOption('label')); |
||
190 | $this->assertEmpty($fieldLabelFalse->getOption('label')); |
||
191 | } |
||
192 | |||
193 | public function testAddViewInlineAction(): void |
||
194 | { |
||
195 | $this->assertFalse($this->listMapper->has('_action')); |
||
196 | $this->listMapper->add('_action', 'actions', ['actions' => ['show' => []]]); |
||
197 | |||
198 | $this->assertTrue($this->listMapper->has('_action')); |
||
199 | |||
200 | $fieldDescription = $this->listMapper->get('_action'); |
||
201 | |||
202 | $this->assertInstanceOf(FieldDescriptionInterface::class, $fieldDescription); |
||
203 | $this->assertSame('_action', $fieldDescription->getName()); |
||
204 | $this->assertCount(1, $fieldDescription->getOption('actions')); |
||
205 | $this->assertSame(['show' => []], $fieldDescription->getOption('actions')); |
||
206 | } |
||
207 | |||
208 | public function testAddRemove(): void |
||
209 | { |
||
210 | $this->assertFalse($this->listMapper->has('fooName')); |
||
211 | |||
212 | $fieldDescription = $this->getFieldDescriptionMock('fooName', 'fooLabel'); |
||
213 | |||
214 | $this->listMapper->add($fieldDescription); |
||
215 | $this->assertTrue($this->listMapper->has('fooName')); |
||
216 | |||
217 | $this->listMapper->remove('fooName'); |
||
218 | $this->assertFalse($this->listMapper->has('fooName')); |
||
219 | } |
||
220 | |||
221 | public function testAddDuplicateNameException(): void |
||
222 | { |
||
223 | $tmpNames = []; |
||
224 | $this->admin |
||
0 ignored issues
–
show
|
|||
225 | ->method('hasListFieldDescription') |
||
226 | ->willReturnCallback(static function (string $name) use (&$tmpNames): bool { |
||
227 | if (isset($tmpNames[$name])) { |
||
228 | return true; |
||
229 | } |
||
230 | $tmpNames[$name] = $name; |
||
231 | |||
232 | return false; |
||
233 | }); |
||
234 | |||
235 | $this->expectException(\LogicException::class); |
||
236 | $this->expectExceptionMessage('Duplicate field name "fooName" in list mapper. Names should be unique.'); |
||
237 | |||
238 | $this->listMapper->add('fooName'); |
||
239 | $this->listMapper->add('fooName'); |
||
240 | } |
||
241 | |||
242 | public function testAddWrongTypeException(): void |
||
243 | { |
||
244 | $this->expectException(\TypeError::class); |
||
245 | $this->expectExceptionMessage('Unknown field name in list mapper. Field name should be either of FieldDescriptionInterface interface or string.'); |
||
246 | |||
247 | $this->listMapper->add(12345); |
||
248 | } |
||
249 | |||
250 | public function testAutoAddVirtualOption(): void |
||
251 | { |
||
252 | foreach (['actions', 'batch', 'select'] as $type) { |
||
253 | $this->listMapper->add(sprintf('_%s', $type), $type); |
||
254 | } |
||
255 | |||
256 | foreach ($this->fieldDescriptionCollection->getElements() as $field) { |
||
257 | $this->assertTrue( |
||
258 | $field->isVirtual(), |
||
259 | sprintf('Failed asserting that FieldDescription with type "%s" is tagged with virtual flag.', $field->getType()) |
||
260 | ); |
||
261 | } |
||
262 | } |
||
263 | |||
264 | public function testAutoSortOnAssociatedProperty(): void |
||
265 | { |
||
266 | $this->listMapper->add('fooName'); |
||
267 | $this->listMapper->add( |
||
268 | 'fooNameAutoSort', |
||
269 | null, |
||
270 | [ |
||
271 | 'associated_property' => 'fooAssociatedProperty', |
||
272 | ] |
||
273 | ); |
||
274 | $this->listMapper->add( |
||
275 | 'fooNameManualSort', |
||
276 | null, |
||
277 | [ |
||
278 | 'associated_property' => 'fooAssociatedProperty', |
||
279 | 'sortable' => false, |
||
280 | 'sort_parent_association_mappings' => 'fooSortParentAssociationMapping', |
||
281 | 'sort_field_mapping' => 'fooSortFieldMapping', |
||
282 | ] |
||
283 | ); |
||
284 | |||
285 | $field = $this->listMapper->get('fooName'); |
||
286 | $fieldAutoSort = $this->listMapper->get('fooNameAutoSort'); |
||
287 | $fieldManualSort = $this->listMapper->get('fooNameManualSort'); |
||
288 | |||
289 | $this->assertNull($field->getOption('associated_property')); |
||
290 | $this->assertNull($field->getOption('sortable')); |
||
291 | $this->assertNull($field->getOption('sort_parent_association_mappings')); |
||
292 | $this->assertNull($field->getOption('sort_field_mapping')); |
||
293 | |||
294 | $this->assertSame('fooAssociatedProperty', $fieldAutoSort->getOption('associated_property')); |
||
295 | $this->assertTrue($fieldAutoSort->getOption('sortable')); |
||
296 | $this->assertSame([['fieldName' => $fieldAutoSort->getName()]], $fieldAutoSort->getOption('sort_parent_association_mappings')); |
||
297 | $this->assertSame(['fieldName' => $fieldAutoSort->getOption('associated_property')], $fieldAutoSort->getOption('sort_field_mapping')); |
||
298 | |||
299 | $this->assertSame('fooAssociatedProperty', $fieldManualSort->getOption('associated_property')); |
||
300 | $this->assertFalse($fieldManualSort->getOption('sortable')); |
||
301 | $this->assertSame('fooSortParentAssociationMapping', $fieldManualSort->getOption('sort_parent_association_mappings')); |
||
302 | $this->assertSame('fooSortFieldMapping', $fieldManualSort->getOption('sort_field_mapping')); |
||
303 | } |
||
304 | |||
305 | public function testKeys(): void |
||
306 | { |
||
307 | $fieldDescription1 = $this->getFieldDescriptionMock('fooName1', 'fooLabel1'); |
||
308 | $fieldDescription2 = $this->getFieldDescriptionMock('fooName2', 'fooLabel2'); |
||
309 | |||
310 | $this->listMapper->add($fieldDescription1); |
||
311 | $this->listMapper->add($fieldDescription2); |
||
312 | |||
313 | $this->assertSame(['fooName1', 'fooName2'], $this->listMapper->keys()); |
||
314 | } |
||
315 | |||
316 | public function testReorder(): void |
||
317 | { |
||
318 | $fieldDescription1 = $this->getFieldDescriptionMock('fooName1', 'fooLabel1'); |
||
319 | $fieldDescription2 = $this->getFieldDescriptionMock('fooName2', 'fooLabel2'); |
||
320 | $fieldDescription3 = $this->getFieldDescriptionMock('fooName3', 'fooLabel3'); |
||
321 | $fieldDescription4 = $this->getFieldDescriptionMock('fooName4', 'fooLabel4'); |
||
322 | |||
323 | $this->listMapper->add($fieldDescription1); |
||
324 | $this->listMapper->add($fieldDescription2); |
||
325 | $this->listMapper->add($fieldDescription3); |
||
326 | $this->listMapper->add($fieldDescription4); |
||
327 | |||
328 | $this->assertSame([ |
||
329 | 'fooName1' => $fieldDescription1, |
||
330 | 'fooName2' => $fieldDescription2, |
||
331 | 'fooName3' => $fieldDescription3, |
||
332 | 'fooName4' => $fieldDescription4, |
||
333 | ], $this->fieldDescriptionCollection->getElements()); |
||
334 | |||
335 | $this->listMapper->reorder(['fooName3', 'fooName2', 'fooName1', 'fooName4']); |
||
336 | |||
337 | // print_r is used to compare order of items in associative arrays |
||
338 | $this->assertSame(print_r([ |
||
339 | 'fooName3' => $fieldDescription3, |
||
340 | 'fooName2' => $fieldDescription2, |
||
341 | 'fooName1' => $fieldDescription1, |
||
342 | 'fooName4' => $fieldDescription4, |
||
343 | ], true), print_r($this->fieldDescriptionCollection->getElements(), true)); |
||
344 | } |
||
345 | |||
346 | public function testAddOptionRole(): void |
||
347 | { |
||
348 | $this->listMapper->add('bar', 'bar'); |
||
349 | |||
350 | $this->assertTrue($this->listMapper->has('bar')); |
||
351 | |||
352 | $this->listMapper->add('quux', 'bar', ['role' => 'ROLE_QUX']); |
||
353 | |||
354 | $this->assertTrue($this->listMapper->has('bar')); |
||
355 | $this->assertFalse($this->listMapper->has('quux')); |
||
356 | |||
357 | $this->listMapper |
||
358 | ->add('foobar', 'bar', ['role' => self::DEFAULT_GRANTED_ROLE]) |
||
359 | ->add('foo', 'bar', ['role' => 'ROLE_QUX']) |
||
360 | ->add('baz', 'bar'); |
||
361 | |||
362 | $this->assertTrue($this->listMapper->has('foobar')); |
||
363 | $this->assertFalse($this->listMapper->has('foo')); |
||
364 | $this->assertTrue($this->listMapper->has('baz')); |
||
365 | } |
||
366 | |||
367 | public function testTypeGuessActionField(): void |
||
368 | { |
||
369 | $this->listMapper->add('_action', null); |
||
370 | |||
371 | $field = $this->fieldDescriptionCollection->get('_action'); |
||
372 | |||
373 | $this->assertTrue( |
||
374 | $field->isVirtual(), |
||
375 | 'Failed asserting that FieldDescription with name "'.$field->getName().'" is tagged with virtual flag.' |
||
376 | ); |
||
377 | } |
||
378 | |||
379 | private function getFieldDescriptionMock(?string $name = null, ?string $label = null): BaseFieldDescription |
||
380 | { |
||
381 | $fieldDescription = $this->getMockForAbstractClass(BaseFieldDescription::class); |
||
382 | |||
383 | if (null !== $name) { |
||
384 | $fieldDescription->setName($name); |
||
385 | } |
||
386 | |||
387 | if (null !== $label) { |
||
388 | $fieldDescription->setOption('label', $label); |
||
389 | } |
||
390 | |||
391 | return $fieldDescription; |
||
392 | } |
||
393 | } |
||
394 |
This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.
This is most likely a typographical error or the method has been renamed.