Completed
Push — 3.x ( c2ec31...538660 )
by Christian
04:44
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\Datagrid\ProxyQueryInterface;
36
use Sonata\AdminBundle\Filter\Persister\FilterPersisterInterface;
37
use Sonata\AdminBundle\Model\AuditManagerInterface;
38
use Sonata\AdminBundle\Model\ModelManagerInterface;
39
use Sonata\AdminBundle\Route\DefaultRouteGenerator;
40
use Sonata\AdminBundle\Route\PathInfoBuilder;
41
use Sonata\AdminBundle\Route\RouteGeneratorInterface;
42
use Sonata\AdminBundle\Route\RoutesCache;
43
use Sonata\AdminBundle\Security\Handler\AclSecurityHandlerInterface;
44
use Sonata\AdminBundle\Security\Handler\SecurityHandlerInterface;
45
use Sonata\AdminBundle\Templating\MutableTemplateRegistryInterface;
46
use Sonata\AdminBundle\Tests\Fixtures\Admin\CommentAdmin;
47
use Sonata\AdminBundle\Tests\Fixtures\Admin\CommentVoteAdmin;
48
use Sonata\AdminBundle\Tests\Fixtures\Admin\CommentWithCustomRouteAdmin;
49
use Sonata\AdminBundle\Tests\Fixtures\Admin\FieldDescription;
50
use Sonata\AdminBundle\Tests\Fixtures\Admin\FilteredAdmin;
51
use Sonata\AdminBundle\Tests\Fixtures\Admin\ModelAdmin;
52
use Sonata\AdminBundle\Tests\Fixtures\Admin\PostAdmin;
53
use Sonata\AdminBundle\Tests\Fixtures\Admin\PostWithCustomRouteAdmin;
54
use Sonata\AdminBundle\Tests\Fixtures\Admin\TagAdmin;
55
use Sonata\AdminBundle\Tests\Fixtures\Bundle\Entity\BlogPost;
56
use Sonata\AdminBundle\Tests\Fixtures\Bundle\Entity\Comment;
57
use Sonata\AdminBundle\Tests\Fixtures\Bundle\Entity\Post;
58
use Sonata\AdminBundle\Tests\Fixtures\Bundle\Entity\Tag;
59
use Sonata\AdminBundle\Tests\Fixtures\Entity\FooToString;
60
use Sonata\AdminBundle\Tests\Fixtures\Entity\FooToStringNull;
61
use Sonata\AdminBundle\Translator\LabelTranslatorStrategyInterface;
62
use Sonata\Doctrine\Adapter\AdapterInterface;
63
use Symfony\Component\DependencyInjection\Container;
64
use Symfony\Component\DependencyInjection\ContainerInterface;
65
use Symfony\Component\Filesystem\Filesystem;
66
use Symfony\Component\Form\FormBuilder;
67
use Symfony\Component\Form\FormBuilderInterface;
68
use Symfony\Component\Form\FormEvent;
69
use Symfony\Component\Form\FormEvents;
70
use Symfony\Component\HttpFoundation\ParameterBag;
71
use Symfony\Component\HttpFoundation\Request;
72
use Symfony\Component\PropertyAccess\PropertyAccess;
73
use Symfony\Component\Routing\RouterInterface;
74
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
75
use Symfony\Component\Translation\TranslatorInterface;
76
use Symfony\Component\Validator\Mapping\MemberMetadata;
77
use Symfony\Component\Validator\Validator\ValidatorInterface;
78
79
class AdminTest extends TestCase
80
{
81
    protected $cacheTempFolder;
82
83
    protected function setUp(): void
84
    {
85
        $this->cacheTempFolder = sys_get_temp_dir().'/sonata_test_route';
86
        $filesystem = new Filesystem();
87
        $filesystem->remove($this->cacheTempFolder);
88
    }
89
90
    /**
91
     * @covers \Sonata\AdminBundle\Admin\AbstractAdmin::__construct
92
     */
93
    public function testConstructor(): void
94
    {
95
        $class = 'Application\Sonata\NewsBundle\Entity\Post';
96
        $baseControllerName = 'Sonata\NewsBundle\Controller\PostAdminController';
97
98
        $admin = new PostAdmin('sonata.post.admin.post', $class, $baseControllerName);
99
        $this->assertInstanceOf(AbstractAdmin::class, $admin);
100
        $this->assertSame($class, $admin->getClass());
101
        $this->assertSame($baseControllerName, $admin->getBaseControllerName());
102
    }
103
104
    public function testGetClass(): void
105
    {
106
        $class = Post::class;
107
        $baseControllerName = 'Sonata\NewsBundle\Controller\PostAdminController';
108
109
        $admin = new PostAdmin('sonata.post.admin.post', $class, $baseControllerName);
110
111
        $admin->setModelManager($this->getMockForAbstractClass(ModelManagerInterface::class));
112
113
        $admin->setSubject(new BlogPost());
114
        $this->assertSame(BlogPost::class, $admin->getClass());
115
116
        $admin->setSubClasses(['foo']);
117
        $this->assertSame(BlogPost::class, $admin->getClass());
118
119
        $admin->setSubject(null);
120
        $admin->setSubClasses([]);
121
        $this->assertSame($class, $admin->getClass());
122
123
        $admin->setSubClasses(['foo' => 'bar']);
124
        $admin->setRequest(new Request(['subclass' => 'foo']));
125
        $this->assertSame('bar', $admin->getClass());
126
    }
127
128
    public function testGetClassException(): void
129
    {
130
        $this->expectException(\RuntimeException::class);
131
        $this->expectExceptionMessage('Feature not implemented: an embedded admin cannot have subclass');
132
133
        $class = 'Application\Sonata\NewsBundle\Entity\Post';
134
        $baseControllerName = 'Sonata\NewsBundle\Controller\PostAdminController';
135
136
        $admin = new PostAdmin('sonata.post.admin.post', $class, $baseControllerName);
137
        $admin->setParentFieldDescription(new FieldDescription());
138
        $admin->setSubClasses(['foo' => 'bar']);
139
        $admin->setRequest(new Request(['subclass' => 'foo']));
140
        $admin->getClass();
141
    }
142
143
    public function testCheckAccessThrowsExceptionOnMadeUpAction(): void
144
    {
145
        $admin = new PostAdmin(
146
            'sonata.post.admin.post',
147
            'Application\Sonata\NewsBundle\Entity\Post',
148
            'Sonata\NewsBundle\Controller\PostAdminController'
149
        );
150
        $this->expectException(
151
            \InvalidArgumentException::class
152
        );
153
        $this->expectExceptionMessage(
154
            'Action "made-up" could not be found'
155
        );
156
        $admin->checkAccess('made-up');
157
    }
158
159
    public function testCheckAccessThrowsAccessDeniedException(): void
160
    {
161
        $admin = new PostAdmin(
162
            'sonata.post.admin.post',
163
            'Application\Sonata\NewsBundle\Entity\Post',
164
            'Sonata\NewsBundle\Controller\PostAdminController'
165
        );
166
        $securityHandler = $this->prophesize(SecurityHandlerInterface::class);
167
        $securityHandler->isGranted($admin, 'CUSTOM_ROLE', $admin)->willReturn(true);
168
        $securityHandler->isGranted($admin, 'EXTRA_CUSTOM_ROLE', $admin)->willReturn(false);
169
        $customExtension = $this->prophesize(AbstractAdminExtension::class);
170
        $customExtension->getAccessMapping($admin)->willReturn(
171
            ['custom_action' => ['CUSTOM_ROLE', 'EXTRA_CUSTOM_ROLE']]
172
        );
173
        $admin->addExtension($customExtension->reveal());
174
        $admin->setSecurityHandler($securityHandler->reveal());
175
        $this->expectException(
176
            AccessDeniedException::class
177
        );
178
        $this->expectExceptionMessage(
179
            'Access Denied to the action custom_action and role EXTRA_CUSTOM_ROLE'
180
        );
181
        $admin->checkAccess('custom_action');
182
    }
183
184
    public function testHasAccessOnMadeUpAction(): void
185
    {
186
        $admin = new PostAdmin(
187
            'sonata.post.admin.post',
188
            'Application\Sonata\NewsBundle\Entity\Post',
189
            'Sonata\NewsBundle\Controller\PostAdminController'
190
        );
191
192
        $this->assertFalse($admin->hasAccess('made-up'));
193
    }
194
195
    public function testHasAccess(): void
196
    {
197
        $admin = new PostAdmin(
198
            'sonata.post.admin.post',
199
            'Application\Sonata\NewsBundle\Entity\Post',
200
            'Sonata\NewsBundle\Controller\PostAdminController'
201
        );
202
        $securityHandler = $this->prophesize(SecurityHandlerInterface::class);
203
        $securityHandler->isGranted($admin, 'CUSTOM_ROLE', $admin)->willReturn(true);
204
        $securityHandler->isGranted($admin, 'EXTRA_CUSTOM_ROLE', $admin)->willReturn(false);
205
        $customExtension = $this->prophesize(AbstractAdminExtension::class);
206
        $customExtension->getAccessMapping($admin)->willReturn(
207
            ['custom_action' => ['CUSTOM_ROLE', 'EXTRA_CUSTOM_ROLE']]
208
        );
209
        $admin->addExtension($customExtension->reveal());
210
        $admin->setSecurityHandler($securityHandler->reveal());
211
212
        $this->assertFalse($admin->hasAccess('custom_action'));
213
    }
214
215
    public function testHasAccessAllowsAccess(): void
216
    {
217
        $admin = new PostAdmin(
218
            'sonata.post.admin.post',
219
            'Application\Sonata\NewsBundle\Entity\Post',
220
            'Sonata\NewsBundle\Controller\PostAdminController'
221
        );
222
        $securityHandler = $this->prophesize(SecurityHandlerInterface::class);
223
        $securityHandler->isGranted($admin, 'CUSTOM_ROLE', $admin)->willReturn(true);
224
        $securityHandler->isGranted($admin, 'EXTRA_CUSTOM_ROLE', $admin)->willReturn(true);
225
        $customExtension = $this->prophesize(AbstractAdminExtension::class);
226
        $customExtension->getAccessMapping($admin)->willReturn(
227
            ['custom_action' => ['CUSTOM_ROLE', 'EXTRA_CUSTOM_ROLE']]
228
        );
229
        $admin->addExtension($customExtension->reveal());
230
        $admin->setSecurityHandler($securityHandler->reveal());
231
232
        $this->assertTrue($admin->hasAccess('custom_action'));
233
    }
234
235
    public function testHasAccessAllowsAccessEditAction(): void
236
    {
237
        $admin = new PostAdmin(
238
            'sonata.post.admin.post',
239
            'Application\Sonata\NewsBundle\Entity\Post',
240
            'Sonata\NewsBundle\Controller\PostAdminController'
241
        );
242
        $securityHandler = $this->prophesize(SecurityHandlerInterface::class);
243
        $securityHandler->isGranted($admin, 'EDIT_ROLE', $admin)->willReturn(true);
244
        $customExtension = $this->prophesize(AbstractAdminExtension::class);
245
        $customExtension->getAccessMapping($admin)->willReturn(
246
            ['edit_action' => ['EDIT_ROLE']]
247
        );
248
        $admin->addExtension($customExtension->reveal());
249
        $admin->setSecurityHandler($securityHandler->reveal());
250
251
        $this->assertTrue($admin->hasAccess('edit_action'));
252
    }
253
254
    /**
255
     * @covers \Sonata\AdminBundle\Admin\AbstractAdmin::hasChild
256
     * @covers \Sonata\AdminBundle\Admin\AbstractAdmin::addChild
257
     * @covers \Sonata\AdminBundle\Admin\AbstractAdmin::getChild
258
     * @covers \Sonata\AdminBundle\Admin\AbstractAdmin::isChild
259
     * @covers \Sonata\AdminBundle\Admin\AbstractAdmin::hasChildren
260
     * @covers \Sonata\AdminBundle\Admin\AbstractAdmin::getChildren
261
     */
262
    public function testChildren(): void
263
    {
264
        $postAdmin = new PostAdmin('sonata.post.admin.post', 'Application\Sonata\NewsBundle\Entity\Post', 'Sonata\NewsBundle\Controller\PostAdminController');
265
        $this->assertFalse($postAdmin->hasChildren());
266
        $this->assertFalse($postAdmin->hasChild('comment'));
267
268
        $commentAdmin = new CommentAdmin('sonata.post.admin.comment', 'Application\Sonata\NewsBundle\Entity\Comment', 'Sonata\NewsBundle\Controller\CommentAdminController');
269
        $postAdmin->addChild($commentAdmin, 'post');
270
271
        $this->assertTrue($postAdmin->hasChildren());
272
        $this->assertTrue($postAdmin->hasChild('sonata.post.admin.comment'));
273
274
        $this->assertSame('sonata.post.admin.comment', $postAdmin->getChild('sonata.post.admin.comment')->getCode());
275
        $this->assertSame('sonata.post.admin.post|sonata.post.admin.comment', $postAdmin->getChild('sonata.post.admin.comment')->getBaseCodeRoute());
276
        $this->assertSame($postAdmin, $postAdmin->getChild('sonata.post.admin.comment')->getParent());
277
        $this->assertSame('post', $commentAdmin->getParentAssociationMapping());
278
279
        $this->assertFalse($postAdmin->isChild());
280
        $this->assertTrue($commentAdmin->isChild());
281
282
        $this->assertSame(['sonata.post.admin.comment' => $commentAdmin], $postAdmin->getChildren());
283
    }
284
285
    /**
286
     * @covers \Sonata\AdminBundle\Admin\AbstractAdmin::configure
287
     */
288
    public function testConfigure(): void
289
    {
290
        $admin = new PostAdmin('sonata.post.admin.post', 'Application\Sonata\NewsBundle\Entity\Post', 'Sonata\NewsBundle\Controller\PostAdminController');
291
        $this->assertNotNull($admin->getUniqid());
292
293
        $admin->initialize();
294
        $this->assertNotNull($admin->getUniqid());
295
        $this->assertSame('Post', $admin->getClassnameLabel());
296
297
        $admin = new CommentAdmin('sonata.post.admin.comment', 'Application\Sonata\NewsBundle\Entity\Comment', 'Sonata\NewsBundle\Controller\CommentAdminController');
298
        $admin->setClassnameLabel('postcomment');
299
300
        $admin->initialize();
301
        $this->assertSame('postcomment', $admin->getClassnameLabel());
302
    }
303
304
    public function testConfigureWithValidParentAssociationMapping(): void
305
    {
306
        $admin = new PostAdmin('sonata.post.admin.post', 'Application\Sonata\NewsBundle\Entity\Post', 'Sonata\NewsBundle\Controller\PostAdminController');
307
        $admin->setParentAssociationMapping('Category');
308
309
        $admin->initialize();
310
        $this->assertSame('Category', $admin->getParentAssociationMapping());
311
    }
312
313
    public function provideGetBaseRoutePattern()
314
    {
315
        return [
316
            [
317
                'Application\Sonata\NewsBundle\Entity\Post',
318
                '/sonata/news/post',
319
            ],
320
            [
321
                'Application\Sonata\NewsBundle\Document\Post',
322
                '/sonata/news/post',
323
            ],
324
            [
325
                'MyApplication\MyBundle\Entity\Post',
326
                '/myapplication/my/post',
327
            ],
328
            [
329
                'MyApplication\MyBundle\Entity\Post\Category',
330
                '/myapplication/my/post-category',
331
            ],
332
            [
333
                'MyApplication\MyBundle\Entity\Product\Category',
334
                '/myapplication/my/product-category',
335
            ],
336
            [
337
                'MyApplication\MyBundle\Entity\Other\Product\Category',
338
                '/myapplication/my/other-product-category',
339
            ],
340
            [
341
                'Symfony\Cmf\Bundle\FooBundle\Document\Menu',
342
                '/cmf/foo/menu',
343
            ],
344
            [
345
                'Symfony\Cmf\Bundle\FooBundle\Doctrine\Phpcr\Menu',
346
                '/cmf/foo/menu',
347
            ],
348
            [
349
                'Symfony\Bundle\BarBarBundle\Doctrine\Phpcr\Menu',
350
                '/symfony/barbar/menu',
351
            ],
352
            [
353
                'Symfony\Bundle\BarBarBundle\Doctrine\Phpcr\Menu\Item',
354
                '/symfony/barbar/menu-item',
355
            ],
356
            [
357
                'Symfony\Cmf\Bundle\FooBundle\Doctrine\Orm\Menu',
358
                '/cmf/foo/menu',
359
            ],
360
            [
361
                'Symfony\Cmf\Bundle\FooBundle\Doctrine\MongoDB\Menu',
362
                '/cmf/foo/menu',
363
            ],
364
            [
365
                'Symfony\Cmf\Bundle\FooBundle\Doctrine\CouchDB\Menu',
366
                '/cmf/foo/menu',
367
            ],
368
            [
369
                'AppBundle\Entity\User',
370
                '/app/user',
371
            ],
372
            [
373
                'App\Entity\User',
374
                '/app/user',
375
            ],
376
        ];
377
    }
378
379
    /**
380
     * @dataProvider provideGetBaseRoutePattern
381
     */
382
    public function testGetBaseRoutePattern(string $objFqn, string $expected): void
383
    {
384
        $admin = new PostAdmin('sonata.post.admin.post', $objFqn, 'Sonata\NewsBundle\Controller\PostAdminController');
385
        $this->assertSame($expected, $admin->getBaseRoutePattern());
386
    }
387
388
    /**
389
     * @dataProvider provideGetBaseRoutePattern
390
     */
391
    public function testGetBaseRoutePatternWithChildAdmin(string $objFqn, string $expected): void
392
    {
393
        $postAdmin = new PostAdmin('sonata.post.admin.post', $objFqn, 'Sonata\NewsBundle\Controller\PostAdminController');
394
        $commentAdmin = new CommentAdmin('sonata.post.admin.comment', 'Application\Sonata\NewsBundle\Entity\Comment', 'Sonata\NewsBundle\Controller\CommentAdminController');
395
        $commentAdmin->setParent($postAdmin);
396
397
        $this->assertSame($expected.'/{id}/comment', $commentAdmin->getBaseRoutePattern());
398
    }
399
400
    /**
401
     * @dataProvider provideGetBaseRoutePattern
402
     */
403
    public function testGetBaseRoutePatternWithTwoNestedChildAdmin(string $objFqn, string $expected): void
404
    {
405
        $postAdmin = new PostAdmin('sonata.post.admin.post', $objFqn, 'Sonata\NewsBundle\Controller\PostAdminController');
406
        $commentAdmin = new CommentAdmin(
407
            'sonata.post.admin.comment',
408
            'Application\Sonata\NewsBundle\Entity\Comment',
409
            'Sonata\NewsBundle\Controller\CommentAdminController'
410
        );
411
        $commentVoteAdmin = new CommentVoteAdmin(
412
            'sonata.post.admin.comment_vote',
413
            'Application\Sonata\NewsBundle\Entity\CommentVote',
414
            'Sonata\NewsBundle\Controller\CommentVoteAdminController'
415
        );
416
        $commentAdmin->setParent($postAdmin);
417
        $commentVoteAdmin->setParent($commentAdmin);
418
419
        $this->assertSame($expected.'/{id}/comment/{childId}/commentvote', $commentVoteAdmin->getBaseRoutePattern());
420
    }
421
422
    public function testGetBaseRoutePatternWithSpecifedPattern(): void
423
    {
424
        $postAdmin = new PostWithCustomRouteAdmin('sonata.post.admin.post_with_custom_route', 'Application\Sonata\NewsBundle\Entity\Post', 'Sonata\NewsBundle\Controller\PostWithCustomRouteAdminController');
425
426
        $this->assertSame('/post-custom', $postAdmin->getBaseRoutePattern());
427
    }
428
429
    public function testGetBaseRoutePatternWithChildAdminAndWithSpecifedPattern(): void
430
    {
431
        $postAdmin = new PostAdmin('sonata.post.admin.post', 'Application\Sonata\NewsBundle\Entity\Post', 'Sonata\NewsBundle\Controller\PostAdminController');
432
        $commentAdmin = new CommentWithCustomRouteAdmin('sonata.post.admin.comment_with_custom_route', 'Application\Sonata\NewsBundle\Entity\Comment', 'Sonata\NewsBundle\Controller\CommentWithCustomRouteAdminController');
433
        $commentAdmin->setParent($postAdmin);
434
435
        $this->assertSame('/sonata/news/post/{id}/comment-custom', $commentAdmin->getBaseRoutePattern());
436
    }
437
438
    public function testGetBaseRoutePatternWithUnreconizedClassname(): void
439
    {
440
        $this->expectException(\RuntimeException::class);
441
442
        $admin = new PostAdmin('sonata.post.admin.post', 'News\Thing\Post', 'Sonata\NewsBundle\Controller\PostAdminController');
443
        $admin->getBaseRoutePattern();
444
    }
445
446
    public function provideGetBaseRouteName()
447
    {
448
        return [
449
            [
450
                'Application\Sonata\NewsBundle\Entity\Post',
451
                'admin_sonata_news_post',
452
            ],
453
            [
454
                'Application\Sonata\NewsBundle\Document\Post',
455
                'admin_sonata_news_post',
456
            ],
457
            [
458
                'MyApplication\MyBundle\Entity\Post',
459
                'admin_myapplication_my_post',
460
            ],
461
            [
462
                'MyApplication\MyBundle\Entity\Post\Category',
463
                'admin_myapplication_my_post_category',
464
            ],
465
            [
466
                'MyApplication\MyBundle\Entity\Product\Category',
467
                'admin_myapplication_my_product_category',
468
            ],
469
            [
470
                'MyApplication\MyBundle\Entity\Other\Product\Category',
471
                'admin_myapplication_my_other_product_category',
472
            ],
473
            [
474
                'Symfony\Cmf\Bundle\FooBundle\Document\Menu',
475
                'admin_cmf_foo_menu',
476
            ],
477
            [
478
                'Symfony\Cmf\Bundle\FooBundle\Doctrine\Phpcr\Menu',
479
                'admin_cmf_foo_menu',
480
            ],
481
            [
482
                'Symfony\Bundle\BarBarBundle\Doctrine\Phpcr\Menu',
483
                'admin_symfony_barbar_menu',
484
            ],
485
            [
486
                'Symfony\Bundle\BarBarBundle\Doctrine\Phpcr\Menu\Item',
487
                'admin_symfony_barbar_menu_item',
488
            ],
489
            [
490
                'Symfony\Cmf\Bundle\FooBundle\Doctrine\Orm\Menu',
491
                'admin_cmf_foo_menu',
492
            ],
493
            [
494
                'Symfony\Cmf\Bundle\FooBundle\Doctrine\MongoDB\Menu',
495
                'admin_cmf_foo_menu',
496
            ],
497
            [
498
                'Symfony\Cmf\Bundle\FooBundle\Doctrine\CouchDB\Menu',
499
                'admin_cmf_foo_menu',
500
            ],
501
            [
502
                'AppBundle\Entity\User',
503
                'admin_app_user',
504
            ],
505
            [
506
                'App\Entity\User',
507
                'admin_app_user',
508
            ],
509
        ];
510
    }
511
512
    /**
513
     * @dataProvider provideGetBaseRouteName
514
     */
515
    public function testGetBaseRouteName(string $objFqn, string $expected): void
516
    {
517
        $admin = new PostAdmin('sonata.post.admin.post', $objFqn, 'Sonata\NewsBundle\Controller\PostAdminController');
518
519
        $this->assertSame($expected, $admin->getBaseRouteName());
520
    }
521
522
    /**
523
     * @group legacy
524
     * @expectedDeprecation Calling "addChild" without second argument is deprecated since sonata-project/admin-bundle 3.35 and will not be allowed in 4.0.
525
     * @dataProvider provideGetBaseRouteName
526
     */
527
    public function testGetBaseRouteNameWithChildAdmin(string $objFqn, string $expected): void
528
    {
529
        $routeGenerator = new DefaultRouteGenerator(
530
            $this->createMock(RouterInterface::class),
531
            new RoutesCache($this->cacheTempFolder, true)
532
        );
533
534
        $container = new Container();
535
        $pool = new Pool($container, 'Sonata Admin', '/path/to/pic.png');
536
537
        $pathInfo = new PathInfoBuilder($this->createMock(AuditManagerInterface::class));
538
        $postAdmin = new PostAdmin('sonata.post.admin.post', $objFqn, 'Sonata\NewsBundle\Controller\PostAdminController');
539
        $container->set('sonata.post.admin.post', $postAdmin);
540
        $postAdmin->setConfigurationPool($pool);
541
        $postAdmin->setRouteBuilder($pathInfo);
542
        $postAdmin->setRouteGenerator($routeGenerator);
543
        $postAdmin->initialize();
544
545
        $commentAdmin = new CommentAdmin(
546
            'sonata.post.admin.comment',
547
            'Application\Sonata\NewsBundle\Entity\Comment',
548
            'Sonata\NewsBundle\Controller\CommentAdminController'
549
        );
550
        $container->set('sonata.post.admin.comment', $commentAdmin);
551
        $commentAdmin->setConfigurationPool($pool);
552
        $commentAdmin->setRouteBuilder($pathInfo);
553
        $commentAdmin->setRouteGenerator($routeGenerator);
554
        $commentAdmin->initialize();
555
556
        $postAdmin->addChild($commentAdmin, 'post');
557
558
        $commentVoteAdmin = new CommentVoteAdmin(
559
            'sonata.post.admin.comment_vote',
560
            'Application\Sonata\NewsBundle\Entity\CommentVote',
561
            'Sonata\NewsBundle\Controller\CommentVoteAdminController'
562
        );
563
564
        $container->set('sonata.post.admin.comment_vote', $commentVoteAdmin);
565
        $commentVoteAdmin->setConfigurationPool($pool);
566
        $commentVoteAdmin->setRouteBuilder($pathInfo);
567
        $commentVoteAdmin->setRouteGenerator($routeGenerator);
568
        $commentVoteAdmin->initialize();
569
570
        $commentAdmin->addChild($commentVoteAdmin);
571
        $pool->setAdminServiceIds([
572
            'sonata.post.admin.post',
573
            'sonata.post.admin.comment',
574
            'sonata.post.admin.comment_vote',
575
        ]);
576
577
        $this->assertSame($expected.'_comment', $commentAdmin->getBaseRouteName());
578
579
        $this->assertTrue($postAdmin->hasRoute('show'));
580
        $this->assertTrue($postAdmin->hasRoute('sonata.post.admin.post.show'));
581
        $this->assertTrue($postAdmin->hasRoute('sonata.post.admin.post|sonata.post.admin.comment.show'));
582
        $this->assertTrue($postAdmin->hasRoute('sonata.post.admin.post|sonata.post.admin.comment|sonata.post.admin.comment_vote.show'));
583
        $this->assertTrue($postAdmin->hasRoute('sonata.post.admin.comment.list'));
584
        $this->assertTrue($postAdmin->hasRoute('sonata.post.admin.comment|sonata.post.admin.comment_vote.list'));
585
        $this->assertFalse($postAdmin->hasRoute('sonata.post.admin.post|sonata.post.admin.comment.edit'));
586
        $this->assertFalse($commentAdmin->hasRoute('edit'));
587
        $this->assertSame('post', $commentAdmin->getParentAssociationMapping());
588
589
        /*
590
         * Test the route name from request
591
         */
592
        $postListRequest = new Request(
593
            [],
594
            [],
595
            [
596
                '_route' => $postAdmin->getBaseRouteName().'_list',
597
            ]
598
        );
599
600
        $postAdmin->setRequest($postListRequest);
601
        $commentAdmin->setRequest($postListRequest);
602
603
        $this->assertTrue($postAdmin->isCurrentRoute('list'));
604
        $this->assertFalse($postAdmin->isCurrentRoute('create'));
605
        $this->assertFalse($commentAdmin->isCurrentRoute('list'));
606
        $this->assertFalse($commentVoteAdmin->isCurrentRoute('list'));
607
        $this->assertTrue($commentAdmin->isCurrentRoute('list', 'sonata.post.admin.post'));
608
        $this->assertFalse($commentAdmin->isCurrentRoute('edit', 'sonata.post.admin.post'));
609
        $this->assertTrue($commentVoteAdmin->isCurrentRoute('list', 'sonata.post.admin.post'));
610
        $this->assertFalse($commentVoteAdmin->isCurrentRoute('edit', 'sonata.post.admin.post'));
611
    }
612
613
    public function testGetBaseRouteNameWithUnreconizedClassname(): void
614
    {
615
        $this->expectException(\RuntimeException::class);
616
617
        $admin = new PostAdmin('sonata.post.admin.post', 'News\Thing\Post', 'Sonata\NewsBundle\Controller\PostAdminController');
618
        $admin->getBaseRouteName();
619
    }
620
621
    public function testGetBaseRouteNameWithSpecifiedName(): void
622
    {
623
        $postAdmin = new PostWithCustomRouteAdmin('sonata.post.admin.post_with_custom_route', 'Application\Sonata\NewsBundle\Entity\Post', 'Sonata\NewsBundle\Controller\PostAdminController');
624
625
        $this->assertSame('post_custom', $postAdmin->getBaseRouteName());
626
    }
627
628
    public function testGetBaseRouteNameWithChildAdminAndWithSpecifiedName(): void
629
    {
630
        $postAdmin = new PostAdmin('sonata.post.admin.post', 'Application\Sonata\NewsBundle\Entity\Post', 'Sonata\NewsBundle\Controller\PostAdminController');
631
        $commentAdmin = new CommentWithCustomRouteAdmin('sonata.post.admin.comment_with_custom_route', 'Application\Sonata\NewsBundle\Entity\Comment', 'Sonata\NewsBundle\Controller\CommentWithCustomRouteAdminController');
632
        $commentAdmin->setParent($postAdmin);
633
634
        $this->assertSame('admin_sonata_news_post_comment_custom', $commentAdmin->getBaseRouteName());
635
    }
636
637
    public function testGetBaseRouteNameWithTwoNestedChildAdminAndWithSpecifiedName(): void
638
    {
639
        $postAdmin = new PostAdmin(
640
            'sonata.post.admin.post',
641
            'Application\Sonata\NewsBundle\Entity\Post',
642
            'Sonata\NewsBundle\Controller\PostAdminController'
643
        );
644
        $commentAdmin = new CommentWithCustomRouteAdmin(
645
            'sonata.post.admin.comment_with_custom_route',
646
            'Application\Sonata\NewsBundle\Entity\Comment',
647
            'Sonata\NewsBundle\Controller\CommentWithCustomRouteAdminController'
648
        );
649
        $commentVoteAdmin = new CommentVoteAdmin(
650
            'sonata.post.admin.comment_vote',
651
            'Application\Sonata\NewsBundle\Entity\CommentVote',
652
            'Sonata\NewsBundle\Controller\CommentVoteAdminController'
653
        );
654
        $commentAdmin->setParent($postAdmin);
655
        $commentVoteAdmin->setParent($commentAdmin);
656
657
        $this->assertSame('admin_sonata_news_post_comment_custom_commentvote', $commentVoteAdmin->getBaseRouteName());
658
    }
659
660
    /**
661
     * @covers \Sonata\AdminBundle\Admin\AbstractAdmin::setUniqid
662
     * @covers \Sonata\AdminBundle\Admin\AbstractAdmin::getUniqid
663
     */
664
    public function testSetUniqid(): void
665
    {
666
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'Sonata\NewsBundle\Controller\PostAdminController');
667
668
        $uniqid = uniqid();
669
        $admin->setUniqid($uniqid);
670
671
        $this->assertSame($uniqid, $admin->getUniqid());
672
    }
673
674
    public function testToString(): void
675
    {
676
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'Sonata\NewsBundle\Controller\PostAdminController');
677
678
        $s = new \stdClass();
679
680
        $this->assertNotEmpty($admin->toString($s));
681
682
        $s = new FooToString();
683
        $this->assertSame('salut', $admin->toString($s));
684
685
        // To string method is implemented, but returns null
686
        $s = new FooToStringNull();
687
        $this->assertNotEmpty($admin->toString($s));
688
689
        $this->assertSame('', $admin->toString(false));
690
    }
691
692
    public function testIsAclEnabled(): void
693
    {
694
        $postAdmin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'Sonata\NewsBundle\Controller\PostAdminController');
695
696
        $this->assertFalse($postAdmin->isAclEnabled());
697
698
        $commentAdmin = new CommentAdmin('sonata.post.admin.comment', 'Application\Sonata\NewsBundle\Entity\Comment', 'Sonata\NewsBundle\Controller\CommentAdminController');
699
        $commentAdmin->setSecurityHandler($this->createMock(AclSecurityHandlerInterface::class));
700
        $this->assertTrue($commentAdmin->isAclEnabled());
701
    }
702
703
    /**
704
     * @group legacy
705
     *
706
     * @expectedDeprecation Calling Sonata\AdminBundle\Admin\AbstractAdmin::getActiveSubclassCode() when there is no active subclass is deprecated since sonata-project/admin-bundle 3.52 and will throw an exception in 4.0. Use Sonata\AdminBundle\Admin\AbstractAdmin::hasActiveSubClass() to know if there is an active subclass.
707
     *
708
     * @covers \Sonata\AdminBundle\Admin\AbstractAdmin::getSubClasses
709
     * @covers \Sonata\AdminBundle\Admin\AbstractAdmin::getSubClass
710
     * @covers \Sonata\AdminBundle\Admin\AbstractAdmin::setSubClasses
711
     * @covers \Sonata\AdminBundle\Admin\AbstractAdmin::hasSubClass
712
     * @covers \Sonata\AdminBundle\Admin\AbstractAdmin::hasActiveSubClass
713
     * @covers \Sonata\AdminBundle\Admin\AbstractAdmin::getActiveSubClass
714
     * @covers \Sonata\AdminBundle\Admin\AbstractAdmin::getActiveSubclassCode
715
     * @covers \Sonata\AdminBundle\Admin\AbstractAdmin::getClass
716
     */
717
    public function testSubClass(): void
718
    {
719
        // NEXT_MAJOR: Remove the "@group" and "@expectedDeprecation" annotations
720
        $admin = new PostAdmin(
721
            'sonata.post.admin.post',
722
            Post::class,
723
            'Sonata\NewsBundle\Controller\PostAdminController'
724
        );
725
        $this->assertFalse($admin->hasSubClass('test'));
726
        $this->assertFalse($admin->hasActiveSubClass());
727
        $this->assertCount(0, $admin->getSubClasses());
728
        $this->assertNull($admin->getActiveSubClass());
729
        $this->assertNull($admin->getActiveSubclassCode());
730
        $this->assertSame(Post::class, $admin->getClass());
731
732
        // Just for the record, if there is no inheritance set, the getSubject is not used
733
        // the getSubject can also lead to some issue
734
        $admin->setSubject(new BlogPost());
735
        $this->assertSame(BlogPost::class, $admin->getClass());
736
737
        $admin->setSubClasses([
738
            'extended1' => 'NewsBundle\Entity\PostExtended1',
739
            'extended2' => 'NewsBundle\Entity\PostExtended2',
740
        ]);
741
        $this->assertFalse($admin->hasSubClass('test'));
742
        $this->assertTrue($admin->hasSubClass('extended1'));
743
        $this->assertFalse($admin->hasActiveSubClass());
744
        $this->assertCount(2, $admin->getSubClasses());
745
        // NEXT_MAJOR: remove the following 2 `assertNull()` assertions
746
        $this->assertNull($admin->getActiveSubClass());
747
        $this->assertNull($admin->getActiveSubclassCode());
748
        $this->assertSame(
749
            BlogPost::class,
750
            $admin->getClass(),
751
            'When there is no subclass in the query the class parameter should be returned'
752
        );
753
754
        $request = new Request(['subclass' => 'extended1']);
755
        $admin->setRequest($request);
756
        $this->assertFalse($admin->hasSubClass('test'));
757
        $this->assertTrue($admin->hasSubClass('extended1'));
758
        $this->assertTrue($admin->hasActiveSubClass());
759
        $this->assertCount(2, $admin->getSubClasses());
760
        $this->assertSame(
761
            'NewsBundle\Entity\PostExtended1',
762
            $admin->getActiveSubClass(),
763
            'It should return the curently active sub class.'
764
        );
765
        $this->assertSame('extended1', $admin->getActiveSubclassCode());
766
        $this->assertSame(
767
            'NewsBundle\Entity\PostExtended1',
768
            $admin->getClass(),
769
            'getClass() should return the name of the sub class when passed through a request query parameter.'
770
        );
771
772
        $request->query->set('subclass', 'inject');
773
774
        $this->assertNull($admin->getActiveSubclassCode());
775
        // NEXT_MAJOR: remove the previous `assertNull()` assertion and uncomment the following lines
776
        // $this->expectException(\LogicException::class);
777
        // $this->expectExceptionMessage(sprintf('Admin "%s" has no active subclass.', PostAdmin::class));
778
    }
779
780
    /**
781
     * @group legacy
782
     *
783
     * @expectedDeprecation Calling Sonata\AdminBundle\Admin\AbstractAdmin::getActiveSubclassCode() when there is no active subclass is deprecated since sonata-project/admin-bundle 3.52 and will throw an exception in 4.0. Use Sonata\AdminBundle\Admin\AbstractAdmin::hasActiveSubClass() to know if there is an active subclass.
784
     */
785
    public function testNonExistantSubclass(): void
786
    {
787
        // NEXT_MAJOR: Remove the "@group" and "@expectedDeprecation" annotations
788
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'Sonata\NewsBundle\Controller\PostAdminController');
789
        $admin->setModelManager($this->getMockForAbstractClass(ModelManagerInterface::class));
790
791
        $admin->setRequest(new Request(['subclass' => 'inject']));
792
793
        $admin->setSubClasses(['extended1' => 'NewsBundle\Entity\PostExtended1', 'extended2' => 'NewsBundle\Entity\PostExtended2']);
794
795
        $this->assertTrue($admin->hasActiveSubClass());
796
797
        $this->expectException(\RuntimeException::class);
798
799
        $admin->getActiveSubClass();
800
    }
801
802
    /**
803
     * @covers \Sonata\AdminBundle\Admin\AbstractAdmin::hasActiveSubClass
804
     */
805
    public function testOnlyOneSubclassNeededToBeActive(): void
806
    {
807
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'Sonata\NewsBundle\Controller\PostAdminController');
808
        $admin->setSubClasses(['extended1' => 'NewsBundle\Entity\PostExtended1']);
809
        $request = new Request(['subclass' => 'extended1']);
810
        $admin->setRequest($request);
811
        $this->assertTrue($admin->hasActiveSubClass());
812
    }
813
814
    /**
815
     * @group legacy
816
     * @expectedDeprecation Method "Sonata\AdminBundle\Admin\AbstractAdmin::addSubClass" is deprecated since sonata-project/admin-bundle 3.30 and will be removed in 4.0.
817
     */
818
    public function testAddSubClassIsDeprecated(): void
819
    {
820
        $admin = new PostAdmin(
821
            'sonata.post.admin.post',
822
            Post::class,
823
            'Sonata\NewsBundle\Controller\PostAdminController'
824
        );
825
        $admin->addSubClass('whatever');
826
    }
827
828
    /**
829
     * @group legacy
830
     */
831
    public function testGetPerPageOptions(): void
832
    {
833
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'Sonata\NewsBundle\Controller\PostAdminController');
834
835
        $perPageOptions = $admin->getPerPageOptions();
836
837
        foreach ($perPageOptions as $perPage) {
838
            $this->assertSame(0, $perPage % 4);
839
        }
840
841
        $admin->setPerPageOptions([500, 1000]);
842
        $this->assertSame([500, 1000], $admin->getPerPageOptions());
843
    }
844
845
    public function testGetLabelTranslatorStrategy(): void
846
    {
847
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'Sonata\NewsBundle\Controller\PostAdminController');
848
849
        $this->assertNull($admin->getLabelTranslatorStrategy());
850
851
        $labelTranslatorStrategy = $this->createMock(LabelTranslatorStrategyInterface::class);
852
        $admin->setLabelTranslatorStrategy($labelTranslatorStrategy);
853
        $this->assertSame($labelTranslatorStrategy, $admin->getLabelTranslatorStrategy());
854
    }
855
856
    public function testGetRouteBuilder(): void
857
    {
858
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'Sonata\NewsBundle\Controller\PostAdminController');
859
860
        $this->assertNull($admin->getRouteBuilder());
861
862
        $routeBuilder = $this->createMock(RouteBuilderInterface::class);
863
        $admin->setRouteBuilder($routeBuilder);
864
        $this->assertSame($routeBuilder, $admin->getRouteBuilder());
865
    }
866
867
    public function testGetMenuFactory(): void
868
    {
869
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'Sonata\NewsBundle\Controller\PostAdminController');
870
871
        $this->assertNull($admin->getMenuFactory());
872
873
        $menuFactory = $this->createMock(FactoryInterface::class);
874
        $admin->setMenuFactory($menuFactory);
875
        $this->assertSame($menuFactory, $admin->getMenuFactory());
876
    }
877
878
    public function testGetExtensions(): void
879
    {
880
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'Sonata\NewsBundle\Controller\PostAdminController');
881
882
        $this->assertSame([], $admin->getExtensions());
883
884
        $adminExtension1 = $this->createMock(AdminExtensionInterface::class);
885
        $adminExtension2 = $this->createMock(AdminExtensionInterface::class);
886
887
        $admin->addExtension($adminExtension1);
888
        $admin->addExtension($adminExtension2);
889
        $this->assertSame([$adminExtension1, $adminExtension2], $admin->getExtensions());
890
    }
891
892
    public function testGetFilterTheme(): void
893
    {
894
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'Sonata\NewsBundle\Controller\PostAdminController');
895
896
        $this->assertSame([], $admin->getFilterTheme());
897
898
        $admin->setFilterTheme(['FooTheme']);
899
        $this->assertSame(['FooTheme'], $admin->getFilterTheme());
900
    }
901
902
    public function testGetFormTheme(): void
903
    {
904
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'Sonata\NewsBundle\Controller\PostAdminController');
905
906
        $this->assertSame([], $admin->getFormTheme());
907
908
        $admin->setFormTheme(['FooTheme']);
909
910
        $this->assertSame(['FooTheme'], $admin->getFormTheme());
911
    }
912
913
    public function testGetValidator(): void
914
    {
915
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'Sonata\NewsBundle\Controller\PostAdminController');
916
917
        $this->assertNull($admin->getValidator());
918
919
        $validator = $this->getMockForAbstractClass(ValidatorInterface::class);
920
921
        $admin->setValidator($validator);
922
        $this->assertSame($validator, $admin->getValidator());
923
    }
924
925
    public function testGetSecurityHandler(): void
926
    {
927
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'Sonata\NewsBundle\Controller\PostAdminController');
928
929
        $this->assertNull($admin->getSecurityHandler());
930
931
        $securityHandler = $this->createMock(SecurityHandlerInterface::class);
932
        $admin->setSecurityHandler($securityHandler);
933
        $this->assertSame($securityHandler, $admin->getSecurityHandler());
934
    }
935
936
    public function testGetSecurityInformation(): void
937
    {
938
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'Sonata\NewsBundle\Controller\PostAdminController');
939
940
        $this->assertSame([], $admin->getSecurityInformation());
941
942
        $securityInformation = [
943
            'GUEST' => ['VIEW', 'LIST'],
944
            'STAFF' => ['EDIT', 'LIST', 'CREATE'],
945
        ];
946
947
        $admin->setSecurityInformation($securityInformation);
948
        $this->assertSame($securityInformation, $admin->getSecurityInformation());
949
    }
950
951
    public function testGetManagerType(): void
952
    {
953
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'Sonata\NewsBundle\Controller\PostAdminController');
954
955
        $this->assertNull($admin->getManagerType());
956
957
        $admin->setManagerType('foo_orm');
958
        $this->assertSame('foo_orm', $admin->getManagerType());
959
    }
960
961
    public function testGetModelManager(): void
962
    {
963
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'Sonata\NewsBundle\Controller\PostAdminController');
964
965
        $this->assertNull($admin->getModelManager());
966
967
        $modelManager = $this->createMock(ModelManagerInterface::class);
968
969
        $admin->setModelManager($modelManager);
970
        $this->assertSame($modelManager, $admin->getModelManager());
971
    }
972
973
    /**
974
     * NEXT_MAJOR: remove this method.
975
     *
976
     * @group legacy
977
     */
978
    public function testGetBaseCodeRoute(): void
979
    {
980
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'Sonata\NewsBundle\Controller\PostAdminController');
981
982
        $this->assertSame('', $admin->getBaseCodeRoute());
983
984
        $admin->setBaseCodeRoute('foo');
985
        $this->assertSame('foo', $admin->getBaseCodeRoute());
986
    }
987
988
    // NEXT_MAJOR: uncomment this method.
989
    // public function testGetBaseCodeRoute()
990
    // {
991
    //     $postAdmin = new PostAdmin(
992
    //         'sonata.post.admin.post',
993
    //         'NewsBundle\Entity\Post',
994
    //         'Sonata\NewsBundle\Controller\PostAdminController'
995
    //     );
996
    //     $commentAdmin = new CommentAdmin(
997
    //         'sonata.post.admin.comment',
998
    //         'Application\Sonata\NewsBundle\Entity\Comment',
999
    //         'Sonata\NewsBundle\Controller\CommentAdminController'
1000
    //     );
1001
    //
1002
    //     $this->assertSame($postAdmin->getCode(), $postAdmin->getBaseCodeRoute());
1003
    //
1004
    //     $postAdmin->addChild($commentAdmin);
1005
    //
1006
    //     $this->assertSame(
1007
    //         'sonata.post.admin.post|sonata.post.admin.comment',
1008
    //         $commentAdmin->getBaseCodeRoute()
1009
    //     );
1010
    // }
1011
1012
    public function testGetRouteGenerator(): void
1013
    {
1014
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'Sonata\NewsBundle\Controller\PostAdminController');
1015
1016
        $this->assertNull($admin->getRouteGenerator());
1017
1018
        $routeGenerator = $this->createMock(RouteGeneratorInterface::class);
1019
1020
        $admin->setRouteGenerator($routeGenerator);
1021
        $this->assertSame($routeGenerator, $admin->getRouteGenerator());
1022
    }
1023
1024
    public function testGetConfigurationPool(): void
1025
    {
1026
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'Sonata\NewsBundle\Controller\PostAdminController');
1027
1028
        $this->assertNull($admin->getConfigurationPool());
1029
1030
        $pool = $this->getMockBuilder(Pool::class)
1031
            ->disableOriginalConstructor()
1032
            ->getMock();
1033
1034
        $admin->setConfigurationPool($pool);
1035
        $this->assertSame($pool, $admin->getConfigurationPool());
1036
    }
1037
1038
    public function testGetShowBuilder(): void
1039
    {
1040
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'Sonata\NewsBundle\Controller\PostAdminController');
1041
1042
        $this->assertNull($admin->getShowBuilder());
1043
1044
        $showBuilder = $this->createMock(ShowBuilderInterface::class);
1045
1046
        $admin->setShowBuilder($showBuilder);
1047
        $this->assertSame($showBuilder, $admin->getShowBuilder());
1048
    }
1049
1050
    public function testGetListBuilder(): void
1051
    {
1052
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'Sonata\NewsBundle\Controller\PostAdminController');
1053
1054
        $this->assertNull($admin->getListBuilder());
1055
1056
        $listBuilder = $this->createMock(ListBuilderInterface::class);
1057
1058
        $admin->setListBuilder($listBuilder);
1059
        $this->assertSame($listBuilder, $admin->getListBuilder());
1060
    }
1061
1062
    public function testGetDatagridBuilder(): void
1063
    {
1064
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'Sonata\NewsBundle\Controller\PostAdminController');
1065
1066
        $this->assertNull($admin->getDatagridBuilder());
1067
1068
        $datagridBuilder = $this->createMock(DatagridBuilderInterface::class);
1069
1070
        $admin->setDatagridBuilder($datagridBuilder);
1071
        $this->assertSame($datagridBuilder, $admin->getDatagridBuilder());
1072
    }
1073
1074
    public function testGetFormContractor(): void
1075
    {
1076
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'Sonata\NewsBundle\Controller\PostAdminController');
1077
1078
        $this->assertNull($admin->getFormContractor());
1079
1080
        $formContractor = $this->createMock(FormContractorInterface::class);
1081
1082
        $admin->setFormContractor($formContractor);
1083
        $this->assertSame($formContractor, $admin->getFormContractor());
1084
    }
1085
1086
    public function testGetRequest(): void
1087
    {
1088
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'Sonata\NewsBundle\Controller\PostAdminController');
1089
1090
        $this->assertFalse($admin->hasRequest());
1091
1092
        $request = new Request();
1093
1094
        $admin->setRequest($request);
1095
        $this->assertSame($request, $admin->getRequest());
1096
        $this->assertTrue($admin->hasRequest());
1097
    }
1098
1099
    public function testGetRequestWithException(): void
1100
    {
1101
        $this->expectException(\RuntimeException::class);
1102
        $this->expectExceptionMessage('The Request object has not been set');
1103
1104
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'Sonata\NewsBundle\Controller\PostAdminController');
1105
        $admin->getRequest();
1106
    }
1107
1108
    public function testGetTranslationDomain(): void
1109
    {
1110
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'Sonata\NewsBundle\Controller\PostAdminController');
1111
1112
        $this->assertSame('messages', $admin->getTranslationDomain());
1113
1114
        $admin->setTranslationDomain('foo');
1115
        $this->assertSame('foo', $admin->getTranslationDomain());
1116
    }
1117
1118
    /**
1119
     * @group legacy
1120
     */
1121
    public function testGetTranslator(): void
1122
    {
1123
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'Sonata\NewsBundle\Controller\PostAdminController');
1124
1125
        $this->assertNull($admin->getTranslator());
1126
1127
        $translator = $this->createMock(TranslatorInterface::class);
1128
1129
        $admin->setTranslator($translator);
1130
        $this->assertSame($translator, $admin->getTranslator());
1131
    }
1132
1133
    public function testGetShowGroups(): void
1134
    {
1135
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'Sonata\NewsBundle\Controller\PostAdminController');
1136
1137
        // NEXT_MAJOR: Remove the argument "sonata_deprecation_mute" in the following call.
1138
        $this->assertFalse($admin->getShowGroups('sonata_deprecation_mute'));
1139
1140
        $groups = ['foo', 'bar', 'baz'];
1141
1142
        $admin->setShowGroups($groups);
1143
        $this->assertSame($groups, $admin->getShowGroups());
1144
    }
1145
1146
    public function testGetFormGroups(): void
1147
    {
1148
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'Sonata\NewsBundle\Controller\PostAdminController');
1149
1150
        // NEXT_MAJOR: Remove the argument "sonata_deprecation_mute" in the following call.
1151
        $this->assertFalse($admin->getFormGroups('sonata_deprecation_mute'));
1152
1153
        $groups = ['foo', 'bar', 'baz'];
1154
1155
        $admin->setFormGroups($groups);
1156
        $this->assertSame($groups, $admin->getFormGroups());
1157
    }
1158
1159
    public function testGetMaxPageLinks(): void
1160
    {
1161
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'Sonata\NewsBundle\Controller\PostAdminController');
1162
1163
        $this->assertSame(25, $admin->getMaxPageLinks());
1164
1165
        $admin->setMaxPageLinks(14);
1166
        $this->assertSame(14, $admin->getMaxPageLinks());
1167
    }
1168
1169
    /**
1170
     * @group legacy
1171
     */
1172
    public function testGetMaxPerPage(): void
1173
    {
1174
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'Sonata\NewsBundle\Controller\PostAdminController');
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', 'Sonata\NewsBundle\Controller\PostAdminController');
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', 'Sonata\NewsBundle\Controller\PostAdminController');
1195
1196
        $this->assertSame('Sonata\NewsBundle\Controller\PostAdminController', $admin->getBaseControllerName());
1197
1198
        $admin->setBaseControllerName('Sonata\NewsBundle\Controller\FooAdminController');
1199
        $this->assertSame('Sonata\NewsBundle\Controller\FooAdminController', $admin->getBaseControllerName());
1200
    }
1201
1202
    public function testGetTemplates(): void
1203
    {
1204
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'Sonata\NewsBundle\Controller\PostAdminController');
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', 'Sonata\NewsBundle\Controller\PostAdminController');
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
            'Sonata\NewsBundle\Controller\PostAdminController'
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
            'Sonata\NewsBundle\Controller\CommentAdminController'
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
            'Sonata\NewsBundle\Controller\CommentVoteAdminController'
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', 'Sonata\NewsBundle\Controller\PostAdminController');
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', 'Sonata\NewsBundle\Controller\PostAdminController');
1276
1277
        $model = new \stdClass();
1278
1279
        $modelManager = $this->createMock(ModelManagerInterface::class);
1280
        $modelManager->expects($this->once())
1281
            ->method('getUrlSafeIdentifier')
1282
            ->with($this->equalTo($model))
1283
            ->willReturn('foo');
1284
        $admin->setModelManager($modelManager);
1285
1286
        $this->assertSame('foo', $admin->getUrlSafeIdentifier($model));
1287
    }
1288
1289
    public function testDeterminedPerPageValue(): void
1290
    {
1291
        $admin = new PostAdmin('sonata.post.admin.post', 'Acme\NewsBundle\Entity\Post', 'Sonata\NewsBundle\Controller\PostAdminController');
1292
1293
        $this->assertFalse($admin->determinedPerPageValue('foo'));
1294
        $this->assertFalse($admin->determinedPerPageValue(123));
1295
        $this->assertTrue($admin->determinedPerPageValue(16));
1296
    }
1297
1298
    public function testIsGranted(): void
1299
    {
1300
        $admin = new PostAdmin('sonata.post.admin.post', 'Acme\NewsBundle\Entity\Post', 'Sonata\NewsBundle\Controller\PostAdminController');
1301
        $modelManager = $this->createStub(ModelManagerInterface::class);
1302
        $modelManager
1303
            ->method('getNormalizedIdentifier')
1304
            ->willReturnCallback(static function (?object $model = null): ?string {
1305
                return $model ? $model->id : null;
1306
            });
1307
1308
        $admin->setModelManager($modelManager);
1309
1310
        $entity1 = new \stdClass();
1311
        $entity1->id = '1';
1312
1313
        $securityHandler = $this->createMock(AclSecurityHandlerInterface::class);
1314
        $securityHandler
1315
            ->expects($this->exactly(6))
1316
            ->method('isGranted')
1317
            ->willReturnCallback(static function (
1318
                AdminInterface $adminIn,
1319
                string $attributes,
1320
                ?object $object = null
1321
            ) use (
1322
                $admin,
1323
                $entity1
1324
            ): bool {
1325
                return $admin === $adminIn && 'FOO' === $attributes &&
1326
                    ($object === $admin || $object === $entity1);
1327
            });
1328
1329
        $admin->setSecurityHandler($securityHandler);
1330
1331
        $this->assertTrue($admin->isGranted('FOO'));
1332
        $this->assertTrue($admin->isGranted('FOO'));
1333
        $this->assertTrue($admin->isGranted('FOO', $entity1));
1334
        $this->assertTrue($admin->isGranted('FOO', $entity1));
1335
        $this->assertFalse($admin->isGranted('BAR'));
1336
        $this->assertFalse($admin->isGranted('BAR'));
1337
        $this->assertFalse($admin->isGranted('BAR', $entity1));
1338
        $this->assertFalse($admin->isGranted('BAR', $entity1));
1339
1340
        $entity2 = new \stdClass();
1341
        $entity2->id = '2';
1342
1343
        $this->assertFalse($admin->isGranted('BAR', $entity2));
1344
        $this->assertFalse($admin->isGranted('BAR', $entity2));
1345
1346
        $entity3 = new \stdClass();
1347
        $entity3->id = '3';
1348
1349
        $this->assertFalse($admin->isGranted('BAR', $entity3));
1350
        $this->assertFalse($admin->isGranted('BAR', $entity3));
1351
    }
1352
1353
    public function testSupportsPreviewMode(): void
1354
    {
1355
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'Sonata\NewsBundle\Controller\PostAdminController');
1356
1357
        $this->assertFalse($admin->supportsPreviewMode());
1358
    }
1359
1360
    public function testGetPermissionsShow(): void
1361
    {
1362
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'Sonata\NewsBundle\Controller\PostAdminController');
1363
1364
        $this->assertSame(['LIST'], $admin->getPermissionsShow(AbstractAdmin::CONTEXT_DASHBOARD));
1365
        $this->assertSame(['LIST'], $admin->getPermissionsShow(AbstractAdmin::CONTEXT_MENU));
1366
        $this->assertSame(['LIST'], $admin->getPermissionsShow('foo'));
1367
    }
1368
1369
    public function testShowIn(): void
1370
    {
1371
        $admin = new PostAdmin('sonata.post.admin.post', 'Acme\NewsBundle\Entity\Post', 'Sonata\NewsBundle\Controller\PostAdminController');
1372
1373
        $securityHandler = $this->createMock(AclSecurityHandlerInterface::class);
1374
        $securityHandler
1375
            ->method('isGranted')
1376
            ->willReturnCallback(static function (AdminInterface $adminIn, array $attributes, $object = null) use ($admin): bool {
1377
                return $admin === $adminIn && $attributes === ['LIST'];
1378
            });
1379
1380
        $admin->setSecurityHandler($securityHandler);
1381
1382
        $this->assertTrue($admin->showIn(AbstractAdmin::CONTEXT_DASHBOARD));
1383
        $this->assertTrue($admin->showIn(AbstractAdmin::CONTEXT_MENU));
1384
        $this->assertTrue($admin->showIn('foo'));
1385
    }
1386
1387
    public function testGetObjectIdentifier(): void
1388
    {
1389
        $admin = new PostAdmin('sonata.post.admin.post', 'Acme\NewsBundle\Entity\Post', 'Sonata\NewsBundle\Controller\PostAdminController');
1390
1391
        $this->assertSame('sonata.post.admin.post', $admin->getObjectIdentifier());
1392
    }
1393
1394
    /**
1395
     * @group legacy
1396
     */
1397
    public function testTrans(): void
1398
    {
1399
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'Sonata\NewsBundle\Controller\PostAdminController');
1400
        $admin->setTranslationDomain('fooMessageDomain');
1401
1402
        $translator = $this->createMock(TranslatorInterface::class);
1403
        $admin->setTranslator($translator);
0 ignored issues
show
Deprecated Code introduced by
The method Sonata\AdminBundle\Admin...tAdmin::setTranslator() has been deprecated with message: since sonata-project/admin-bundle 3.9, to be removed with 4.0

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

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

Loading history...
1404
1405
        $translator->expects($this->once())
1406
            ->method('trans')
1407
            ->with($this->equalTo('foo'), $this->equalTo([]), $this->equalTo('fooMessageDomain'))
1408
            ->willReturn('fooTranslated');
1409
1410
        $this->assertSame('fooTranslated', $admin->trans('foo'));
1411
    }
1412
1413
    /**
1414
     * @group legacy
1415
     */
1416
    public function testTransWithMessageDomain(): void
1417
    {
1418
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'Sonata\NewsBundle\Controller\PostAdminController');
1419
1420
        $translator = $this->createMock(TranslatorInterface::class);
1421
        $admin->setTranslator($translator);
0 ignored issues
show
Deprecated Code introduced by
The method Sonata\AdminBundle\Admin...tAdmin::setTranslator() has been deprecated with message: since sonata-project/admin-bundle 3.9, to be removed with 4.0

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

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

Loading history...
1422
1423
        $translator->expects($this->once())
1424
            ->method('trans')
1425
            ->with($this->equalTo('foo'), $this->equalTo(['name' => 'Andrej']), $this->equalTo('fooMessageDomain'))
1426
            ->willReturn('fooTranslated');
1427
1428
        $this->assertSame('fooTranslated', $admin->trans('foo', ['name' => 'Andrej'], 'fooMessageDomain'));
1429
    }
1430
1431
    /**
1432
     * @group legacy
1433
     */
1434
    public function testTransChoice(): void
1435
    {
1436
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'Sonata\NewsBundle\Controller\PostAdminController');
1437
        $admin->setTranslationDomain('fooMessageDomain');
1438
1439
        $translator = $this->createMock(TranslatorInterface::class);
1440
        $admin->setTranslator($translator);
0 ignored issues
show
Deprecated Code introduced by
The method Sonata\AdminBundle\Admin...tAdmin::setTranslator() has been deprecated with message: since sonata-project/admin-bundle 3.9, to be removed with 4.0

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

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

Loading history...
1441
1442
        $translator->expects($this->once())
1443
            ->method('transChoice')
1444
            ->with($this->equalTo('foo'), $this->equalTo(2), $this->equalTo([]), $this->equalTo('fooMessageDomain'))
1445
            ->willReturn('fooTranslated');
1446
1447
        $this->assertSame('fooTranslated', $admin->transChoice('foo', 2));
1448
    }
1449
1450
    /**
1451
     * @group legacy
1452
     */
1453
    public function testTransChoiceWithMessageDomain(): void
1454
    {
1455
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'Sonata\NewsBundle\Controller\PostAdminController');
1456
1457
        $translator = $this->createMock(TranslatorInterface::class);
1458
        $admin->setTranslator($translator);
0 ignored issues
show
Deprecated Code introduced by
The method Sonata\AdminBundle\Admin...tAdmin::setTranslator() has been deprecated with message: since sonata-project/admin-bundle 3.9, to be removed with 4.0

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

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

Loading history...
1459
1460
        $translator->expects($this->once())
1461
            ->method('transChoice')
1462
            ->with($this->equalTo('foo'), $this->equalTo(2), $this->equalTo(['name' => 'Andrej']), $this->equalTo('fooMessageDomain'))
1463
            ->willReturn('fooTranslated');
1464
1465
        $this->assertSame('fooTranslated', $admin->transChoice('foo', 2, ['name' => 'Andrej'], 'fooMessageDomain'));
1466
    }
1467
1468
    public function testSetFilterPersister(): void
1469
    {
1470
        $admin = new class('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'SonataNewsBundle\Controller\PostAdminController') extends PostAdmin {
1471
            public function persistFilters(): bool
1472
            {
1473
                return $this->persistFilters;
0 ignored issues
show
Deprecated Code introduced by
The property Sonata\AdminBundle\Admin...tAdmin::$persistFilters has been deprecated with message: since sonata-project/admin-bundle 3.34, to be removed in 4.0.

This property 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 property will be removed from the class and what other property to use instead.

Loading history...
1474
            }
1475
        };
1476
1477
        $filterPersister = $this->createMock(FilterPersisterInterface::class);
1478
1479
        $admin->setFilterPersister($filterPersister);
1480
        $this->assertTrue($admin->persistFilters());
1481
    }
1482
1483
    public function testGetRootCode(): void
1484
    {
1485
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'Sonata\NewsBundle\Controller\PostAdminController');
1486
1487
        $this->assertSame('sonata.post.admin.post', $admin->getRootCode());
1488
1489
        $parentAdmin = new PostAdmin('sonata.post.admin.post.parent', 'NewsBundle\Entity\PostParent', 'Sonata\NewsBundle\Controller\PostParentAdminController');
1490
        $parentFieldDescription = $this->createMock(FieldDescriptionInterface::class);
1491
        $parentFieldDescription->expects($this->once())
1492
            ->method('getAdmin')
1493
            ->willReturn($parentAdmin);
1494
1495
        $this->assertFalse($admin->hasParentFieldDescription());
1496
        $admin->setParentFieldDescription($parentFieldDescription);
1497
        $this->assertSame($parentFieldDescription, $admin->getParentFieldDescription());
1498
        $this->assertSame('sonata.post.admin.post.parent', $admin->getRootCode());
1499
    }
1500
1501
    public function testGetRoot(): void
1502
    {
1503
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'Sonata\NewsBundle\Controller\PostAdminController');
1504
1505
        $this->assertSame($admin, $admin->getRoot());
1506
1507
        $parentAdmin = new PostAdmin('sonata.post.admin.post.parent', 'NewsBundle\Entity\PostParent', 'Sonata\NewsBundle\Controller\PostParentAdminController');
1508
        $parentFieldDescription = $this->createMock(FieldDescriptionInterface::class);
1509
        $parentFieldDescription->expects($this->once())
1510
            ->method('getAdmin')
1511
            ->willReturn($parentAdmin);
1512
1513
        $this->assertFalse($admin->hasParentFieldDescription());
1514
        $admin->setParentFieldDescription($parentFieldDescription);
1515
        $this->assertSame($parentFieldDescription, $admin->getParentFieldDescription());
1516
        $this->assertSame($parentAdmin, $admin->getRoot());
1517
    }
1518
1519
    public function testGetExportFields(): void
1520
    {
1521
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'Sonata\NewsBundle\Controller\PostAdminController');
1522
1523
        $modelManager = $this->createMock(ModelManagerInterface::class);
1524
        $modelManager->expects($this->once())
1525
            ->method('getExportFields')
1526
            ->with($this->equalTo('NewsBundle\Entity\Post'))
1527
            ->willReturn(['foo', 'bar']);
1528
1529
        $admin->setModelManager($modelManager);
1530
        $this->assertSame(['foo', 'bar'], $admin->getExportFields());
1531
    }
1532
1533
    public function testGetPersistentParametersWithNoExtension(): void
1534
    {
1535
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'Sonata\NewsBundle\Controller\PostAdminController');
1536
1537
        $this->assertEmpty($admin->getPersistentParameters());
1538
    }
1539
1540
    public function testGetPersistentParametersWithInvalidExtension(): void
1541
    {
1542
        $this->expectException(\RuntimeException::class);
1543
1544
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'Sonata\NewsBundle\Controller\PostAdminController');
1545
1546
        $extension = $this->createMock(AdminExtensionInterface::class);
1547
        $extension->expects($this->once())->method('getPersistentParameters')->willReturn(null);
1548
1549
        $admin->addExtension($extension);
1550
1551
        $admin->getPersistentParameters();
1552
    }
1553
1554
    public function testGetPersistentParametersWithValidExtension(): void
1555
    {
1556
        $expected = [
1557
            'context' => 'foobar',
1558
        ];
1559
1560
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'Sonata\NewsBundle\Controller\PostAdminController');
1561
1562
        $extension = $this->createMock(AdminExtensionInterface::class);
1563
        $extension->expects($this->once())->method('getPersistentParameters')->willReturn($expected);
1564
1565
        $admin->addExtension($extension);
1566
1567
        $this->assertSame($expected, $admin->getPersistentParameters());
1568
    }
1569
1570
    public function testGetFormWithNonCollectionParentValue(): void
1571
    {
1572
        $post = new Post();
1573
        $tagAdmin = $this->createTagAdmin($post);
1574
        $tag = $tagAdmin->getSubject();
1575
1576
        $tag->setPosts(null);
1577
        $tagAdmin->getForm();
1578
        $this->assertSame($post, $tag->getPosts());
1579
    }
1580
1581
    public function testGetFormWithCollectionParentValue(): void
1582
    {
1583
        $post = new Post();
1584
        $tagAdmin = $this->createTagAdmin($post);
1585
        $tag = $tagAdmin->getSubject();
1586
1587
        // Case of a doctrine collection
1588
        $this->assertInstanceOf(Collection::class, $tag->getPosts());
1589
        $this->assertCount(0, $tag->getPosts());
1590
1591
        $tag->addPost(new Post());
1592
1593
        $this->assertCount(1, $tag->getPosts());
1594
1595
        $tagAdmin->getForm();
1596
1597
        $this->assertInstanceOf(Collection::class, $tag->getPosts());
1598
        $this->assertCount(2, $tag->getPosts());
1599
        $this->assertContains($post, $tag->getPosts());
1600
1601
        // Case of an array
1602
        $tag->setPosts([]);
1603
        $this->assertCount(0, $tag->getPosts());
1604
1605
        $tag->addPost(new Post());
1606
1607
        $this->assertCount(1, $tag->getPosts());
1608
1609
        $tagAdmin->getForm();
1610
1611
        $this->assertIsArray($tag->getPosts());
1612
        $this->assertCount(2, $tag->getPosts());
1613
        $this->assertContains($post, $tag->getPosts());
1614
    }
1615
1616
    public function testFormAddPostSubmitEventForPreValidation(): void
1617
    {
1618
        $modelAdmin = new ModelAdmin('sonata.post.admin.model', \stdClass::class, 'Sonata\FooBundle\Controller\ModelAdminController');
1619
        $object = new \stdClass();
1620
1621
        $labelTranslatorStrategy = $this->createMock(LabelTranslatorStrategyInterface::class);
1622
        $modelAdmin->setLabelTranslatorStrategy($labelTranslatorStrategy);
1623
1624
        $validator = $this->createMock(ValidatorInterface::class);
1625
        $validator
1626
                ->method('getMetadataFor')
1627
                ->willReturn($this->createMock(MemberMetadata::class));
1628
        $modelAdmin->setValidator($validator);
1629
1630
        $modelManager = $this->createMock(ModelManagerInterface::class);
1631
        $modelManager
1632
            ->method('getNewFieldDescriptionInstance')
1633
            ->willReturn(new FieldDescription());
1634
        $modelAdmin->setModelManager($modelManager);
1635
1636
        // a Admin class to test that preValidate is called
1637
        $testAdminPreValidate = $this->createMock(AbstractAdmin::class);
1638
        $testAdminPreValidate->expects($this->once())
1639
                ->method('preValidate')
1640
                ->with($this->identicalTo($object));
1641
1642
        $event = $this->createMock(FormEvent::class);
1643
        $event
1644
                ->method('getData')
1645
                ->willReturn($object);
1646
1647
        $formBuild = $this->createMock(FormBuilder::class);
1648
        $formBuild->expects($this->once())
1649
                ->method('addEventListener')
1650
                ->with(
1651
                    $this->identicalTo(FormEvents::POST_SUBMIT),
1652
                    $this->callback(static function ($callback) use ($testAdminPreValidate, $event): bool {
1653
                        if (\is_callable($callback)) {
1654
                            $closure = $callback->bindTo($testAdminPreValidate);
1655
                            $closure($event);
1656
1657
                            return true;
1658
                        }
1659
1660
                        return false;
1661
                    }),
1662
                    $this->greaterThan(0)
1663
                );
1664
1665
        $formContractor = $this->createMock(FormContractorInterface::class);
1666
        $formContractor
1667
                ->method('getDefaultOptions')
1668
                ->willReturn([]);
1669
        $formContractor
1670
                ->method('getFormBuilder')
1671
                ->willReturn($formBuild);
1672
1673
        $modelAdmin->setFormContractor($formContractor);
1674
        $modelAdmin->setSubject($object);
1675
        $modelAdmin->defineFormBuilder($formBuild);
1676
        $modelAdmin->getForm();
1677
    }
1678
1679
    public function testRemoveFieldFromFormGroup(): void
1680
    {
1681
        $formGroups = [
1682
            'foobar' => [
1683
                'fields' => [
1684
                    'foo' => 'foo',
1685
                    'bar' => 'bar',
1686
                ],
1687
            ],
1688
        ];
1689
1690
        $admin = new PostAdmin('sonata.post.admin.post', 'Application\Sonata\NewsBundle\Entity\Post', 'Sonata\NewsBundle\Controller\PostAdminController');
1691
        $admin->setFormGroups($formGroups);
1692
1693
        $admin->removeFieldFromFormGroup('foo');
1694
        $this->assertSame($admin->getFormGroups(), [
1695
            'foobar' => [
1696
                'fields' => [
1697
                    'bar' => 'bar',
1698
                ],
1699
            ],
1700
        ]);
1701
1702
        $admin->removeFieldFromFormGroup('bar');
1703
        $this->assertSame($admin->getFormGroups(), []);
1704
    }
1705
1706
    public function testGetFilterParameters(): void
1707
    {
1708
        $authorId = uniqid();
1709
1710
        $postAdmin = new PostAdmin('sonata.post.admin.post', 'Application\Sonata\NewsBundle\Entity\Post', 'Sonata\NewsBundle\Controller\PostAdminController');
1711
1712
        $commentAdmin = new CommentAdmin('sonata.post.admin.comment', 'Application\Sonata\NewsBundle\Entity\Comment', 'Sonata\NewsBundle\Controller\CommentAdminController');
1713
        $commentAdmin->setParentAssociationMapping('post.author');
1714
        $commentAdmin->setParent($postAdmin);
1715
1716
        $request = $this->createMock(Request::class);
1717
        $query = $this->createMock(ParameterBag::class);
1718
        $query
1719
            ->method('get')
1720
            ->willReturn([
1721
                'filter' => [
1722
                    '_page' => '1',
1723
                    '_per_page' => '32',
1724
                ],
1725
            ]);
1726
1727
        $request->query = $query;
1728
        $request
1729
            ->method('get')
1730
            ->willReturn($authorId);
1731
1732
        $commentAdmin->setRequest($request);
1733
1734
        $modelManager = $this->createMock(ModelManagerInterface::class);
1735
        $modelManager
1736
            ->method('getDefaultSortValues')
1737
            ->willReturn([]);
1738
1739
        $commentAdmin->setModelManager($modelManager);
1740
1741
        $parameters = $commentAdmin->getFilterParameters();
1742
1743
        $this->assertTrue(isset($parameters['post__author']));
1744
        $this->assertSame(['value' => $authorId], $parameters['post__author']);
1745
    }
1746
1747
    public function testGetFilterFieldDescription(): void
1748
    {
1749
        $modelAdmin = new ModelAdmin('sonata.post.admin.model', 'Application\Sonata\FooBundle\Entity\Model', 'Sonata\FooBundle\Controller\ModelAdminController');
1750
1751
        $fooFieldDescription = new FieldDescription();
1752
        $barFieldDescription = new FieldDescription();
1753
        $bazFieldDescription = new FieldDescription();
1754
1755
        $modelManager = $this->createMock(ModelManagerInterface::class);
1756
        $modelManager->expects($this->exactly(3))
1757
            ->method('getNewFieldDescriptionInstance')
1758
            ->willReturnCallback(static function ($adminClass, string $name, $filterOptions) use ($fooFieldDescription, $barFieldDescription, $bazFieldDescription) {
1759
                switch ($name) {
1760
                    case 'foo':
1761
                        $fieldDescription = $fooFieldDescription;
1762
1763
                        break;
1764
1765
                    case 'bar':
1766
                        $fieldDescription = $barFieldDescription;
1767
1768
                        break;
1769
1770
                    case 'baz':
1771
                        $fieldDescription = $bazFieldDescription;
1772
1773
                        break;
1774
1775
                    default:
1776
                        throw new \RuntimeException(sprintf('Unknown filter name "%s"', $name));
1777
                        break;
1778
                }
1779
1780
                $fieldDescription->setName($name);
1781
1782
                return $fieldDescription;
1783
            });
1784
1785
        $modelAdmin->setModelManager($modelManager);
1786
1787
        $pager = $this->createMock(PagerInterface::class);
1788
1789
        $datagrid = $this->createMock(DatagridInterface::class);
1790
        $datagrid->expects($this->once())
1791
            ->method('getPager')
1792
            ->willReturn($pager);
1793
1794
        $datagridBuilder = $this->createMock(DatagridBuilderInterface::class);
1795
        $datagridBuilder->expects($this->once())
1796
            ->method('getBaseDatagrid')
1797
            ->with($this->identicalTo($modelAdmin), [])
1798
            ->willReturn($datagrid);
1799
1800
        $datagridBuilder->expects($this->exactly(3))
1801
            ->method('addFilter')
1802
            ->willReturnCallback(static function ($datagrid, $type, $fieldDescription, AdminInterface $admin): void {
1803
                $admin->addFilterFieldDescription($fieldDescription->getName(), $fieldDescription);
1804
                $fieldDescription->mergeOption('field_options', ['required' => false]);
1805
            });
1806
1807
        $modelAdmin->setDatagridBuilder($datagridBuilder);
1808
1809
        $this->assertSame(['foo' => $fooFieldDescription, 'bar' => $barFieldDescription, 'baz' => $bazFieldDescription], $modelAdmin->getFilterFieldDescriptions());
1810
        $this->assertFalse($modelAdmin->hasFilterFieldDescription('fooBar'));
1811
        $this->assertTrue($modelAdmin->hasFilterFieldDescription('foo'));
1812
        $this->assertTrue($modelAdmin->hasFilterFieldDescription('bar'));
1813
        $this->assertTrue($modelAdmin->hasFilterFieldDescription('baz'));
1814
        $this->assertSame($fooFieldDescription, $modelAdmin->getFilterFieldDescription('foo'));
1815
        $this->assertSame($barFieldDescription, $modelAdmin->getFilterFieldDescription('bar'));
1816
        $this->assertSame($bazFieldDescription, $modelAdmin->getFilterFieldDescription('baz'));
1817
    }
1818
1819
    public function testGetSubjectNoRequest(): void
1820
    {
1821
        $modelManager = $this->createMock(ModelManagerInterface::class);
1822
        $modelManager
1823
            ->expects($this->never())
1824
            ->method('find');
1825
1826
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'Sonata\NewsBundle\Controller\PostAdminController');
1827
        $admin->setModelManager($modelManager);
1828
1829
        $this->assertFalse($admin->hasSubject());
1830
    }
1831
1832
    public function testGetSideMenu(): void
1833
    {
1834
        $item = $this->createMock(ItemInterface::class);
1835
        $item
1836
            ->expects($this->once())
1837
            ->method('setChildrenAttribute')
1838
            ->with('class', 'nav navbar-nav');
1839
        $item
1840
            ->expects($this->once())
1841
            ->method('setExtra')
1842
            ->with('translation_domain', 'foo_bar_baz');
1843
1844
        $menuFactory = $this->createMock(FactoryInterface::class);
1845
        $menuFactory
1846
            ->expects($this->once())
1847
            ->method('createItem')
1848
            ->willReturn($item);
1849
1850
        $modelAdmin = new ModelAdmin('sonata.post.admin.model', 'Application\Sonata\FooBundle\Entity\Model', 'Sonata\FooBundle\Controller\ModelAdminController');
1851
        $modelAdmin->setMenuFactory($menuFactory);
1852
        $modelAdmin->setTranslationDomain('foo_bar_baz');
1853
1854
        $modelAdmin->getSideMenu('foo');
1855
    }
1856
1857
    /**
1858
     * @return array
1859
     */
1860
    public function provideGetSubject()
1861
    {
1862
        return [
1863
            [23],
1864
            ['azerty'],
1865
            ['4f69bbb5f14a13347f000092'],
1866
            ['0779ca8d-e2be-11e4-ac58-0242ac11000b'],
1867
            ['123'.AdapterInterface::ID_SEPARATOR.'my_type'], // composite keys are supported
1868
        ];
1869
    }
1870
1871
    /**
1872
     * @dataProvider provideGetSubject
1873
     */
1874
    public function testGetSubjectFailed($id): void
1875
    {
1876
        $modelManager = $this->createMock(ModelManagerInterface::class);
1877
        $modelManager
1878
            ->expects($this->once())
1879
            ->method('find')
1880
            ->with('NewsBundle\Entity\Post', $id)
1881
            ->willReturn(null); // entity not found
1882
1883
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'Sonata\NewsBundle\Controller\PostAdminController');
1884
        $admin->setModelManager($modelManager);
1885
1886
        $admin->setRequest(new Request(['id' => $id]));
1887
        $this->assertFalse($admin->hasSubject());
1888
    }
1889
1890
    /**
1891
     * @dataProvider provideGetSubject
1892
     */
1893
    public function testGetSubject($id): void
1894
    {
1895
        $model = new Post();
1896
1897
        $modelManager = $this->createMock(ModelManagerInterface::class);
1898
        $modelManager
1899
            ->expects($this->once())
1900
            ->method('find')
1901
            ->with('NewsBundle\Entity\Post', $id)
1902
            ->willReturn($model);
1903
1904
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'Sonata\NewsBundle\Controller\PostAdminController');
1905
        $admin->setModelManager($modelManager);
1906
1907
        $admin->setRequest(new Request(['id' => $id]));
1908
        $this->assertTrue($admin->hasSubject());
1909
        $this->assertSame($model, $admin->getSubject());
1910
        $this->assertSame($model, $admin->getSubject()); // model manager must be used only once
1911
    }
1912
1913
    public function testGetSubjectWithParentDescription(): void
1914
    {
1915
        $adminId = 1;
1916
1917
        $comment = new Comment();
1918
1919
        $modelManager = $this->createMock(ModelManagerInterface::class);
1920
        $modelManager
1921
            ->method('find')
1922
            ->with('NewsBundle\Entity\Comment', $adminId)
1923
            ->willReturn($comment);
1924
1925
        $request = new Request(['id' => $adminId]);
1926
1927
        $postAdmin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'Sonata\NewsBundle\Controller\PostAdminController');
1928
        $postAdmin->setRequest($request);
1929
1930
        $commentAdmin = new CommentAdmin('sonata.post.admin.comment', 'NewsBundle\Entity\Comment', 'Sonata\NewsBundle\Controller\CommentAdminController');
1931
        $commentAdmin->setRequest($request);
1932
        $commentAdmin->setModelManager($modelManager);
1933
1934
        $this->assertTrue($commentAdmin->hasSubject());
1935
        $this->assertSame($comment, $commentAdmin->getSubject());
1936
1937
        $commentAdmin->setSubject(null);
1938
        $commentAdmin->setParentFieldDescription(new FieldDescription());
1939
1940
        $this->assertFalse($commentAdmin->hasSubject());
1941
    }
1942
1943
    /**
1944
     * @covers \Sonata\AdminBundle\Admin\AbstractAdmin::configureActionButtons
1945
     */
1946
    public function testGetActionButtonsList(): void
1947
    {
1948
        $expected = [
1949
            'create' => [
1950
                'template' => 'Foo.html.twig',
1951
            ],
1952
        ];
1953
1954
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'Sonata\NewsBundle\Controller\PostAdminController');
1955
1956
        $templateRegistry = $this->prophesize(MutableTemplateRegistryInterface::class);
1957
        $templateRegistry->getTemplate('button_create')->willReturn('Foo.html.twig');
1958
1959
        $admin->setTemplateRegistry($templateRegistry->reveal());
1960
1961
        $securityHandler = $this->createMock(SecurityHandlerInterface::class);
1962
        $securityHandler
1963
            ->expects($this->once())
1964
            ->method('isGranted')
1965
            ->with($admin, 'CREATE', $admin)
1966
            ->willReturn(true);
1967
        $admin->setSecurityHandler($securityHandler);
1968
1969
        $routeGenerator = $this->createMock(RouteGeneratorInterface::class);
1970
        $routeGenerator
1971
            ->expects($this->once())
1972
            ->method('hasAdminRoute')
1973
            ->with($admin, 'create')
1974
            ->willReturn(true);
1975
        $admin->setRouteGenerator($routeGenerator);
1976
1977
        $this->assertSame($expected, $admin->getActionButtons('list', null));
1978
    }
1979
1980
    /**
1981
     * @covers \Sonata\AdminBundle\Admin\AbstractAdmin::configureActionButtons
1982
     */
1983
    public function testGetActionButtonsListCreateDisabled(): void
1984
    {
1985
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'Sonata\NewsBundle\Controller\PostAdminController');
1986
1987
        $securityHandler = $this->createMock(SecurityHandlerInterface::class);
1988
        $securityHandler
1989
            ->expects($this->once())
1990
            ->method('isGranted')
1991
            ->with($admin, 'CREATE', $admin)
1992
            ->willReturn(false);
1993
        $admin->setSecurityHandler($securityHandler);
1994
1995
        $this->assertSame([], $admin->getActionButtons('list', null));
1996
    }
1997
1998
    /**
1999
     * @covers \Sonata\AdminBundle\Admin\AbstractAdmin::configureBatchActions
2000
     */
2001
    public function testGetBatchActions(): void
2002
    {
2003
        $expected = [
2004
            'delete' => [
2005
                'label' => 'action_delete',
2006
                'translation_domain' => 'SonataAdminBundle',
2007
                'ask_confirmation' => true, // by default always true
2008
            ],
2009
            'foo' => [
2010
                'label' => 'action_foo',
2011
                'translation_domain' => 'SonataAdminBundle',
2012
            ],
2013
            'bar' => [
2014
                'label' => 'batch.label_bar',
2015
                'translation_domain' => 'SonataAdminBundle',
2016
            ],
2017
            'baz' => [
2018
                'label' => 'action_baz',
2019
                'translation_domain' => 'AcmeAdminBundle',
2020
            ],
2021
        ];
2022
2023
        $pathInfo = new PathInfoBuilder($this->createMock(AuditManagerInterface::class));
2024
2025
        $labelTranslatorStrategy = $this->createMock(LabelTranslatorStrategyInterface::class);
2026
        $labelTranslatorStrategy
2027
            ->method('getLabel')
2028
            ->willReturnCallback(static function (string $label, string $context = '', string $type = ''): string {
2029
                return $context.'.'.$type.'_'.$label;
2030
            });
2031
2032
        $admin = new PostAdmin('sonata.post.admin.model', 'Application\Sonata\FooBundle\Entity\Model', 'Sonata\FooBundle\Controller\ModelAdminController');
2033
        $admin->setRouteBuilder($pathInfo);
2034
        $admin->setTranslationDomain('SonataAdminBundle');
2035
        $admin->setLabelTranslatorStrategy($labelTranslatorStrategy);
2036
2037
        $routeGenerator = $this->createMock(RouteGeneratorInterface::class);
2038
        $routeGenerator
2039
            ->expects($this->once())
2040
            ->method('hasAdminRoute')
2041
            ->with($admin, 'delete')
2042
            ->willReturn(true);
2043
        $admin->setRouteGenerator($routeGenerator);
2044
2045
        $securityHandler = $this->createMock(SecurityHandlerInterface::class);
2046
        $securityHandler
2047
            ->method('isGranted')
2048
            ->willReturnCallback(static function (AdminInterface $adminIn, string $attributes, $object = null) use ($admin): bool {
2049
                return $admin === $adminIn && 'DELETE' === $attributes;
2050
            });
2051
        $admin->setSecurityHandler($securityHandler);
2052
2053
        $this->assertSame($expected, $admin->getBatchActions());
2054
    }
2055
2056
    /**
2057
     * @covers \Sonata\AdminBundle\Admin\AbstractAdmin::showMosaicButton
2058
     */
2059
    public function testShowMosaicButton(): void
2060
    {
2061
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'Sonata\NewsBundle\Controller\PostAdminController');
2062
        $listModes = $admin->getListModes();
2063
2064
        $admin->showMosaicButton(true);
2065
2066
        $this->assertSame($listModes, $admin->getListModes());
2067
    }
2068
2069
    /**
2070
     * @covers \Sonata\AdminBundle\Admin\AbstractAdmin::showMosaicButton
2071
     */
2072
    public function testShowMosaicButtonHideMosaic(): void
2073
    {
2074
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'Sonata\NewsBundle\Controller\PostAdminController');
2075
        $listModes = $admin->getListModes();
2076
        $expected['list'] = $listModes['list'];
2077
2078
        $admin->showMosaicButton(false);
2079
2080
        $this->assertSame($expected, $admin->getListModes());
2081
    }
2082
2083
    /**
2084
     * @covers \Sonata\AdminBundle\Admin\AbstractAdmin::getDashboardActions
2085
     * @dataProvider provideGetBaseRouteName
2086
     */
2087
    public function testDefaultDashboardActionsArePresent(string $objFqn, string $expected): void
2088
    {
2089
        $pathInfo = new PathInfoBuilder($this->createMock(AuditManagerInterface::class));
2090
2091
        $routeGenerator = new DefaultRouteGenerator(
2092
            $this->createMock(RouterInterface::class),
2093
            new RoutesCache($this->cacheTempFolder, true)
2094
        );
2095
2096
        $admin = new PostAdmin('sonata.post.admin.post', $objFqn, 'Sonata\NewsBundle\Controller\PostAdminController');
2097
        $admin->setRouteBuilder($pathInfo);
2098
        $admin->setRouteGenerator($routeGenerator);
2099
        $admin->initialize();
2100
2101
        $templateRegistry = $this->prophesize(MutableTemplateRegistryInterface::class);
2102
        $templateRegistry->getTemplate('action_create')->willReturn('Foo.html.twig');
2103
2104
        $admin->setTemplateRegistry($templateRegistry->reveal());
2105
2106
        $securityHandler = $this->createMock(SecurityHandlerInterface::class);
2107
        $securityHandler
2108
            ->method('isGranted')
2109
            ->willReturnCallback(static function (AdminInterface $adminIn, string $attributes, $object = null) use ($admin): bool {
2110
                return $admin === $adminIn && ('CREATE' === $attributes || 'LIST' === $attributes);
2111
            });
2112
2113
        $admin->setSecurityHandler($securityHandler);
2114
2115
        $this->assertArrayHasKey('list', $admin->getDashboardActions());
2116
        $this->assertArrayHasKey('create', $admin->getDashboardActions());
2117
    }
2118
2119
    public function testDefaultFilters(): void
2120
    {
2121
        $admin = new FilteredAdmin('sonata.post.admin.model', 'Application\Sonata\FooBundle\Entity\Model', 'Sonata\FooBundle\Controller\ModelAdminController');
2122
2123
        $subjectId = uniqid();
2124
2125
        $request = $this->createMock(Request::class);
2126
        $query = $this->createMock(ParameterBag::class);
2127
        $query
2128
            ->method('get')
2129
            ->with($this->equalTo('filter'))
2130
            ->willReturn([
2131
                'a' => [
2132
                    'value' => 'b',
2133
                ],
2134
                'foo' => [
2135
                    'type' => '1',
2136
                    'value' => 'bar',
2137
                ],
2138
                'baz' => [
2139
                    'type' => '5',
2140
                    'value' => 'test',
2141
                ],
2142
            ]);
2143
        $request->query = $query;
2144
2145
        $request
2146
            ->method('get')
2147
            ->willReturn($subjectId);
2148
2149
        $admin->setRequest($request);
2150
2151
        $modelManager = $this->createMock(ModelManagerInterface::class);
2152
        $modelManager
2153
            ->method('getDefaultSortValues')
2154
            ->willReturn([]);
2155
2156
        $admin->setModelManager($modelManager);
2157
2158
        $this->assertSame([
2159
            '_page' => 1,
2160
            '_per_page' => 32,
2161
            'foo' => [
2162
                'type' => '1',
2163
                'value' => 'bar',
2164
            ],
2165
            'baz' => [
2166
                'type' => '5',
2167
                'value' => 'test',
2168
            ],
2169
            'a' => [
2170
                'value' => 'b',
2171
            ],
2172
        ], $admin->getFilterParameters());
2173
2174
        $this->assertTrue($admin->isDefaultFilter('foo'));
2175
        $this->assertFalse($admin->isDefaultFilter('bar'));
2176
        $this->assertFalse($admin->isDefaultFilter('a'));
2177
    }
2178
2179
    /**
2180
     * @group legacy
2181
     */
2182
    public function testDefaultBreadcrumbsBuilder(): void
2183
    {
2184
        $container = $this->createMock(ContainerInterface::class);
2185
        $container->expects($this->once())
2186
            ->method('getParameter')
2187
            ->with('sonata.admin.configuration.breadcrumbs')
2188
            ->willReturn([]);
2189
2190
        $pool = $this->getMockBuilder(Pool::class)
2191
            ->disableOriginalConstructor()
2192
            ->getMock();
2193
        $pool->expects($this->once())
2194
            ->method('getContainer')
2195
            ->willReturn($container);
2196
2197
        $admin = $this->getMockForAbstractClass(AbstractAdmin::class, [
2198
            'admin.my_code', 'My\Class', 'MyBundle\ClassAdminController',
2199
        ], '', true, true, true, ['getConfigurationPool']);
2200
        $admin->expects($this->once())
2201
            ->method('getConfigurationPool')
2202
            ->willReturn($pool);
2203
2204
        $this->assertInstanceOf(BreadcrumbsBuilder::class, $admin->getBreadcrumbsBuilder());
2205
    }
2206
2207
    /**
2208
     * @group legacy
2209
     */
2210
    public function testBreadcrumbsBuilderSetter(): void
2211
    {
2212
        $admin = $this->getMockForAbstractClass(AbstractAdmin::class, [
2213
            'admin.my_code', 'My\Class', 'MyBundle\ClassAdminController',
2214
        ]);
2215
        $this->assertSame($admin, $admin->setBreadcrumbsBuilder($builder = $this->createMock(
2216
            BreadcrumbsBuilderInterface::class
2217
        )));
2218
        $this->assertSame($builder, $admin->getBreadcrumbsBuilder());
2219
    }
2220
2221
    /**
2222
     * @group legacy
2223
     */
2224
    public function testGetBreadcrumbs(): void
2225
    {
2226
        $admin = $this->getMockForAbstractClass(AbstractAdmin::class, [
2227
            'admin.my_code', 'My\Class', 'MyBundle\ClassAdminController',
2228
        ]);
2229
        $builder = $this->prophesize(BreadcrumbsBuilderInterface::class);
2230
        $action = 'myaction';
2231
        $builder->getBreadcrumbs($admin, $action)->shouldBeCalled();
2232
        $admin->setBreadcrumbsBuilder($builder->reveal())->getBreadcrumbs($action);
2233
    }
2234
2235
    /**
2236
     * @group legacy
2237
     */
2238
    public function testBuildBreadcrumbs(): void
2239
    {
2240
        $admin = $this->getMockForAbstractClass(AbstractAdmin::class, [
2241
            'admin.my_code', 'My\Class', 'MyBundle\ClassAdminController',
2242
        ]);
2243
        $builder = $this->prophesize(BreadcrumbsBuilderInterface::class);
2244
        $action = 'myaction';
2245
        $menu = $this->createMock(ItemInterface::class);
2246
        $builder->buildBreadcrumbs($admin, $action, $menu)
2247
            ->shouldBeCalledTimes(1)
2248
            ->willReturn($menu);
2249
        $admin->setBreadcrumbsBuilder($builder->reveal());
2250
2251
        /* check the called is proxied only once */
2252
        $this->assertSame($menu, $admin->buildBreadcrumbs($action, $menu));
2253
        $this->assertSame($menu, $admin->buildBreadcrumbs($action, $menu));
2254
    }
2255
2256
    /**
2257
     * NEXT_MAJOR: remove this method.
2258
     *
2259
     * @group legacy
2260
     */
2261
    public function testCreateQueryLegacyCallWorks(): void
2262
    {
2263
        $admin = $this->getMockForAbstractClass(AbstractAdmin::class, [
2264
            'admin.my_code', 'My\Class', 'MyBundle\ClassAdminController',
2265
        ]);
2266
        $query = $this->createMock(ProxyQueryInterface::class);
2267
        $modelManager = $this->createMock(ModelManagerInterface::class);
2268
        $modelManager->expects($this->once())
2269
            ->method('createQuery')
2270
            ->with('My\Class')
2271
            ->willReturn($query);
2272
2273
        $admin->setModelManager($modelManager);
2274
        $this->assertSame($query, $admin->createQuery('list'));
2275
    }
2276
2277
    public function testGetDataSourceIterator(): void
2278
    {
2279
        $datagrid = $this->createMock(DatagridInterface::class);
2280
        $datagrid->method('buildPager');
2281
2282
        $modelManager = $this->createMock(ModelManagerInterface::class);
2283
        $modelManager->method('getExportFields')->willReturn([
2284
            'field',
2285
            'foo',
2286
            'bar',
2287
        ]);
2288
        $modelManager->expects($this->once())->method('getDataSourceIterator')
2289
            ->with($this->equalTo($datagrid), $this->equalTo([
2290
                'Feld' => 'field',
2291
                1 => 'foo',
2292
                2 => 'bar',
2293
            ]));
2294
2295
        $admin = $this->getMockBuilder(AbstractAdmin::class)
2296
            ->disableOriginalConstructor()
2297
            ->setMethods(['getDatagrid', 'getTranslationLabel', 'trans'])
2298
            ->getMockForAbstractClass();
2299
        $admin->method('getDatagrid')->willReturn($datagrid);
2300
        $admin->setModelManager($modelManager);
2301
2302
        $admin
2303
            ->method('getTranslationLabel')
2304
            ->willReturnCallback(static function (string $label, string $context = '', string $type = ''): string {
2305
                return $context.'.'.$type.'_'.$label;
2306
            });
2307
        $admin
2308
            ->method('trans')
2309
            ->willReturnCallback(static function (string $label): string {
2310
                if ('export.label_field' === $label) {
2311
                    return 'Feld';
2312
                }
2313
2314
                return $label;
2315
            });
2316
2317
        $admin->getDataSourceIterator();
2318
    }
2319
2320
    public function testCircularChildAdmin(): void
2321
    {
2322
        $this->expectException(\RuntimeException::class);
2323
        $this->expectExceptionMessage(
2324
            'Circular reference detected! The child admin `sonata.post.admin.post` is already in the parent tree of the `sonata.post.admin.comment` admin.'
2325
        );
2326
2327
        $postAdmin = new PostAdmin(
2328
            'sonata.post.admin.post',
2329
            'Application\Sonata\NewsBundle\Entity\Post',
2330
            'Sonata\NewsBundle\Controller\PostAdminController'
2331
        );
2332
        $commentAdmin = new CommentAdmin(
2333
            'sonata.post.admin.comment',
2334
            'Application\Sonata\NewsBundle\Entity\Comment',
2335
            'Sonata\NewsBundle\Controller\CommentAdminController'
2336
        );
2337
        $postAdmin->addChild($commentAdmin, 'post');
2338
        $commentAdmin->addChild($postAdmin, 'comment');
2339
    }
2340
2341
    public function testCircularChildAdminTripleLevel(): void
2342
    {
2343
        $this->expectException(\RuntimeException::class);
2344
        $this->expectExceptionMessage(
2345
            'Circular reference detected! The child admin `sonata.post.admin.post` is already in the parent tree of the `sonata.post.admin.comment_vote` admin.'
2346
        );
2347
2348
        $postAdmin = new PostAdmin(
2349
            'sonata.post.admin.post',
2350
            'Application\Sonata\NewsBundle\Entity\Post',
2351
            'Sonata\NewsBundle\Controller\PostAdminController'
2352
        );
2353
        $commentAdmin = new CommentAdmin(
2354
            'sonata.post.admin.comment',
2355
            'Application\Sonata\NewsBundle\Entity\Comment',
2356
            'Sonata\NewsBundle\Controller\CommentAdminController'
2357
        );
2358
        $commentVoteAdmin = new CommentVoteAdmin(
2359
            'sonata.post.admin.comment_vote',
2360
            'Application\Sonata\NewsBundle\Entity\CommentVote',
2361
            'Sonata\NewsBundle\Controller\CommentVoteAdminController'
2362
        );
2363
        $postAdmin->addChild($commentAdmin, 'post');
2364
        $commentAdmin->addChild($commentVoteAdmin, 'comment');
2365
        $commentVoteAdmin->addChild($postAdmin, 'post');
2366
    }
2367
2368
    public function testCircularChildAdminWithItself(): void
2369
    {
2370
        $this->expectException(\RuntimeException::class);
2371
        $this->expectExceptionMessage(
2372
            'Circular reference detected! The child admin `sonata.post.admin.post` is already in the parent tree of the `sonata.post.admin.post` admin.'
2373
        );
2374
2375
        $postAdmin = new PostAdmin(
2376
            'sonata.post.admin.post',
2377
            'Application\Sonata\NewsBundle\Entity\Post',
2378
            'Sonata\NewsBundle\Controller\PostAdminController'
2379
        );
2380
        $postAdmin->addChild($postAdmin);
2381
    }
2382
2383
    public function testGetRootAncestor(): void
2384
    {
2385
        $postAdmin = new PostAdmin(
2386
            'sonata.post.admin.post',
2387
            'Application\Sonata\NewsBundle\Entity\Post',
2388
            'Sonata\NewsBundle\Controller\PostAdminController'
2389
        );
2390
        $commentAdmin = new CommentAdmin(
2391
            'sonata.post.admin.comment',
2392
            'Application\Sonata\NewsBundle\Entity\Comment',
2393
            'Sonata\NewsBundle\Controller\CommentAdminController'
2394
        );
2395
        $commentVoteAdmin = new CommentVoteAdmin(
2396
            'sonata.post.admin.comment_vote',
2397
            'Application\Sonata\NewsBundle\Entity\CommentVote',
2398
            'Sonata\NewsBundle\Controller\CommentVoteAdminController'
2399
        );
2400
2401
        $this->assertSame($postAdmin, $postAdmin->getRootAncestor());
2402
        $this->assertSame($commentAdmin, $commentAdmin->getRootAncestor());
2403
        $this->assertSame($commentVoteAdmin, $commentVoteAdmin->getRootAncestor());
2404
2405
        $postAdmin->addChild($commentAdmin, 'post');
2406
2407
        $this->assertSame($postAdmin, $postAdmin->getRootAncestor());
2408
        $this->assertSame($postAdmin, $commentAdmin->getRootAncestor());
2409
        $this->assertSame($commentVoteAdmin, $commentVoteAdmin->getRootAncestor());
2410
2411
        $commentAdmin->addChild($commentVoteAdmin, 'comment');
2412
2413
        $this->assertSame($postAdmin, $postAdmin->getRootAncestor());
2414
        $this->assertSame($postAdmin, $commentAdmin->getRootAncestor());
2415
        $this->assertSame($postAdmin, $commentVoteAdmin->getRootAncestor());
2416
    }
2417
2418
    public function testGetChildDepth(): void
2419
    {
2420
        $postAdmin = new PostAdmin(
2421
            'sonata.post.admin.post',
2422
            'Application\Sonata\NewsBundle\Entity\Post',
2423
            'Sonata\NewsBundle\Controller\PostAdminController'
2424
        );
2425
        $commentAdmin = new CommentAdmin(
2426
            'sonata.post.admin.comment',
2427
            'Application\Sonata\NewsBundle\Entity\Comment',
2428
            'Sonata\NewsBundle\Controller\CommentAdminController'
2429
        );
2430
        $commentVoteAdmin = new CommentVoteAdmin(
2431
            'sonata.post.admin.comment_vote',
2432
            'Application\Sonata\NewsBundle\Entity\CommentVote',
2433
            'Sonata\NewsBundle\Controller\CommentVoteAdminController'
2434
        );
2435
2436
        $this->assertSame(0, $postAdmin->getChildDepth());
2437
        $this->assertSame(0, $commentAdmin->getChildDepth());
2438
        $this->assertSame(0, $commentVoteAdmin->getChildDepth());
2439
2440
        $postAdmin->addChild($commentAdmin, 'post');
2441
2442
        $this->assertSame(0, $postAdmin->getChildDepth());
2443
        $this->assertSame(1, $commentAdmin->getChildDepth());
2444
        $this->assertSame(0, $commentVoteAdmin->getChildDepth());
2445
2446
        $commentAdmin->addChild($commentVoteAdmin, 'comment');
2447
2448
        $this->assertSame(0, $postAdmin->getChildDepth());
2449
        $this->assertSame(1, $commentAdmin->getChildDepth());
2450
        $this->assertSame(2, $commentVoteAdmin->getChildDepth());
2451
    }
2452
2453
    public function testGetCurrentLeafChildAdmin(): void
2454
    {
2455
        $postAdmin = new PostAdmin(
2456
            'sonata.post.admin.post',
2457
            'Application\Sonata\NewsBundle\Entity\Post',
2458
            'Sonata\NewsBundle\Controller\PostAdminController'
2459
        );
2460
        $commentAdmin = new CommentAdmin(
2461
            'sonata.post.admin.comment',
2462
            'Application\Sonata\NewsBundle\Entity\Comment',
2463
            'Sonata\NewsBundle\Controller\CommentAdminController'
2464
        );
2465
        $commentVoteAdmin = new CommentVoteAdmin(
2466
            'sonata.post.admin.comment_vote',
2467
            'Application\Sonata\NewsBundle\Entity\CommentVote',
2468
            'Sonata\NewsBundle\Controller\CommentVoteAdminController'
2469
        );
2470
2471
        $postAdmin->addChild($commentAdmin, 'post');
2472
        $commentAdmin->addChild($commentVoteAdmin, 'comment');
2473
2474
        $this->assertNull($postAdmin->getCurrentLeafChildAdmin());
2475
        $this->assertNull($commentAdmin->getCurrentLeafChildAdmin());
2476
        $this->assertNull($commentVoteAdmin->getCurrentLeafChildAdmin());
2477
2478
        $commentAdmin->setCurrentChild(true);
2479
2480
        $this->assertSame($commentAdmin, $postAdmin->getCurrentLeafChildAdmin());
2481
        $this->assertNull($commentAdmin->getCurrentLeafChildAdmin());
2482
        $this->assertNull($commentVoteAdmin->getCurrentLeafChildAdmin());
2483
2484
        $commentVoteAdmin->setCurrentChild(true);
2485
2486
        $this->assertSame($commentVoteAdmin, $postAdmin->getCurrentLeafChildAdmin());
2487
        $this->assertSame($commentVoteAdmin, $commentAdmin->getCurrentLeafChildAdmin());
2488
        $this->assertNull($commentVoteAdmin->getCurrentLeafChildAdmin());
2489
    }
2490
2491
    public function testAdminWithoutControllerName(): void
2492
    {
2493
        $admin = new PostAdmin('sonata.post.admin.post', 'Application\Sonata\NewsBundle\Entity\Post', null);
2494
2495
        $this->assertNull($admin->getBaseControllerName());
2496
    }
2497
2498
    /**
2499
     * NEXT_MAJOR: Remove this test and its data provider.
2500
     *
2501
     * @group legacy
2502
     *
2503
     * @dataProvider getDeprecatedAbstractAdminConstructorArgs
2504
     *
2505
     * @expectedDeprecation Passing other type than string%S as argument %d for method Sonata\AdminBundle\Admin\AbstractAdmin::__construct() is deprecated since sonata-project/admin-bundle 3.65. It will accept only string%S in version 4.0.
2506
     */
2507
    public function testDeprecatedAbstractAdminConstructorArgs($code, $class, $baseControllerName): void
2508
    {
2509
        new PostAdmin($code, $class, $baseControllerName);
2510
    }
2511
2512
    public function getDeprecatedAbstractAdminConstructorArgs(): iterable
2513
    {
2514
        yield from [
2515
            ['sonata.post.admin.post', null, null],
2516
            [null, null, null],
2517
            ['sonata.post.admin.post', 'Application\Sonata\NewsBundle\Entity\Post', false],
2518
            ['sonata.post.admin.post', false, false],
2519
            [false, false, false],
2520
            [true, true, true],
2521
            [new \stdClass(), new \stdClass(), new \stdClass()],
2522
            [0, 0, 0],
2523
            [1, 1, 1],
2524
        ];
2525
    }
2526
2527
    private function createTagAdmin(Post $post): TagAdmin
2528
    {
2529
        $postAdmin = $this->getMockBuilder(PostAdmin::class)
2530
            ->disableOriginalConstructor()
2531
            ->getMock();
2532
2533
        $postAdmin->method('getObject')->willReturn($post);
2534
2535
        $formBuilder = $this->createMock(FormBuilderInterface::class);
2536
        $formBuilder->method('getForm')->willReturn(null);
2537
2538
        $tagAdmin = $this->getMockBuilder(TagAdmin::class)
2539
            ->setConstructorArgs([
2540
                'admin.tag',
2541
                Tag::class,
2542
                'MyBundle\MyController',
2543
            ])
2544
            ->setMethods(['getFormBuilder'])
2545
            ->getMock();
2546
2547
        $tagAdmin->method('getFormBuilder')->willReturn($formBuilder);
2548
        $tagAdmin->setParent($postAdmin);
2549
2550
        $tag = new Tag();
2551
        $tagAdmin->setSubject($tag);
2552
2553
        $request = $this->createMock(Request::class);
2554
        $tagAdmin->setRequest($request);
2555
2556
        $configurationPool = $this->getMockBuilder(Pool::class)
2557
            ->disableOriginalConstructor()
2558
            ->getMock();
2559
2560
        $configurationPool->method('getPropertyAccessor')->willReturn(PropertyAccess::createPropertyAccessor());
2561
2562
        $tagAdmin->setConfigurationPool($configurationPool);
2563
2564
        return $tagAdmin;
2565
    }
2566
}
2567