Completed
Push — master ( 4e1c5d...6050c4 )
by Grégoire
22:25 queued 19:06
created

AdminTest::testGetBaseRoutePatternWithChildAdmin()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 8
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 2
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\Admin;
15
16
use Doctrine\Common\Collections\Collection;
17
use Knp\Menu\FactoryInterface;
18
use Knp\Menu\ItemInterface;
19
use PHPUnit\Framework\TestCase;
20
use Sonata\AdminBundle\Admin\AbstractAdmin;
21
use Sonata\AdminBundle\Admin\AbstractAdminExtension;
22
use Sonata\AdminBundle\Admin\AdminExtensionInterface;
23
use Sonata\AdminBundle\Admin\AdminInterface;
24
use Sonata\AdminBundle\Admin\FieldDescriptionInterface;
25
use Sonata\AdminBundle\Admin\Pool;
26
use Sonata\AdminBundle\Builder\DatagridBuilderInterface;
27
use Sonata\AdminBundle\Builder\FormContractorInterface;
28
use Sonata\AdminBundle\Builder\ListBuilderInterface;
29
use Sonata\AdminBundle\Builder\RouteBuilderInterface;
30
use Sonata\AdminBundle\Builder\ShowBuilderInterface;
31
use Sonata\AdminBundle\Datagrid\DatagridInterface;
32
use Sonata\AdminBundle\Datagrid\PagerInterface;
33
use Sonata\AdminBundle\Model\AuditManagerInterface;
34
use Sonata\AdminBundle\Model\ModelManagerInterface;
35
use Sonata\AdminBundle\Route\DefaultRouteGenerator;
36
use Sonata\AdminBundle\Route\PathInfoBuilder;
37
use Sonata\AdminBundle\Route\RouteGeneratorInterface;
38
use Sonata\AdminBundle\Route\RoutesCache;
39
use Sonata\AdminBundle\Security\Handler\AclSecurityHandlerInterface;
40
use Sonata\AdminBundle\Security\Handler\SecurityHandlerInterface;
41
use Sonata\AdminBundle\Templating\MutableTemplateRegistryInterface;
42
use Sonata\AdminBundle\Tests\Fixtures\Admin\CommentAdmin;
43
use Sonata\AdminBundle\Tests\Fixtures\Admin\CommentVoteAdmin;
44
use Sonata\AdminBundle\Tests\Fixtures\Admin\CommentWithCustomRouteAdmin;
45
use Sonata\AdminBundle\Tests\Fixtures\Admin\FieldDescription;
46
use Sonata\AdminBundle\Tests\Fixtures\Admin\FilteredAdmin;
47
use Sonata\AdminBundle\Tests\Fixtures\Admin\ModelAdmin;
48
use Sonata\AdminBundle\Tests\Fixtures\Admin\PostAdmin;
49
use Sonata\AdminBundle\Tests\Fixtures\Admin\PostWithCustomRouteAdmin;
50
use Sonata\AdminBundle\Tests\Fixtures\Admin\TagAdmin;
51
use Sonata\AdminBundle\Tests\Fixtures\Bundle\Entity\BlogPost;
52
use Sonata\AdminBundle\Tests\Fixtures\Bundle\Entity\Comment;
53
use Sonata\AdminBundle\Tests\Fixtures\Bundle\Entity\Post;
54
use Sonata\AdminBundle\Tests\Fixtures\Bundle\Entity\Tag;
55
use Sonata\AdminBundle\Tests\Fixtures\Entity\FooToString;
56
use Sonata\AdminBundle\Tests\Fixtures\Entity\FooToStringNull;
57
use Sonata\AdminBundle\Translator\LabelTranslatorStrategyInterface;
58
use Sonata\Doctrine\Adapter\AdapterInterface;
59
use Symfony\Component\DependencyInjection\Container;
60
use Symfony\Component\Filesystem\Filesystem;
61
use Symfony\Component\Form\FormBuilder;
62
use Symfony\Component\Form\FormBuilderInterface;
63
use Symfony\Component\Form\FormEvent;
64
use Symfony\Component\Form\FormEvents;
65
use Symfony\Component\HttpFoundation\ParameterBag;
66
use Symfony\Component\HttpFoundation\Request;
67
use Symfony\Component\PropertyAccess\PropertyAccess;
68
use Symfony\Component\Routing\RouterInterface;
69
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
70
use Symfony\Component\Translation\TranslatorInterface;
71
use Symfony\Component\Validator\Mapping\MemberMetadata;
72
use Symfony\Component\Validator\Validator\ValidatorInterface;
73
74
class AdminTest extends TestCase
75
{
76
    protected $cacheTempFolder;
77
78
    public function setUp(): void
79
    {
80
        $this->cacheTempFolder = sys_get_temp_dir().'/sonata_test_route';
81
        $filesystem = new Filesystem();
82
        $filesystem->remove($this->cacheTempFolder);
83
    }
84
85
    /**
86
     * @covers \Sonata\AdminBundle\Admin\AbstractAdmin::__construct
87
     */
88
    public function testConstructor(): void
89
    {
90
        $class = 'Application\Sonata\NewsBundle\Entity\Post';
91
        $baseControllerName = 'SonataNewsBundle:PostAdmin';
92
93
        $admin = new PostAdmin('sonata.post.admin.post', $class, $baseControllerName);
94
        $this->assertInstanceOf(AbstractAdmin::class, $admin);
95
        $this->assertSame($class, $admin->getClass());
96
        $this->assertSame($baseControllerName, $admin->getBaseControllerName());
97
    }
98
99
    public function testGetClass(): void
100
    {
101
        $class = Post::class;
102
        $baseControllerName = 'SonataNewsBundle:PostAdmin';
103
104
        $admin = new PostAdmin('sonata.post.admin.post', $class, $baseControllerName);
105
106
        $admin->setModelManager($this->getMockForAbstractClass(ModelManagerInterface::class));
107
108
        $admin->setSubject(new BlogPost());
109
        $this->assertSame(BlogPost::class, $admin->getClass());
110
111
        $admin->setSubClasses(['foo']);
112
        $this->assertSame(BlogPost::class, $admin->getClass());
113
114
        $admin->setSubject(null);
115
        $admin->setSubClasses([]);
116
        $this->assertSame($class, $admin->getClass());
117
118
        $admin->setSubClasses(['foo' => 'bar']);
119
        $admin->setRequest(new Request(['subclass' => 'foo']));
120
        $this->assertSame('bar', $admin->getClass());
121
    }
122
123
    public function testGetClassException(): void
124
    {
125
        $this->expectException(\RuntimeException::class);
126
        $this->expectExceptionMessage('Feature not implemented: an embedded admin cannot have subclass');
127
128
        $class = 'Application\Sonata\NewsBundle\Entity\Post';
129
        $baseControllerName = 'SonataNewsBundle:PostAdmin';
130
131
        $admin = new PostAdmin('sonata.post.admin.post', $class, $baseControllerName);
132
        $admin->setParentFieldDescription(new FieldDescription());
133
        $admin->setSubClasses(['foo' => 'bar']);
134
        $admin->setRequest(new Request(['subclass' => 'foo']));
135
        $admin->getClass();
136
    }
137
138
    public function testCheckAccessThrowsExceptionOnMadeUpAction(): void
139
    {
140
        $admin = new PostAdmin(
141
            'sonata.post.admin.post',
142
            'Application\Sonata\NewsBundle\Entity\Post',
143
            'SonataNewsBundle:PostAdmin'
144
        );
145
        $this->expectException(
146
            \InvalidArgumentException::class
147
        );
148
        $this->expectExceptionMessage(
149
            'Action "made-up" could not be found'
150
        );
151
        $admin->checkAccess('made-up');
152
    }
153
154
    public function testCheckAccessThrowsAccessDeniedException(): void
155
    {
156
        $admin = new PostAdmin(
157
            'sonata.post.admin.post',
158
            'Application\Sonata\NewsBundle\Entity\Post',
159
            'SonataNewsBundle:PostAdmin'
160
        );
161
        $securityHandler = $this->prophesize(SecurityHandlerInterface::class);
162
        $securityHandler->isGranted($admin, 'CUSTOM_ROLE', $admin)->willReturn(true);
163
        $securityHandler->isGranted($admin, 'EXTRA_CUSTOM_ROLE', $admin)->willReturn(false);
164
        $customExtension = $this->prophesize(AbstractAdminExtension::class);
165
        $customExtension->getAccessMapping($admin)->willReturn(
166
            ['custom_action' => ['CUSTOM_ROLE', 'EXTRA_CUSTOM_ROLE']]
167
        );
168
        $admin->addExtension($customExtension->reveal());
169
        $admin->setSecurityHandler($securityHandler->reveal());
170
        $this->expectException(
171
            AccessDeniedException::class
172
        );
173
        $this->expectExceptionMessage(
174
            'Access Denied to the action custom_action and role EXTRA_CUSTOM_ROLE'
175
        );
176
        $admin->checkAccess('custom_action');
177
    }
178
179
    public function testHasAccessOnMadeUpAction(): void
180
    {
181
        $admin = new PostAdmin(
182
            'sonata.post.admin.post',
183
            'Application\Sonata\NewsBundle\Entity\Post',
184
            'SonataNewsBundle:PostAdmin'
185
        );
186
187
        $this->assertFalse($admin->hasAccess('made-up'));
188
    }
189
190
    public function testHasAccess(): void
191
    {
192
        $admin = new PostAdmin(
193
            'sonata.post.admin.post',
194
            'Application\Sonata\NewsBundle\Entity\Post',
195
            'SonataNewsBundle:PostAdmin'
196
        );
197
        $securityHandler = $this->prophesize(SecurityHandlerInterface::class);
198
        $securityHandler->isGranted($admin, 'CUSTOM_ROLE', $admin)->willReturn(true);
199
        $securityHandler->isGranted($admin, 'EXTRA_CUSTOM_ROLE', $admin)->willReturn(false);
200
        $customExtension = $this->prophesize(AbstractAdminExtension::class);
201
        $customExtension->getAccessMapping($admin)->willReturn(
202
            ['custom_action' => ['CUSTOM_ROLE', 'EXTRA_CUSTOM_ROLE']]
203
        );
204
        $admin->addExtension($customExtension->reveal());
205
        $admin->setSecurityHandler($securityHandler->reveal());
206
207
        $this->assertFalse($admin->hasAccess('custom_action'));
208
    }
209
210
    public function testHasAccessAllowsAccess(): void
211
    {
212
        $admin = new PostAdmin(
213
            'sonata.post.admin.post',
214
            'Application\Sonata\NewsBundle\Entity\Post',
215
            'SonataNewsBundle:PostAdmin'
216
        );
217
        $securityHandler = $this->prophesize(SecurityHandlerInterface::class);
218
        $securityHandler->isGranted($admin, 'CUSTOM_ROLE', $admin)->willReturn(true);
219
        $securityHandler->isGranted($admin, 'EXTRA_CUSTOM_ROLE', $admin)->willReturn(true);
220
        $customExtension = $this->prophesize(AbstractAdminExtension::class);
221
        $customExtension->getAccessMapping($admin)->willReturn(
222
            ['custom_action' => ['CUSTOM_ROLE', 'EXTRA_CUSTOM_ROLE']]
223
        );
224
        $admin->addExtension($customExtension->reveal());
225
        $admin->setSecurityHandler($securityHandler->reveal());
226
227
        $this->assertTrue($admin->hasAccess('custom_action'));
228
    }
229
230
    public function testHasAccessAllowsAccessEditAction(): void
231
    {
232
        $admin = new PostAdmin(
233
            'sonata.post.admin.post',
234
            'Application\Sonata\NewsBundle\Entity\Post',
235
            'SonataNewsBundle:PostAdmin'
236
        );
237
        $securityHandler = $this->prophesize(SecurityHandlerInterface::class);
238
        $securityHandler->isGranted($admin, 'EDIT_ROLE', $admin)->willReturn(true);
239
        $customExtension = $this->prophesize(AbstractAdminExtension::class);
240
        $customExtension->getAccessMapping($admin)->willReturn(
241
            ['edit_action' => ['EDIT_ROLE']]
242
        );
243
        $admin->addExtension($customExtension->reveal());
244
        $admin->setSecurityHandler($securityHandler->reveal());
245
246
        $this->assertTrue($admin->hasAccess('edit_action'));
247
    }
248
249
    /**
250
     * @covers \Sonata\AdminBundle\Admin\AbstractAdmin::hasChild
251
     * @covers \Sonata\AdminBundle\Admin\AbstractAdmin::addChild
252
     * @covers \Sonata\AdminBundle\Admin\AbstractAdmin::getChild
253
     * @covers \Sonata\AdminBundle\Admin\AbstractAdmin::isChild
254
     * @covers \Sonata\AdminBundle\Admin\AbstractAdmin::hasChildren
255
     * @covers \Sonata\AdminBundle\Admin\AbstractAdmin::getChildren
256
     */
257
    public function testChildren(): void
258
    {
259
        $postAdmin = new PostAdmin('sonata.post.admin.post', 'Application\Sonata\NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
260
        $this->assertFalse($postAdmin->hasChildren());
261
        $this->assertFalse($postAdmin->hasChild('comment'));
262
263
        $commentAdmin = new CommentAdmin('sonata.post.admin.comment', 'Application\Sonata\NewsBundle\Entity\Comment', 'SonataNewsBundle:CommentAdmin');
264
        $postAdmin->addChild($commentAdmin, 'post');
265
266
        $this->assertTrue($postAdmin->hasChildren());
267
        $this->assertTrue($postAdmin->hasChild('sonata.post.admin.comment'));
268
269
        $this->assertSame('sonata.post.admin.comment', $postAdmin->getChild('sonata.post.admin.comment')->getCode());
270
        $this->assertSame('sonata.post.admin.post|sonata.post.admin.comment', $postAdmin->getChild('sonata.post.admin.comment')->getBaseCodeRoute());
271
        $this->assertSame($postAdmin, $postAdmin->getChild('sonata.post.admin.comment')->getParent());
272
        $this->assertSame('post', $commentAdmin->getParentAssociationMapping());
273
274
        $this->assertFalse($postAdmin->isChild());
275
        $this->assertTrue($commentAdmin->isChild());
276
277
        $this->assertSame(['sonata.post.admin.comment' => $commentAdmin], $postAdmin->getChildren());
278
    }
279
280
    /**
281
     * @covers \Sonata\AdminBundle\Admin\AbstractAdmin::configure
282
     */
283
    public function testConfigure(): void
284
    {
285
        $admin = new PostAdmin('sonata.post.admin.post', 'Application\Sonata\NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
286
        $this->assertNotNull($admin->getUniqid());
287
288
        $admin->initialize();
289
        $this->assertNotNull($admin->getUniqid());
290
        $this->assertSame('Post', $admin->getClassnameLabel());
291
292
        $admin = new CommentAdmin('sonata.post.admin.comment', 'Application\Sonata\NewsBundle\Entity\Comment', 'SonataNewsBundle:CommentAdmin');
293
        $admin->setClassnameLabel('postcomment');
294
295
        $admin->initialize();
296
        $this->assertSame('postcomment', $admin->getClassnameLabel());
297
    }
298
299
    public function testConfigureWithValidParentAssociationMapping(): void
300
    {
301
        $admin = new PostAdmin('sonata.post.admin.post', 'Application\Sonata\NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
302
        $admin->setParentAssociationMapping('Category');
303
304
        $admin->initialize();
305
        $this->assertSame('Category', $admin->getParentAssociationMapping());
306
    }
307
308
    public function provideGetBaseRoutePattern()
309
    {
310
        return [
311
            [
312
                'Application\Sonata\NewsBundle\Entity\Post',
313
                '/sonata/news/post',
314
            ],
315
            [
316
                'Application\Sonata\NewsBundle\Document\Post',
317
                '/sonata/news/post',
318
            ],
319
            [
320
                'MyApplication\MyBundle\Entity\Post',
321
                '/myapplication/my/post',
322
            ],
323
            [
324
                'MyApplication\MyBundle\Entity\Post\Category',
325
                '/myapplication/my/post-category',
326
            ],
327
            [
328
                'MyApplication\MyBundle\Entity\Product\Category',
329
                '/myapplication/my/product-category',
330
            ],
331
            [
332
                'MyApplication\MyBundle\Entity\Other\Product\Category',
333
                '/myapplication/my/other-product-category',
334
            ],
335
            [
336
                'Symfony\Cmf\Bundle\FooBundle\Document\Menu',
337
                '/cmf/foo/menu',
338
            ],
339
            [
340
                'Symfony\Cmf\Bundle\FooBundle\Doctrine\Phpcr\Menu',
341
                '/cmf/foo/menu',
342
            ],
343
            [
344
                'Symfony\Bundle\BarBarBundle\Doctrine\Phpcr\Menu',
345
                '/symfony/barbar/menu',
346
            ],
347
            [
348
                'Symfony\Bundle\BarBarBundle\Doctrine\Phpcr\Menu\Item',
349
                '/symfony/barbar/menu-item',
350
            ],
351
            [
352
                'Symfony\Cmf\Bundle\FooBundle\Doctrine\Orm\Menu',
353
                '/cmf/foo/menu',
354
            ],
355
            [
356
                'Symfony\Cmf\Bundle\FooBundle\Doctrine\MongoDB\Menu',
357
                '/cmf/foo/menu',
358
            ],
359
            [
360
                'Symfony\Cmf\Bundle\FooBundle\Doctrine\CouchDB\Menu',
361
                '/cmf/foo/menu',
362
            ],
363
            [
364
                'AppBundle\Entity\User',
365
                '/app/user',
366
            ],
367
            [
368
                'App\Entity\User',
369
                '/app/user',
370
            ],
371
        ];
372
    }
373
374
    /**
375
     * @dataProvider provideGetBaseRoutePattern
376
     */
377
    public function testGetBaseRoutePattern(string $objFqn, string $expected): void
378
    {
379
        $admin = new PostAdmin('sonata.post.admin.post', $objFqn, 'SonataNewsBundle:PostAdmin');
380
        $this->assertSame($expected, $admin->getBaseRoutePattern());
381
    }
382
383
    /**
384
     * @dataProvider provideGetBaseRoutePattern
385
     */
386
    public function testGetBaseRoutePatternWithChildAdmin(string $objFqn, string $expected): void
387
    {
388
        $postAdmin = new PostAdmin('sonata.post.admin.post', $objFqn, 'SonataNewsBundle:PostAdmin');
389
        $commentAdmin = new CommentAdmin('sonata.post.admin.comment', 'Application\Sonata\NewsBundle\Entity\Comment', 'SonataNewsBundle:CommentAdmin');
390
        $commentAdmin->setParent($postAdmin);
391
392
        $this->assertSame($expected.'/{id}/comment', $commentAdmin->getBaseRoutePattern());
393
    }
394
395
    /**
396
     * @dataProvider provideGetBaseRoutePattern
397
     */
398
    public function testGetBaseRoutePatternWithTwoNestedChildAdmin(string $objFqn, string $expected): void
399
    {
400
        $postAdmin = new PostAdmin('sonata.post.admin.post', $objFqn, 'SonataNewsBundle:PostAdmin');
401
        $commentAdmin = new CommentAdmin(
402
            'sonata.post.admin.comment',
403
            'Application\Sonata\NewsBundle\Entity\Comment',
404
            'SonataNewsBundle:CommentAdmin'
405
        );
406
        $commentVoteAdmin = new CommentVoteAdmin(
407
            'sonata.post.admin.comment_vote',
408
            'Application\Sonata\NewsBundle\Entity\CommentVote',
409
            'SonataNewsBundle:CommentVoteAdmin'
410
        );
411
        $commentAdmin->setParent($postAdmin);
412
        $commentVoteAdmin->setParent($commentAdmin);
413
414
        $this->assertSame($expected.'/{id}/comment/{childId}/commentvote', $commentVoteAdmin->getBaseRoutePattern());
415
    }
416
417
    public function testGetBaseRoutePatternWithSpecifedPattern(): void
418
    {
419
        $postAdmin = new PostWithCustomRouteAdmin('sonata.post.admin.post_with_custom_route', 'Application\Sonata\NewsBundle\Entity\Post', 'SonataNewsBundle:PostWithCustomRouteAdmin');
420
421
        $this->assertSame('/post-custom', $postAdmin->getBaseRoutePattern());
422
    }
423
424
    public function testGetBaseRoutePatternWithChildAdminAndWithSpecifedPattern(): void
425
    {
426
        $postAdmin = new PostAdmin('sonata.post.admin.post', 'Application\Sonata\NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
427
        $commentAdmin = new CommentWithCustomRouteAdmin('sonata.post.admin.comment_with_custom_route', 'Application\Sonata\NewsBundle\Entity\Comment', 'SonataNewsBundle:CommentWithCustomRouteAdmin');
428
        $commentAdmin->setParent($postAdmin);
429
430
        $this->assertSame('/sonata/news/post/{id}/comment-custom', $commentAdmin->getBaseRoutePattern());
431
    }
432
433
    public function testGetBaseRoutePatternWithUnreconizedClassname(): void
434
    {
435
        $this->expectException(\RuntimeException::class);
436
437
        $admin = new PostAdmin('sonata.post.admin.post', 'News\Thing\Post', 'SonataNewsBundle:PostAdmin');
438
        $admin->getBaseRoutePattern();
439
    }
440
441
    public function provideGetBaseRouteName()
442
    {
443
        return [
444
            [
445
                'Application\Sonata\NewsBundle\Entity\Post',
446
                'admin_sonata_news_post',
447
            ],
448
            [
449
                'Application\Sonata\NewsBundle\Document\Post',
450
                'admin_sonata_news_post',
451
            ],
452
            [
453
                'MyApplication\MyBundle\Entity\Post',
454
                'admin_myapplication_my_post',
455
            ],
456
            [
457
                'MyApplication\MyBundle\Entity\Post\Category',
458
                'admin_myapplication_my_post_category',
459
            ],
460
            [
461
                'MyApplication\MyBundle\Entity\Product\Category',
462
                'admin_myapplication_my_product_category',
463
            ],
464
            [
465
                'MyApplication\MyBundle\Entity\Other\Product\Category',
466
                'admin_myapplication_my_other_product_category',
467
            ],
468
            [
469
                'Symfony\Cmf\Bundle\FooBundle\Document\Menu',
470
                'admin_cmf_foo_menu',
471
            ],
472
            [
473
                'Symfony\Cmf\Bundle\FooBundle\Doctrine\Phpcr\Menu',
474
                'admin_cmf_foo_menu',
475
            ],
476
            [
477
                'Symfony\Bundle\BarBarBundle\Doctrine\Phpcr\Menu',
478
                'admin_symfony_barbar_menu',
479
            ],
480
            [
481
                'Symfony\Bundle\BarBarBundle\Doctrine\Phpcr\Menu\Item',
482
                'admin_symfony_barbar_menu_item',
483
            ],
484
            [
485
                'Symfony\Cmf\Bundle\FooBundle\Doctrine\Orm\Menu',
486
                'admin_cmf_foo_menu',
487
            ],
488
            [
489
                'Symfony\Cmf\Bundle\FooBundle\Doctrine\MongoDB\Menu',
490
                'admin_cmf_foo_menu',
491
            ],
492
            [
493
                'Symfony\Cmf\Bundle\FooBundle\Doctrine\CouchDB\Menu',
494
                'admin_cmf_foo_menu',
495
            ],
496
            [
497
                'AppBundle\Entity\User',
498
                'admin_app_user',
499
            ],
500
            [
501
                'App\Entity\User',
502
                'admin_app_user',
503
            ],
504
        ];
505
    }
506
507
    /**
508
     * @dataProvider provideGetBaseRouteName
509
     */
510
    public function testGetBaseRouteName(string $objFqn, string $expected): void
511
    {
512
        $admin = new PostAdmin('sonata.post.admin.post', $objFqn, 'SonataNewsBundle:PostAdmin');
513
514
        $this->assertSame($expected, $admin->getBaseRouteName());
515
    }
516
517
    /**
518
     * @group legacy
519
     * @expectedDeprecation Calling "addChild" without second argument is deprecated since sonata-project/admin-bundle 3.35 and will not be allowed in 4.0.
520
     * @dataProvider provideGetBaseRouteName
521
     */
522
    public function testGetBaseRouteNameWithChildAdmin(string $objFqn, string $expected): void
523
    {
524
        $routeGenerator = new DefaultRouteGenerator(
525
            $this->createMock(RouterInterface::class),
526
            new RoutesCache($this->cacheTempFolder, true)
527
        );
528
529
        $container = new Container();
530
        $pool = new Pool($container, 'Sonata Admin', '/path/to/pic.png');
531
532
        $pathInfo = new PathInfoBuilder($this->createMock(AuditManagerInterface::class));
533
        $postAdmin = new PostAdmin('sonata.post.admin.post', $objFqn, 'SonataNewsBundle:PostAdmin');
534
        $container->set('sonata.post.admin.post', $postAdmin);
535
        $postAdmin->setConfigurationPool($pool);
536
        $postAdmin->setRouteBuilder($pathInfo);
537
        $postAdmin->setRouteGenerator($routeGenerator);
538
        $postAdmin->initialize();
539
540
        $commentAdmin = new CommentAdmin(
541
            'sonata.post.admin.comment',
542
            'Application\Sonata\NewsBundle\Entity\Comment',
543
            'SonataNewsBundle:CommentAdmin'
544
        );
545
        $container->set('sonata.post.admin.comment', $commentAdmin);
546
        $commentAdmin->setConfigurationPool($pool);
547
        $commentAdmin->setRouteBuilder($pathInfo);
548
        $commentAdmin->setRouteGenerator($routeGenerator);
549
        $commentAdmin->initialize();
550
551
        $postAdmin->addChild($commentAdmin, 'post');
552
553
        $commentVoteAdmin = new CommentVoteAdmin(
554
            'sonata.post.admin.comment_vote',
555
            'Application\Sonata\NewsBundle\Entity\CommentVote',
556
            'SonataNewsBundle:CommentVoteAdmin'
557
        );
558
559
        $container->set('sonata.post.admin.comment_vote', $commentVoteAdmin);
560
        $commentVoteAdmin->setConfigurationPool($pool);
561
        $commentVoteAdmin->setRouteBuilder($pathInfo);
562
        $commentVoteAdmin->setRouteGenerator($routeGenerator);
563
        $commentVoteAdmin->initialize();
564
565
        $commentAdmin->addChild($commentVoteAdmin);
566
        $pool->setAdminServiceIds([
567
            'sonata.post.admin.post',
568
            'sonata.post.admin.comment',
569
            'sonata.post.admin.comment_vote',
570
        ]);
571
572
        $this->assertSame($expected.'_comment', $commentAdmin->getBaseRouteName());
573
574
        $this->assertTrue($postAdmin->hasRoute('show'));
575
        $this->assertTrue($postAdmin->hasRoute('sonata.post.admin.post.show'));
576
        $this->assertTrue($postAdmin->hasRoute('sonata.post.admin.post|sonata.post.admin.comment.show'));
577
        $this->assertTrue($postAdmin->hasRoute('sonata.post.admin.post|sonata.post.admin.comment|sonata.post.admin.comment_vote.show'));
578
        $this->assertTrue($postAdmin->hasRoute('sonata.post.admin.comment.list'));
579
        $this->assertTrue($postAdmin->hasRoute('sonata.post.admin.comment|sonata.post.admin.comment_vote.list'));
580
        $this->assertFalse($postAdmin->hasRoute('sonata.post.admin.post|sonata.post.admin.comment.edit'));
581
        $this->assertFalse($commentAdmin->hasRoute('edit'));
582
        $this->assertSame('post', $commentAdmin->getParentAssociationMapping());
583
584
        /*
585
         * Test the route name from request
586
         */
587
        $postListRequest = new Request(
588
            [],
589
            [],
590
            [
591
                '_route' => $postAdmin->getBaseRouteName().'_list',
592
            ]
593
        );
594
595
        $postAdmin->setRequest($postListRequest);
596
        $commentAdmin->setRequest($postListRequest);
597
598
        $this->assertTrue($postAdmin->isCurrentRoute('list'));
599
        $this->assertFalse($postAdmin->isCurrentRoute('create'));
600
        $this->assertFalse($commentAdmin->isCurrentRoute('list'));
601
        $this->assertFalse($commentVoteAdmin->isCurrentRoute('list'));
602
        $this->assertTrue($commentAdmin->isCurrentRoute('list', 'sonata.post.admin.post'));
603
        $this->assertFalse($commentAdmin->isCurrentRoute('edit', 'sonata.post.admin.post'));
604
        $this->assertTrue($commentVoteAdmin->isCurrentRoute('list', 'sonata.post.admin.post'));
605
        $this->assertFalse($commentVoteAdmin->isCurrentRoute('edit', 'sonata.post.admin.post'));
606
    }
607
608
    public function testGetBaseRouteNameWithUnreconizedClassname(): void
609
    {
610
        $this->expectException(\RuntimeException::class);
611
612
        $admin = new PostAdmin('sonata.post.admin.post', 'News\Thing\Post', 'SonataNewsBundle:PostAdmin');
613
        $admin->getBaseRouteName();
614
    }
615
616
    public function testGetBaseRouteNameWithSpecifiedName(): void
617
    {
618
        $postAdmin = new PostWithCustomRouteAdmin('sonata.post.admin.post_with_custom_route', 'Application\Sonata\NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
619
620
        $this->assertSame('post_custom', $postAdmin->getBaseRouteName());
621
    }
622
623
    public function testGetBaseRouteNameWithChildAdminAndWithSpecifiedName(): void
624
    {
625
        $postAdmin = new PostAdmin('sonata.post.admin.post', 'Application\Sonata\NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
626
        $commentAdmin = new CommentWithCustomRouteAdmin('sonata.post.admin.comment_with_custom_route', 'Application\Sonata\NewsBundle\Entity\Comment', 'SonataNewsBundle:CommentWithCustomRouteAdmin');
627
        $commentAdmin->setParent($postAdmin);
628
629
        $this->assertSame('admin_sonata_news_post_comment_custom', $commentAdmin->getBaseRouteName());
630
    }
631
632
    public function testGetBaseRouteNameWithTwoNestedChildAdminAndWithSpecifiedName(): void
633
    {
634
        $postAdmin = new PostAdmin(
635
            'sonata.post.admin.post',
636
            'Application\Sonata\NewsBundle\Entity\Post',
637
            'SonataNewsBundle:PostAdmin'
638
        );
639
        $commentAdmin = new CommentWithCustomRouteAdmin(
640
            'sonata.post.admin.comment_with_custom_route',
641
            'Application\Sonata\NewsBundle\Entity\Comment',
642
            'SonataNewsBundle:CommentWithCustomRouteAdmin'
643
        );
644
        $commentVoteAdmin = new CommentVoteAdmin(
645
            'sonata.post.admin.comment_vote',
646
            'Application\Sonata\NewsBundle\Entity\CommentVote',
647
            'SonataNewsBundle:CommentVoteAdmin'
648
        );
649
        $commentAdmin->setParent($postAdmin);
650
        $commentVoteAdmin->setParent($commentAdmin);
651
652
        $this->assertSame('admin_sonata_news_post_comment_custom_commentvote', $commentVoteAdmin->getBaseRouteName());
653
    }
654
655
    /**
656
     * @covers \Sonata\AdminBundle\Admin\AbstractAdmin::setUniqid
657
     * @covers \Sonata\AdminBundle\Admin\AbstractAdmin::getUniqid
658
     */
659
    public function testSetUniqid(): void
660
    {
661
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
662
663
        $uniqid = uniqid();
664
        $admin->setUniqid($uniqid);
665
666
        $this->assertSame($uniqid, $admin->getUniqid());
667
    }
668
669
    public function testToString(): void
670
    {
671
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
672
673
        $s = new \stdClass();
674
675
        $this->assertNotEmpty($admin->toString($s));
676
677
        $s = new FooToString();
678
        $this->assertSame('salut', $admin->toString($s));
679
680
        // To string method is implemented, but returns null
681
        $s = new FooToStringNull();
682
        $this->assertNotEmpty($admin->toString($s));
683
684
        $this->assertSame('', $admin->toString(false));
0 ignored issues
show
Documentation introduced by
false is of type boolean, but the function expects a object.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
685
    }
686
687
    public function testIsAclEnabled(): void
688
    {
689
        $postAdmin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
690
691
        $this->assertFalse($postAdmin->isAclEnabled());
692
693
        $commentAdmin = new CommentAdmin('sonata.post.admin.comment', 'Application\Sonata\NewsBundle\Entity\Comment', 'SonataNewsBundle:CommentAdmin');
694
        $commentAdmin->setSecurityHandler($this->createMock(AclSecurityHandlerInterface::class));
695
        $this->assertTrue($commentAdmin->isAclEnabled());
696
    }
697
698
    /**
699
     * @group legacy
700
     *
701
     * @expectedDeprecation Calling Sonata\AdminBundle\Admin\AbstractAdmin::getActiveSubclassCode() when there is no active subclass is deprecated since sonata-project/admin-bundle 3.52 and will throw an exception in 4.0. Use Sonata\AdminBundle\Admin\AbstractAdmin::hasActiveSubClass() to know if there is an active subclass.
702
     *
703
     * @covers \Sonata\AdminBundle\Admin\AbstractAdmin::getSubClasses
704
     * @covers \Sonata\AdminBundle\Admin\AbstractAdmin::getSubClass
705
     * @covers \Sonata\AdminBundle\Admin\AbstractAdmin::setSubClasses
706
     * @covers \Sonata\AdminBundle\Admin\AbstractAdmin::hasSubClass
707
     * @covers \Sonata\AdminBundle\Admin\AbstractAdmin::hasActiveSubClass
708
     * @covers \Sonata\AdminBundle\Admin\AbstractAdmin::getActiveSubClass
709
     * @covers \Sonata\AdminBundle\Admin\AbstractAdmin::getActiveSubclassCode
710
     * @covers \Sonata\AdminBundle\Admin\AbstractAdmin::getClass
711
     */
712
    public function testSubClass(): void
713
    {
714
        // NEXT_MAJOR: Remove the "@group" and "@expectedDeprecation" annotations
715
        $admin = new PostAdmin(
716
            'sonata.post.admin.post',
717
            Post::class,
718
            'SonataNewsBundle:PostAdmin'
719
        );
720
        $this->assertFalse($admin->hasSubClass('test'));
721
        $this->assertFalse($admin->hasActiveSubClass());
722
        $this->assertCount(0, $admin->getSubClasses());
723
        $this->assertNull($admin->getActiveSubClass());
724
        $this->assertNull($admin->getActiveSubclassCode());
725
        $this->assertSame(Post::class, $admin->getClass());
726
727
        // Just for the record, if there is no inheritance set, the getSubject is not used
728
        // the getSubject can also lead to some issue
729
        $admin->setSubject(new BlogPost());
730
        $this->assertSame(BlogPost::class, $admin->getClass());
731
732
        $admin->setSubClasses([
733
            'extended1' => 'NewsBundle\Entity\PostExtended1',
734
            'extended2' => 'NewsBundle\Entity\PostExtended2',
735
        ]);
736
        $this->assertFalse($admin->hasSubClass('test'));
737
        $this->assertTrue($admin->hasSubClass('extended1'));
738
        $this->assertFalse($admin->hasActiveSubClass());
739
        $this->assertCount(2, $admin->getSubClasses());
740
        // NEXT_MAJOR: remove the following 2 `assertNull()` assertions
741
        $this->assertNull($admin->getActiveSubClass());
742
        $this->assertNull($admin->getActiveSubclassCode());
743
        $this->assertSame(
744
            BlogPost::class,
745
            $admin->getClass(),
746
            'When there is no subclass in the query the class parameter should be returned'
747
        );
748
749
        $request = new Request(['subclass' => 'extended1']);
750
        $admin->setRequest($request);
751
        $this->assertFalse($admin->hasSubClass('test'));
752
        $this->assertTrue($admin->hasSubClass('extended1'));
753
        $this->assertTrue($admin->hasActiveSubClass());
754
        $this->assertCount(2, $admin->getSubClasses());
755
        $this->assertSame(
756
            'NewsBundle\Entity\PostExtended1',
757
            $admin->getActiveSubClass(),
758
            'It should return the curently active sub class.'
759
        );
760
        $this->assertSame('extended1', $admin->getActiveSubclassCode());
761
        $this->assertSame(
762
            'NewsBundle\Entity\PostExtended1',
763
            $admin->getClass(),
764
            'getClass() should return the name of the sub class when passed through a request query parameter.'
765
        );
766
767
        $request->query->set('subclass', 'inject');
768
769
        $this->assertNull($admin->getActiveSubclassCode());
770
        // NEXT_MAJOR: remove the previous `assertNull()` assertion and uncomment the following lines
771
        // $this->expectException(\LogicException::class);
772
        // $this->expectExceptionMessage(sprintf('Admin "%s" has no active subclass.', PostAdmin::class));
773
    }
774
775
    /**
776
     * @group legacy
777
     *
778
     * @expectedDeprecation Calling Sonata\AdminBundle\Admin\AbstractAdmin::getActiveSubclassCode() when there is no active subclass is deprecated since sonata-project/admin-bundle 3.52 and will throw an exception in 4.0. Use Sonata\AdminBundle\Admin\AbstractAdmin::hasActiveSubClass() to know if there is an active subclass.
779
     */
780
    public function testNonExistantSubclass(): void
781
    {
782
        // NEXT_MAJOR: Remove the "@group" and "@expectedDeprecation" annotations
783
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
784
        $admin->setModelManager($this->getMockForAbstractClass(ModelManagerInterface::class));
785
786
        $admin->setRequest(new Request(['subclass' => 'inject']));
787
788
        $admin->setSubClasses(['extended1' => 'NewsBundle\Entity\PostExtended1', 'extended2' => 'NewsBundle\Entity\PostExtended2']);
789
790
        $this->assertTrue($admin->hasActiveSubClass());
791
792
        $this->expectException(\RuntimeException::class);
793
794
        $admin->getActiveSubClass();
795
    }
796
797
    /**
798
     * @covers \Sonata\AdminBundle\Admin\AbstractAdmin::hasActiveSubClass
799
     */
800
    public function testOnlyOneSubclassNeededToBeActive(): void
801
    {
802
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
803
        $admin->setSubClasses(['extended1' => 'NewsBundle\Entity\PostExtended1']);
804
        $request = new Request(['subclass' => 'extended1']);
805
        $admin->setRequest($request);
806
        $this->assertTrue($admin->hasActiveSubClass());
807
    }
808
809
    /**
810
     * @group legacy
811
     * @expectedDeprecation Method "Sonata\AdminBundle\Admin\AbstractAdmin::addSubClass" is deprecated since sonata-project/admin-bundle 3.30 and will be removed in 4.0.
812
     */
813
    public function testAddSubClassIsDeprecated(): void
814
    {
815
        $admin = new PostAdmin(
816
            'sonata.post.admin.post',
817
            Post::class,
818
            'SonataNewsBundle:PostAdmin'
819
        );
820
        $admin->addSubClass('whatever');
821
    }
822
823
    public function testGetPerPageOptions(): void
824
    {
825
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
826
827
        $perPageOptions = $admin->getPerPageOptions();
828
829
        foreach ($perPageOptions as $perPage) {
830
            $this->assertSame(0, $perPage % 4);
831
        }
832
833
        $admin->setPerPageOptions([500, 1000]);
834
        $this->assertSame([500, 1000], $admin->getPerPageOptions());
835
    }
836
837
    public function testGetLabelTranslatorStrategy(): void
838
    {
839
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
840
841
        $this->assertNull($admin->getLabelTranslatorStrategy());
842
843
        $labelTranslatorStrategy = $this->createMock(LabelTranslatorStrategyInterface::class);
844
        $admin->setLabelTranslatorStrategy($labelTranslatorStrategy);
845
        $this->assertSame($labelTranslatorStrategy, $admin->getLabelTranslatorStrategy());
846
    }
847
848
    public function testGetRouteBuilder(): void
849
    {
850
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
851
852
        $this->assertNull($admin->getRouteBuilder());
853
854
        $routeBuilder = $this->createMock(RouteBuilderInterface::class);
855
        $admin->setRouteBuilder($routeBuilder);
856
        $this->assertSame($routeBuilder, $admin->getRouteBuilder());
857
    }
858
859
    public function testGetMenuFactory(): void
860
    {
861
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
862
863
        $this->assertNull($admin->getMenuFactory());
864
865
        $menuFactory = $this->createMock(FactoryInterface::class);
866
        $admin->setMenuFactory($menuFactory);
867
        $this->assertSame($menuFactory, $admin->getMenuFactory());
868
    }
869
870
    public function testGetExtensions(): void
871
    {
872
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
873
874
        $this->assertSame([], $admin->getExtensions());
875
876
        $adminExtension1 = $this->createMock(AdminExtensionInterface::class);
877
        $adminExtension2 = $this->createMock(AdminExtensionInterface::class);
878
879
        $admin->addExtension($adminExtension1);
880
        $admin->addExtension($adminExtension2);
881
        $this->assertSame([$adminExtension1, $adminExtension2], $admin->getExtensions());
882
    }
883
884
    public function testGetFilterTheme(): void
885
    {
886
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
887
888
        $this->assertSame([], $admin->getFilterTheme());
889
890
        $admin->setFilterTheme(['FooTheme']);
891
        $this->assertSame(['FooTheme'], $admin->getFilterTheme());
892
    }
893
894
    public function testGetFormTheme(): void
895
    {
896
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
897
898
        $this->assertSame([], $admin->getFormTheme());
899
900
        $admin->setFormTheme(['FooTheme']);
901
902
        $this->assertSame(['FooTheme'], $admin->getFormTheme());
903
    }
904
905
    public function testGetValidator(): void
906
    {
907
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
908
909
        $this->assertNull($admin->getValidator());
910
911
        $validator = $this->getMockForAbstractClass(ValidatorInterface::class);
912
913
        $admin->setValidator($validator);
914
        $this->assertSame($validator, $admin->getValidator());
915
    }
916
917
    public function testGetSecurityHandler(): void
918
    {
919
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
920
921
        $this->assertNull($admin->getSecurityHandler());
922
923
        $securityHandler = $this->createMock(SecurityHandlerInterface::class);
924
        $admin->setSecurityHandler($securityHandler);
925
        $this->assertSame($securityHandler, $admin->getSecurityHandler());
926
    }
927
928
    public function testGetSecurityInformation(): void
929
    {
930
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
931
932
        $this->assertSame([], $admin->getSecurityInformation());
933
934
        $securityInformation = [
935
            'GUEST' => ['VIEW', 'LIST'],
936
            'STAFF' => ['EDIT', 'LIST', 'CREATE'],
937
        ];
938
939
        $admin->setSecurityInformation($securityInformation);
940
        $this->assertSame($securityInformation, $admin->getSecurityInformation());
941
    }
942
943
    public function testGetManagerType(): void
944
    {
945
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
946
947
        $this->assertNull($admin->getManagerType());
948
949
        $admin->setManagerType('foo_orm');
950
        $this->assertSame('foo_orm', $admin->getManagerType());
951
    }
952
953
    public function testGetModelManager(): void
954
    {
955
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
956
957
        $this->assertNull($admin->getModelManager());
958
959
        $modelManager = $this->createMock(ModelManagerInterface::class);
960
961
        $admin->setModelManager($modelManager);
962
        $this->assertSame($modelManager, $admin->getModelManager());
963
    }
964
965
    public function testGetBaseCodeRoute(): void
966
    {
967
        $postAdmin = new PostAdmin(
968
            'sonata.post.admin.post',
969
            'NewsBundle\Entity\Post',
970
            'SonataNewsBundle:PostAdmin'
971
        );
972
        $commentAdmin = new CommentAdmin(
973
            'sonata.post.admin.comment',
974
            'Application\Sonata\NewsBundle\Entity\Comment',
975
            'SonataNewsBundle:CommentAdmin'
976
        );
977
978
        $this->assertSame($postAdmin->getCode(), $postAdmin->getBaseCodeRoute());
979
980
        $postAdmin->addChild($commentAdmin, 'post');
981
982
        $this->assertSame(
983
            'sonata.post.admin.post|sonata.post.admin.comment',
984
            $commentAdmin->getBaseCodeRoute()
985
        );
986
    }
987
988
    public function testGetRouteGenerator(): void
989
    {
990
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
991
992
        $this->assertNull($admin->getRouteGenerator());
993
994
        $routeGenerator = $this->createMock(RouteGeneratorInterface::class);
995
996
        $admin->setRouteGenerator($routeGenerator);
997
        $this->assertSame($routeGenerator, $admin->getRouteGenerator());
998
    }
999
1000
    public function testGetConfigurationPool(): void
1001
    {
1002
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
1003
1004
        $this->assertNull($admin->getConfigurationPool());
1005
1006
        $pool = $this->getMockBuilder(Pool::class)
1007
            ->disableOriginalConstructor()
1008
            ->getMock();
1009
1010
        $admin->setConfigurationPool($pool);
1011
        $this->assertSame($pool, $admin->getConfigurationPool());
1012
    }
1013
1014
    public function testGetShowBuilder(): void
1015
    {
1016
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
1017
1018
        $this->assertNull($admin->getShowBuilder());
1019
1020
        $showBuilder = $this->createMock(ShowBuilderInterface::class);
1021
1022
        $admin->setShowBuilder($showBuilder);
1023
        $this->assertSame($showBuilder, $admin->getShowBuilder());
1024
    }
1025
1026
    public function testGetListBuilder(): void
1027
    {
1028
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
1029
1030
        $this->assertNull($admin->getListBuilder());
1031
1032
        $listBuilder = $this->createMock(ListBuilderInterface::class);
1033
1034
        $admin->setListBuilder($listBuilder);
1035
        $this->assertSame($listBuilder, $admin->getListBuilder());
1036
    }
1037
1038
    public function testGetDatagridBuilder(): void
1039
    {
1040
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
1041
1042
        $this->assertNull($admin->getDatagridBuilder());
1043
1044
        $datagridBuilder = $this->createMock(DatagridBuilderInterface::class);
1045
1046
        $admin->setDatagridBuilder($datagridBuilder);
1047
        $this->assertSame($datagridBuilder, $admin->getDatagridBuilder());
1048
    }
1049
1050
    public function testGetFormContractor(): void
1051
    {
1052
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
1053
1054
        $this->assertNull($admin->getFormContractor());
1055
1056
        $formContractor = $this->createMock(FormContractorInterface::class);
1057
1058
        $admin->setFormContractor($formContractor);
1059
        $this->assertSame($formContractor, $admin->getFormContractor());
1060
    }
1061
1062
    public function testGetRequest(): void
1063
    {
1064
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
1065
1066
        $this->assertFalse($admin->hasRequest());
1067
1068
        $request = new Request();
1069
1070
        $admin->setRequest($request);
1071
        $this->assertSame($request, $admin->getRequest());
1072
        $this->assertTrue($admin->hasRequest());
1073
    }
1074
1075
    public function testGetRequestWithException(): void
1076
    {
1077
        $this->expectException(\RuntimeException::class);
1078
        $this->expectExceptionMessage('The Request object has not been set');
1079
1080
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
1081
        $admin->getRequest();
1082
    }
1083
1084
    public function testGetTranslationDomain(): void
1085
    {
1086
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
1087
1088
        $this->assertSame('messages', $admin->getTranslationDomain());
1089
1090
        $admin->setTranslationDomain('foo');
1091
        $this->assertSame('foo', $admin->getTranslationDomain());
1092
    }
1093
1094
    /**
1095
     * @group legacy
1096
     */
1097
    public function testGetTranslator(): void
1098
    {
1099
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
1100
1101
        $this->assertNull($admin->getTranslator());
0 ignored issues
show
Deprecated Code introduced by
The method Sonata\AdminBundle\Admin...tAdmin::getTranslator() has been deprecated with message: since sonata-project/admin-bundle 3.9, to be removed with 4.0

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
1102
1103
        $translator = $this->createMock(TranslatorInterface::class);
1104
1105
        $admin->setTranslator($translator);
0 ignored issues
show
Deprecated Code introduced by
The method Sonata\AdminBundle\Admin...tAdmin::setTranslator() has been deprecated with message: since sonata-project/admin-bundle 3.9, to be removed with 4.0

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
1106
        $this->assertSame($translator, $admin->getTranslator());
0 ignored issues
show
Deprecated Code introduced by
The method Sonata\AdminBundle\Admin...tAdmin::getTranslator() has been deprecated with message: since sonata-project/admin-bundle 3.9, to be removed with 4.0

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
1107
    }
1108
1109
    public function testGetShowGroups(): void
1110
    {
1111
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
1112
1113
        $this->assertFalse($admin->getShowGroups());
1114
1115
        $groups = ['foo', 'bar', 'baz'];
1116
1117
        $admin->setShowGroups($groups);
1118
        $this->assertSame($groups, $admin->getShowGroups());
1119
    }
1120
1121
    public function testGetFormGroups(): void
1122
    {
1123
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
1124
1125
        $this->assertFalse($admin->getFormGroups());
1126
1127
        $groups = ['foo', 'bar', 'baz'];
1128
1129
        $admin->setFormGroups($groups);
1130
        $this->assertSame($groups, $admin->getFormGroups());
1131
    }
1132
1133
    public function testGetMaxPageLinks(): void
1134
    {
1135
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
1136
1137
        $this->assertSame(25, $admin->getMaxPageLinks());
1138
1139
        $admin->setMaxPageLinks(14);
1140
        $this->assertSame(14, $admin->getMaxPageLinks());
1141
    }
1142
1143
    public function testGetMaxPerPage(): void
1144
    {
1145
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
1146
1147
        $this->assertSame(32, $admin->getMaxPerPage());
1148
1149
        $admin->setMaxPerPage(94);
1150
        $this->assertSame(94, $admin->getMaxPerPage());
1151
    }
1152
1153
    public function testGetLabel(): void
1154
    {
1155
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
1156
1157
        $this->assertNull($admin->getLabel());
1158
1159
        $admin->setLabel('FooLabel');
1160
        $this->assertSame('FooLabel', $admin->getLabel());
1161
    }
1162
1163
    public function testGetBaseController(): void
1164
    {
1165
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
1166
1167
        $this->assertSame('SonataNewsBundle:PostAdmin', $admin->getBaseControllerName());
1168
1169
        $admin->setBaseControllerName('SonataNewsBundle:FooAdmin');
1170
        $this->assertSame('SonataNewsBundle:FooAdmin', $admin->getBaseControllerName());
1171
    }
1172
1173
    public function testGetIdParameter(): void
1174
    {
1175
        $postAdmin = new PostAdmin(
1176
            'sonata.post.admin.post',
1177
            'NewsBundle\Entity\Post',
1178
            'SonataNewsBundle:PostAdmin'
1179
        );
1180
1181
        $this->assertSame('id', $postAdmin->getIdParameter());
1182
        $this->assertFalse($postAdmin->isChild());
1183
1184
        $commentAdmin = new CommentAdmin(
1185
            'sonata.post.admin.comment',
1186
            'Application\Sonata\NewsBundle\Entity\Comment',
1187
            'SonataNewsBundle:CommentAdmin'
1188
        );
1189
        $commentAdmin->setParent($postAdmin);
1190
1191
        $this->assertTrue($commentAdmin->isChild());
1192
        $this->assertSame('childId', $commentAdmin->getIdParameter());
1193
1194
        $commentVoteAdmin = new CommentVoteAdmin(
1195
            'sonata.post.admin.comment_vote',
1196
            'Application\Sonata\NewsBundle\Entity\CommentVote',
1197
            'SonataNewsBundle:CommentVoteAdmin'
1198
        );
1199
        $commentVoteAdmin->setParent($commentAdmin);
1200
1201
        $this->assertTrue($commentVoteAdmin->isChild());
1202
        $this->assertSame('childChildId', $commentVoteAdmin->getIdParameter());
1203
    }
1204
1205
    public function testGetExportFormats(): void
1206
    {
1207
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
1208
1209
        $this->assertSame(['json', 'xml', 'csv', 'xls'], $admin->getExportFormats());
1210
    }
1211
1212
    public function testGetUrlsafeIdentifier(): void
1213
    {
1214
        $admin = new PostAdmin('sonata.post.admin.post', 'Acme\NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
1215
1216
        $entity = new \stdClass();
1217
1218
        $modelManager = $this->createMock(ModelManagerInterface::class);
1219
        $modelManager->expects($this->once())
1220
            ->method('getUrlsafeIdentifier')
1221
            ->with($this->equalTo($entity))
1222
            ->willReturn('foo');
1223
        $admin->setModelManager($modelManager);
1224
1225
        $this->assertSame('foo', $admin->getUrlsafeIdentifier($entity));
1226
    }
1227
1228
    public function testDeterminedPerPageValue(): void
1229
    {
1230
        $admin = new PostAdmin('sonata.post.admin.post', 'Acme\NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
1231
1232
        $this->assertFalse($admin->determinedPerPageValue('foo'));
1233
        $this->assertFalse($admin->determinedPerPageValue(123));
1234
        $this->assertTrue($admin->determinedPerPageValue(16));
1235
1236
        $admin->setPerPageOptions([101, 102, 103]);
1237
        $this->assertFalse($admin->determinedPerPageValue(16));
1238
        $this->assertTrue($admin->determinedPerPageValue(101));
1239
    }
1240
1241
    public function testIsGranted(): void
1242
    {
1243
        $admin = new PostAdmin('sonata.post.admin.post', 'Acme\NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
1244
1245
        $entity = new \stdClass();
1246
1247
        $securityHandler = $this->createMock(AclSecurityHandlerInterface::class);
1248
        $securityHandler
1249
            ->method('isGranted')
1250
            ->willReturnCallback(static function (
1251
                AdminInterface $adminIn,
1252
                string $attributes,
1253
                $object = null
1254
            ) use (
1255
                $admin,
1256
                $entity
1257
            ): bool {
1258
                if ($admin === $adminIn && 'FOO' === $attributes) {
1259
                    if (($object === $admin) || ($object === $entity)) {
1260
                        return true;
1261
                    }
1262
                }
1263
1264
                return false;
1265
            });
1266
1267
        $admin->setSecurityHandler($securityHandler);
1268
1269
        $this->assertTrue($admin->isGranted('FOO'));
1270
        $this->assertTrue($admin->isGranted('FOO', $entity));
1271
        $this->assertFalse($admin->isGranted('BAR'));
1272
        $this->assertFalse($admin->isGranted('BAR', $entity));
1273
    }
1274
1275
    public function testSupportsPreviewMode(): void
1276
    {
1277
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
1278
1279
        $this->assertFalse($admin->supportsPreviewMode());
1280
    }
1281
1282
    public function testGetPermissionsShow(): void
1283
    {
1284
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
1285
1286
        $this->assertSame(['LIST'], $admin->getPermissionsShow(AbstractAdmin::CONTEXT_DASHBOARD));
1287
        $this->assertSame(['LIST'], $admin->getPermissionsShow(AbstractAdmin::CONTEXT_MENU));
1288
        $this->assertSame(['LIST'], $admin->getPermissionsShow('foo'));
1289
    }
1290
1291
    public function testShowIn(): void
1292
    {
1293
        $admin = new PostAdmin('sonata.post.admin.post', 'Acme\NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
1294
1295
        $securityHandler = $this->createMock(AclSecurityHandlerInterface::class);
1296
        $securityHandler
1297
            ->method('isGranted')
1298
            ->willReturnCallback(static function (AdminInterface $adminIn, array $attributes, $object = null) use ($admin): bool {
0 ignored issues
show
Unused Code introduced by
The parameter $object is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
1299
                return $admin === $adminIn && $attributes === ['LIST'];
1300
            });
1301
1302
        $admin->setSecurityHandler($securityHandler);
1303
1304
        $this->assertTrue($admin->showIn(AbstractAdmin::CONTEXT_DASHBOARD));
1305
        $this->assertTrue($admin->showIn(AbstractAdmin::CONTEXT_MENU));
1306
        $this->assertTrue($admin->showIn('foo'));
1307
    }
1308
1309
    public function testGetObjectIdentifier(): void
1310
    {
1311
        $admin = new PostAdmin('sonata.post.admin.post', 'Acme\NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
1312
1313
        $this->assertSame('sonata.post.admin.post', $admin->getObjectIdentifier());
1314
    }
1315
1316
    /**
1317
     * @group legacy
1318
     */
1319
    public function testTrans(): void
1320
    {
1321
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
1322
        $admin->setTranslationDomain('fooMessageDomain');
1323
1324
        $translator = $this->createMock(TranslatorInterface::class);
1325
        $admin->setTranslator($translator);
0 ignored issues
show
Deprecated Code introduced by
The method Sonata\AdminBundle\Admin...tAdmin::setTranslator() has been deprecated with message: since sonata-project/admin-bundle 3.9, to be removed with 4.0

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
1326
1327
        $translator->expects($this->once())
1328
            ->method('trans')
1329
            ->with($this->equalTo('foo'), $this->equalTo([]), $this->equalTo('fooMessageDomain'))
1330
            ->willReturn('fooTranslated');
1331
1332
        $this->assertSame('fooTranslated', $admin->trans('foo'));
1333
    }
1334
1335
    /**
1336
     * @group legacy
1337
     */
1338
    public function testTransWithMessageDomain(): void
1339
    {
1340
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
1341
1342
        $translator = $this->createMock(TranslatorInterface::class);
1343
        $admin->setTranslator($translator);
0 ignored issues
show
Deprecated Code introduced by
The method Sonata\AdminBundle\Admin...tAdmin::setTranslator() has been deprecated with message: since sonata-project/admin-bundle 3.9, to be removed with 4.0

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
1344
1345
        $translator->expects($this->once())
1346
            ->method('trans')
1347
            ->with($this->equalTo('foo'), $this->equalTo(['name' => 'Andrej']), $this->equalTo('fooMessageDomain'))
1348
            ->willReturn('fooTranslated');
1349
1350
        $this->assertSame('fooTranslated', $admin->trans('foo', ['name' => 'Andrej'], 'fooMessageDomain'));
1351
    }
1352
1353
    /**
1354
     * @group legacy
1355
     */
1356
    public function testTransChoice(): void
1357
    {
1358
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
1359
        $admin->setTranslationDomain('fooMessageDomain');
1360
1361
        $translator = $this->createMock(TranslatorInterface::class);
1362
        $admin->setTranslator($translator);
0 ignored issues
show
Deprecated Code introduced by
The method Sonata\AdminBundle\Admin...tAdmin::setTranslator() has been deprecated with message: since sonata-project/admin-bundle 3.9, to be removed with 4.0

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
1363
1364
        $translator->expects($this->once())
1365
            ->method('transChoice')
1366
            ->with($this->equalTo('foo'), $this->equalTo(2), $this->equalTo([]), $this->equalTo('fooMessageDomain'))
1367
            ->willReturn('fooTranslated');
1368
1369
        $this->assertSame('fooTranslated', $admin->transChoice('foo', 2));
0 ignored issues
show
Deprecated Code introduced by
The method Sonata\AdminBundle\Admin...actAdmin::transChoice() has been deprecated with message: since sonata-project/admin-bundle 3.9, to be removed with 4.0

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
1370
    }
1371
1372
    /**
1373
     * @group legacy
1374
     */
1375
    public function testTransChoiceWithMessageDomain(): void
1376
    {
1377
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
1378
1379
        $translator = $this->createMock(TranslatorInterface::class);
1380
        $admin->setTranslator($translator);
0 ignored issues
show
Deprecated Code introduced by
The method Sonata\AdminBundle\Admin...tAdmin::setTranslator() has been deprecated with message: since sonata-project/admin-bundle 3.9, to be removed with 4.0

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
1381
1382
        $translator->expects($this->once())
1383
            ->method('transChoice')
1384
            ->with($this->equalTo('foo'), $this->equalTo(2), $this->equalTo(['name' => 'Andrej']), $this->equalTo('fooMessageDomain'))
1385
            ->willReturn('fooTranslated');
1386
1387
        $this->assertSame('fooTranslated', $admin->transChoice('foo', 2, ['name' => 'Andrej'], 'fooMessageDomain'));
0 ignored issues
show
Deprecated Code introduced by
The method Sonata\AdminBundle\Admin...actAdmin::transChoice() has been deprecated with message: since sonata-project/admin-bundle 3.9, to be removed with 4.0

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
1388
    }
1389
1390
    public function testSetFilterPersister(): void
1391
    {
1392
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
1393
1394
        $filterPersister = $this->createMock('Sonata\AdminBundle\Filter\Persister\FilterPersisterInterface');
1395
1396
        $reflector = new \ReflectionObject($admin);
1397
1398
        $persistFiltersAttribute = $reflector->getProperty('persistFilters');
1399
        $persistFiltersAttribute->setAccessible(true);
1400
        $this->assertFalse($persistFiltersAttribute->getValue($admin));
1401
        $admin->setFilterPersister($filterPersister);
1402
        $this->assertTrue($persistFiltersAttribute->getValue($admin));
1403
    }
1404
1405
    public function testGetRootCode(): void
1406
    {
1407
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
1408
1409
        $this->assertSame('sonata.post.admin.post', $admin->getRootCode());
1410
1411
        $parentAdmin = new PostAdmin('sonata.post.admin.post.parent', 'NewsBundle\Entity\PostParent', 'SonataNewsBundle:PostParentAdmin');
1412
        $parentFieldDescription = $this->createMock(FieldDescriptionInterface::class);
1413
        $parentFieldDescription->expects($this->once())
1414
            ->method('getAdmin')
1415
            ->willReturn($parentAdmin);
1416
1417
        $this->assertNull($admin->getParentFieldDescription());
1418
        $admin->setParentFieldDescription($parentFieldDescription);
1419
        $this->assertSame($parentFieldDescription, $admin->getParentFieldDescription());
1420
        $this->assertSame('sonata.post.admin.post.parent', $admin->getRootCode());
1421
    }
1422
1423
    public function testGetRoot(): void
1424
    {
1425
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
1426
1427
        $this->assertSame($admin, $admin->getRoot());
1428
1429
        $parentAdmin = new PostAdmin('sonata.post.admin.post.parent', 'NewsBundle\Entity\PostParent', 'SonataNewsBundle:PostParentAdmin');
1430
        $parentFieldDescription = $this->createMock(FieldDescriptionInterface::class);
1431
        $parentFieldDescription->expects($this->once())
1432
            ->method('getAdmin')
1433
            ->willReturn($parentAdmin);
1434
1435
        $this->assertNull($admin->getParentFieldDescription());
1436
        $admin->setParentFieldDescription($parentFieldDescription);
1437
        $this->assertSame($parentFieldDescription, $admin->getParentFieldDescription());
1438
        $this->assertSame($parentAdmin, $admin->getRoot());
1439
    }
1440
1441
    public function testGetExportFields(): void
1442
    {
1443
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
1444
1445
        $modelManager = $this->createMock(ModelManagerInterface::class);
1446
        $modelManager->expects($this->once())
1447
            ->method('getExportFields')
1448
            ->with($this->equalTo('NewsBundle\Entity\Post'))
1449
            ->willReturn(['foo', 'bar']);
1450
1451
        $admin->setModelManager($modelManager);
1452
        $this->assertSame(['foo', 'bar'], $admin->getExportFields());
1453
    }
1454
1455
    public function testGetPersistentParametersWithNoExtension(): void
1456
    {
1457
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
1458
1459
        $this->assertEmpty($admin->getPersistentParameters());
1460
    }
1461
1462
    public function testGetPersistentParametersWithInvalidExtension(): void
1463
    {
1464
        $this->expectException(\RuntimeException::class);
1465
1466
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
1467
1468
        $extension = $this->createMock(AdminExtensionInterface::class);
1469
        $extension->expects($this->once())->method('getPersistentParameters')->willReturn(null);
1470
1471
        $admin->addExtension($extension);
1472
1473
        $admin->getPersistentParameters();
1474
    }
1475
1476
    public function testGetPersistentParametersWithValidExtension(): void
1477
    {
1478
        $expected = [
1479
            'context' => 'foobar',
1480
        ];
1481
1482
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
1483
1484
        $extension = $this->createMock(AdminExtensionInterface::class);
1485
        $extension->expects($this->once())->method('getPersistentParameters')->willReturn($expected);
1486
1487
        $admin->addExtension($extension);
1488
1489
        $this->assertSame($expected, $admin->getPersistentParameters());
1490
    }
1491
1492
    public function testGetFormWithNonCollectionParentValue(): void
1493
    {
1494
        $post = new Post();
1495
        $tagAdmin = $this->createTagAdmin($post);
1496
        $tag = $tagAdmin->getSubject();
1497
1498
        $tag->setPosts(null);
1499
        $tagAdmin->getForm();
1500
        $this->assertSame($post, $tag->getPosts());
1501
    }
1502
1503
    public function testGetFormWithCollectionParentValue(): void
1504
    {
1505
        $post = new Post();
1506
        $tagAdmin = $this->createTagAdmin($post);
1507
        $tag = $tagAdmin->getSubject();
1508
1509
        // Case of a doctrine collection
1510
        $this->assertInstanceOf(Collection::class, $tag->getPosts());
1511
        $this->assertCount(0, $tag->getPosts());
1512
1513
        $tag->addPost(new Post());
1514
1515
        $this->assertCount(1, $tag->getPosts());
1516
1517
        $tagAdmin->getForm();
1518
1519
        $this->assertInstanceOf(Collection::class, $tag->getPosts());
1520
        $this->assertCount(2, $tag->getPosts());
1521
        $this->assertContains($post, $tag->getPosts());
1522
1523
        // Case of an array
1524
        $tag->setPosts([]);
1525
        $this->assertCount(0, $tag->getPosts());
1526
1527
        $tag->addPost(new Post());
1528
1529
        $this->assertCount(1, $tag->getPosts());
1530
1531
        $tagAdmin->getForm();
1532
1533
        $this->assertIsArray($tag->getPosts());
1534
        $this->assertCount(2, $tag->getPosts());
1535
        $this->assertContains($post, $tag->getPosts());
1536
    }
1537
1538
    public function testFormAddPostSubmitEventForPreValidation(): void
1539
    {
1540
        $modelAdmin = new ModelAdmin('sonata.post.admin.model', 'Application\Sonata\FooBundle\Entity\Model', 'SonataFooBundle:ModelAdmin');
1541
        $object = new \stdClass();
1542
1543
        $labelTranslatorStrategy = $this->createMock(LabelTranslatorStrategyInterface::class);
1544
        $modelAdmin->setLabelTranslatorStrategy($labelTranslatorStrategy);
1545
1546
        $validator = $this->createMock(ValidatorInterface::class);
1547
        $validator
1548
                ->method('getMetadataFor')
1549
                ->willReturn($this->createMock(MemberMetadata::class));
1550
        $modelAdmin->setValidator($validator);
1551
1552
        $modelManager = $this->createMock(ModelManagerInterface::class);
1553
        $modelManager
1554
            ->method('getNewFieldDescriptionInstance')
1555
            ->willReturn(new FieldDescription());
1556
        $modelAdmin->setModelManager($modelManager);
1557
1558
        // a Admin class to test that preValidate is called
1559
        $testAdminPreValidate = $this->createMock(AbstractAdmin::class);
1560
        $testAdminPreValidate->expects($this->once())
1561
                ->method('preValidate')
1562
                ->with($this->identicalTo($object));
1563
1564
        $event = $this->createMock(FormEvent::class);
1565
        $event
1566
                ->method('getData')
1567
                ->willReturn($object);
1568
1569
        $formBuild = $this->createMock(FormBuilder::class);
1570
        $formBuild->expects($this->once())
1571
                ->method('addEventListener')
1572
                ->with($this->identicalTo(FormEvents::POST_SUBMIT),
1573
                        $this->callback(static function ($callback) use ($testAdminPreValidate, $event): bool {
1574
                            if (\is_callable($callback)) {
1575
                                $closure = $callback->bindTo($testAdminPreValidate);
0 ignored issues
show
Bug introduced by
The method bindTo cannot be called on $callback (of type callable).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
1576
                                $closure($event);
1577
1578
                                return true;
1579
                            }
1580
1581
                            return false;
1582
                        }),
1583
                        $this->greaterThan(0)
1584
                    );
1585
1586
        $formContractor = $this->createMock(FormContractorInterface::class);
1587
        $formContractor
1588
                ->method('getDefaultOptions')
1589
                ->willReturn([]);
1590
        $formContractor
1591
                ->method('getFormBuilder')
1592
                ->willReturn($formBuild);
1593
1594
        $modelAdmin->setFormContractor($formContractor);
1595
        $modelAdmin->defineFormBuilder($formBuild);
1596
        $modelAdmin->getForm();
1597
    }
1598
1599
    public function testRemoveFieldFromFormGroup(): void
1600
    {
1601
        $formGroups = [
1602
            'foobar' => [
1603
                'fields' => [
1604
                    'foo' => 'foo',
1605
                    'bar' => 'bar',
1606
                ],
1607
            ],
1608
        ];
1609
1610
        $admin = new PostAdmin('sonata.post.admin.post', 'Application\Sonata\NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
1611
        $admin->setFormGroups($formGroups);
1612
1613
        $admin->removeFieldFromFormGroup('foo');
1614
        $this->assertSame($admin->getFormGroups(), [
1615
            'foobar' => [
1616
                'fields' => [
1617
                    'bar' => 'bar',
1618
                ],
1619
            ],
1620
        ]);
1621
1622
        $admin->removeFieldFromFormGroup('bar');
1623
        $this->assertSame($admin->getFormGroups(), []);
1624
    }
1625
1626
    public function testGetFilterParameters(): void
1627
    {
1628
        $authorId = uniqid();
1629
1630
        $postAdmin = new PostAdmin('sonata.post.admin.post', 'Application\Sonata\NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
1631
1632
        $commentAdmin = new CommentAdmin('sonata.post.admin.comment', 'Application\Sonata\NewsBundle\Entity\Comment', 'SonataNewsBundle:CommentAdmin');
1633
        $commentAdmin->setParentAssociationMapping('post.author');
1634
        $commentAdmin->setParent($postAdmin);
1635
1636
        $request = $this->createMock(Request::class);
1637
        $query = $this->createMock(ParameterBag::class);
1638
        $query
1639
            ->method('get')
1640
            ->willReturn([
1641
                'filter' => [
1642
                    '_page' => '1',
1643
                    '_per_page' => '32',
1644
                ],
1645
            ]);
1646
1647
        $request->query = $query;
1648
        $request
1649
            ->method('get')
1650
            ->willReturn($authorId);
1651
1652
        $commentAdmin->setRequest($request);
1653
1654
        $modelManager = $this->createMock(ModelManagerInterface::class);
1655
        $modelManager
1656
            ->method('getDefaultSortValues')
1657
            ->willReturn([]);
1658
1659
        $commentAdmin->setModelManager($modelManager);
1660
1661
        $parameters = $commentAdmin->getFilterParameters();
1662
1663
        $this->assertTrue(isset($parameters['post__author']));
1664
        $this->assertSame(['value' => $authorId], $parameters['post__author']);
1665
    }
1666
1667
    public function testGetFilterFieldDescription(): void
1668
    {
1669
        $modelAdmin = new ModelAdmin('sonata.post.admin.model', 'Application\Sonata\FooBundle\Entity\Model', 'SonataFooBundle:ModelAdmin');
1670
1671
        $fooFieldDescription = new FieldDescription();
1672
        $barFieldDescription = new FieldDescription();
1673
        $bazFieldDescription = new FieldDescription();
1674
1675
        $modelManager = $this->createMock(ModelManagerInterface::class);
1676
        $modelManager->expects($this->exactly(3))
1677
            ->method('getNewFieldDescriptionInstance')
1678
            ->willReturnCallback(static function ($adminClass, string $name, $filterOptions) use ($fooFieldDescription, $barFieldDescription, $bazFieldDescription) {
0 ignored issues
show
Unused Code introduced by
The parameter $filterOptions is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
1679
                switch ($name) {
1680
                    case 'foo':
1681
                        $fieldDescription = $fooFieldDescription;
1682
1683
                        break;
1684
1685
                    case 'bar':
1686
                        $fieldDescription = $barFieldDescription;
1687
1688
                        break;
1689
1690
                    case 'baz':
1691
                        $fieldDescription = $bazFieldDescription;
1692
1693
                        break;
1694
1695
                    default:
1696
                        throw new \RuntimeException(sprintf('Unknown filter name "%s"', $name));
1697
                        break;
0 ignored issues
show
Unused Code introduced by
break; does not seem to be reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
1698
                }
1699
1700
                $fieldDescription->setName($name);
1701
1702
                return $fieldDescription;
1703
            });
1704
1705
        $modelAdmin->setModelManager($modelManager);
1706
1707
        $pager = $this->createMock(PagerInterface::class);
1708
1709
        $datagrid = $this->createMock(DatagridInterface::class);
1710
        $datagrid->expects($this->once())
1711
            ->method('getPager')
1712
            ->willReturn($pager);
1713
1714
        $datagridBuilder = $this->createMock(DatagridBuilderInterface::class);
1715
        $datagridBuilder->expects($this->once())
1716
            ->method('getBaseDatagrid')
1717
            ->with($this->identicalTo($modelAdmin), [])
1718
            ->willReturn($datagrid);
1719
1720
        $datagridBuilder->expects($this->exactly(3))
1721
            ->method('addFilter')
1722
            ->willReturnCallback(static function ($datagrid, $type, $fieldDescription, AdminInterface $admin): void {
1723
                $admin->addFilterFieldDescription($fieldDescription->getName(), $fieldDescription);
1724
                $fieldDescription->mergeOption('field_options', ['required' => false]);
1725
            });
1726
1727
        $modelAdmin->setDatagridBuilder($datagridBuilder);
1728
1729
        $this->assertSame(['foo' => $fooFieldDescription, 'bar' => $barFieldDescription, 'baz' => $bazFieldDescription], $modelAdmin->getFilterFieldDescriptions());
1730
        $this->assertFalse($modelAdmin->hasFilterFieldDescription('fooBar'));
1731
        $this->assertTrue($modelAdmin->hasFilterFieldDescription('foo'));
1732
        $this->assertTrue($modelAdmin->hasFilterFieldDescription('bar'));
1733
        $this->assertTrue($modelAdmin->hasFilterFieldDescription('baz'));
1734
        $this->assertSame($fooFieldDescription, $modelAdmin->getFilterFieldDescription('foo'));
1735
        $this->assertSame($barFieldDescription, $modelAdmin->getFilterFieldDescription('bar'));
1736
        $this->assertSame($bazFieldDescription, $modelAdmin->getFilterFieldDescription('baz'));
1737
    }
1738
1739
    public function testGetSubjectNoRequest(): void
1740
    {
1741
        $modelManager = $this->createMock(ModelManagerInterface::class);
1742
        $modelManager
1743
            ->expects($this->never())
1744
            ->method('find');
1745
1746
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
1747
        $admin->setModelManager($modelManager);
1748
1749
        $this->assertNull($admin->getSubject());
1750
    }
1751
1752
    public function testGetSideMenu(): void
1753
    {
1754
        $item = $this->createMock(ItemInterface::class);
1755
        $item
1756
            ->expects($this->once())
1757
            ->method('setChildrenAttribute')
1758
            ->with('class', 'nav navbar-nav');
1759
        $item
1760
            ->expects($this->once())
1761
            ->method('setExtra')
1762
            ->with('translation_domain', 'foo_bar_baz');
1763
1764
        $menuFactory = $this->createMock(FactoryInterface::class);
1765
        $menuFactory
1766
            ->expects($this->once())
1767
            ->method('createItem')
1768
            ->willReturn($item);
1769
1770
        $modelAdmin = new ModelAdmin('sonata.post.admin.model', 'Application\Sonata\FooBundle\Entity\Model', 'SonataFooBundle:ModelAdmin');
1771
        $modelAdmin->setMenuFactory($menuFactory);
1772
        $modelAdmin->setTranslationDomain('foo_bar_baz');
1773
1774
        $modelAdmin->getSideMenu('foo');
1775
    }
1776
1777
    /**
1778
     * @return array
1779
     */
1780
    public function provideGetSubject()
1781
    {
1782
        return [
1783
            [23],
1784
            ['azerty'],
1785
            ['4f69bbb5f14a13347f000092'],
1786
            ['0779ca8d-e2be-11e4-ac58-0242ac11000b'],
1787
            ['123'.AdapterInterface::ID_SEPARATOR.'my_type'], // composite keys are supported
1788
        ];
1789
    }
1790
1791
    /**
1792
     * @dataProvider provideGetSubject
1793
     */
1794
    public function testGetSubjectFailed($id): void
1795
    {
1796
        $modelManager = $this->createMock(ModelManagerInterface::class);
1797
        $modelManager
1798
            ->expects($this->once())
1799
            ->method('find')
1800
            ->with('NewsBundle\Entity\Post', $id)
1801
            ->willReturn(null); // entity not found
1802
1803
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
1804
        $admin->setModelManager($modelManager);
1805
1806
        $admin->setRequest(new Request(['id' => $id]));
1807
        $this->assertNull($admin->getSubject());
1808
    }
1809
1810
    /**
1811
     * @dataProvider provideGetSubject
1812
     */
1813
    public function testGetSubject($id): void
1814
    {
1815
        $entity = new Post();
1816
1817
        $modelManager = $this->createMock(ModelManagerInterface::class);
1818
        $modelManager
1819
            ->expects($this->once())
1820
            ->method('find')
1821
            ->with('NewsBundle\Entity\Post', $id)
1822
            ->willReturn($entity);
1823
1824
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
1825
        $admin->setModelManager($modelManager);
1826
1827
        $admin->setRequest(new Request(['id' => $id]));
1828
        $this->assertSame($entity, $admin->getSubject());
1829
        $this->assertSame($entity, $admin->getSubject()); // model manager must be used only once
1830
    }
1831
1832
    public function testGetSubjectWithParentDescription(): void
1833
    {
1834
        $adminId = 1;
1835
1836
        $comment = new Comment();
1837
1838
        $modelManager = $this->createMock(ModelManagerInterface::class);
1839
        $modelManager
1840
            ->method('find')
1841
            ->with('NewsBundle\Entity\Comment', $adminId)
1842
            ->willReturn($comment);
1843
1844
        $request = new Request(['id' => $adminId]);
1845
1846
        $postAdmin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
1847
        $postAdmin->setRequest($request);
1848
1849
        $commentAdmin = new CommentAdmin('sonata.post.admin.comment', 'NewsBundle\Entity\Comment', 'SonataNewsBundle:CommentAdmin');
1850
        $commentAdmin->setRequest($request);
1851
        $commentAdmin->setModelManager($modelManager);
1852
1853
        $this->assertSame($comment, $commentAdmin->getSubject());
1854
1855
        $commentAdmin->setSubject(null);
1856
        $commentAdmin->setParentFieldDescription(new FieldDescription());
1857
1858
        $this->assertNull($commentAdmin->getSubject());
1859
    }
1860
1861
    /**
1862
     * @covers \Sonata\AdminBundle\Admin\AbstractAdmin::configureActionButtons
1863
     */
1864
    public function testGetActionButtonsList(): void
1865
    {
1866
        $expected = [
1867
            'create' => [
1868
                'template' => 'Foo.html.twig',
1869
            ],
1870
        ];
1871
1872
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
1873
1874
        $templateRegistry = $this->prophesize(MutableTemplateRegistryInterface::class);
1875
        $templateRegistry->getTemplate('button_create')->willReturn('Foo.html.twig');
1876
1877
        $admin->setTemplateRegistry($templateRegistry->reveal());
1878
1879
        $securityHandler = $this->createMock(SecurityHandlerInterface::class);
1880
        $securityHandler
1881
            ->expects($this->once())
1882
            ->method('isGranted')
1883
            ->with($admin, 'CREATE', $admin)
1884
            ->willReturn(true);
1885
        $admin->setSecurityHandler($securityHandler);
1886
1887
        $routeGenerator = $this->createMock(RouteGeneratorInterface::class);
1888
        $routeGenerator
1889
            ->expects($this->once())
1890
            ->method('hasAdminRoute')
1891
            ->with($admin, 'create')
1892
            ->willReturn(true);
1893
        $admin->setRouteGenerator($routeGenerator);
1894
1895
        $this->assertSame($expected, $admin->getActionButtons('list', null));
1896
    }
1897
1898
    /**
1899
     * @covers \Sonata\AdminBundle\Admin\AbstractAdmin::configureActionButtons
1900
     */
1901
    public function testGetActionButtonsListCreateDisabled(): void
1902
    {
1903
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
1904
1905
        $securityHandler = $this->createMock(SecurityHandlerInterface::class);
1906
        $securityHandler
1907
            ->expects($this->once())
1908
            ->method('isGranted')
1909
            ->with($admin, 'CREATE', $admin)
1910
            ->willReturn(false);
1911
        $admin->setSecurityHandler($securityHandler);
1912
1913
        $this->assertSame([], $admin->getActionButtons('list', null));
1914
    }
1915
1916
    /**
1917
     * @covers \Sonata\AdminBundle\Admin\AbstractAdmin::configureBatchActions
1918
     */
1919
    public function testGetBatchActions(): void
1920
    {
1921
        $expected = [
1922
            'delete' => [
1923
                'label' => 'action_delete',
1924
                'translation_domain' => 'SonataAdminBundle',
1925
                'ask_confirmation' => true, // by default always true
1926
            ],
1927
            'foo' => [
1928
                'label' => 'action_foo',
1929
                'translation_domain' => 'SonataAdminBundle',
1930
            ],
1931
            'bar' => [
1932
                'label' => 'batch.label_bar',
1933
                'translation_domain' => 'SonataAdminBundle',
1934
            ],
1935
            'baz' => [
1936
                'label' => 'action_baz',
1937
                'translation_domain' => 'AcmeAdminBundle',
1938
            ],
1939
        ];
1940
1941
        $pathInfo = new PathInfoBuilder($this->createMock(AuditManagerInterface::class));
1942
1943
        $labelTranslatorStrategy = $this->createMock(LabelTranslatorStrategyInterface::class);
1944
        $labelTranslatorStrategy
1945
            ->method('getLabel')
1946
            ->willReturnCallback(static function (string $label, string $context = '', string $type = ''): string {
1947
                return $context.'.'.$type.'_'.$label;
1948
            });
1949
1950
        $admin = new PostAdmin('sonata.post.admin.model', 'Application\Sonata\FooBundle\Entity\Model', 'SonataFooBundle:ModelAdmin');
1951
        $admin->setRouteBuilder($pathInfo);
1952
        $admin->setTranslationDomain('SonataAdminBundle');
1953
        $admin->setLabelTranslatorStrategy($labelTranslatorStrategy);
1954
1955
        $routeGenerator = $this->createMock(RouteGeneratorInterface::class);
1956
        $routeGenerator
1957
            ->expects($this->once())
1958
            ->method('hasAdminRoute')
1959
            ->with($admin, 'delete')
1960
            ->willReturn(true);
1961
        $admin->setRouteGenerator($routeGenerator);
1962
1963
        $securityHandler = $this->createMock(SecurityHandlerInterface::class);
1964
        $securityHandler
1965
            ->method('isGranted')
1966
            ->willReturnCallback(static function (AdminInterface $adminIn, string $attributes, $object = null) use ($admin): bool {
0 ignored issues
show
Unused Code introduced by
The parameter $object is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
1967
                return $admin === $adminIn && 'DELETE' === $attributes;
1968
            });
1969
        $admin->setSecurityHandler($securityHandler);
1970
1971
        $this->assertSame($expected, $admin->getBatchActions());
1972
    }
1973
1974
    /**
1975
     * @covers \Sonata\AdminBundle\Admin\AbstractAdmin::showMosaicButton
1976
     */
1977
    public function testShowMosaicButton(): void
1978
    {
1979
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
1980
        $listModes = $admin->getListModes();
1981
1982
        $admin->showMosaicButton(true);
1983
1984
        $this->assertSame($listModes, $admin->getListModes());
1985
    }
1986
1987
    /**
1988
     * @covers \Sonata\AdminBundle\Admin\AbstractAdmin::showMosaicButton
1989
     */
1990
    public function testShowMosaicButtonHideMosaic(): void
1991
    {
1992
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
1993
        $listModes = $admin->getListModes();
1994
        $expected['list'] = $listModes['list'];
0 ignored issues
show
Coding Style Comprehensibility introduced by
$expected was never initialized. Although not strictly required by PHP, it is generally a good practice to add $expected = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
1995
1996
        $admin->showMosaicButton(false);
1997
1998
        $this->assertSame($expected, $admin->getListModes());
1999
    }
2000
2001
    /**
2002
     * @covers \Sonata\AdminBundle\Admin\AbstractAdmin::getDashboardActions
2003
     * @dataProvider provideGetBaseRouteName
2004
     */
2005
    public function testDefaultDashboardActionsArePresent(string $objFqn, string $expected): void
2006
    {
2007
        $pathInfo = new PathInfoBuilder($this->createMock(AuditManagerInterface::class));
2008
2009
        $routeGenerator = new DefaultRouteGenerator(
2010
            $this->createMock(RouterInterface::class),
2011
            new RoutesCache($this->cacheTempFolder, true)
2012
        );
2013
2014
        $admin = new PostAdmin('sonata.post.admin.post', $objFqn, 'SonataNewsBundle:PostAdmin');
2015
        $admin->setRouteBuilder($pathInfo);
2016
        $admin->setRouteGenerator($routeGenerator);
2017
        $admin->initialize();
2018
2019
        $templateRegistry = $this->prophesize(MutableTemplateRegistryInterface::class);
2020
        $templateRegistry->getTemplate('action_create')->willReturn('Foo.html.twig');
2021
2022
        $admin->setTemplateRegistry($templateRegistry->reveal());
2023
2024
        $securityHandler = $this->createMock(SecurityHandlerInterface::class);
2025
        $securityHandler
2026
            ->method('isGranted')
2027
            ->willReturnCallback(static function (AdminInterface $adminIn, string $attributes, $object = null) use ($admin): bool {
0 ignored issues
show
Unused Code introduced by
The parameter $object is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
2028
                return $admin === $adminIn && ('CREATE' === $attributes || 'LIST' === $attributes);
2029
            });
2030
2031
        $admin->setSecurityHandler($securityHandler);
2032
2033
        $this->assertArrayHasKey('list', $admin->getDashboardActions());
2034
        $this->assertArrayHasKey('create', $admin->getDashboardActions());
2035
    }
2036
2037
    public function testDefaultFilters(): void
2038
    {
2039
        $admin = new FilteredAdmin('sonata.post.admin.model', 'Application\Sonata\FooBundle\Entity\Model', 'SonataFooBundle:ModelAdmin');
2040
2041
        $subjectId = uniqid();
2042
2043
        $request = $this->createMock(Request::class);
2044
        $query = $this->createMock(ParameterBag::class);
2045
        $query
2046
            ->method('get')
2047
            ->with($this->equalTo('filter'))
2048
            ->willReturn([
2049
                'a' => [
2050
                    'value' => 'b',
2051
                ],
2052
                'foo' => [
2053
                    'type' => '1',
2054
                    'value' => 'bar',
2055
                ],
2056
                'baz' => [
2057
                    'type' => '5',
2058
                    'value' => 'test',
2059
                ],
2060
            ]);
2061
        $request->query = $query;
2062
2063
        $request
2064
            ->method('get')
2065
            ->willReturn($subjectId);
2066
2067
        $admin->setRequest($request);
2068
2069
        $modelManager = $this->createMock(ModelManagerInterface::class);
2070
        $modelManager
2071
            ->method('getDefaultSortValues')
2072
            ->willReturn([]);
2073
2074
        $admin->setModelManager($modelManager);
2075
2076
        $this->assertSame([
2077
            '_page' => 1,
2078
            '_per_page' => 32,
2079
            'foo' => [
2080
                'type' => '1',
2081
                'value' => 'bar',
2082
            ],
2083
            'baz' => [
2084
                'type' => '5',
2085
                'value' => 'test',
2086
            ],
2087
            'a' => [
2088
                'value' => 'b',
2089
            ],
2090
        ], $admin->getFilterParameters());
2091
2092
        $this->assertTrue($admin->isDefaultFilter('foo'));
2093
        $this->assertFalse($admin->isDefaultFilter('bar'));
2094
        $this->assertFalse($admin->isDefaultFilter('a'));
2095
    }
2096
2097
    /**
2098
     * NEXT_MAJOR: remove this method.
2099
     *
2100
     * @group legacy
2101
     */
2102
    public function testCreateQueryLegacyCallWorks(): void
2103
    {
2104
        $admin = $this->getMockForAbstractClass(AbstractAdmin::class, [
2105
            'admin.my_code', 'My\Class', 'MyBundle:ClassAdmin',
2106
        ]);
2107
        $modelManager = $this->createMock(ModelManagerInterface::class);
2108
        $modelManager->expects($this->once())
2109
            ->method('createQuery')
2110
            ->with('My\Class')
2111
            ->willReturn('a query');
2112
2113
        $admin->setModelManager($modelManager);
2114
        $this->assertSame('a query', $admin->createQuery('list'));
2115
    }
2116
2117
    public function testGetDataSourceIterator(): void
2118
    {
2119
        $datagrid = $this->createMock(DatagridInterface::class);
2120
        $datagrid->method('buildPager');
2121
2122
        $modelManager = $this->createMock(ModelManagerInterface::class);
2123
        $modelManager->method('getExportFields')->willReturn([
2124
            'field',
2125
            'foo',
2126
            'bar',
2127
        ]);
2128
        $modelManager->expects($this->once())->method('getDataSourceIterator')
2129
            ->with($this->equalTo($datagrid), $this->equalTo([
2130
                'Feld' => 'field',
2131
                1 => 'foo',
2132
                2 => 'bar',
2133
            ]));
2134
2135
        $admin = $this->getMockBuilder(AbstractAdmin::class)
2136
            ->disableOriginalConstructor()
2137
            ->setMethods(['getDatagrid', 'getTranslationLabel', 'trans'])
2138
            ->getMockForAbstractClass();
2139
        $admin->method('getDatagrid')->willReturn($datagrid);
2140
        $admin->setModelManager($modelManager);
2141
2142
        $admin
2143
            ->method('getTranslationLabel')
2144
            ->willReturnCallback(static function (string $label, string $context = '', string $type = ''): string {
2145
                return $context.'.'.$type.'_'.$label;
2146
            });
2147
        $admin
2148
            ->method('trans')
2149
            ->willReturnCallback(static function (string $label): string {
2150
                if ('export.label_field' === $label) {
2151
                    return 'Feld';
2152
                }
2153
2154
                return $label;
2155
            });
2156
2157
        $admin->getDataSourceIterator();
2158
    }
2159
2160
    public function testCircularChildAdmin(): void
2161
    {
2162
        $this->expectException(\RuntimeException::class);
2163
        $this->expectExceptionMessage(
2164
            'Circular reference detected! The child admin `sonata.post.admin.post` is already in the parent tree of the `sonata.post.admin.comment` admin.'
2165
        );
2166
2167
        $postAdmin = new PostAdmin(
2168
            'sonata.post.admin.post',
2169
            'Application\Sonata\NewsBundle\Entity\Post',
2170
            'SonataNewsBundle:PostAdmin'
2171
        );
2172
        $commentAdmin = new CommentAdmin(
2173
            'sonata.post.admin.comment',
2174
            'Application\Sonata\NewsBundle\Entity\Comment',
2175
            'SonataNewsBundle:CommentAdmin'
2176
        );
2177
        $postAdmin->addChild($commentAdmin, 'post');
2178
        $commentAdmin->addChild($postAdmin, 'comment');
2179
    }
2180
2181
    public function testCircularChildAdminTripleLevel(): void
2182
    {
2183
        $this->expectException(\RuntimeException::class);
2184
        $this->expectExceptionMessage(
2185
            'Circular reference detected! The child admin `sonata.post.admin.post` is already in the parent tree of the `sonata.post.admin.comment_vote` admin.'
2186
        );
2187
2188
        $postAdmin = new PostAdmin(
2189
            'sonata.post.admin.post',
2190
            'Application\Sonata\NewsBundle\Entity\Post',
2191
            'SonataNewsBundle:PostAdmin'
2192
        );
2193
        $commentAdmin = new CommentAdmin(
2194
            'sonata.post.admin.comment',
2195
            'Application\Sonata\NewsBundle\Entity\Comment',
2196
            'SonataNewsBundle:CommentAdmin'
2197
        );
2198
        $commentVoteAdmin = new CommentVoteAdmin(
2199
            'sonata.post.admin.comment_vote',
2200
            'Application\Sonata\NewsBundle\Entity\CommentVote',
2201
            'SonataNewsBundle:CommentVoteAdmin'
2202
        );
2203
        $postAdmin->addChild($commentAdmin, 'post');
2204
        $commentAdmin->addChild($commentVoteAdmin, 'comment');
2205
        $commentVoteAdmin->addChild($postAdmin, 'post');
2206
    }
2207
2208
    public function testCircularChildAdminWithItself(): void
2209
    {
2210
        $this->expectException(\RuntimeException::class);
2211
        $this->expectExceptionMessage(
2212
            'Circular reference detected! The child admin `sonata.post.admin.post` is already in the parent tree of the `sonata.post.admin.post` admin.'
2213
        );
2214
2215
        $postAdmin = new PostAdmin(
2216
            'sonata.post.admin.post',
2217
            'Application\Sonata\NewsBundle\Entity\Post',
2218
            'SonataNewsBundle:PostAdmin'
2219
        );
2220
        $postAdmin->addChild($postAdmin);
2221
    }
2222
2223
    public function testGetRootAncestor(): void
2224
    {
2225
        $postAdmin = new PostAdmin(
2226
            'sonata.post.admin.post',
2227
            'Application\Sonata\NewsBundle\Entity\Post',
2228
            'SonataNewsBundle:PostAdmin'
2229
        );
2230
        $commentAdmin = new CommentAdmin(
2231
            'sonata.post.admin.comment',
2232
            'Application\Sonata\NewsBundle\Entity\Comment',
2233
            'SonataNewsBundle:CommentAdmin'
2234
        );
2235
        $commentVoteAdmin = new CommentVoteAdmin(
2236
            'sonata.post.admin.comment_vote',
2237
            'Application\Sonata\NewsBundle\Entity\CommentVote',
2238
            'SonataNewsBundle:CommentVoteAdmin'
2239
        );
2240
2241
        $this->assertSame($postAdmin, $postAdmin->getRootAncestor());
2242
        $this->assertSame($commentAdmin, $commentAdmin->getRootAncestor());
2243
        $this->assertSame($commentVoteAdmin, $commentVoteAdmin->getRootAncestor());
2244
2245
        $postAdmin->addChild($commentAdmin, 'post');
2246
2247
        $this->assertSame($postAdmin, $postAdmin->getRootAncestor());
2248
        $this->assertSame($postAdmin, $commentAdmin->getRootAncestor());
2249
        $this->assertSame($commentVoteAdmin, $commentVoteAdmin->getRootAncestor());
2250
2251
        $commentAdmin->addChild($commentVoteAdmin, 'comment');
2252
2253
        $this->assertSame($postAdmin, $postAdmin->getRootAncestor());
2254
        $this->assertSame($postAdmin, $commentAdmin->getRootAncestor());
2255
        $this->assertSame($postAdmin, $commentVoteAdmin->getRootAncestor());
2256
    }
2257
2258
    public function testGetChildDepth(): void
2259
    {
2260
        $postAdmin = new PostAdmin(
2261
            'sonata.post.admin.post',
2262
            'Application\Sonata\NewsBundle\Entity\Post',
2263
            'SonataNewsBundle:PostAdmin'
2264
        );
2265
        $commentAdmin = new CommentAdmin(
2266
            'sonata.post.admin.comment',
2267
            'Application\Sonata\NewsBundle\Entity\Comment',
2268
            'SonataNewsBundle:CommentAdmin'
2269
        );
2270
        $commentVoteAdmin = new CommentVoteAdmin(
2271
            'sonata.post.admin.comment_vote',
2272
            'Application\Sonata\NewsBundle\Entity\CommentVote',
2273
            'SonataNewsBundle:CommentVoteAdmin'
2274
        );
2275
2276
        $this->assertSame(0, $postAdmin->getChildDepth());
2277
        $this->assertSame(0, $commentAdmin->getChildDepth());
2278
        $this->assertSame(0, $commentVoteAdmin->getChildDepth());
2279
2280
        $postAdmin->addChild($commentAdmin, 'post');
2281
2282
        $this->assertSame(0, $postAdmin->getChildDepth());
2283
        $this->assertSame(1, $commentAdmin->getChildDepth());
2284
        $this->assertSame(0, $commentVoteAdmin->getChildDepth());
2285
2286
        $commentAdmin->addChild($commentVoteAdmin, 'comment');
2287
2288
        $this->assertSame(0, $postAdmin->getChildDepth());
2289
        $this->assertSame(1, $commentAdmin->getChildDepth());
2290
        $this->assertSame(2, $commentVoteAdmin->getChildDepth());
2291
    }
2292
2293
    public function testGetCurrentLeafChildAdmin(): void
2294
    {
2295
        $postAdmin = new PostAdmin(
2296
            'sonata.post.admin.post',
2297
            'Application\Sonata\NewsBundle\Entity\Post',
2298
            'SonataNewsBundle:PostAdmin'
2299
        );
2300
        $commentAdmin = new CommentAdmin(
2301
            'sonata.post.admin.comment',
2302
            'Application\Sonata\NewsBundle\Entity\Comment',
2303
            'SonataNewsBundle:CommentAdmin'
2304
        );
2305
        $commentVoteAdmin = new CommentVoteAdmin(
2306
            'sonata.post.admin.comment_vote',
2307
            'Application\Sonata\NewsBundle\Entity\CommentVote',
2308
            'SonataNewsBundle:CommentVoteAdmin'
2309
        );
2310
2311
        $postAdmin->addChild($commentAdmin, 'post');
2312
        $commentAdmin->addChild($commentVoteAdmin, 'comment');
2313
2314
        $this->assertNull($postAdmin->getCurrentLeafChildAdmin());
2315
        $this->assertNull($commentAdmin->getCurrentLeafChildAdmin());
2316
        $this->assertNull($commentVoteAdmin->getCurrentLeafChildAdmin());
2317
2318
        $commentAdmin->setCurrentChild(true);
2319
2320
        $this->assertSame($commentAdmin, $postAdmin->getCurrentLeafChildAdmin());
2321
        $this->assertNull($commentAdmin->getCurrentLeafChildAdmin());
2322
        $this->assertNull($commentVoteAdmin->getCurrentLeafChildAdmin());
2323
2324
        $commentVoteAdmin->setCurrentChild(true);
2325
2326
        $this->assertSame($commentVoteAdmin, $postAdmin->getCurrentLeafChildAdmin());
2327
        $this->assertSame($commentVoteAdmin, $commentAdmin->getCurrentLeafChildAdmin());
2328
        $this->assertNull($commentVoteAdmin->getCurrentLeafChildAdmin());
2329
    }
2330
2331
    private function createTagAdmin(Post $post): TagAdmin
2332
    {
2333
        $postAdmin = $this->getMockBuilder(PostAdmin::class)
2334
            ->disableOriginalConstructor()
2335
            ->getMock();
2336
2337
        $postAdmin->method('getObject')->willReturn($post);
2338
2339
        $formBuilder = $this->createMock(FormBuilderInterface::class);
2340
        $formBuilder->method('getForm')->willReturn(null);
2341
2342
        $tagAdmin = $this->getMockBuilder(TagAdmin::class)
2343
            ->setConstructorArgs([
2344
                'admin.tag',
2345
                Tag::class,
2346
                'MyBundle:MyController',
2347
            ])
2348
            ->setMethods(['getFormBuilder'])
2349
            ->getMock();
2350
2351
        $tagAdmin->method('getFormBuilder')->willReturn($formBuilder);
2352
        $tagAdmin->setParent($postAdmin);
2353
2354
        $tag = new Tag();
2355
        $tagAdmin->setSubject($tag);
2356
2357
        $request = $this->createMock(Request::class);
2358
        $tagAdmin->setRequest($request);
2359
2360
        $configurationPool = $this->getMockBuilder(Pool::class)
2361
            ->disableOriginalConstructor()
2362
            ->getMock();
2363
2364
        $configurationPool->method('getPropertyAccessor')->willReturn(PropertyAccess::createPropertyAccessor());
2365
2366
        $tagAdmin->setConfigurationPool($configurationPool);
2367
2368
        return $tagAdmin;
2369
    }
2370
}
2371