Completed
Push — 3.x ( 05ced7...c72a17 )
by Oskar
03:54
created

tests/Admin/AdminTest.php (5 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of the Sonata Project package.
7
 *
8
 * (c) Thomas Rabaix <[email protected]>
9
 *
10
 * For the full copyright and license information, please view the LICENSE
11
 * file that was distributed with this source code.
12
 */
13
14
namespace Sonata\AdminBundle\Tests\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\BreadcrumbsBuilder;
25
use Sonata\AdminBundle\Admin\BreadcrumbsBuilderInterface;
26
use Sonata\AdminBundle\Admin\FieldDescriptionInterface;
27
use Sonata\AdminBundle\Admin\Pool;
28
use Sonata\AdminBundle\Builder\DatagridBuilderInterface;
29
use Sonata\AdminBundle\Builder\FormContractorInterface;
30
use Sonata\AdminBundle\Builder\ListBuilderInterface;
31
use Sonata\AdminBundle\Builder\RouteBuilderInterface;
32
use Sonata\AdminBundle\Builder\ShowBuilderInterface;
33
use Sonata\AdminBundle\Datagrid\DatagridInterface;
34
use Sonata\AdminBundle\Datagrid\PagerInterface;
35
use Sonata\AdminBundle\Model\AuditManagerInterface;
36
use Sonata\AdminBundle\Model\ModelManagerInterface;
37
use Sonata\AdminBundle\Route\DefaultRouteGenerator;
38
use Sonata\AdminBundle\Route\PathInfoBuilder;
39
use Sonata\AdminBundle\Route\RouteGeneratorInterface;
40
use Sonata\AdminBundle\Route\RoutesCache;
41
use Sonata\AdminBundle\Security\Handler\AclSecurityHandlerInterface;
42
use Sonata\AdminBundle\Security\Handler\SecurityHandlerInterface;
43
use Sonata\AdminBundle\Templating\MutableTemplateRegistryInterface;
44
use Sonata\AdminBundle\Tests\Fixtures\Admin\CommentAdmin;
45
use Sonata\AdminBundle\Tests\Fixtures\Admin\CommentVoteAdmin;
46
use Sonata\AdminBundle\Tests\Fixtures\Admin\CommentWithCustomRouteAdmin;
47
use Sonata\AdminBundle\Tests\Fixtures\Admin\FieldDescription;
48
use Sonata\AdminBundle\Tests\Fixtures\Admin\FilteredAdmin;
49
use Sonata\AdminBundle\Tests\Fixtures\Admin\ModelAdmin;
50
use Sonata\AdminBundle\Tests\Fixtures\Admin\PostAdmin;
51
use Sonata\AdminBundle\Tests\Fixtures\Admin\PostWithCustomRouteAdmin;
52
use Sonata\AdminBundle\Tests\Fixtures\Admin\TagAdmin;
53
use Sonata\AdminBundle\Tests\Fixtures\Bundle\Entity\BlogPost;
54
use Sonata\AdminBundle\Tests\Fixtures\Bundle\Entity\Comment;
55
use Sonata\AdminBundle\Tests\Fixtures\Bundle\Entity\Post;
56
use Sonata\AdminBundle\Tests\Fixtures\Bundle\Entity\Tag;
57
use Sonata\AdminBundle\Tests\Fixtures\Entity\FooToString;
58
use Sonata\AdminBundle\Tests\Fixtures\Entity\FooToStringNull;
59
use Sonata\AdminBundle\Translator\LabelTranslatorStrategyInterface;
60
use Sonata\Doctrine\Adapter\AdapterInterface;
61
use Symfony\Component\DependencyInjection\Container;
62
use Symfony\Component\DependencyInjection\ContainerInterface;
63
use Symfony\Component\Form\FormBuilder;
64
use Symfony\Component\Form\FormBuilderInterface;
65
use Symfony\Component\Form\FormEvent;
66
use Symfony\Component\Form\FormEvents;
67
use Symfony\Component\HttpFoundation\ParameterBag;
68
use Symfony\Component\HttpFoundation\Request;
69
use Symfony\Component\PropertyAccess\PropertyAccess;
70
use Symfony\Component\Routing\RouterInterface;
71
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
72
use Symfony\Component\Translation\TranslatorInterface;
73
use Symfony\Component\Validator\Mapping\MemberMetadata;
74
use Symfony\Component\Validator\Validator\ValidatorInterface;
75
76
class AdminTest extends TestCase
77
{
78
    protected $cacheTempFolder;
79
80
    public function setUp(): void
81
    {
82
        $this->cacheTempFolder = sys_get_temp_dir().'/sonata_test_route';
83
84
        exec('rm -rf '.$this->cacheTempFolder);
85
    }
86
87
    /**
88
     * @covers \Sonata\AdminBundle\Admin\AbstractAdmin::__construct
89
     */
90
    public function testConstructor(): void
91
    {
92
        $class = 'Application\Sonata\NewsBundle\Entity\Post';
93
        $baseControllerName = 'SonataNewsBundle:PostAdmin';
94
95
        $admin = new PostAdmin('sonata.post.admin.post', $class, $baseControllerName);
96
        $this->assertInstanceOf(AbstractAdmin::class, $admin);
97
        $this->assertSame($class, $admin->getClass());
98
        $this->assertSame($baseControllerName, $admin->getBaseControllerName());
99
    }
100
101
    public function testGetClass(): void
102
    {
103
        $class = Post::class;
104
        $baseControllerName = 'SonataNewsBundle:PostAdmin';
105
106
        $admin = new PostAdmin('sonata.post.admin.post', $class, $baseControllerName);
107
108
        $admin->setModelManager($this->getMockForAbstractClass(ModelManagerInterface::class));
109
110
        $admin->setSubject(new BlogPost());
111
        $this->assertSame(BlogPost::class, $admin->getClass());
112
113
        $admin->setSubClasses(['foo']);
114
        $this->assertSame(BlogPost::class, $admin->getClass());
115
116
        $admin->setSubject(null);
117
        $admin->setSubClasses([]);
118
        $this->assertSame($class, $admin->getClass());
119
120
        $admin->setSubClasses(['foo' => 'bar']);
121
        $admin->setRequest(new Request(['subclass' => 'foo']));
122
        $this->assertSame('bar', $admin->getClass());
123
    }
124
125
    public function testGetClassException(): void
126
    {
127
        $this->expectException(\RuntimeException::class);
128
        $this->expectExceptionMessage('Feature not implemented: an embedded admin cannot have subclass');
129
130
        $class = 'Application\Sonata\NewsBundle\Entity\Post';
131
        $baseControllerName = 'SonataNewsBundle:PostAdmin';
132
133
        $admin = new PostAdmin('sonata.post.admin.post', $class, $baseControllerName);
134
        $admin->setParentFieldDescription(new FieldDescription());
135
        $admin->setSubClasses(['foo' => 'bar']);
136
        $admin->setRequest(new Request(['subclass' => 'foo']));
137
        $admin->getClass();
138
    }
139
140
    public function testCheckAccessThrowsExceptionOnMadeUpAction(): void
141
    {
142
        $admin = new PostAdmin(
143
            'sonata.post.admin.post',
144
            'Application\Sonata\NewsBundle\Entity\Post',
145
            'SonataNewsBundle:PostAdmin'
146
        );
147
        $this->expectException(
148
            \InvalidArgumentException::class
149
        );
150
        $this->expectExceptionMessage(
151
            'Action "made-up" could not be found'
152
        );
153
        $admin->checkAccess('made-up');
154
    }
155
156
    public function testCheckAccessThrowsAccessDeniedException(): void
157
    {
158
        $admin = new PostAdmin(
159
            'sonata.post.admin.post',
160
            'Application\Sonata\NewsBundle\Entity\Post',
161
            'SonataNewsBundle:PostAdmin'
162
        );
163
        $securityHandler = $this->prophesize(SecurityHandlerInterface::class);
164
        $securityHandler->isGranted($admin, 'CUSTOM_ROLE', $admin)->willReturn(true);
165
        $securityHandler->isGranted($admin, 'EXTRA_CUSTOM_ROLE', $admin)->willReturn(false);
166
        $customExtension = $this->prophesize(AbstractAdminExtension::class);
167
        $customExtension->getAccessMapping($admin)->willReturn(
168
            ['custom_action' => ['CUSTOM_ROLE', 'EXTRA_CUSTOM_ROLE']]
169
        );
170
        $admin->addExtension($customExtension->reveal());
171
        $admin->setSecurityHandler($securityHandler->reveal());
172
        $this->expectException(
173
            AccessDeniedException::class
174
        );
175
        $this->expectExceptionMessage(
176
            'Access Denied to the action custom_action and role EXTRA_CUSTOM_ROLE'
177
        );
178
        $admin->checkAccess('custom_action');
179
    }
180
181
    public function testHasAccessOnMadeUpAction(): void
182
    {
183
        $admin = new PostAdmin(
184
            'sonata.post.admin.post',
185
            'Application\Sonata\NewsBundle\Entity\Post',
186
            'SonataNewsBundle:PostAdmin'
187
        );
188
189
        $this->assertFalse($admin->hasAccess('made-up'));
190
    }
191
192
    public function testHasAccess(): void
193
    {
194
        $admin = new PostAdmin(
195
            'sonata.post.admin.post',
196
            'Application\Sonata\NewsBundle\Entity\Post',
197
            'SonataNewsBundle:PostAdmin'
198
        );
199
        $securityHandler = $this->prophesize(SecurityHandlerInterface::class);
200
        $securityHandler->isGranted($admin, 'CUSTOM_ROLE', $admin)->willReturn(true);
201
        $securityHandler->isGranted($admin, 'EXTRA_CUSTOM_ROLE', $admin)->willReturn(false);
202
        $customExtension = $this->prophesize(AbstractAdminExtension::class);
203
        $customExtension->getAccessMapping($admin)->willReturn(
204
            ['custom_action' => ['CUSTOM_ROLE', 'EXTRA_CUSTOM_ROLE']]
205
        );
206
        $admin->addExtension($customExtension->reveal());
207
        $admin->setSecurityHandler($securityHandler->reveal());
208
209
        $this->assertFalse($admin->hasAccess('custom_action'));
210
    }
211
212
    public function testHasAccessAllowsAccess(): void
213
    {
214
        $admin = new PostAdmin(
215
            'sonata.post.admin.post',
216
            'Application\Sonata\NewsBundle\Entity\Post',
217
            'SonataNewsBundle:PostAdmin'
218
        );
219
        $securityHandler = $this->prophesize(SecurityHandlerInterface::class);
220
        $securityHandler->isGranted($admin, 'CUSTOM_ROLE', $admin)->willReturn(true);
221
        $securityHandler->isGranted($admin, 'EXTRA_CUSTOM_ROLE', $admin)->willReturn(true);
222
        $customExtension = $this->prophesize(AbstractAdminExtension::class);
223
        $customExtension->getAccessMapping($admin)->willReturn(
224
            ['custom_action' => ['CUSTOM_ROLE', 'EXTRA_CUSTOM_ROLE']]
225
        );
226
        $admin->addExtension($customExtension->reveal());
227
        $admin->setSecurityHandler($securityHandler->reveal());
228
229
        $this->assertTrue($admin->hasAccess('custom_action'));
230
    }
231
232
    public function testHasAccessAllowsAccessEditAction(): void
233
    {
234
        $admin = new PostAdmin(
235
            'sonata.post.admin.post',
236
            'Application\Sonata\NewsBundle\Entity\Post',
237
            'SonataNewsBundle:PostAdmin'
238
        );
239
        $securityHandler = $this->prophesize(SecurityHandlerInterface::class);
240
        $securityHandler->isGranted($admin, 'EDIT_ROLE', $admin)->willReturn(true);
241
        $customExtension = $this->prophesize(AbstractAdminExtension::class);
242
        $customExtension->getAccessMapping($admin)->willReturn(
243
            ['edit_action' => ['EDIT_ROLE']]
244
        );
245
        $admin->addExtension($customExtension->reveal());
246
        $admin->setSecurityHandler($securityHandler->reveal());
247
248
        $this->assertTrue($admin->hasAccess('edit_action'));
249
    }
250
251
    /**
252
     * @covers \Sonata\AdminBundle\Admin\AbstractAdmin::hasChild
253
     * @covers \Sonata\AdminBundle\Admin\AbstractAdmin::addChild
254
     * @covers \Sonata\AdminBundle\Admin\AbstractAdmin::getChild
255
     * @covers \Sonata\AdminBundle\Admin\AbstractAdmin::isChild
256
     * @covers \Sonata\AdminBundle\Admin\AbstractAdmin::hasChildren
257
     * @covers \Sonata\AdminBundle\Admin\AbstractAdmin::getChildren
258
     */
259
    public function testChildren(): void
260
    {
261
        $postAdmin = new PostAdmin('sonata.post.admin.post', 'Application\Sonata\NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
262
        $this->assertFalse($postAdmin->hasChildren());
263
        $this->assertFalse($postAdmin->hasChild('comment'));
264
265
        $commentAdmin = new CommentAdmin('sonata.post.admin.comment', 'Application\Sonata\NewsBundle\Entity\Comment', 'SonataNewsBundle:CommentAdmin');
266
        $postAdmin->addChild($commentAdmin, 'post');
267
268
        $this->assertTrue($postAdmin->hasChildren());
269
        $this->assertTrue($postAdmin->hasChild('sonata.post.admin.comment'));
270
271
        $this->assertSame('sonata.post.admin.comment', $postAdmin->getChild('sonata.post.admin.comment')->getCode());
272
        $this->assertSame('sonata.post.admin.post|sonata.post.admin.comment', $postAdmin->getChild('sonata.post.admin.comment')->getBaseCodeRoute());
273
        $this->assertSame($postAdmin, $postAdmin->getChild('sonata.post.admin.comment')->getParent());
274
        $this->assertSame('post', $commentAdmin->getParentAssociationMapping());
275
276
        $this->assertFalse($postAdmin->isChild());
277
        $this->assertTrue($commentAdmin->isChild());
278
279
        $this->assertSame(['sonata.post.admin.comment' => $commentAdmin], $postAdmin->getChildren());
280
    }
281
282
    /**
283
     * @covers \Sonata\AdminBundle\Admin\AbstractAdmin::configure
284
     */
285
    public function testConfigure(): void
286
    {
287
        $admin = new PostAdmin('sonata.post.admin.post', 'Application\Sonata\NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
288
        $this->assertNotNull($admin->getUniqid());
289
290
        $admin->initialize();
291
        $this->assertNotNull($admin->getUniqid());
292
        $this->assertSame('Post', $admin->getClassnameLabel());
293
294
        $admin = new CommentAdmin('sonata.post.admin.comment', 'Application\Sonata\NewsBundle\Entity\Comment', 'SonataNewsBundle:CommentAdmin');
295
        $admin->setClassnameLabel('postcomment');
296
297
        $admin->initialize();
298
        $this->assertSame('postcomment', $admin->getClassnameLabel());
299
    }
300
301
    public function testConfigureWithValidParentAssociationMapping(): void
302
    {
303
        $admin = new PostAdmin('sonata.post.admin.post', 'Application\Sonata\NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
304
        $admin->setParentAssociationMapping('Category');
305
306
        $admin->initialize();
307
        $this->assertSame('Category', $admin->getParentAssociationMapping());
308
    }
309
310
    public function provideGetBaseRoutePattern()
311
    {
312
        return [
313
            [
314
                'Application\Sonata\NewsBundle\Entity\Post',
315
                '/sonata/news/post',
316
            ],
317
            [
318
                'Application\Sonata\NewsBundle\Document\Post',
319
                '/sonata/news/post',
320
            ],
321
            [
322
                'MyApplication\MyBundle\Entity\Post',
323
                '/myapplication/my/post',
324
            ],
325
            [
326
                'MyApplication\MyBundle\Entity\Post\Category',
327
                '/myapplication/my/post-category',
328
            ],
329
            [
330
                'MyApplication\MyBundle\Entity\Product\Category',
331
                '/myapplication/my/product-category',
332
            ],
333
            [
334
                'MyApplication\MyBundle\Entity\Other\Product\Category',
335
                '/myapplication/my/other-product-category',
336
            ],
337
            [
338
                'Symfony\Cmf\Bundle\FooBundle\Document\Menu',
339
                '/cmf/foo/menu',
340
            ],
341
            [
342
                'Symfony\Cmf\Bundle\FooBundle\Doctrine\Phpcr\Menu',
343
                '/cmf/foo/menu',
344
            ],
345
            [
346
                'Symfony\Bundle\BarBarBundle\Doctrine\Phpcr\Menu',
347
                '/symfony/barbar/menu',
348
            ],
349
            [
350
                'Symfony\Bundle\BarBarBundle\Doctrine\Phpcr\Menu\Item',
351
                '/symfony/barbar/menu-item',
352
            ],
353
            [
354
                'Symfony\Cmf\Bundle\FooBundle\Doctrine\Orm\Menu',
355
                '/cmf/foo/menu',
356
            ],
357
            [
358
                'Symfony\Cmf\Bundle\FooBundle\Doctrine\MongoDB\Menu',
359
                '/cmf/foo/menu',
360
            ],
361
            [
362
                'Symfony\Cmf\Bundle\FooBundle\Doctrine\CouchDB\Menu',
363
                '/cmf/foo/menu',
364
            ],
365
            [
366
                'AppBundle\Entity\User',
367
                '/app/user',
368
            ],
369
            [
370
                'App\Entity\User',
371
                '/app/user',
372
            ],
373
        ];
374
    }
375
376
    /**
377
     * @dataProvider provideGetBaseRoutePattern
378
     */
379
    public function testGetBaseRoutePattern($objFqn, $expected): void
380
    {
381
        $admin = new PostAdmin('sonata.post.admin.post', $objFqn, 'SonataNewsBundle:PostAdmin');
382
        $this->assertSame($expected, $admin->getBaseRoutePattern());
383
    }
384
385
    /**
386
     * @dataProvider provideGetBaseRoutePattern
387
     */
388
    public function testGetBaseRoutePatternWithChildAdmin($objFqn, $expected): void
389
    {
390
        $postAdmin = new PostAdmin('sonata.post.admin.post', $objFqn, 'SonataNewsBundle:PostAdmin');
391
        $commentAdmin = new CommentAdmin('sonata.post.admin.comment', 'Application\Sonata\NewsBundle\Entity\Comment', 'SonataNewsBundle:CommentAdmin');
392
        $commentAdmin->setParent($postAdmin);
393
394
        $this->assertSame($expected.'/{id}/comment', $commentAdmin->getBaseRoutePattern());
395
    }
396
397
    /**
398
     * @dataProvider provideGetBaseRoutePattern
399
     */
400
    public function testGetBaseRoutePatternWithTwoNestedChildAdmin($objFqn, $expected): void
401
    {
402
        $postAdmin = new PostAdmin('sonata.post.admin.post', $objFqn, 'SonataNewsBundle:PostAdmin');
403
        $commentAdmin = new CommentAdmin(
404
            'sonata.post.admin.comment',
405
            'Application\Sonata\NewsBundle\Entity\Comment',
406
            'SonataNewsBundle:CommentAdmin'
407
        );
408
        $commentVoteAdmin = new CommentVoteAdmin(
409
            'sonata.post.admin.comment_vote',
410
            'Application\Sonata\NewsBundle\Entity\CommentVote',
411
            'SonataNewsBundle:CommentVoteAdmin'
412
        );
413
        $commentAdmin->setParent($postAdmin);
414
        $commentVoteAdmin->setParent($commentAdmin);
415
416
        $this->assertSame($expected.'/{id}/comment/{childId}/commentvote', $commentVoteAdmin->getBaseRoutePattern());
417
    }
418
419
    public function testGetBaseRoutePatternWithSpecifedPattern(): void
420
    {
421
        $postAdmin = new PostWithCustomRouteAdmin('sonata.post.admin.post_with_custom_route', 'Application\Sonata\NewsBundle\Entity\Post', 'SonataNewsBundle:PostWithCustomRouteAdmin');
422
423
        $this->assertSame('/post-custom', $postAdmin->getBaseRoutePattern());
424
    }
425
426
    public function testGetBaseRoutePatternWithChildAdminAndWithSpecifedPattern(): void
427
    {
428
        $postAdmin = new PostAdmin('sonata.post.admin.post', 'Application\Sonata\NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
429
        $commentAdmin = new CommentWithCustomRouteAdmin('sonata.post.admin.comment_with_custom_route', 'Application\Sonata\NewsBundle\Entity\Comment', 'SonataNewsBundle:CommentWithCustomRouteAdmin');
430
        $commentAdmin->setParent($postAdmin);
431
432
        $this->assertSame('/sonata/news/post/{id}/comment-custom', $commentAdmin->getBaseRoutePattern());
433
    }
434
435
    public function testGetBaseRoutePatternWithUnreconizedClassname(): void
436
    {
437
        $this->expectException(\RuntimeException::class);
438
439
        $admin = new PostAdmin('sonata.post.admin.post', 'News\Thing\Post', 'SonataNewsBundle:PostAdmin');
440
        $admin->getBaseRoutePattern();
441
    }
442
443
    public function provideGetBaseRouteName()
444
    {
445
        return [
446
            [
447
                'Application\Sonata\NewsBundle\Entity\Post',
448
                'admin_sonata_news_post',
449
            ],
450
            [
451
                'Application\Sonata\NewsBundle\Document\Post',
452
                'admin_sonata_news_post',
453
            ],
454
            [
455
                'MyApplication\MyBundle\Entity\Post',
456
                'admin_myapplication_my_post',
457
            ],
458
            [
459
                'MyApplication\MyBundle\Entity\Post\Category',
460
                'admin_myapplication_my_post_category',
461
            ],
462
            [
463
                'MyApplication\MyBundle\Entity\Product\Category',
464
                'admin_myapplication_my_product_category',
465
            ],
466
            [
467
                'MyApplication\MyBundle\Entity\Other\Product\Category',
468
                'admin_myapplication_my_other_product_category',
469
            ],
470
            [
471
                'Symfony\Cmf\Bundle\FooBundle\Document\Menu',
472
                'admin_cmf_foo_menu',
473
            ],
474
            [
475
                'Symfony\Cmf\Bundle\FooBundle\Doctrine\Phpcr\Menu',
476
                'admin_cmf_foo_menu',
477
            ],
478
            [
479
                'Symfony\Bundle\BarBarBundle\Doctrine\Phpcr\Menu',
480
                'admin_symfony_barbar_menu',
481
            ],
482
            [
483
                'Symfony\Bundle\BarBarBundle\Doctrine\Phpcr\Menu\Item',
484
                'admin_symfony_barbar_menu_item',
485
            ],
486
            [
487
                'Symfony\Cmf\Bundle\FooBundle\Doctrine\Orm\Menu',
488
                'admin_cmf_foo_menu',
489
            ],
490
            [
491
                'Symfony\Cmf\Bundle\FooBundle\Doctrine\MongoDB\Menu',
492
                'admin_cmf_foo_menu',
493
            ],
494
            [
495
                'Symfony\Cmf\Bundle\FooBundle\Doctrine\CouchDB\Menu',
496
                'admin_cmf_foo_menu',
497
            ],
498
            [
499
                'AppBundle\Entity\User',
500
                'admin_app_user',
501
            ],
502
            [
503
                'App\Entity\User',
504
                'admin_app_user',
505
            ],
506
        ];
507
    }
508
509
    /**
510
     * @dataProvider provideGetBaseRouteName
511
     */
512
    public function testGetBaseRouteName($objFqn, $expected): void
513
    {
514
        $admin = new PostAdmin('sonata.post.admin.post', $objFqn, 'SonataNewsBundle:PostAdmin');
515
516
        $this->assertSame($expected, $admin->getBaseRouteName());
517
    }
518
519
    /**
520
     * @group legacy
521
     * @expectedDeprecation Calling "addChild" without second argument is deprecated since 3.35 and will not be allowed in 4.0.
522
     * @dataProvider provideGetBaseRouteName
523
     */
524
    public function testGetBaseRouteNameWithChildAdmin($objFqn, $expected): void
525
    {
526
        $routeGenerator = new DefaultRouteGenerator(
527
            $this->createMock(RouterInterface::class),
528
            new RoutesCache($this->cacheTempFolder, true)
529
        );
530
531
        $container = new Container();
532
        $pool = new Pool($container, 'Sonata Admin', '/path/to/pic.png');
533
534
        $pathInfo = new PathInfoBuilder($this->createMock(AuditManagerInterface::class));
535
        $postAdmin = new PostAdmin('sonata.post.admin.post', $objFqn, 'SonataNewsBundle:PostAdmin');
536
        $container->set('sonata.post.admin.post', $postAdmin);
537
        $postAdmin->setConfigurationPool($pool);
538
        $postAdmin->setRouteBuilder($pathInfo);
539
        $postAdmin->setRouteGenerator($routeGenerator);
540
        $postAdmin->initialize();
541
542
        $commentAdmin = new CommentAdmin(
543
            'sonata.post.admin.comment',
544
            'Application\Sonata\NewsBundle\Entity\Comment',
545
            'SonataNewsBundle:CommentAdmin'
546
        );
547
        $container->set('sonata.post.admin.comment', $commentAdmin);
548
        $commentAdmin->setConfigurationPool($pool);
549
        $commentAdmin->setRouteBuilder($pathInfo);
550
        $commentAdmin->setRouteGenerator($routeGenerator);
551
        $commentAdmin->initialize();
552
553
        $postAdmin->addChild($commentAdmin, 'post');
554
555
        $commentVoteAdmin = new CommentVoteAdmin(
556
            'sonata.post.admin.comment_vote',
557
            'Application\Sonata\NewsBundle\Entity\CommentVote',
558
            'SonataNewsBundle:CommentVoteAdmin'
559
        );
560
561
        $container->set('sonata.post.admin.comment_vote', $commentVoteAdmin);
562
        $commentVoteAdmin->setConfigurationPool($pool);
563
        $commentVoteAdmin->setRouteBuilder($pathInfo);
564
        $commentVoteAdmin->setRouteGenerator($routeGenerator);
565
        $commentVoteAdmin->initialize();
566
567
        $commentAdmin->addChild($commentVoteAdmin);
568
        $pool->setAdminServiceIds([
569
            'sonata.post.admin.post',
570
            'sonata.post.admin.comment',
571
            'sonata.post.admin.comment_vote',
572
        ]);
573
574
        $this->assertSame($expected.'_comment', $commentAdmin->getBaseRouteName());
575
576
        $this->assertTrue($postAdmin->hasRoute('show'));
577
        $this->assertTrue($postAdmin->hasRoute('sonata.post.admin.post.show'));
578
        $this->assertTrue($postAdmin->hasRoute('sonata.post.admin.post|sonata.post.admin.comment.show'));
579
        $this->assertTrue($postAdmin->hasRoute('sonata.post.admin.post|sonata.post.admin.comment|sonata.post.admin.comment_vote.show'));
580
        $this->assertTrue($postAdmin->hasRoute('sonata.post.admin.comment.list'));
581
        $this->assertTrue($postAdmin->hasRoute('sonata.post.admin.comment|sonata.post.admin.comment_vote.list'));
582
        $this->assertFalse($postAdmin->hasRoute('sonata.post.admin.post|sonata.post.admin.comment.edit'));
583
        $this->assertFalse($commentAdmin->hasRoute('edit'));
584
        $this->assertSame('post', $commentAdmin->getParentAssociationMapping());
585
586
        /*
587
         * Test the route name from request
588
         */
589
        $postListRequest = new Request(
590
            [],
591
            [],
592
            [
593
                '_route' => $postAdmin->getBaseRouteName().'_list',
594
            ]
595
        );
596
597
        $postAdmin->setRequest($postListRequest);
598
        $commentAdmin->setRequest($postListRequest);
599
600
        $this->assertTrue($postAdmin->isCurrentRoute('list'));
601
        $this->assertFalse($postAdmin->isCurrentRoute('create'));
602
        $this->assertFalse($commentAdmin->isCurrentRoute('list'));
603
        $this->assertFalse($commentVoteAdmin->isCurrentRoute('list'));
604
        $this->assertTrue($commentAdmin->isCurrentRoute('list', 'sonata.post.admin.post'));
605
        $this->assertFalse($commentAdmin->isCurrentRoute('edit', 'sonata.post.admin.post'));
606
        $this->assertTrue($commentVoteAdmin->isCurrentRoute('list', 'sonata.post.admin.post'));
607
        $this->assertFalse($commentVoteAdmin->isCurrentRoute('edit', 'sonata.post.admin.post'));
608
    }
609
610
    public function testGetBaseRouteNameWithUnreconizedClassname(): void
611
    {
612
        $this->expectException(\RuntimeException::class);
613
614
        $admin = new PostAdmin('sonata.post.admin.post', 'News\Thing\Post', 'SonataNewsBundle:PostAdmin');
615
        $admin->getBaseRouteName();
616
    }
617
618
    public function testGetBaseRouteNameWithSpecifiedName(): void
619
    {
620
        $postAdmin = new PostWithCustomRouteAdmin('sonata.post.admin.post_with_custom_route', 'Application\Sonata\NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
621
622
        $this->assertSame('post_custom', $postAdmin->getBaseRouteName());
623
    }
624
625
    public function testGetBaseRouteNameWithChildAdminAndWithSpecifiedName(): void
626
    {
627
        $postAdmin = new PostAdmin('sonata.post.admin.post', 'Application\Sonata\NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
628
        $commentAdmin = new CommentWithCustomRouteAdmin('sonata.post.admin.comment_with_custom_route', 'Application\Sonata\NewsBundle\Entity\Comment', 'SonataNewsBundle:CommentWithCustomRouteAdmin');
629
        $commentAdmin->setParent($postAdmin);
630
631
        $this->assertSame('admin_sonata_news_post_comment_custom', $commentAdmin->getBaseRouteName());
632
    }
633
634
    public function testGetBaseRouteNameWithTwoNestedChildAdminAndWithSpecifiedName(): void
635
    {
636
        $postAdmin = new PostAdmin(
637
            'sonata.post.admin.post',
638
            'Application\Sonata\NewsBundle\Entity\Post',
639
            'SonataNewsBundle:PostAdmin'
640
        );
641
        $commentAdmin = new CommentWithCustomRouteAdmin(
642
            'sonata.post.admin.comment_with_custom_route',
643
            'Application\Sonata\NewsBundle\Entity\Comment',
644
            'SonataNewsBundle:CommentWithCustomRouteAdmin'
645
        );
646
        $commentVoteAdmin = new CommentVoteAdmin(
647
            'sonata.post.admin.comment_vote',
648
            'Application\Sonata\NewsBundle\Entity\CommentVote',
649
            'SonataNewsBundle:CommentVoteAdmin'
650
        );
651
        $commentAdmin->setParent($postAdmin);
652
        $commentVoteAdmin->setParent($commentAdmin);
653
654
        $this->assertSame('admin_sonata_news_post_comment_custom_commentvote', $commentVoteAdmin->getBaseRouteName());
655
    }
656
657
    /**
658
     * @covers \Sonata\AdminBundle\Admin\AbstractAdmin::setUniqid
659
     * @covers \Sonata\AdminBundle\Admin\AbstractAdmin::getUniqid
660
     */
661
    public function testSetUniqid(): void
662
    {
663
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
664
665
        $uniqid = uniqid();
666
        $admin->setUniqid($uniqid);
667
668
        $this->assertSame($uniqid, $admin->getUniqid());
669
    }
670
671
    public function testUniqidConsistency(): void
672
    {
673
        $admin = $this->getMockForAbstractClass(AbstractAdmin::class, [
674
            'sonata.abstract.admin',
675
            'AbstractBundle\Entity\Foo',
676
            'SonataAbstractBundle:FooAdmin',
677
        ]);
678
        $admin->initialize();
679
680
        $uniqid = $admin->getUniqid();
681
        $admin->setUniqid(null);
682
683
        $this->assertSame($uniqid, $admin->getUniqid());
684
685
        $parentAdmin = $this->getMockForAbstractClass(AbstractAdmin::class, [
686
            'sonata.abstract.parent.admin',
687
            'AbstractBundle\Entity\Bar',
688
            'SonataAbstractBundle:BarAdmin',
689
        ]);
690
        $parentAdmin->initialize();
691
692
        $admin->setParent($parentAdmin);
693
        $admin->setUniqid(null);
694
695
        $this->assertNotSame($uniqid, $admin->getUniqid());
696
    }
697
698
    public function testToString(): void
699
    {
700
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
701
702
        $s = new \stdClass();
703
704
        $this->assertNotEmpty($admin->toString($s));
705
706
        $s = new FooToString();
707
        $this->assertSame('salut', $admin->toString($s));
708
709
        // To string method is implemented, but returns null
710
        $s = new FooToStringNull();
711
        $this->assertNotEmpty($admin->toString($s));
712
713
        $this->assertSame('', $admin->toString(false));
714
    }
715
716
    public function testIsAclEnabled(): void
717
    {
718
        $postAdmin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
719
720
        $this->assertFalse($postAdmin->isAclEnabled());
721
722
        $commentAdmin = new CommentAdmin('sonata.post.admin.comment', 'Application\Sonata\NewsBundle\Entity\Comment', 'SonataNewsBundle:CommentAdmin');
723
        $commentAdmin->setSecurityHandler($this->createMock(AclSecurityHandlerInterface::class));
724
        $this->assertTrue($commentAdmin->isAclEnabled());
725
    }
726
727
    /**
728
     * @covers \Sonata\AdminBundle\Admin\AbstractAdmin::getSubClasses
729
     * @covers \Sonata\AdminBundle\Admin\AbstractAdmin::getSubClass
730
     * @covers \Sonata\AdminBundle\Admin\AbstractAdmin::setSubClasses
731
     * @covers \Sonata\AdminBundle\Admin\AbstractAdmin::hasSubClass
732
     * @covers \Sonata\AdminBundle\Admin\AbstractAdmin::hasActiveSubClass
733
     * @covers \Sonata\AdminBundle\Admin\AbstractAdmin::getActiveSubClass
734
     * @covers \Sonata\AdminBundle\Admin\AbstractAdmin::getActiveSubclassCode
735
     * @covers \Sonata\AdminBundle\Admin\AbstractAdmin::getClass
736
     */
737
    public function testSubClass(): void
738
    {
739
        $admin = new PostAdmin(
740
            'sonata.post.admin.post',
741
            Post::class,
742
            'SonataNewsBundle:PostAdmin'
743
        );
744
        $this->assertFalse($admin->hasSubClass('test'));
745
        $this->assertFalse($admin->hasActiveSubClass());
746
        $this->assertCount(0, $admin->getSubClasses());
747
        $this->assertNull($admin->getActiveSubClass());
748
        $this->assertNull($admin->getActiveSubclassCode());
749
        $this->assertSame(Post::class, $admin->getClass());
750
751
        // Just for the record, if there is no inheritance set, the getSubject is not used
752
        // the getSubject can also lead to some issue
753
        $admin->setSubject(new BlogPost());
754
        $this->assertSame(BlogPost::class, $admin->getClass());
755
756
        $admin->setSubClasses([
757
            'extended1' => 'NewsBundle\Entity\PostExtended1',
758
            'extended2' => 'NewsBundle\Entity\PostExtended2',
759
        ]);
760
        $this->assertFalse($admin->hasSubClass('test'));
761
        $this->assertTrue($admin->hasSubClass('extended1'));
762
        $this->assertFalse($admin->hasActiveSubClass());
763
        $this->assertCount(2, $admin->getSubClasses());
764
        $this->assertNull($admin->getActiveSubClass());
765
        $this->assertNull($admin->getActiveSubclassCode());
766
        $this->assertSame(
767
            BlogPost::class,
768
            $admin->getClass(),
769
            'When there is no subclass in the query the class parameter should be returned'
770
        );
771
772
        $request = new Request(['subclass' => 'extended1']);
773
        $admin->setRequest($request);
774
        $this->assertFalse($admin->hasSubClass('test'));
775
        $this->assertTrue($admin->hasSubClass('extended1'));
776
        $this->assertTrue($admin->hasActiveSubClass());
777
        $this->assertCount(2, $admin->getSubClasses());
778
        $this->assertSame(
779
            'NewsBundle\Entity\PostExtended1',
780
            $admin->getActiveSubClass(),
781
            'It should return the curently active sub class.'
782
        );
783
        $this->assertSame('extended1', $admin->getActiveSubclassCode());
784
        $this->assertSame(
785
            'NewsBundle\Entity\PostExtended1',
786
            $admin->getClass(),
787
            'getClass() should return the name of the sub class when passed through a request query parameter.'
788
        );
789
790
        $request->query->set('subclass', 'inject');
791
        $this->assertNull($admin->getActiveSubclassCode());
792
    }
793
794
    public function testNonExistantSubclass(): void
795
    {
796
        $this->expectException(\RuntimeException::class);
797
798
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
799
        $admin->setModelManager($this->getMockForAbstractClass(ModelManagerInterface::class));
800
801
        $admin->setRequest(new Request(['subclass' => 'inject']));
802
803
        $admin->setSubClasses(['extended1' => 'NewsBundle\Entity\PostExtended1', 'extended2' => 'NewsBundle\Entity\PostExtended2']);
804
805
        $this->assertTrue($admin->hasActiveSubClass());
806
807
        $admin->getActiveSubClass();
808
    }
809
810
    /**
811
     * @covers \Sonata\AdminBundle\Admin\AbstractAdmin::hasActiveSubClass
812
     */
813
    public function testOnlyOneSubclassNeededToBeActive(): void
814
    {
815
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
816
        $admin->setSubClasses(['extended1' => 'NewsBundle\Entity\PostExtended1']);
817
        $request = new Request(['subclass' => 'extended1']);
818
        $admin->setRequest($request);
819
        $this->assertTrue($admin->hasActiveSubClass());
820
    }
821
822
    /**
823
     * @group legacy
824
     * @expectedDeprecation Method "Sonata\AdminBundle\Admin\AbstractAdmin::addSubClass" is deprecated since 3.30 and will be removed in 4.0.
825
     */
826
    public function testAddSubClassIsDeprecated(): void
827
    {
828
        $admin = new PostAdmin(
829
            'sonata.post.admin.post',
830
            Post::class,
831
            'SonataNewsBundle:PostAdmin'
832
        );
833
        $admin->addSubClass('whatever');
834
    }
835
836
    public function testGetPerPageOptions(): void
837
    {
838
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
839
840
        $perPageOptions = $admin->getPerPageOptions();
841
842
        foreach ($perPageOptions as $perPage) {
843
            $this->assertSame(0, $perPage % 4);
844
        }
845
846
        $admin->setPerPageOptions([500, 1000]);
847
        $this->assertSame([500, 1000], $admin->getPerPageOptions());
848
    }
849
850
    public function testGetLabelTranslatorStrategy(): void
851
    {
852
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
853
854
        $this->assertNull($admin->getLabelTranslatorStrategy());
855
856
        $labelTranslatorStrategy = $this->createMock(LabelTranslatorStrategyInterface::class);
857
        $admin->setLabelTranslatorStrategy($labelTranslatorStrategy);
858
        $this->assertSame($labelTranslatorStrategy, $admin->getLabelTranslatorStrategy());
859
    }
860
861
    public function testGetRouteBuilder(): void
862
    {
863
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
864
865
        $this->assertNull($admin->getRouteBuilder());
866
867
        $routeBuilder = $this->createMock(RouteBuilderInterface::class);
868
        $admin->setRouteBuilder($routeBuilder);
869
        $this->assertSame($routeBuilder, $admin->getRouteBuilder());
870
    }
871
872
    public function testGetMenuFactory(): void
873
    {
874
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
875
876
        $this->assertNull($admin->getMenuFactory());
877
878
        $menuFactory = $this->createMock(FactoryInterface::class);
879
        $admin->setMenuFactory($menuFactory);
880
        $this->assertSame($menuFactory, $admin->getMenuFactory());
881
    }
882
883
    public function testGetExtensions(): void
884
    {
885
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
886
887
        $this->assertSame([], $admin->getExtensions());
888
889
        $adminExtension1 = $this->createMock(AdminExtensionInterface::class);
890
        $adminExtension2 = $this->createMock(AdminExtensionInterface::class);
891
892
        $admin->addExtension($adminExtension1);
893
        $admin->addExtension($adminExtension2);
894
        $this->assertSame([$adminExtension1, $adminExtension2], $admin->getExtensions());
895
    }
896
897
    public function testGetFilterTheme(): void
898
    {
899
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
900
901
        $this->assertSame([], $admin->getFilterTheme());
902
903
        $admin->setFilterTheme(['FooTheme']);
904
        $this->assertSame(['FooTheme'], $admin->getFilterTheme());
905
    }
906
907
    public function testGetFormTheme(): void
908
    {
909
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
910
911
        $this->assertSame([], $admin->getFormTheme());
912
913
        $admin->setFormTheme(['FooTheme']);
914
915
        $this->assertSame(['FooTheme'], $admin->getFormTheme());
916
    }
917
918
    public function testGetValidator(): void
919
    {
920
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
921
922
        $this->assertNull($admin->getValidator());
923
924
        $validator = $this->getMockForAbstractClass(ValidatorInterface::class);
925
926
        $admin->setValidator($validator);
927
        $this->assertSame($validator, $admin->getValidator());
928
    }
929
930
    public function testGetSecurityHandler(): void
931
    {
932
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
933
934
        $this->assertNull($admin->getSecurityHandler());
935
936
        $securityHandler = $this->createMock(SecurityHandlerInterface::class);
937
        $admin->setSecurityHandler($securityHandler);
938
        $this->assertSame($securityHandler, $admin->getSecurityHandler());
939
    }
940
941
    public function testGetSecurityInformation(): void
942
    {
943
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
944
945
        $this->assertSame([], $admin->getSecurityInformation());
946
947
        $securityInformation = [
948
            'GUEST' => ['VIEW', 'LIST'],
949
            'STAFF' => ['EDIT', 'LIST', 'CREATE'],
950
        ];
951
952
        $admin->setSecurityInformation($securityInformation);
953
        $this->assertSame($securityInformation, $admin->getSecurityInformation());
954
    }
955
956
    public function testGetManagerType(): void
957
    {
958
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
959
960
        $this->assertNull($admin->getManagerType());
961
962
        $admin->setManagerType('foo_orm');
963
        $this->assertSame('foo_orm', $admin->getManagerType());
964
    }
965
966
    public function testGetModelManager(): void
967
    {
968
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
969
970
        $this->assertNull($admin->getModelManager());
971
972
        $modelManager = $this->createMock(ModelManagerInterface::class);
973
974
        $admin->setModelManager($modelManager);
975
        $this->assertSame($modelManager, $admin->getModelManager());
976
    }
977
978
    /**
979
     * NEXT_MAJOR: remove this method.
980
     *
981
     * @group legacy
982
     */
983
    public function testGetBaseCodeRoute(): void
984
    {
985
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
986
987
        $this->assertSame('', $admin->getBaseCodeRoute());
988
989
        $admin->setBaseCodeRoute('foo');
990
        $this->assertSame('foo', $admin->getBaseCodeRoute());
991
    }
992
993
    // NEXT_MAJOR: uncomment this method.
994
    // public function testGetBaseCodeRoute()
995
    // {
996
    //     $postAdmin = new PostAdmin(
997
    //         'sonata.post.admin.post',
998
    //         'NewsBundle\Entity\Post',
999
    //         'SonataNewsBundle:PostAdmin'
1000
    //     );
1001
    //     $commentAdmin = new CommentAdmin(
1002
    //         'sonata.post.admin.comment',
1003
    //         'Application\Sonata\NewsBundle\Entity\Comment',
1004
    //         'SonataNewsBundle:CommentAdmin'
1005
    //     );
1006
    //
1007
    //     $this->assertSame($postAdmin->getCode(), $postAdmin->getBaseCodeRoute());
1008
    //
1009
    //     $postAdmin->addChild($commentAdmin);
1010
    //
1011
    //     $this->assertSame(
1012
    //         'sonata.post.admin.post|sonata.post.admin.comment',
1013
    //         $commentAdmin->getBaseCodeRoute()
1014
    //     );
1015
    // }
1016
1017
    public function testGetRouteGenerator(): void
1018
    {
1019
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
1020
1021
        $this->assertNull($admin->getRouteGenerator());
1022
1023
        $routeGenerator = $this->createMock(RouteGeneratorInterface::class);
1024
1025
        $admin->setRouteGenerator($routeGenerator);
1026
        $this->assertSame($routeGenerator, $admin->getRouteGenerator());
1027
    }
1028
1029
    public function testGetConfigurationPool(): void
1030
    {
1031
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
1032
1033
        $this->assertNull($admin->getConfigurationPool());
1034
1035
        $pool = $this->getMockBuilder(Pool::class)
1036
            ->disableOriginalConstructor()
1037
            ->getMock();
1038
1039
        $admin->setConfigurationPool($pool);
1040
        $this->assertSame($pool, $admin->getConfigurationPool());
1041
    }
1042
1043
    public function testGetShowBuilder(): void
1044
    {
1045
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
1046
1047
        $this->assertNull($admin->getShowBuilder());
1048
1049
        $showBuilder = $this->createMock(ShowBuilderInterface::class);
1050
1051
        $admin->setShowBuilder($showBuilder);
1052
        $this->assertSame($showBuilder, $admin->getShowBuilder());
1053
    }
1054
1055
    public function testGetListBuilder(): void
1056
    {
1057
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
1058
1059
        $this->assertNull($admin->getListBuilder());
1060
1061
        $listBuilder = $this->createMock(ListBuilderInterface::class);
1062
1063
        $admin->setListBuilder($listBuilder);
1064
        $this->assertSame($listBuilder, $admin->getListBuilder());
1065
    }
1066
1067
    public function testGetDatagridBuilder(): void
1068
    {
1069
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
1070
1071
        $this->assertNull($admin->getDatagridBuilder());
1072
1073
        $datagridBuilder = $this->createMock(DatagridBuilderInterface::class);
1074
1075
        $admin->setDatagridBuilder($datagridBuilder);
1076
        $this->assertSame($datagridBuilder, $admin->getDatagridBuilder());
1077
    }
1078
1079
    public function testGetFormContractor(): void
1080
    {
1081
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
1082
1083
        $this->assertNull($admin->getFormContractor());
1084
1085
        $formContractor = $this->createMock(FormContractorInterface::class);
1086
1087
        $admin->setFormContractor($formContractor);
1088
        $this->assertSame($formContractor, $admin->getFormContractor());
1089
    }
1090
1091
    public function testGetRequest(): void
1092
    {
1093
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
1094
1095
        $this->assertFalse($admin->hasRequest());
1096
1097
        $request = new Request();
1098
1099
        $admin->setRequest($request);
1100
        $this->assertSame($request, $admin->getRequest());
1101
        $this->assertTrue($admin->hasRequest());
1102
    }
1103
1104
    public function testGetRequestWithException(): void
1105
    {
1106
        $this->expectException(\RuntimeException::class);
1107
        $this->expectExceptionMessage('The Request object has not been set');
1108
1109
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
1110
        $admin->getRequest();
1111
    }
1112
1113
    public function testGetTranslationDomain(): void
1114
    {
1115
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
1116
1117
        $this->assertSame('messages', $admin->getTranslationDomain());
1118
1119
        $admin->setTranslationDomain('foo');
1120
        $this->assertSame('foo', $admin->getTranslationDomain());
1121
    }
1122
1123
    /**
1124
     * @group legacy
1125
     */
1126
    public function testGetTranslator(): void
1127
    {
1128
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
1129
1130
        $this->assertNull($admin->getTranslator());
1131
1132
        $translator = $this->createMock(TranslatorInterface::class);
1133
1134
        $admin->setTranslator($translator);
0 ignored issues
show
Deprecated Code introduced by
The method Sonata\AdminBundle\Admin...tAdmin::setTranslator() has been deprecated with message: since 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...
1135
        $this->assertSame($translator, $admin->getTranslator());
1136
    }
1137
1138
    public function testGetShowGroups(): void
1139
    {
1140
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
1141
1142
        $this->assertFalse($admin->getShowGroups());
1143
1144
        $groups = ['foo', 'bar', 'baz'];
1145
1146
        $admin->setShowGroups($groups);
1147
        $this->assertSame($groups, $admin->getShowGroups());
1148
    }
1149
1150
    public function testGetFormGroups(): void
1151
    {
1152
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
1153
1154
        $this->assertFalse($admin->getFormGroups());
1155
1156
        $groups = ['foo', 'bar', 'baz'];
1157
1158
        $admin->setFormGroups($groups);
1159
        $this->assertSame($groups, $admin->getFormGroups());
1160
    }
1161
1162
    public function testGetMaxPageLinks(): void
1163
    {
1164
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
1165
1166
        $this->assertSame(25, $admin->getMaxPageLinks());
1167
1168
        $admin->setMaxPageLinks(14);
1169
        $this->assertSame(14, $admin->getMaxPageLinks());
1170
    }
1171
1172
    public function testGetMaxPerPage(): void
1173
    {
1174
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
1175
1176
        $this->assertSame(32, $admin->getMaxPerPage());
1177
1178
        $admin->setMaxPerPage(94);
1179
        $this->assertSame(94, $admin->getMaxPerPage());
1180
    }
1181
1182
    public function testGetLabel(): void
1183
    {
1184
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
1185
1186
        $this->assertNull($admin->getLabel());
1187
1188
        $admin->setLabel('FooLabel');
1189
        $this->assertSame('FooLabel', $admin->getLabel());
1190
    }
1191
1192
    public function testGetBaseController(): void
1193
    {
1194
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
1195
1196
        $this->assertSame('SonataNewsBundle:PostAdmin', $admin->getBaseControllerName());
1197
1198
        $admin->setBaseControllerName('SonataNewsBundle:FooAdmin');
1199
        $this->assertSame('SonataNewsBundle:FooAdmin', $admin->getBaseControllerName());
1200
    }
1201
1202
    public function testGetTemplates(): void
1203
    {
1204
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
1205
1206
        $templates = [
1207
            'list' => '@FooAdmin/CRUD/list.html.twig',
1208
            'show' => '@FooAdmin/CRUD/show.html.twig',
1209
            'edit' => '@FooAdmin/CRUD/edit.html.twig',
1210
        ];
1211
1212
        $templateRegistry = $this->prophesize(MutableTemplateRegistryInterface::class);
1213
        $templateRegistry->getTemplates()->shouldBeCalled()->willReturn($templates);
1214
1215
        $admin->setTemplateRegistry($templateRegistry->reveal());
1216
1217
        $this->assertSame($templates, $admin->getTemplates());
1218
    }
1219
1220
    public function testGetTemplate1(): void
1221
    {
1222
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
1223
1224
        $templateRegistry = $this->prophesize(MutableTemplateRegistryInterface::class);
1225
        $templateRegistry->getTemplate('edit')->shouldBeCalled()->willReturn('@FooAdmin/CRUD/edit.html.twig');
1226
        $templateRegistry->getTemplate('show')->shouldBeCalled()->willReturn('@FooAdmin/CRUD/show.html.twig');
1227
1228
        $admin->setTemplateRegistry($templateRegistry->reveal());
1229
1230
        $this->assertSame('@FooAdmin/CRUD/edit.html.twig', $admin->getTemplate('edit'));
1231
        $this->assertSame('@FooAdmin/CRUD/show.html.twig', $admin->getTemplate('show'));
1232
    }
1233
1234
    public function testGetIdParameter(): void
1235
    {
1236
        $postAdmin = new PostAdmin(
1237
            'sonata.post.admin.post',
1238
            'NewsBundle\Entity\Post',
1239
            'SonataNewsBundle:PostAdmin'
1240
        );
1241
1242
        $this->assertSame('id', $postAdmin->getIdParameter());
1243
        $this->assertFalse($postAdmin->isChild());
1244
1245
        $commentAdmin = new CommentAdmin(
1246
            'sonata.post.admin.comment',
1247
            'Application\Sonata\NewsBundle\Entity\Comment',
1248
            'SonataNewsBundle:CommentAdmin'
1249
        );
1250
        $commentAdmin->setParent($postAdmin);
1251
1252
        $this->assertTrue($commentAdmin->isChild());
1253
        $this->assertSame('childId', $commentAdmin->getIdParameter());
1254
1255
        $commentVoteAdmin = new CommentVoteAdmin(
1256
            'sonata.post.admin.comment_vote',
1257
            'Application\Sonata\NewsBundle\Entity\CommentVote',
1258
            'SonataNewsBundle:CommentVoteAdmin'
1259
        );
1260
        $commentVoteAdmin->setParent($commentAdmin);
1261
1262
        $this->assertTrue($commentVoteAdmin->isChild());
1263
        $this->assertSame('childChildId', $commentVoteAdmin->getIdParameter());
1264
    }
1265
1266
    public function testGetExportFormats(): void
1267
    {
1268
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
1269
1270
        $this->assertSame(['json', 'xml', 'csv', 'xls'], $admin->getExportFormats());
1271
    }
1272
1273
    public function testGetUrlsafeIdentifier(): void
1274
    {
1275
        $admin = new PostAdmin('sonata.post.admin.post', 'Acme\NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
1276
1277
        $entity = new \stdClass();
1278
1279
        $modelManager = $this->createMock(ModelManagerInterface::class);
1280
        $modelManager->expects($this->once())
1281
            ->method('getUrlsafeIdentifier')
1282
            ->with($this->equalTo($entity))
1283
            ->willReturn('foo');
1284
        $admin->setModelManager($modelManager);
1285
1286
        $this->assertSame('foo', $admin->getUrlsafeIdentifier($entity));
1287
    }
1288
1289
    public function testDeterminedPerPageValue(): void
1290
    {
1291
        $admin = new PostAdmin('sonata.post.admin.post', 'Acme\NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
1292
1293
        $this->assertFalse($admin->determinedPerPageValue('foo'));
1294
        $this->assertFalse($admin->determinedPerPageValue(123));
1295
        $this->assertTrue($admin->determinedPerPageValue(16));
1296
1297
        $admin->setPerPageOptions([101, 102, 103]);
1298
        $this->assertFalse($admin->determinedPerPageValue(16));
1299
        $this->assertTrue($admin->determinedPerPageValue(101));
1300
    }
1301
1302
    public function testIsGranted(): void
1303
    {
1304
        $admin = new PostAdmin('sonata.post.admin.post', 'Acme\NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
1305
1306
        $entity = new \stdClass();
1307
1308
        $securityHandler = $this->createMock(AclSecurityHandlerInterface::class);
1309
        $securityHandler->expects($this->any())
1310
            ->method('isGranted')
1311
            ->willReturnCallback(static function (AdminInterface $adminIn, $attributes, $object = null) use ($admin, $entity) {
1312
                if ($admin === $adminIn && 'FOO' === $attributes) {
1313
                    if (($object === $admin) || ($object === $entity)) {
1314
                        return true;
1315
                    }
1316
                }
1317
1318
                return false;
1319
            });
1320
1321
        $admin->setSecurityHandler($securityHandler);
1322
1323
        $this->assertTrue($admin->isGranted('FOO'));
1324
        $this->assertTrue($admin->isGranted('FOO', $entity));
1325
        $this->assertFalse($admin->isGranted('BAR'));
1326
        $this->assertFalse($admin->isGranted('BAR', $entity));
1327
    }
1328
1329
    public function testSupportsPreviewMode(): void
1330
    {
1331
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
1332
1333
        $this->assertFalse($admin->supportsPreviewMode());
1334
    }
1335
1336
    public function testGetPermissionsShow(): void
1337
    {
1338
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
1339
1340
        $this->assertSame(['LIST'], $admin->getPermissionsShow(AbstractAdmin::CONTEXT_DASHBOARD));
1341
        $this->assertSame(['LIST'], $admin->getPermissionsShow(AbstractAdmin::CONTEXT_MENU));
1342
        $this->assertSame(['LIST'], $admin->getPermissionsShow('foo'));
1343
    }
1344
1345
    public function testShowIn(): void
1346
    {
1347
        $admin = new PostAdmin('sonata.post.admin.post', 'Acme\NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
1348
1349
        $securityHandler = $this->createMock(AclSecurityHandlerInterface::class);
1350
        $securityHandler->expects($this->any())
1351
            ->method('isGranted')
1352
            ->willReturnCallback(static function (AdminInterface $adminIn, $attributes, $object = null) use ($admin) {
1353
                if ($admin === $adminIn && $attributes === ['LIST']) {
1354
                    return true;
1355
                }
1356
1357
                return false;
1358
            });
1359
1360
        $admin->setSecurityHandler($securityHandler);
1361
1362
        $this->assertTrue($admin->showIn(AbstractAdmin::CONTEXT_DASHBOARD));
1363
        $this->assertTrue($admin->showIn(AbstractAdmin::CONTEXT_MENU));
1364
        $this->assertTrue($admin->showIn('foo'));
1365
    }
1366
1367
    public function testGetObjectIdentifier(): void
1368
    {
1369
        $admin = new PostAdmin('sonata.post.admin.post', 'Acme\NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
1370
1371
        $this->assertSame('sonata.post.admin.post', $admin->getObjectIdentifier());
1372
    }
1373
1374
    /**
1375
     * @group legacy
1376
     */
1377
    public function testTrans(): void
1378
    {
1379
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
1380
        $admin->setTranslationDomain('fooMessageDomain');
1381
1382
        $translator = $this->createMock(TranslatorInterface::class);
1383
        $admin->setTranslator($translator);
0 ignored issues
show
Deprecated Code introduced by
The method Sonata\AdminBundle\Admin...tAdmin::setTranslator() has been deprecated with message: since 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...
1384
1385
        $translator->expects($this->once())
1386
            ->method('trans')
1387
            ->with($this->equalTo('foo'), $this->equalTo([]), $this->equalTo('fooMessageDomain'))
1388
            ->willReturn('fooTranslated');
1389
1390
        $this->assertSame('fooTranslated', $admin->trans('foo'));
1391
    }
1392
1393
    /**
1394
     * @group legacy
1395
     */
1396
    public function testTransWithMessageDomain(): void
1397
    {
1398
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
1399
1400
        $translator = $this->createMock(TranslatorInterface::class);
1401
        $admin->setTranslator($translator);
0 ignored issues
show
Deprecated Code introduced by
The method Sonata\AdminBundle\Admin...tAdmin::setTranslator() has been deprecated with message: since 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...
1402
1403
        $translator->expects($this->once())
1404
            ->method('trans')
1405
            ->with($this->equalTo('foo'), $this->equalTo(['name' => 'Andrej']), $this->equalTo('fooMessageDomain'))
1406
            ->willReturn('fooTranslated');
1407
1408
        $this->assertSame('fooTranslated', $admin->trans('foo', ['name' => 'Andrej'], 'fooMessageDomain'));
1409
    }
1410
1411
    /**
1412
     * @group legacy
1413
     */
1414
    public function testTransChoice(): void
1415
    {
1416
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
1417
        $admin->setTranslationDomain('fooMessageDomain');
1418
1419
        $translator = $this->createMock(TranslatorInterface::class);
1420
        $admin->setTranslator($translator);
0 ignored issues
show
Deprecated Code introduced by
The method Sonata\AdminBundle\Admin...tAdmin::setTranslator() has been deprecated with message: since 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...
1421
1422
        $translator->expects($this->once())
1423
            ->method('transChoice')
1424
            ->with($this->equalTo('foo'), $this->equalTo(2), $this->equalTo([]), $this->equalTo('fooMessageDomain'))
1425
            ->willReturn('fooTranslated');
1426
1427
        $this->assertSame('fooTranslated', $admin->transChoice('foo', 2));
1428
    }
1429
1430
    /**
1431
     * @group legacy
1432
     */
1433
    public function testTransChoiceWithMessageDomain(): void
1434
    {
1435
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
1436
1437
        $translator = $this->createMock(TranslatorInterface::class);
1438
        $admin->setTranslator($translator);
0 ignored issues
show
Deprecated Code introduced by
The method Sonata\AdminBundle\Admin...tAdmin::setTranslator() has been deprecated with message: since 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...
1439
1440
        $translator->expects($this->once())
1441
            ->method('transChoice')
1442
            ->with($this->equalTo('foo'), $this->equalTo(2), $this->equalTo(['name' => 'Andrej']), $this->equalTo('fooMessageDomain'))
1443
            ->willReturn('fooTranslated');
1444
1445
        $this->assertSame('fooTranslated', $admin->transChoice('foo', 2, ['name' => 'Andrej'], 'fooMessageDomain'));
1446
    }
1447
1448
    public function testSetFilterPersister(): void
1449
    {
1450
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
1451
1452
        $filterPersister = $this->createMock('Sonata\AdminBundle\Filter\Persister\FilterPersisterInterface');
1453
1454
        $this->assertAttributeSame(null, 'filterPersister', $admin);
1455
        $admin->setFilterPersister($filterPersister);
1456
        $this->assertAttributeSame($filterPersister, 'filterPersister', $admin);
1457
        $this->assertAttributeSame(true, 'persistFilters', $admin);
1458
    }
1459
1460
    public function testGetRootCode(): void
1461
    {
1462
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
1463
1464
        $this->assertSame('sonata.post.admin.post', $admin->getRootCode());
1465
1466
        $parentAdmin = new PostAdmin('sonata.post.admin.post.parent', 'NewsBundle\Entity\PostParent', 'SonataNewsBundle:PostParentAdmin');
1467
        $parentFieldDescription = $this->createMock(FieldDescriptionInterface::class);
1468
        $parentFieldDescription->expects($this->once())
1469
            ->method('getAdmin')
1470
            ->willReturn($parentAdmin);
1471
1472
        $this->assertNull($admin->getParentFieldDescription());
1473
        $admin->setParentFieldDescription($parentFieldDescription);
1474
        $this->assertSame($parentFieldDescription, $admin->getParentFieldDescription());
1475
        $this->assertSame('sonata.post.admin.post.parent', $admin->getRootCode());
1476
    }
1477
1478
    public function testGetRoot(): void
1479
    {
1480
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
1481
1482
        $this->assertSame($admin, $admin->getRoot());
1483
1484
        $parentAdmin = new PostAdmin('sonata.post.admin.post.parent', 'NewsBundle\Entity\PostParent', 'SonataNewsBundle:PostParentAdmin');
1485
        $parentFieldDescription = $this->createMock(FieldDescriptionInterface::class);
1486
        $parentFieldDescription->expects($this->once())
1487
            ->method('getAdmin')
1488
            ->willReturn($parentAdmin);
1489
1490
        $this->assertNull($admin->getParentFieldDescription());
1491
        $admin->setParentFieldDescription($parentFieldDescription);
1492
        $this->assertSame($parentFieldDescription, $admin->getParentFieldDescription());
1493
        $this->assertSame($parentAdmin, $admin->getRoot());
1494
    }
1495
1496
    public function testGetExportFields(): void
1497
    {
1498
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
1499
1500
        $modelManager = $this->createMock(ModelManagerInterface::class);
1501
        $modelManager->expects($this->once())
1502
            ->method('getExportFields')
1503
            ->with($this->equalTo('NewsBundle\Entity\Post'))
1504
            ->willReturn(['foo', 'bar']);
1505
1506
        $admin->setModelManager($modelManager);
1507
        $this->assertSame(['foo', 'bar'], $admin->getExportFields());
1508
    }
1509
1510
    public function testGetPersistentParametersWithNoExtension(): void
1511
    {
1512
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
1513
1514
        $this->assertEmpty($admin->getPersistentParameters());
1515
    }
1516
1517
    public function testGetPersistentParametersWithInvalidExtension(): void
1518
    {
1519
        $this->expectException(\RuntimeException::class);
1520
1521
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
1522
1523
        $extension = $this->createMock(AdminExtensionInterface::class);
1524
        $extension->expects($this->once())->method('getPersistentParameters')->willReturn(null);
1525
1526
        $admin->addExtension($extension);
1527
1528
        $admin->getPersistentParameters();
1529
    }
1530
1531
    public function testGetPersistentParametersWithValidExtension(): void
1532
    {
1533
        $expected = [
1534
            'context' => 'foobar',
1535
        ];
1536
1537
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
1538
1539
        $extension = $this->createMock(AdminExtensionInterface::class);
1540
        $extension->expects($this->once())->method('getPersistentParameters')->willReturn($expected);
1541
1542
        $admin->addExtension($extension);
1543
1544
        $this->assertSame($expected, $admin->getPersistentParameters());
1545
    }
1546
1547
    public function testGetFormWithNonCollectionParentValue(): void
1548
    {
1549
        $post = new Post();
1550
        $tagAdmin = $this->createTagAdmin($post);
1551
        $tag = $tagAdmin->getSubject();
1552
1553
        $tag->setPosts(null);
1554
        $tagAdmin->getForm();
1555
        $this->assertSame($post, $tag->getPosts());
1556
    }
1557
1558
    public function testGetFormWithCollectionParentValue(): void
1559
    {
1560
        $post = new Post();
1561
        $tagAdmin = $this->createTagAdmin($post);
1562
        $tag = $tagAdmin->getSubject();
1563
1564
        // Case of a doctrine collection
1565
        $this->assertInstanceOf(Collection::class, $tag->getPosts());
1566
        $this->assertCount(0, $tag->getPosts());
1567
1568
        $tag->addPost(new Post());
1569
1570
        $this->assertCount(1, $tag->getPosts());
1571
1572
        $tagAdmin->getForm();
1573
1574
        $this->assertInstanceOf(Collection::class, $tag->getPosts());
1575
        $this->assertCount(2, $tag->getPosts());
1576
        $this->assertContains($post, $tag->getPosts());
1577
1578
        // Case of an array
1579
        $tag->setPosts([]);
1580
        $this->assertCount(0, $tag->getPosts());
1581
1582
        $tag->addPost(new Post());
1583
1584
        $this->assertCount(1, $tag->getPosts());
1585
1586
        $tagAdmin->getForm();
1587
1588
        $this->assertInternalType('array', $tag->getPosts());
1589
        $this->assertCount(2, $tag->getPosts());
1590
        $this->assertContains($post, $tag->getPosts());
1591
    }
1592
1593
    public function testFormAddPostSubmitEventForPreValidation(): void
1594
    {
1595
        $modelAdmin = new ModelAdmin('sonata.post.admin.model', 'Application\Sonata\FooBundle\Entity\Model', 'SonataFooBundle:ModelAdmin');
1596
        $object = new \stdClass();
1597
1598
        $labelTranslatorStrategy = $this->createMock(LabelTranslatorStrategyInterface::class);
1599
        $modelAdmin->setLabelTranslatorStrategy($labelTranslatorStrategy);
1600
1601
        $validator = $this->createMock(ValidatorInterface::class);
1602
        $validator->expects($this->any())
1603
                ->method('getMetadataFor')
1604
                ->willReturn($this->createMock(MemberMetadata::class));
1605
        $modelAdmin->setValidator($validator);
1606
1607
        $modelManager = $this->createMock(ModelManagerInterface::class);
1608
        $modelManager->expects($this->any())
1609
            ->method('getNewFieldDescriptionInstance')
1610
            ->willReturn(new FieldDescription());
1611
        $modelAdmin->setModelManager($modelManager);
1612
1613
        // a Admin class to test that preValidate is called
1614
        $testAdminPreValidate = $this->createMock(AbstractAdmin::class, ['preValidate']);
1615
        $testAdminPreValidate->expects($this->once())
1616
                ->method('preValidate')
1617
                ->with($this->identicalTo($object));
1618
1619
        $event = $this->createMock(FormEvent::class);
1620
        $event->expects($this->any())
1621
                ->method('getData')
1622
                ->willReturn($object);
1623
1624
        $formBuild = $this->createMock(FormBuilder::class, ['addEventListener']);
1625
        $formBuild->expects($this->once())
1626
                ->method('addEventListener')
1627
                ->with($this->identicalTo(FormEvents::POST_SUBMIT),
1628
                        $this->callback(static function ($callback) use ($testAdminPreValidate, $event) {
1629
                            if (\is_callable($callback)) {
1630
                                $closure = $callback->bindTo($testAdminPreValidate);
1631
                                $closure($event);
1632
1633
                                return true;
1634
                            }
1635
1636
                            return false;
1637
                        }),
1638
                        $this->greaterThan(0)
1639
                    );
1640
1641
        $formContractor = $this->createMock(FormContractorInterface::class, ['getDefaultOptions', 'getFormBuilder']);
1642
        $formContractor->expects($this->any())
1643
                ->method('getDefaultOptions')
1644
                ->willReturn([]);
1645
        $formContractor->expects($this->any())
1646
                ->method('getFormBuilder')
1647
                ->willReturn($formBuild);
1648
1649
        $modelAdmin->setFormContractor($formContractor);
1650
        $modelAdmin->defineFormBuilder($formBuild);
1651
        $modelAdmin->getForm();
1652
    }
1653
1654
    public function testRemoveFieldFromFormGroup(): void
1655
    {
1656
        $formGroups = [
1657
            'foobar' => [
1658
                'fields' => [
1659
                    'foo' => 'foo',
1660
                    'bar' => 'bar',
1661
                ],
1662
            ],
1663
        ];
1664
1665
        $admin = new PostAdmin('sonata.post.admin.post', 'Application\Sonata\NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
1666
        $admin->setFormGroups($formGroups);
1667
1668
        $admin->removeFieldFromFormGroup('foo');
1669
        $this->assertSame($admin->getFormGroups(), [
1670
            'foobar' => [
1671
                'fields' => [
1672
                    'bar' => 'bar',
1673
                ],
1674
            ],
1675
        ]);
1676
1677
        $admin->removeFieldFromFormGroup('bar');
1678
        $this->assertSame($admin->getFormGroups(), []);
1679
    }
1680
1681
    public function testGetFilterParameters(): void
1682
    {
1683
        $authorId = uniqid();
1684
1685
        $postAdmin = new PostAdmin('sonata.post.admin.post', 'Application\Sonata\NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
1686
1687
        $commentAdmin = new CommentAdmin('sonata.post.admin.comment', 'Application\Sonata\NewsBundle\Entity\Comment', 'SonataNewsBundle:CommentAdmin');
1688
        $commentAdmin->setParentAssociationMapping('post.author');
1689
        $commentAdmin->setParent($postAdmin);
1690
1691
        $request = $this->createMock(Request::class, ['get']);
1692
        $query = $this->createMock(ParameterBag::class, ['get']);
1693
        $query->expects($this->any())
1694
            ->method('get')
1695
            ->willReturn([
1696
                'filter' => [
1697
                    '_page' => '1',
1698
                    '_per_page' => '32',
1699
                ],
1700
            ]);
1701
1702
        $request->query = $query;
1703
        $request->expects($this->any())
1704
            ->method('get')
1705
            ->willReturn($authorId);
1706
1707
        $commentAdmin->setRequest($request);
1708
1709
        $modelManager = $this->createMock(ModelManagerInterface::class);
1710
        $modelManager->expects($this->any())
1711
            ->method('getDefaultSortValues')
1712
            ->willReturn([]);
1713
1714
        $commentAdmin->setModelManager($modelManager);
1715
1716
        $parameters = $commentAdmin->getFilterParameters();
1717
1718
        $this->assertTrue(isset($parameters['post__author']));
1719
        $this->assertSame(['value' => $authorId], $parameters['post__author']);
1720
    }
1721
1722
    public function testGetFilterFieldDescription(): void
1723
    {
1724
        $modelAdmin = new ModelAdmin('sonata.post.admin.model', 'Application\Sonata\FooBundle\Entity\Model', 'SonataFooBundle:ModelAdmin');
1725
1726
        $fooFieldDescription = new FieldDescription();
1727
        $barFieldDescription = new FieldDescription();
1728
        $bazFieldDescription = new FieldDescription();
1729
1730
        $modelManager = $this->createMock(ModelManagerInterface::class);
1731
        $modelManager->expects($this->exactly(3))
1732
            ->method('getNewFieldDescriptionInstance')
1733
            ->willReturnCallback(static function ($adminClass, $name, $filterOptions) use ($fooFieldDescription, $barFieldDescription, $bazFieldDescription) {
1734
                switch ($name) {
1735
                    case 'foo':
1736
                        $fieldDescription = $fooFieldDescription;
1737
1738
                        break;
1739
1740
                    case 'bar':
1741
                        $fieldDescription = $barFieldDescription;
1742
1743
                        break;
1744
1745
                    case 'baz':
1746
                        $fieldDescription = $bazFieldDescription;
1747
1748
                        break;
1749
1750
                    default:
1751
                        throw new \RuntimeException(sprintf('Unknown filter name "%s"', $name));
1752
                        break;
1753
                }
1754
1755
                $fieldDescription->setName($name);
1756
1757
                return $fieldDescription;
1758
            });
1759
1760
        $modelAdmin->setModelManager($modelManager);
1761
1762
        $pager = $this->createMock(PagerInterface::class);
1763
1764
        $datagrid = $this->createMock(DatagridInterface::class);
1765
        $datagrid->expects($this->once())
1766
            ->method('getPager')
1767
            ->willReturn($pager);
1768
1769
        $datagridBuilder = $this->createMock(DatagridBuilderInterface::class);
1770
        $datagridBuilder->expects($this->once())
1771
            ->method('getBaseDatagrid')
1772
            ->with($this->identicalTo($modelAdmin), [])
1773
            ->willReturn($datagrid);
1774
1775
        $datagridBuilder->expects($this->exactly(3))
1776
            ->method('addFilter')
1777
            ->willReturnCallback(static function ($datagrid, $type, $fieldDescription, AdminInterface $admin): void {
1778
                $admin->addFilterFieldDescription($fieldDescription->getName(), $fieldDescription);
1779
                $fieldDescription->mergeOption('field_options', ['required' => false]);
1780
            });
1781
1782
        $modelAdmin->setDatagridBuilder($datagridBuilder);
1783
1784
        $this->assertSame(['foo' => $fooFieldDescription, 'bar' => $barFieldDescription, 'baz' => $bazFieldDescription], $modelAdmin->getFilterFieldDescriptions());
1785
        $this->assertFalse($modelAdmin->hasFilterFieldDescription('fooBar'));
1786
        $this->assertTrue($modelAdmin->hasFilterFieldDescription('foo'));
1787
        $this->assertTrue($modelAdmin->hasFilterFieldDescription('bar'));
1788
        $this->assertTrue($modelAdmin->hasFilterFieldDescription('baz'));
1789
        $this->assertSame($fooFieldDescription, $modelAdmin->getFilterFieldDescription('foo'));
1790
        $this->assertSame($barFieldDescription, $modelAdmin->getFilterFieldDescription('bar'));
1791
        $this->assertSame($bazFieldDescription, $modelAdmin->getFilterFieldDescription('baz'));
1792
    }
1793
1794
    public function testGetSubjectNoRequest(): void
1795
    {
1796
        $modelManager = $this->createMock(ModelManagerInterface::class);
1797
        $modelManager
1798
            ->expects($this->never())
1799
            ->method('find');
1800
1801
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
1802
        $admin->setModelManager($modelManager);
1803
1804
        $this->assertNull($admin->getSubject());
1805
    }
1806
1807
    public function testGetSideMenu(): void
1808
    {
1809
        $item = $this->createMock(ItemInterface::class);
1810
        $item
1811
            ->expects($this->once())
1812
            ->method('setChildrenAttribute')
1813
            ->with('class', 'nav navbar-nav');
1814
        $item
1815
            ->expects($this->once())
1816
            ->method('setExtra')
1817
            ->with('translation_domain', 'foo_bar_baz');
1818
1819
        $menuFactory = $this->createMock(FactoryInterface::class);
1820
        $menuFactory
1821
            ->expects($this->once())
1822
            ->method('createItem')
1823
            ->willReturn($item);
1824
1825
        $modelAdmin = new ModelAdmin('sonata.post.admin.model', 'Application\Sonata\FooBundle\Entity\Model', 'SonataFooBundle:ModelAdmin');
1826
        $modelAdmin->setMenuFactory($menuFactory);
1827
        $modelAdmin->setTranslationDomain('foo_bar_baz');
1828
1829
        $modelAdmin->getSideMenu('foo');
1830
    }
1831
1832
    /**
1833
     * @return array
1834
     */
1835
    public function provideGetSubject()
1836
    {
1837
        return [
1838
            [23],
1839
            ['azerty'],
1840
            ['4f69bbb5f14a13347f000092'],
1841
            ['0779ca8d-e2be-11e4-ac58-0242ac11000b'],
1842
            ['123'.AdapterInterface::ID_SEPARATOR.'my_type'], // composite keys are supported
1843
        ];
1844
    }
1845
1846
    /**
1847
     * @dataProvider provideGetSubject
1848
     */
1849
    public function testGetSubjectFailed($id): void
1850
    {
1851
        $modelManager = $this->createMock(ModelManagerInterface::class);
1852
        $modelManager
1853
            ->expects($this->once())
1854
            ->method('find')
1855
            ->with('NewsBundle\Entity\Post', $id)
1856
            ->willReturn(null); // entity not found
1857
1858
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
1859
        $admin->setModelManager($modelManager);
1860
1861
        $admin->setRequest(new Request(['id' => $id]));
1862
        $this->assertNull($admin->getSubject());
1863
    }
1864
1865
    /**
1866
     * @dataProvider provideGetSubject
1867
     */
1868
    public function testGetSubject($id): void
1869
    {
1870
        $entity = new Post();
1871
1872
        $modelManager = $this->createMock(ModelManagerInterface::class);
1873
        $modelManager
1874
            ->expects($this->once())
1875
            ->method('find')
1876
            ->with('NewsBundle\Entity\Post', $id)
1877
            ->willReturn($entity);
1878
1879
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
1880
        $admin->setModelManager($modelManager);
1881
1882
        $admin->setRequest(new Request(['id' => $id]));
1883
        $this->assertSame($entity, $admin->getSubject());
1884
        $this->assertSame($entity, $admin->getSubject()); // model manager must be used only once
1885
    }
1886
1887
    public function testGetSubjectWithParentDescription(): void
1888
    {
1889
        $adminId = 1;
1890
1891
        $comment = new Comment();
1892
1893
        $modelManager = $this->createMock(ModelManagerInterface::class);
1894
        $modelManager
1895
            ->expects($this->any())
1896
            ->method('find')
1897
            ->with('NewsBundle\Entity\Comment', $adminId)
1898
            ->willReturn($comment);
1899
1900
        $request = new Request(['id' => $adminId]);
1901
1902
        $postAdmin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
1903
        $postAdmin->setRequest($request);
1904
1905
        $commentAdmin = new CommentAdmin('sonata.post.admin.comment', 'NewsBundle\Entity\Comment', 'SonataNewsBundle:CommentAdmin');
1906
        $commentAdmin->setRequest($request);
1907
        $commentAdmin->setModelManager($modelManager);
1908
1909
        $this->assertSame($comment, $commentAdmin->getSubject());
1910
1911
        $commentAdmin->setSubject(null);
1912
        $commentAdmin->setParentFieldDescription(new FieldDescription());
1913
1914
        $this->assertNull($commentAdmin->getSubject());
1915
    }
1916
1917
    /**
1918
     * @covers \Sonata\AdminBundle\Admin\AbstractAdmin::configureActionButtons
1919
     */
1920
    public function testGetActionButtonsList(): void
1921
    {
1922
        $expected = [
1923
            'create' => [
1924
                'template' => 'Foo.html.twig',
1925
            ],
1926
        ];
1927
1928
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
1929
1930
        $templateRegistry = $this->prophesize(MutableTemplateRegistryInterface::class);
1931
        $templateRegistry->getTemplate('button_create')->willReturn('Foo.html.twig');
1932
1933
        $admin->setTemplateRegistry($templateRegistry->reveal());
1934
1935
        $securityHandler = $this->createMock(SecurityHandlerInterface::class);
1936
        $securityHandler
1937
            ->expects($this->once())
1938
            ->method('isGranted')
1939
            ->with($admin, 'CREATE', $admin)
1940
            ->willReturn(true);
1941
        $admin->setSecurityHandler($securityHandler);
1942
1943
        $routeGenerator = $this->createMock(RouteGeneratorInterface::class);
1944
        $routeGenerator
1945
            ->expects($this->once())
1946
            ->method('hasAdminRoute')
1947
            ->with($admin, 'create')
1948
            ->willReturn(true);
1949
        $admin->setRouteGenerator($routeGenerator);
1950
1951
        $this->assertSame($expected, $admin->getActionButtons('list', null));
1952
    }
1953
1954
    /**
1955
     * @covers \Sonata\AdminBundle\Admin\AbstractAdmin::configureActionButtons
1956
     */
1957
    public function testGetActionButtonsListCreateDisabled(): void
1958
    {
1959
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
1960
1961
        $securityHandler = $this->createMock(SecurityHandlerInterface::class);
1962
        $securityHandler
1963
            ->expects($this->once())
1964
            ->method('isGranted')
1965
            ->with($admin, 'CREATE', $admin)
1966
            ->willReturn(false);
1967
        $admin->setSecurityHandler($securityHandler);
1968
1969
        $this->assertSame([], $admin->getActionButtons('list', null));
1970
    }
1971
1972
    /**
1973
     * @covers \Sonata\AdminBundle\Admin\AbstractAdmin::configureBatchActions
1974
     */
1975
    public function testGetBatchActions(): void
1976
    {
1977
        $expected = [
1978
            'delete' => [
1979
                'label' => 'action_delete',
1980
                'translation_domain' => 'SonataAdminBundle',
1981
                'ask_confirmation' => true, // by default always true
1982
            ],
1983
            'foo' => [
1984
                'label' => 'action_foo',
1985
                'translation_domain' => 'SonataAdminBundle',
1986
            ],
1987
            'bar' => [
1988
                'label' => 'batch.label_bar',
1989
                'translation_domain' => 'SonataAdminBundle',
1990
            ],
1991
            'baz' => [
1992
                'label' => 'action_baz',
1993
                'translation_domain' => 'AcmeAdminBundle',
1994
            ],
1995
        ];
1996
1997
        $pathInfo = new PathInfoBuilder($this->createMock(AuditManagerInterface::class));
1998
1999
        $labelTranslatorStrategy = $this->createMock(LabelTranslatorStrategyInterface::class);
2000
        $labelTranslatorStrategy->expects($this->any())
2001
            ->method('getLabel')
2002
            ->willReturnCallback(static function ($label, $context = '', $type = '') {
2003
                return $context.'.'.$type.'_'.$label;
2004
            });
2005
2006
        $admin = new PostAdmin('sonata.post.admin.model', 'Application\Sonata\FooBundle\Entity\Model', 'SonataFooBundle:ModelAdmin');
2007
        $admin->setRouteBuilder($pathInfo);
2008
        $admin->setTranslationDomain('SonataAdminBundle');
2009
        $admin->setLabelTranslatorStrategy($labelTranslatorStrategy);
2010
2011
        $routeGenerator = $this->createMock(RouteGeneratorInterface::class);
2012
        $routeGenerator
2013
            ->expects($this->once())
2014
            ->method('hasAdminRoute')
2015
            ->with($admin, 'delete')
2016
            ->willReturn(true);
2017
        $admin->setRouteGenerator($routeGenerator);
2018
2019
        $securityHandler = $this->createMock(SecurityHandlerInterface::class);
2020
        $securityHandler->expects($this->any())
2021
            ->method('isGranted')
2022
            ->willReturnCallback(static function (AdminInterface $adminIn, $attributes, $object = null) use ($admin) {
2023
                if ($admin === $adminIn && 'DELETE' === $attributes) {
2024
                    return true;
2025
                }
2026
2027
                return false;
2028
            });
2029
        $admin->setSecurityHandler($securityHandler);
2030
2031
        $this->assertSame($expected, $admin->getBatchActions());
2032
    }
2033
2034
    /**
2035
     * @covers \Sonata\AdminBundle\Admin\AbstractAdmin::showMosaicButton
2036
     */
2037
    public function testShowMosaicButton(): void
2038
    {
2039
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
2040
        $listModes = $admin->getListModes();
2041
2042
        $admin->showMosaicButton(true);
2043
2044
        $this->assertSame($listModes, $admin->getListModes());
2045
    }
2046
2047
    /**
2048
     * @covers \Sonata\AdminBundle\Admin\AbstractAdmin::showMosaicButton
2049
     */
2050
    public function testShowMosaicButtonHideMosaic(): void
2051
    {
2052
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'SonataNewsBundle:PostAdmin');
2053
        $listModes = $admin->getListModes();
2054
        $expected['list'] = $listModes['list'];
2055
2056
        $admin->showMosaicButton(false);
2057
2058
        $this->assertSame($expected, $admin->getListModes());
2059
    }
2060
2061
    /**
2062
     * @covers \Sonata\AdminBundle\Admin\AbstractAdmin::getDashboardActions
2063
     * @dataProvider provideGetBaseRouteName
2064
     */
2065
    public function testDefaultDashboardActionsArePresent($objFqn, $expected): void
2066
    {
2067
        $pathInfo = new PathInfoBuilder($this->createMock(AuditManagerInterface::class));
2068
2069
        $routeGenerator = new DefaultRouteGenerator(
2070
            $this->createMock(RouterInterface::class),
2071
            new RoutesCache($this->cacheTempFolder, true)
2072
        );
2073
2074
        $admin = new PostAdmin('sonata.post.admin.post', $objFqn, 'SonataNewsBundle:PostAdmin');
2075
        $admin->setRouteBuilder($pathInfo);
2076
        $admin->setRouteGenerator($routeGenerator);
2077
        $admin->initialize();
2078
2079
        $templateRegistry = $this->prophesize(MutableTemplateRegistryInterface::class);
2080
        $templateRegistry->getTemplate('action_create')->willReturn('Foo.html.twig');
2081
2082
        $admin->setTemplateRegistry($templateRegistry->reveal());
2083
2084
        $securityHandler = $this->createMock(SecurityHandlerInterface::class);
2085
        $securityHandler->expects($this->any())
2086
            ->method('isGranted')
2087
            ->willReturnCallback(static function (AdminInterface $adminIn, $attributes, $object = null) use ($admin) {
2088
                if ($admin === $adminIn && ('CREATE' === $attributes || 'LIST' === $attributes)) {
2089
                    return true;
2090
                }
2091
2092
                return false;
2093
            });
2094
2095
        $admin->setSecurityHandler($securityHandler);
2096
2097
        $this->assertArrayHasKey('list', $admin->getDashboardActions());
2098
        $this->assertArrayHasKey('create', $admin->getDashboardActions());
2099
    }
2100
2101
    public function testDefaultFilters(): void
2102
    {
2103
        $admin = new FilteredAdmin('sonata.post.admin.model', 'Application\Sonata\FooBundle\Entity\Model', 'SonataFooBundle:ModelAdmin');
2104
2105
        $subjectId = uniqid();
2106
2107
        $request = $this->createMock(Request::class, ['get']);
2108
        $query = $this->createMock(ParameterBag::class, ['set', 'get']);
2109
        $query->expects($this->any())
2110
            ->method('get')
2111
            ->with($this->equalTo('filter'))
2112
            ->willReturn([
2113
                'a' => [
2114
                    'value' => 'b',
2115
                ],
2116
                'foo' => [
2117
                    'type' => '1',
2118
                    'value' => 'bar',
2119
                ],
2120
                'baz' => [
2121
                    'type' => '5',
2122
                    'value' => 'test',
2123
                ],
2124
            ]);
2125
        $request->query = $query;
2126
2127
        $request->expects($this->any())
2128
            ->method('get')
2129
            ->willReturn($subjectId);
2130
2131
        $admin->setRequest($request);
2132
2133
        $modelManager = $this->createMock(ModelManagerInterface::class);
2134
        $modelManager->expects($this->any())
2135
            ->method('getDefaultSortValues')
2136
            ->willReturn([]);
2137
2138
        $admin->setModelManager($modelManager);
2139
2140
        $this->assertSame([
2141
            '_page' => 1,
2142
            '_per_page' => 32,
2143
            'foo' => [
2144
                'type' => '1',
2145
                'value' => 'bar',
2146
            ],
2147
            'baz' => [
2148
                'type' => '5',
2149
                'value' => 'test',
2150
            ],
2151
            'a' => [
2152
                'value' => 'b',
2153
            ],
2154
        ], $admin->getFilterParameters());
2155
2156
        $this->assertTrue($admin->isDefaultFilter('foo'));
2157
        $this->assertFalse($admin->isDefaultFilter('bar'));
2158
        $this->assertFalse($admin->isDefaultFilter('a'));
2159
    }
2160
2161
    /**
2162
     * @group legacy
2163
     */
2164
    public function testDefaultBreadcrumbsBuilder(): void
2165
    {
2166
        $container = $this->createMock(ContainerInterface::class);
2167
        $container->expects($this->once())
2168
            ->method('getParameter')
2169
            ->with('sonata.admin.configuration.breadcrumbs')
2170
            ->willReturn([]);
2171
2172
        $pool = $this->getMockBuilder(Pool::class)
2173
            ->disableOriginalConstructor()
2174
            ->getMock();
2175
        $pool->expects($this->once())
2176
            ->method('getContainer')
2177
            ->willReturn($container);
2178
2179
        $admin = $this->getMockForAbstractClass(AbstractAdmin::class, [
2180
            'admin.my_code', 'My\Class', 'MyBundle:ClassAdmin',
2181
        ], '', true, true, true, ['getConfigurationPool']);
2182
        $admin->expects($this->once())
2183
            ->method('getConfigurationPool')
2184
            ->willReturn($pool);
2185
2186
        $this->assertInstanceOf(BreadcrumbsBuilder::class, $admin->getBreadcrumbsBuilder());
2187
    }
2188
2189
    /**
2190
     * @group legacy
2191
     */
2192
    public function testBreadcrumbsBuilderSetter(): void
2193
    {
2194
        $admin = $this->getMockForAbstractClass(AbstractAdmin::class, [
2195
            'admin.my_code', 'My\Class', 'MyBundle:ClassAdmin',
2196
        ]);
2197
        $this->assertSame($admin, $admin->setBreadcrumbsBuilder($builder = $this->createMock(
2198
            BreadcrumbsBuilderInterface::class
2199
        )));
2200
        $this->assertSame($builder, $admin->getBreadcrumbsBuilder());
2201
    }
2202
2203
    /**
2204
     * @group legacy
2205
     */
2206
    public function testGetBreadcrumbs(): void
2207
    {
2208
        $admin = $this->getMockForAbstractClass(AbstractAdmin::class, [
2209
            'admin.my_code', 'My\Class', 'MyBundle:ClassAdmin',
2210
        ]);
2211
        $builder = $this->prophesize(BreadcrumbsBuilderInterface::class);
2212
        $action = 'myaction';
2213
        $builder->getBreadcrumbs($admin, $action)->shouldBeCalled();
2214
        $admin->setBreadcrumbsBuilder($builder->reveal())->getBreadcrumbs($action);
2215
    }
2216
2217
    /**
2218
     * @group legacy
2219
     */
2220
    public function testBuildBreadcrumbs(): void
2221
    {
2222
        $admin = $this->getMockForAbstractClass(AbstractAdmin::class, [
2223
            'admin.my_code', 'My\Class', 'MyBundle:ClassAdmin',
2224
        ]);
2225
        $builder = $this->prophesize(BreadcrumbsBuilderInterface::class);
2226
        $action = 'myaction';
2227
        $menu = $this->createMock(ItemInterface::class);
2228
        $builder->buildBreadcrumbs($admin, $action, $menu)
2229
            ->shouldBeCalledTimes(1)
2230
            ->willReturn($menu);
2231
        $admin->setBreadcrumbsBuilder($builder->reveal());
2232
2233
        /* check the called is proxied only once */
2234
        $this->assertSame($menu, $admin->buildBreadcrumbs($action, $menu));
2235
        $this->assertSame($menu, $admin->buildBreadcrumbs($action, $menu));
2236
    }
2237
2238
    /**
2239
     * NEXT_MAJOR: remove this method.
2240
     *
2241
     * @group legacy
2242
     */
2243
    public function testCreateQueryLegacyCallWorks(): void
2244
    {
2245
        $admin = $this->getMockForAbstractClass(AbstractAdmin::class, [
2246
            'admin.my_code', 'My\Class', 'MyBundle:ClassAdmin',
2247
        ]);
2248
        $modelManager = $this->createMock(ModelManagerInterface::class);
2249
        $modelManager->expects($this->once())
2250
            ->method('createQuery')
2251
            ->with('My\Class')
2252
            ->willReturn('a query');
2253
2254
        $admin->setModelManager($modelManager);
2255
        $this->assertSame('a query', $admin->createQuery('list'));
2256
    }
2257
2258
    public function testGetDataSourceIterator(): void
2259
    {
2260
        $datagrid = $this->createMock(DatagridInterface::class);
2261
        $datagrid->method('buildPager');
2262
2263
        $modelManager = $this->createMock(ModelManagerInterface::class);
2264
        $modelManager->method('getExportFields')->willReturn([
2265
            'field',
2266
            'foo',
2267
            'bar',
2268
        ]);
2269
        $modelManager->expects($this->once())->method('getDataSourceIterator')
2270
            ->with($this->equalTo($datagrid), $this->equalTo([
2271
                'Feld' => 'field',
2272
                1 => 'foo',
2273
                2 => 'bar',
2274
            ]));
2275
2276
        $admin = $this->getMockBuilder(AbstractAdmin::class)
2277
            ->disableOriginalConstructor()
2278
            ->setMethods(['getDatagrid', 'getTranslationLabel', 'trans'])
2279
            ->getMockForAbstractClass();
2280
        $admin->method('getDatagrid')->willReturn($datagrid);
2281
        $admin->setModelManager($modelManager);
2282
2283
        $admin->expects($this->any())
2284
            ->method('getTranslationLabel')
2285
            ->willReturnCallback(static function ($label, $context = '', $type = '') {
2286
                return $context.'.'.$type.'_'.$label;
2287
            });
2288
        $admin->expects($this->any())
2289
            ->method('trans')
2290
            ->willReturnCallback(static function ($label) {
2291
                if ('export.label_field' === $label) {
2292
                    return 'Feld';
2293
                }
2294
2295
                return $label;
2296
            });
2297
2298
        $admin->getDataSourceIterator();
2299
    }
2300
2301
    public function testCircularChildAdmin(): void
2302
    {
2303
        $this->expectException(
2304
            \RuntimeException::class,
2305
            'Circular reference detected! The child admin `sonata.post.admin.post` is already in the parent tree of the `sonata.post.admin.comment` admin.'
2306
        );
2307
2308
        $postAdmin = new PostAdmin(
2309
            'sonata.post.admin.post',
2310
            'Application\Sonata\NewsBundle\Entity\Post',
2311
            'SonataNewsBundle:PostAdmin'
2312
        );
2313
        $commentAdmin = new CommentAdmin(
2314
            'sonata.post.admin.comment',
2315
            'Application\Sonata\NewsBundle\Entity\Comment',
2316
            'SonataNewsBundle:CommentAdmin'
2317
        );
2318
        $postAdmin->addChild($commentAdmin, 'post');
2319
        $commentAdmin->addChild($postAdmin, 'comment');
2320
    }
2321
2322
    public function testCircularChildAdminTripleLevel(): void
2323
    {
2324
        $this->expectException(
2325
            \RuntimeException::class,
2326
            'Circular reference detected! The child admin `sonata.post.admin.post` is already in the parent tree of the `sonata.post.admin.comment_vote` admin.'
2327
        );
2328
2329
        $postAdmin = new PostAdmin(
2330
            'sonata.post.admin.post',
2331
            'Application\Sonata\NewsBundle\Entity\Post',
2332
            'SonataNewsBundle:PostAdmin'
2333
        );
2334
        $commentAdmin = new CommentAdmin(
2335
            'sonata.post.admin.comment',
2336
            'Application\Sonata\NewsBundle\Entity\Comment',
2337
            'SonataNewsBundle:CommentAdmin'
2338
        );
2339
        $commentVoteAdmin = new CommentVoteAdmin(
2340
            'sonata.post.admin.comment_vote',
2341
            'Application\Sonata\NewsBundle\Entity\CommentVote',
2342
            'SonataNewsBundle:CommentVoteAdmin'
2343
        );
2344
        $postAdmin->addChild($commentAdmin, 'post');
2345
        $commentAdmin->addChild($commentVoteAdmin, 'comment');
2346
        $commentVoteAdmin->addChild($postAdmin, 'post');
2347
    }
2348
2349
    public function testCircularChildAdminWithItself(): void
2350
    {
2351
        $this->expectException(
2352
            \RuntimeException::class,
2353
            'Circular reference detected! The child admin `sonata.post.admin.post` is already in the parent tree of the `sonata.post.admin.post` admin.'
2354
        );
2355
2356
        $postAdmin = new PostAdmin(
2357
            'sonata.post.admin.post',
2358
            'Application\Sonata\NewsBundle\Entity\Post',
2359
            'SonataNewsBundle:PostAdmin'
2360
        );
2361
        $postAdmin->addChild($postAdmin);
2362
    }
2363
2364
    public function testGetRootAncestor(): void
2365
    {
2366
        $postAdmin = new PostAdmin(
2367
            'sonata.post.admin.post',
2368
            'Application\Sonata\NewsBundle\Entity\Post',
2369
            'SonataNewsBundle:PostAdmin'
2370
        );
2371
        $commentAdmin = new CommentAdmin(
2372
            'sonata.post.admin.comment',
2373
            'Application\Sonata\NewsBundle\Entity\Comment',
2374
            'SonataNewsBundle:CommentAdmin'
2375
        );
2376
        $commentVoteAdmin = new CommentVoteAdmin(
2377
            'sonata.post.admin.comment_vote',
2378
            'Application\Sonata\NewsBundle\Entity\CommentVote',
2379
            'SonataNewsBundle:CommentVoteAdmin'
2380
        );
2381
2382
        $this->assertSame($postAdmin, $postAdmin->getRootAncestor());
2383
        $this->assertSame($commentAdmin, $commentAdmin->getRootAncestor());
2384
        $this->assertSame($commentVoteAdmin, $commentVoteAdmin->getRootAncestor());
2385
2386
        $postAdmin->addChild($commentAdmin, 'post');
2387
2388
        $this->assertSame($postAdmin, $postAdmin->getRootAncestor());
2389
        $this->assertSame($postAdmin, $commentAdmin->getRootAncestor());
2390
        $this->assertSame($commentVoteAdmin, $commentVoteAdmin->getRootAncestor());
2391
2392
        $commentAdmin->addChild($commentVoteAdmin, 'comment');
2393
2394
        $this->assertSame($postAdmin, $postAdmin->getRootAncestor());
2395
        $this->assertSame($postAdmin, $commentAdmin->getRootAncestor());
2396
        $this->assertSame($postAdmin, $commentVoteAdmin->getRootAncestor());
2397
    }
2398
2399
    public function testGetChildDepth(): void
2400
    {
2401
        $postAdmin = new PostAdmin(
2402
            'sonata.post.admin.post',
2403
            'Application\Sonata\NewsBundle\Entity\Post',
2404
            'SonataNewsBundle:PostAdmin'
2405
        );
2406
        $commentAdmin = new CommentAdmin(
2407
            'sonata.post.admin.comment',
2408
            'Application\Sonata\NewsBundle\Entity\Comment',
2409
            'SonataNewsBundle:CommentAdmin'
2410
        );
2411
        $commentVoteAdmin = new CommentVoteAdmin(
2412
            'sonata.post.admin.comment_vote',
2413
            'Application\Sonata\NewsBundle\Entity\CommentVote',
2414
            'SonataNewsBundle:CommentVoteAdmin'
2415
        );
2416
2417
        $this->assertSame(0, $postAdmin->getChildDepth());
2418
        $this->assertSame(0, $commentAdmin->getChildDepth());
2419
        $this->assertSame(0, $commentVoteAdmin->getChildDepth());
2420
2421
        $postAdmin->addChild($commentAdmin, 'post');
2422
2423
        $this->assertSame(0, $postAdmin->getChildDepth());
2424
        $this->assertSame(1, $commentAdmin->getChildDepth());
2425
        $this->assertSame(0, $commentVoteAdmin->getChildDepth());
2426
2427
        $commentAdmin->addChild($commentVoteAdmin, 'comment');
2428
2429
        $this->assertSame(0, $postAdmin->getChildDepth());
2430
        $this->assertSame(1, $commentAdmin->getChildDepth());
2431
        $this->assertSame(2, $commentVoteAdmin->getChildDepth());
2432
    }
2433
2434
    public function testGetCurrentLeafChildAdmin(): void
2435
    {
2436
        $postAdmin = new PostAdmin(
2437
            'sonata.post.admin.post',
2438
            'Application\Sonata\NewsBundle\Entity\Post',
2439
            'SonataNewsBundle:PostAdmin'
2440
        );
2441
        $commentAdmin = new CommentAdmin(
2442
            'sonata.post.admin.comment',
2443
            'Application\Sonata\NewsBundle\Entity\Comment',
2444
            'SonataNewsBundle:CommentAdmin'
2445
        );
2446
        $commentVoteAdmin = new CommentVoteAdmin(
2447
            'sonata.post.admin.comment_vote',
2448
            'Application\Sonata\NewsBundle\Entity\CommentVote',
2449
            'SonataNewsBundle:CommentVoteAdmin'
2450
        );
2451
2452
        $postAdmin->addChild($commentAdmin, 'post');
2453
        $commentAdmin->addChild($commentVoteAdmin, 'comment');
2454
2455
        $this->assertNull($postAdmin->getCurrentLeafChildAdmin());
2456
        $this->assertNull($commentAdmin->getCurrentLeafChildAdmin());
2457
        $this->assertNull($commentVoteAdmin->getCurrentLeafChildAdmin());
2458
2459
        $commentAdmin->setCurrentChild(true);
2460
2461
        $this->assertSame($commentAdmin, $postAdmin->getCurrentLeafChildAdmin());
2462
        $this->assertNull($commentAdmin->getCurrentLeafChildAdmin());
2463
        $this->assertNull($commentVoteAdmin->getCurrentLeafChildAdmin());
2464
2465
        $commentVoteAdmin->setCurrentChild(true);
2466
2467
        $this->assertSame($commentVoteAdmin, $postAdmin->getCurrentLeafChildAdmin());
2468
        $this->assertSame($commentVoteAdmin, $commentAdmin->getCurrentLeafChildAdmin());
2469
        $this->assertNull($commentVoteAdmin->getCurrentLeafChildAdmin());
2470
    }
2471
2472
    private function createTagAdmin(Post $post): TagAdmin
2473
    {
2474
        $postAdmin = $this->getMockBuilder(PostAdmin::class)
2475
            ->disableOriginalConstructor()
2476
            ->getMock();
2477
2478
        $postAdmin->expects($this->any())->method('getObject')->willReturn($post);
2479
2480
        $formBuilder = $this->createMock(FormBuilderInterface::class);
2481
        $formBuilder->expects($this->any())->method('getForm')->willReturn(null);
2482
2483
        $tagAdmin = $this->getMockBuilder(TagAdmin::class)
2484
            ->setConstructorArgs([
2485
                'admin.tag',
2486
                Tag::class,
2487
                'MyBundle:MyController',
2488
            ])
2489
            ->setMethods(['getFormBuilder'])
2490
            ->getMock();
2491
2492
        $tagAdmin->expects($this->any())->method('getFormBuilder')->willReturn($formBuilder);
2493
        $tagAdmin->setParent($postAdmin);
2494
2495
        $tag = new Tag();
2496
        $tagAdmin->setSubject($tag);
2497
2498
        $request = $this->createMock(Request::class);
2499
        $tagAdmin->setRequest($request);
2500
2501
        $configurationPool = $this->getMockBuilder(Pool::class)
2502
            ->disableOriginalConstructor()
2503
            ->getMock();
2504
2505
        $configurationPool->expects($this->any())->method('getPropertyAccessor')->willReturn(PropertyAccess::createPropertyAccessor());
2506
2507
        $tagAdmin->setConfigurationPool($configurationPool);
2508
2509
        return $tagAdmin;
2510
    }
2511
}
2512