Completed
Pull Request — master (#6209)
by Jordi Sala
03:47 queued 54s
created

testDeprecatedAbstractAdminConstructorArgs()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

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

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

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

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

function acceptsInteger($int) { }

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

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
699
    }
700
701
    public function testIsAclEnabled(): void
702
    {
703
        $postAdmin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'Sonata\NewsBundle\Controller\PostAdminController');
704
705
        $this->assertFalse($postAdmin->isAclEnabled());
706
707
        $commentAdmin = new CommentAdmin('sonata.post.admin.comment', 'Application\Sonata\NewsBundle\Entity\Comment', 'Sonata\NewsBundle\Controller\CommentAdminController');
708
        $commentAdmin->setSecurityHandler($this->createMock(AclSecurityHandlerInterface::class));
709
        $this->assertTrue($commentAdmin->isAclEnabled());
710
    }
711
712
    /**
713
     * @covers \Sonata\AdminBundle\Admin\AbstractAdmin::getSubClasses
714
     * @covers \Sonata\AdminBundle\Admin\AbstractAdmin::getSubClass
715
     * @covers \Sonata\AdminBundle\Admin\AbstractAdmin::setSubClasses
716
     * @covers \Sonata\AdminBundle\Admin\AbstractAdmin::hasSubClass
717
     * @covers \Sonata\AdminBundle\Admin\AbstractAdmin::hasActiveSubClass
718
     * @covers \Sonata\AdminBundle\Admin\AbstractAdmin::getActiveSubClass
719
     * @covers \Sonata\AdminBundle\Admin\AbstractAdmin::getActiveSubclassCode
720
     * @covers \Sonata\AdminBundle\Admin\AbstractAdmin::getClass
721
     */
722
    public function testSubClass(): void
723
    {
724
        // NEXT_MAJOR: Remove the "@group" and "@expectedDeprecation" annotations
725
        $admin = new PostAdmin(
726
            'sonata.post.admin.post',
727
            Post::class,
728
            'Sonata\NewsBundle\Controller\PostAdminController'
729
        );
730
        $this->assertFalse($admin->hasSubClass('test'));
731
        $this->assertFalse($admin->hasActiveSubClass());
732
        $this->assertCount(0, $admin->getSubClasses());
733
        $this->assertSame(Post::class, $admin->getClass());
734
735
        // Just for the record, if there is no inheritance set, the getSubject is not used
736
        // the getSubject can also lead to some issue
737
        $admin->setSubject(new BlogPost());
738
        $this->assertSame(BlogPost::class, $admin->getClass());
739
740
        $admin->setSubClasses([
741
            'extended1' => 'NewsBundle\Entity\PostExtended1',
742
            'extended2' => 'NewsBundle\Entity\PostExtended2',
743
        ]);
744
        $this->assertFalse($admin->hasSubClass('test'));
745
        $this->assertTrue($admin->hasSubClass('extended1'));
746
        $this->assertFalse($admin->hasActiveSubClass());
747
        $this->assertCount(2, $admin->getSubClasses());
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->expectException(\LogicException::class);
775
        $this->expectExceptionMessage(sprintf('Admin "%s" has no active subclass.', PostAdmin::class));
776
777
        $admin->getActiveSubclassCode();
778
    }
779
780
    public function testNonExistantSubclass(): void
781
    {
782
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'Sonata\NewsBundle\Controller\PostAdminController');
783
        $admin->setModelManager($this->getMockForAbstractClass(ModelManagerInterface::class));
784
785
        $admin->setRequest(new Request(['subclass' => 'inject']));
786
787
        $admin->setSubClasses(['extended1' => 'NewsBundle\Entity\PostExtended1', 'extended2' => 'NewsBundle\Entity\PostExtended2']);
788
789
        $this->assertTrue($admin->hasActiveSubClass());
790
791
        $this->expectException(\LogicException::class);
792
793
        $admin->getActiveSubClass();
794
    }
795
796
    /**
797
     * @covers \Sonata\AdminBundle\Admin\AbstractAdmin::hasActiveSubClass
798
     */
799
    public function testOnlyOneSubclassNeededToBeActive(): void
800
    {
801
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'Sonata\NewsBundle\Controller\PostAdminController');
802
        $admin->setSubClasses(['extended1' => 'NewsBundle\Entity\PostExtended1']);
803
        $request = new Request(['subclass' => 'extended1']);
804
        $admin->setRequest($request);
805
        $this->assertTrue($admin->hasActiveSubClass());
806
    }
807
808
    /**
809
     * @group legacy
810
     * @expectedDeprecation Method "Sonata\AdminBundle\Admin\AbstractAdmin::addSubClass" is deprecated since sonata-project/admin-bundle 3.30 and will be removed in 4.0.
811
     */
812
    public function testAddSubClassIsDeprecated(): void
813
    {
814
        $admin = new PostAdmin(
815
            'sonata.post.admin.post',
816
            Post::class,
817
            'Sonata\NewsBundle\Controller\PostAdminController'
818
        );
819
        $admin->addSubClass('whatever');
820
    }
821
822
    /**
823
     * @group legacy
824
     */
825
    public function testGetPerPageOptions(): void
826
    {
827
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'Sonata\NewsBundle\Controller\PostAdminController');
828
829
        $perPageOptions = $admin->getPerPageOptions();
830
831
        foreach ($perPageOptions as $perPage) {
832
            $this->assertSame(0, $perPage % 4);
833
        }
834
835
        $admin->setPerPageOptions([500, 1000]);
0 ignored issues
show
Deprecated Code introduced by
The method Sonata\AdminBundle\Admin...in::setPerPageOptions() has been deprecated with message: since sonata-project/admin-bundle 3.67, to be removed in 4.0. Set custom per page options.

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...
836
        $this->assertSame([500, 1000], $admin->getPerPageOptions());
837
    }
838
839
    public function testGetLabelTranslatorStrategy(): void
840
    {
841
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'Sonata\NewsBundle\Controller\PostAdminController');
842
843
        $this->assertNull($admin->getLabelTranslatorStrategy());
844
845
        $labelTranslatorStrategy = $this->createMock(LabelTranslatorStrategyInterface::class);
846
        $admin->setLabelTranslatorStrategy($labelTranslatorStrategy);
847
        $this->assertSame($labelTranslatorStrategy, $admin->getLabelTranslatorStrategy());
848
    }
849
850
    public function testGetRouteBuilder(): void
851
    {
852
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'Sonata\NewsBundle\Controller\PostAdminController');
853
854
        $this->assertNull($admin->getRouteBuilder());
855
856
        $routeBuilder = $this->createMock(RouteBuilderInterface::class);
857
        $admin->setRouteBuilder($routeBuilder);
858
        $this->assertSame($routeBuilder, $admin->getRouteBuilder());
859
    }
860
861
    public function testGetMenuFactory(): void
862
    {
863
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'Sonata\NewsBundle\Controller\PostAdminController');
864
865
        $this->assertNull($admin->getMenuFactory());
866
867
        $menuFactory = $this->createMock(FactoryInterface::class);
868
        $admin->setMenuFactory($menuFactory);
869
        $this->assertSame($menuFactory, $admin->getMenuFactory());
870
    }
871
872
    public function testGetExtensions(): void
873
    {
874
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'Sonata\NewsBundle\Controller\PostAdminController');
875
876
        $this->assertSame([], $admin->getExtensions());
877
878
        $adminExtension1 = $this->createMock(AdminExtensionInterface::class);
879
        $adminExtension2 = $this->createMock(AdminExtensionInterface::class);
880
881
        $admin->addExtension($adminExtension1);
882
        $admin->addExtension($adminExtension2);
883
        $this->assertSame([$adminExtension1, $adminExtension2], $admin->getExtensions());
884
    }
885
886
    public function testGetFilterTheme(): void
887
    {
888
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'Sonata\NewsBundle\Controller\PostAdminController');
889
890
        $this->assertSame([], $admin->getFilterTheme());
891
892
        $admin->setFilterTheme(['FooTheme']);
893
        $this->assertSame(['FooTheme'], $admin->getFilterTheme());
894
    }
895
896
    public function testGetFormTheme(): void
897
    {
898
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'Sonata\NewsBundle\Controller\PostAdminController');
899
900
        $this->assertSame([], $admin->getFormTheme());
901
902
        $admin->setFormTheme(['FooTheme']);
903
904
        $this->assertSame(['FooTheme'], $admin->getFormTheme());
905
    }
906
907
    public function testGetValidator(): void
908
    {
909
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'Sonata\NewsBundle\Controller\PostAdminController');
910
911
        $this->assertNull($admin->getValidator());
912
913
        $validator = $this->getMockForAbstractClass(ValidatorInterface::class);
914
915
        $admin->setValidator($validator);
916
        $this->assertSame($validator, $admin->getValidator());
917
    }
918
919
    public function testGetSecurityHandler(): void
920
    {
921
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'Sonata\NewsBundle\Controller\PostAdminController');
922
923
        $this->assertNull($admin->getSecurityHandler());
924
925
        $securityHandler = $this->createMock(SecurityHandlerInterface::class);
926
        $admin->setSecurityHandler($securityHandler);
927
        $this->assertSame($securityHandler, $admin->getSecurityHandler());
928
    }
929
930
    public function testGetSecurityInformation(): void
931
    {
932
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'Sonata\NewsBundle\Controller\PostAdminController');
933
934
        $this->assertSame([], $admin->getSecurityInformation());
935
936
        $securityInformation = [
937
            'GUEST' => ['VIEW', 'LIST'],
938
            'STAFF' => ['EDIT', 'LIST', 'CREATE'],
939
        ];
940
941
        $admin->setSecurityInformation($securityInformation);
942
        $this->assertSame($securityInformation, $admin->getSecurityInformation());
943
    }
944
945
    public function testGetManagerType(): void
946
    {
947
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'Sonata\NewsBundle\Controller\PostAdminController');
948
949
        $this->assertNull($admin->getManagerType());
950
951
        $admin->setManagerType('foo_orm');
952
        $this->assertSame('foo_orm', $admin->getManagerType());
953
    }
954
955
    public function testGetModelManager(): void
956
    {
957
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'Sonata\NewsBundle\Controller\PostAdminController');
958
959
        $this->assertNull($admin->getModelManager());
960
961
        $modelManager = $this->createMock(ModelManagerInterface::class);
962
963
        $admin->setModelManager($modelManager);
964
        $this->assertSame($modelManager, $admin->getModelManager());
965
    }
966
967
    public function testGetBaseCodeRoute(): void
968
    {
969
        $postAdmin = new PostAdmin(
970
            'sonata.post.admin.post',
971
            'NewsBundle\Entity\Post',
972
            'Sonata\NewsBundle\Controller\PostAdminController'
973
        );
974
        $commentAdmin = new CommentAdmin(
975
            'sonata.post.admin.comment',
976
            'Application\Sonata\NewsBundle\Entity\Comment',
977
            'Sonata\NewsBundle\Controller\CommentAdminController'
978
        );
979
980
        $this->assertSame($postAdmin->getCode(), $postAdmin->getBaseCodeRoute());
981
982
        $postAdmin->addChild($commentAdmin, 'post');
983
984
        $this->assertSame(
985
            'sonata.post.admin.post|sonata.post.admin.comment',
986
            $commentAdmin->getBaseCodeRoute()
987
        );
988
    }
989
990
    public function testGetRouteGenerator(): void
991
    {
992
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'Sonata\NewsBundle\Controller\PostAdminController');
993
994
        $this->assertNull($admin->getRouteGenerator());
995
996
        $routeGenerator = $this->createMock(RouteGeneratorInterface::class);
997
998
        $admin->setRouteGenerator($routeGenerator);
999
        $this->assertSame($routeGenerator, $admin->getRouteGenerator());
1000
    }
1001
1002
    public function testGetConfigurationPool(): void
1003
    {
1004
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'Sonata\NewsBundle\Controller\PostAdminController');
1005
1006
        $this->assertNull($admin->getConfigurationPool());
1007
1008
        $pool = $this->getMockBuilder(Pool::class)
1009
            ->disableOriginalConstructor()
1010
            ->getMock();
1011
1012
        $admin->setConfigurationPool($pool);
1013
        $this->assertSame($pool, $admin->getConfigurationPool());
1014
    }
1015
1016
    public function testGetShowBuilder(): void
1017
    {
1018
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'Sonata\NewsBundle\Controller\PostAdminController');
1019
1020
        $this->assertNull($admin->getShowBuilder());
1021
1022
        $showBuilder = $this->createMock(ShowBuilderInterface::class);
1023
1024
        $admin->setShowBuilder($showBuilder);
1025
        $this->assertSame($showBuilder, $admin->getShowBuilder());
1026
    }
1027
1028
    public function testGetListBuilder(): void
1029
    {
1030
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'Sonata\NewsBundle\Controller\PostAdminController');
1031
1032
        $this->assertNull($admin->getListBuilder());
1033
1034
        $listBuilder = $this->createMock(ListBuilderInterface::class);
1035
1036
        $admin->setListBuilder($listBuilder);
1037
        $this->assertSame($listBuilder, $admin->getListBuilder());
1038
    }
1039
1040
    public function testGetDatagridBuilder(): void
1041
    {
1042
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'Sonata\NewsBundle\Controller\PostAdminController');
1043
1044
        $this->assertNull($admin->getDatagridBuilder());
1045
1046
        $datagridBuilder = $this->createMock(DatagridBuilderInterface::class);
1047
1048
        $admin->setDatagridBuilder($datagridBuilder);
1049
        $this->assertSame($datagridBuilder, $admin->getDatagridBuilder());
1050
    }
1051
1052
    public function testGetFormContractor(): void
1053
    {
1054
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'Sonata\NewsBundle\Controller\PostAdminController');
1055
1056
        $this->assertNull($admin->getFormContractor());
1057
1058
        $formContractor = $this->createMock(FormContractorInterface::class);
1059
1060
        $admin->setFormContractor($formContractor);
1061
        $this->assertSame($formContractor, $admin->getFormContractor());
1062
    }
1063
1064
    public function testGetRequest(): void
1065
    {
1066
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'Sonata\NewsBundle\Controller\PostAdminController');
1067
1068
        $this->assertFalse($admin->hasRequest());
1069
1070
        $request = new Request();
1071
1072
        $admin->setRequest($request);
1073
        $this->assertSame($request, $admin->getRequest());
1074
        $this->assertTrue($admin->hasRequest());
1075
    }
1076
1077
    public function testGetRequestWithException(): void
1078
    {
1079
        $this->expectException(\RuntimeException::class);
1080
        $this->expectExceptionMessage('The Request object has not been set');
1081
1082
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'Sonata\NewsBundle\Controller\PostAdminController');
1083
        $admin->getRequest();
1084
    }
1085
1086
    public function testGetTranslationDomain(): void
1087
    {
1088
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'Sonata\NewsBundle\Controller\PostAdminController');
1089
1090
        $this->assertSame('messages', $admin->getTranslationDomain());
1091
1092
        $admin->setTranslationDomain('foo');
1093
        $this->assertSame('foo', $admin->getTranslationDomain());
1094
    }
1095
1096
    /**
1097
     * @group legacy
1098
     */
1099
    public function testGetTranslator(): void
1100
    {
1101
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'Sonata\NewsBundle\Controller\PostAdminController');
1102
1103
        $this->assertNull($admin->getTranslator());
0 ignored issues
show
Deprecated Code introduced by
The method Sonata\AdminBundle\Admin...tAdmin::getTranslator() has been deprecated with message: since sonata-project/admin-bundle 3.9, to be removed with 4.0

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

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

Loading history...
1104
1105
        $translator = $this->createMock(TranslatorInterface::class);
1106
1107
        $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...
1108
        $this->assertSame($translator, $admin->getTranslator());
0 ignored issues
show
Deprecated Code introduced by
The method Sonata\AdminBundle\Admin...tAdmin::getTranslator() has been deprecated with message: since sonata-project/admin-bundle 3.9, to be removed with 4.0

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

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

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

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

Loading history...
1320
                return $admin === $adminIn && $attributes === ['LIST'];
1321
            });
1322
1323
        $admin->setSecurityHandler($securityHandler);
1324
1325
        $this->assertTrue($admin->showIn(AbstractAdmin::CONTEXT_DASHBOARD));
1326
        $this->assertTrue($admin->showIn(AbstractAdmin::CONTEXT_MENU));
1327
        $this->assertTrue($admin->showIn('foo'));
1328
    }
1329
1330
    public function testGetObjectIdentifier(): void
1331
    {
1332
        $admin = new PostAdmin('sonata.post.admin.post', 'Acme\NewsBundle\Entity\Post', 'Sonata\NewsBundle\Controller\PostAdminController');
1333
1334
        $this->assertSame('sonata.post.admin.post', $admin->getObjectIdentifier());
1335
    }
1336
1337
    /**
1338
     * @group legacy
1339
     */
1340
    public function testTrans(): void
1341
    {
1342
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'Sonata\NewsBundle\Controller\PostAdminController');
1343
        $admin->setTranslationDomain('fooMessageDomain');
1344
1345
        $translator = $this->createMock(TranslatorInterface::class);
1346
        $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...
1347
1348
        $translator->expects($this->once())
1349
            ->method('trans')
1350
            ->with($this->equalTo('foo'), $this->equalTo([]), $this->equalTo('fooMessageDomain'))
1351
            ->willReturn('fooTranslated');
1352
1353
        $this->assertSame('fooTranslated', $admin->trans('foo'));
1354
    }
1355
1356
    /**
1357
     * @group legacy
1358
     */
1359
    public function testTransWithMessageDomain(): void
1360
    {
1361
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'Sonata\NewsBundle\Controller\PostAdminController');
1362
1363
        $translator = $this->createMock(TranslatorInterface::class);
1364
        $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...
1365
1366
        $translator->expects($this->once())
1367
            ->method('trans')
1368
            ->with($this->equalTo('foo'), $this->equalTo(['name' => 'Andrej']), $this->equalTo('fooMessageDomain'))
1369
            ->willReturn('fooTranslated');
1370
1371
        $this->assertSame('fooTranslated', $admin->trans('foo', ['name' => 'Andrej'], 'fooMessageDomain'));
1372
    }
1373
1374
    /**
1375
     * @group legacy
1376
     */
1377
    public function testTransChoice(): void
1378
    {
1379
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'Sonata\NewsBundle\Controller\PostAdminController');
1380
        $admin->setTranslationDomain('fooMessageDomain');
1381
1382
        $translator = $this->createMock(TranslatorInterface::class);
1383
        $admin->setTranslator($translator);
0 ignored issues
show
Deprecated Code introduced by
The method Sonata\AdminBundle\Admin...tAdmin::setTranslator() has been deprecated with message: since 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...
1384
1385
        $translator->expects($this->once())
1386
            ->method('transChoice')
1387
            ->with($this->equalTo('foo'), $this->equalTo(2), $this->equalTo([]), $this->equalTo('fooMessageDomain'))
1388
            ->willReturn('fooTranslated');
1389
1390
        $this->assertSame('fooTranslated', $admin->transChoice('foo', 2));
0 ignored issues
show
Deprecated Code introduced by
The method Sonata\AdminBundle\Admin...actAdmin::transChoice() has been deprecated with message: since sonata-project/admin-bundle 3.9, to be removed with 4.0

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

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

Loading history...
1391
    }
1392
1393
    /**
1394
     * @group legacy
1395
     */
1396
    public function testTransChoiceWithMessageDomain(): void
1397
    {
1398
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'Sonata\NewsBundle\Controller\PostAdminController');
1399
1400
        $translator = $this->createMock(TranslatorInterface::class);
1401
        $admin->setTranslator($translator);
0 ignored issues
show
Deprecated Code introduced by
The method Sonata\AdminBundle\Admin...tAdmin::setTranslator() has been deprecated with message: since 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...
1402
1403
        $translator->expects($this->once())
1404
            ->method('transChoice')
1405
            ->with($this->equalTo('foo'), $this->equalTo(2), $this->equalTo(['name' => 'Andrej']), $this->equalTo('fooMessageDomain'))
1406
            ->willReturn('fooTranslated');
1407
1408
        $this->assertSame('fooTranslated', $admin->transChoice('foo', 2, ['name' => 'Andrej'], 'fooMessageDomain'));
0 ignored issues
show
Deprecated Code introduced by
The method Sonata\AdminBundle\Admin...actAdmin::transChoice() has been deprecated with message: since sonata-project/admin-bundle 3.9, to be removed with 4.0

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

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

Loading history...
1409
    }
1410
1411
    public function testSetFilterPersister(): void
1412
    {
1413
        $admin = new class('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'SonataNewsBundle\Controller\PostAdminController') extends PostAdmin {
1414
            public function persistFilters(): bool
1415
            {
1416
                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...
1417
            }
1418
        };
1419
1420
        $filterPersister = $this->createMock(FilterPersisterInterface::class);
1421
1422
        $admin->setFilterPersister($filterPersister);
1423
        $this->assertTrue($admin->persistFilters());
1424
    }
1425
1426
    public function testGetRootCode(): void
1427
    {
1428
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'Sonata\NewsBundle\Controller\PostAdminController');
1429
1430
        $this->assertSame('sonata.post.admin.post', $admin->getRootCode());
1431
1432
        $parentAdmin = new PostAdmin('sonata.post.admin.post.parent', 'NewsBundle\Entity\PostParent', 'Sonata\NewsBundle\Controller\PostParentAdminController');
1433
        $parentFieldDescription = $this->createMock(FieldDescriptionInterface::class);
1434
        $parentFieldDescription->expects($this->once())
1435
            ->method('getAdmin')
1436
            ->willReturn($parentAdmin);
1437
1438
        $this->assertFalse($admin->hasParentFieldDescription());
1439
        $admin->setParentFieldDescription($parentFieldDescription);
1440
        $this->assertSame($parentFieldDescription, $admin->getParentFieldDescription());
1441
        $this->assertSame('sonata.post.admin.post.parent', $admin->getRootCode());
1442
    }
1443
1444
    public function testGetRoot(): void
1445
    {
1446
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'Sonata\NewsBundle\Controller\PostAdminController');
1447
1448
        $this->assertSame($admin, $admin->getRoot());
1449
1450
        $parentAdmin = new PostAdmin('sonata.post.admin.post.parent', 'NewsBundle\Entity\PostParent', 'Sonata\NewsBundle\Controller\PostParentAdminController');
1451
        $parentFieldDescription = $this->createMock(FieldDescriptionInterface::class);
1452
        $parentFieldDescription->expects($this->once())
1453
            ->method('getAdmin')
1454
            ->willReturn($parentAdmin);
1455
1456
        $this->assertFalse($admin->hasParentFieldDescription());
1457
        $admin->setParentFieldDescription($parentFieldDescription);
1458
        $this->assertSame($parentFieldDescription, $admin->getParentFieldDescription());
1459
        $this->assertSame($parentAdmin, $admin->getRoot());
1460
    }
1461
1462
    public function testGetExportFields(): void
1463
    {
1464
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'Sonata\NewsBundle\Controller\PostAdminController');
1465
1466
        $modelManager = $this->createMock(ModelManagerInterface::class);
1467
        $modelManager->expects($this->once())
1468
            ->method('getExportFields')
1469
            ->with($this->equalTo('NewsBundle\Entity\Post'))
1470
            ->willReturn(['foo', 'bar']);
1471
1472
        $admin->setModelManager($modelManager);
1473
        $this->assertSame(['foo', 'bar'], $admin->getExportFields());
1474
    }
1475
1476
    public function testGetPersistentParametersWithNoExtension(): void
1477
    {
1478
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'Sonata\NewsBundle\Controller\PostAdminController');
1479
1480
        $this->assertEmpty($admin->getPersistentParameters());
1481
    }
1482
1483
    public function testGetPersistentParametersWithValidExtension(): void
1484
    {
1485
        $expected = [
1486
            'context' => 'foobar',
1487
        ];
1488
1489
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'Sonata\NewsBundle\Controller\PostAdminController');
1490
1491
        $extension = $this->createMock(AdminExtensionInterface::class);
1492
        $extension->expects($this->once())->method('getPersistentParameters')->willReturn($expected);
1493
1494
        $admin->addExtension($extension);
1495
1496
        $this->assertSame($expected, $admin->getPersistentParameters());
1497
    }
1498
1499
    public function testGetNewInstanceForChildAdminWithParentValue(): void
1500
    {
1501
        $post = new Post();
1502
1503
        $postAdmin = $this->getMockBuilder(PostAdmin::class)->disableOriginalConstructor()->getMock();
1504
        $postAdmin->method('getObject')->willReturn($post);
1505
1506
        $formBuilder = $this->createStub(FormBuilderInterface::class);
1507
        $formBuilder->method('getForm')->willReturn(null);
1508
1509
        $tag = new Tag();
1510
1511
        $modelManager = $this->createStub(ModelManagerInterface::class);
1512
        $modelManager->method('getModelInstance')->willReturn($tag);
1513
1514
        $tagAdmin = new TagAdmin('admin.tag', Tag::class, 'MyBundle\MyController');
1515
        $tagAdmin->setModelManager($modelManager);
1516
        $tagAdmin->setParent($postAdmin);
1517
1518
        $request = $this->createStub(Request::class);
1519
        $tagAdmin->setRequest($request);
1520
1521
        $configurationPool = $this->getMockBuilder(Pool::class)
1522
            ->disableOriginalConstructor()
1523
            ->getMock();
1524
1525
        $configurationPool->method('getPropertyAccessor')->willReturn(PropertyAccess::createPropertyAccessor());
1526
1527
        $tagAdmin->setConfigurationPool($configurationPool);
1528
1529
        $tag = $tagAdmin->getNewInstance();
1530
1531
        $this->assertSame($post, $tag->getPost());
1532
    }
1533
1534
    public function testGetNewInstanceForChildAdminWithCollectionParentValue(): void
1535
    {
1536
        $post = new Post();
1537
1538
        $postAdmin = $this->getMockBuilder(PostAdmin::class)->disableOriginalConstructor()->getMock();
1539
        $postAdmin->method('getObject')->willReturn($post);
1540
1541
        $formBuilder = $this->createStub(FormBuilderInterface::class);
1542
        $formBuilder->method('getForm')->willReturn(null);
1543
1544
        $postCategory = new PostCategory();
1545
1546
        $modelManager = $this->createStub(ModelManagerInterface::class);
1547
        $modelManager->method('getModelInstance')->willReturn($postCategory);
1548
1549
        $postCategoryAdmin = new PostCategoryAdmin('admin.post_category', PostCategoryAdmin::class, 'MyBundle\MyController');
1550
        $postCategoryAdmin->setModelManager($modelManager);
1551
        $postCategoryAdmin->setParent($postAdmin);
1552
1553
        $request = $this->createStub(Request::class);
1554
        $postCategoryAdmin->setRequest($request);
1555
1556
        $configurationPool = $this->getMockBuilder(Pool::class)
1557
            ->disableOriginalConstructor()
1558
            ->getMock();
1559
1560
        $configurationPool->method('getPropertyAccessor')->willReturn(PropertyAccess::createPropertyAccessor());
1561
1562
        $postCategoryAdmin->setConfigurationPool($configurationPool);
1563
1564
        $postCategory = $postCategoryAdmin->getNewInstance();
1565
1566
        $this->assertInstanceOf(Collection::class, $postCategory->getPosts());
1567
        $this->assertCount(1, $postCategory->getPosts());
1568
        $this->assertContains($post, $postCategory->getPosts());
1569
    }
1570
1571
    public function testGetNewInstanceForEmbededAdminWithParentValue(): void
1572
    {
1573
        $post = new Post();
1574
1575
        $postAdmin = $this->getMockBuilder(PostAdmin::class)->disableOriginalConstructor()->getMock();
1576
        $postAdmin->method('getObject')->willReturn($post);
1577
1578
        $formBuilder = $this->createStub(FormBuilderInterface::class);
1579
        $formBuilder->method('getForm')->willReturn(null);
1580
1581
        $parentField = $this->createStub(FieldDescriptionInterface::class);
1582
        $parentField->method('getAdmin')->willReturn($postAdmin);
1583
        $parentField->method('getParentAssociationMappings')->willReturn([]);
1584
        $parentField->method('getAssociationMapping')->willReturn(['fieldName' => 'tag', 'mappedBy' => 'post']);
1585
1586
        $tag = new Tag();
1587
1588
        $modelManager = $this->createStub(ModelManagerInterface::class);
1589
        $modelManager->method('getModelInstance')->willReturn($tag);
1590
1591
        $tagAdmin = new TagAdmin('admin.tag', Tag::class, 'MyBundle\MyController');
1592
        $tagAdmin->setModelManager($modelManager);
1593
        $tagAdmin->setParentFieldDescription($parentField);
1594
1595
        $request = $this->createStub(Request::class);
1596
        $tagAdmin->setRequest($request);
1597
1598
        $configurationPool = $this->getMockBuilder(Pool::class)
1599
            ->disableOriginalConstructor()
1600
            ->getMock();
1601
1602
        $configurationPool->method('getPropertyAccessor')->willReturn(PropertyAccess::createPropertyAccessor());
1603
1604
        $tagAdmin->setConfigurationPool($configurationPool);
1605
1606
        $tag = $tagAdmin->getNewInstance();
1607
1608
        $this->assertSame($post, $tag->getPost());
1609
    }
1610
1611
    public function testFormAddPostSubmitEventForPreValidation(): void
1612
    {
1613
        $modelAdmin = new ModelAdmin('sonata.post.admin.model', \stdClass::class, 'Sonata\FooBundle\Controller\ModelAdminController');
1614
        $object = new \stdClass();
1615
1616
        $labelTranslatorStrategy = $this->createMock(LabelTranslatorStrategyInterface::class);
1617
        $modelAdmin->setLabelTranslatorStrategy($labelTranslatorStrategy);
1618
1619
        $validator = $this->createMock(ValidatorInterface::class);
1620
        $validator
1621
                ->method('getMetadataFor')
1622
                ->willReturn($this->createMock(MemberMetadata::class));
1623
        $modelAdmin->setValidator($validator);
1624
1625
        $modelManager = $this->createMock(ModelManagerInterface::class);
1626
        $modelManager
1627
            ->method('getNewFieldDescriptionInstance')
1628
            ->willReturn(new FieldDescription());
1629
        $modelAdmin->setModelManager($modelManager);
1630
1631
        // a Admin class to test that preValidate is called
1632
        $testAdminPreValidate = $this->createMock(AbstractAdmin::class);
1633
        $testAdminPreValidate->expects($this->once())
1634
                ->method('preValidate')
1635
                ->with($this->identicalTo($object));
1636
1637
        $event = $this->createMock(FormEvent::class);
1638
        $event
1639
                ->method('getData')
1640
                ->willReturn($object);
1641
1642
        $formBuild = $this->createMock(FormBuilder::class);
1643
        $formBuild->expects($this->once())
1644
                ->method('addEventListener')
1645
                ->with(
1646
                    $this->identicalTo(FormEvents::POST_SUBMIT),
1647
                    $this->callback(static function ($callback) use ($testAdminPreValidate, $event): bool {
1648
                        if (\is_callable($callback)) {
1649
                            $closure = $callback->bindTo($testAdminPreValidate);
0 ignored issues
show
Bug introduced by
The method bindTo cannot be called on $callback (of type callable).

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

Loading history...
1650
                            $closure($event);
1651
1652
                            return true;
1653
                        }
1654
1655
                        return false;
1656
                    }),
1657
                    $this->greaterThan(0)
1658
                );
1659
1660
        $formContractor = $this->createMock(FormContractorInterface::class);
1661
        $formContractor
1662
                ->method('getDefaultOptions')
1663
                ->willReturn([]);
1664
        $formContractor
1665
                ->method('getFormBuilder')
1666
                ->willReturn($formBuild);
1667
1668
        $modelAdmin->setFormContractor($formContractor);
1669
        $modelAdmin->setSubject($object);
1670
        $modelAdmin->defineFormBuilder($formBuild);
1671
        $modelAdmin->getForm();
1672
    }
1673
1674
    public function testCanAddInlineValidationOnlyForGenericMetadata(): void
1675
    {
1676
        $modelAdmin = new ModelAdmin('sonata.post.admin.model', \stdClass::class, 'Sonata\FooBundle\Controller\ModelAdminController');
1677
        $object = new \stdClass();
1678
1679
        $labelTranslatorStrategy = $this->createStub(LabelTranslatorStrategyInterface::class);
1680
        $modelAdmin->setLabelTranslatorStrategy($labelTranslatorStrategy);
1681
1682
        $validator = $this->createStub(ValidatorInterface::class);
1683
        $metadata = $this->createStub(PropertyMetadataInterface::class);
1684
        $validator
1685
            ->method('getMetadataFor')
1686
            ->willReturn($metadata);
1687
        $modelAdmin->setValidator($validator);
1688
1689
        $modelManager = $this->createStub(ModelManagerInterface::class);
1690
        $modelManager
1691
            ->method('getNewFieldDescriptionInstance')
1692
            ->willReturn(new FieldDescription());
1693
        $modelAdmin->setModelManager($modelManager);
1694
1695
        $event = $this->createStub(FormEvent::class);
1696
        $event
1697
            ->method('getData')
1698
            ->willReturn($object);
1699
1700
        $formBuild = $this->createStub(FormBuilder::class);
1701
1702
        $formContractor = $this->createStub(FormContractorInterface::class);
1703
        $formContractor
1704
            ->method('getDefaultOptions')
1705
            ->willReturn([]);
1706
        $formContractor
1707
            ->method('getFormBuilder')
1708
            ->willReturn($formBuild);
1709
1710
        $modelAdmin->setFormContractor($formContractor);
1711
        $modelAdmin->setSubject($object);
1712
1713
        $this->expectException(\RuntimeException::class);
1714
        $this->expectExceptionMessage(
1715
            sprintf(
1716
                'Cannot add inline validator for stdClass because its metadata is an instance of %s instead of Symfony\Component\Validator\Mapping\GenericMetadata',
1717
                \get_class($metadata)
1718
            )
1719
        );
1720
1721
        $modelAdmin->defineFormBuilder($formBuild);
1722
    }
1723
1724
    public function testRemoveFieldFromFormGroup(): void
1725
    {
1726
        $formGroups = [
1727
            'foobar' => [
1728
                'fields' => [
1729
                    'foo' => 'foo',
1730
                    'bar' => 'bar',
1731
                ],
1732
            ],
1733
        ];
1734
1735
        $admin = new PostAdmin('sonata.post.admin.post', 'Application\Sonata\NewsBundle\Entity\Post', 'Sonata\NewsBundle\Controller\PostAdminController');
1736
        $admin->setFormGroups($formGroups);
1737
1738
        $admin->removeFieldFromFormGroup('foo');
1739
        $this->assertSame($admin->getFormGroups(), [
1740
            'foobar' => [
1741
                'fields' => [
1742
                    'bar' => 'bar',
1743
                ],
1744
            ],
1745
        ]);
1746
1747
        $admin->removeFieldFromFormGroup('bar');
1748
        $this->assertSame($admin->getFormGroups(), []);
1749
    }
1750
1751
    public function testGetFilterParameters(): void
1752
    {
1753
        $authorId = uniqid();
1754
1755
        $postAdmin = new PostAdmin('sonata.post.admin.post', 'Application\Sonata\NewsBundle\Entity\Post', 'Sonata\NewsBundle\Controller\PostAdminController');
1756
1757
        $commentAdmin = new CommentAdmin('sonata.post.admin.comment', 'Application\Sonata\NewsBundle\Entity\Comment', 'Sonata\NewsBundle\Controller\CommentAdminController');
1758
        $commentAdmin->setParentAssociationMapping('post.author');
1759
        $commentAdmin->setParent($postAdmin);
1760
1761
        $request = $this->createMock(Request::class);
1762
        $query = $this->createMock(ParameterBag::class);
1763
        $query
1764
            ->method('get')
1765
            ->willReturn([
1766
                'filter' => [
1767
                    '_page' => '1',
1768
                    '_per_page' => '32',
1769
                ],
1770
            ]);
1771
1772
        $request->query = $query;
1773
        $request
1774
            ->method('get')
1775
            ->willReturn($authorId);
1776
1777
        $commentAdmin->setRequest($request);
1778
1779
        $modelManager = $this->createMock(ModelManagerInterface::class);
1780
        $modelManager
1781
            ->method('getDefaultSortValues')
1782
            ->willReturn([]);
1783
1784
        $commentAdmin->setModelManager($modelManager);
1785
1786
        $parameters = $commentAdmin->getFilterParameters();
1787
1788
        $this->assertTrue(isset($parameters['post__author']));
1789
        $this->assertSame(['value' => $authorId], $parameters['post__author']);
1790
    }
1791
1792
    public function testGetFilterFieldDescription(): void
1793
    {
1794
        $modelAdmin = new ModelAdmin('sonata.post.admin.model', 'Application\Sonata\FooBundle\Entity\Model', 'Sonata\FooBundle\Controller\ModelAdminController');
1795
1796
        $fooFieldDescription = new FieldDescription();
1797
        $barFieldDescription = new FieldDescription();
1798
        $bazFieldDescription = new FieldDescription();
1799
1800
        $modelManager = $this->createMock(ModelManagerInterface::class);
1801
        $modelManager->expects($this->exactly(3))
1802
            ->method('getNewFieldDescriptionInstance')
1803
            ->willReturnCallback(static function ($adminClass, string $name, $filterOptions) use ($fooFieldDescription, $barFieldDescription, $bazFieldDescription) {
0 ignored issues
show
Unused Code introduced by
The parameter $filterOptions is not used and could be removed.

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

Loading history...
1804
                switch ($name) {
1805
                    case 'foo':
1806
                        $fieldDescription = $fooFieldDescription;
1807
1808
                        break;
1809
1810
                    case 'bar':
1811
                        $fieldDescription = $barFieldDescription;
1812
1813
                        break;
1814
1815
                    case 'baz':
1816
                        $fieldDescription = $bazFieldDescription;
1817
1818
                        break;
1819
1820
                    default:
1821
                        throw new \RuntimeException(sprintf('Unknown filter name "%s"', $name));
1822
                        break;
0 ignored issues
show
Unused Code introduced by
break; does not seem to be reachable.

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

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

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

    return false;
}

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

Loading history...
1823
                }
1824
1825
                $fieldDescription->setName($name);
1826
1827
                return $fieldDescription;
1828
            });
1829
1830
        $modelAdmin->setModelManager($modelManager);
1831
1832
        $pager = $this->createMock(PagerInterface::class);
1833
1834
        $datagrid = $this->createMock(DatagridInterface::class);
1835
        $datagrid->expects($this->once())
1836
            ->method('getPager')
1837
            ->willReturn($pager);
1838
1839
        $datagridBuilder = $this->createMock(DatagridBuilderInterface::class);
1840
        $datagridBuilder->expects($this->once())
1841
            ->method('getBaseDatagrid')
1842
            ->with($this->identicalTo($modelAdmin), [])
1843
            ->willReturn($datagrid);
1844
1845
        $datagridBuilder->expects($this->exactly(3))
1846
            ->method('addFilter')
1847
            ->willReturnCallback(static function ($datagrid, $type, $fieldDescription, AdminInterface $admin): void {
1848
                $admin->addFilterFieldDescription($fieldDescription->getName(), $fieldDescription);
1849
                $fieldDescription->mergeOption('field_options', ['required' => false]);
1850
            });
1851
1852
        $modelAdmin->setDatagridBuilder($datagridBuilder);
1853
1854
        $this->assertSame(['foo' => $fooFieldDescription, 'bar' => $barFieldDescription, 'baz' => $bazFieldDescription], $modelAdmin->getFilterFieldDescriptions());
1855
        $this->assertFalse($modelAdmin->hasFilterFieldDescription('fooBar'));
1856
        $this->assertTrue($modelAdmin->hasFilterFieldDescription('foo'));
1857
        $this->assertTrue($modelAdmin->hasFilterFieldDescription('bar'));
1858
        $this->assertTrue($modelAdmin->hasFilterFieldDescription('baz'));
1859
        $this->assertSame($fooFieldDescription, $modelAdmin->getFilterFieldDescription('foo'));
1860
        $this->assertSame($barFieldDescription, $modelAdmin->getFilterFieldDescription('bar'));
1861
        $this->assertSame($bazFieldDescription, $modelAdmin->getFilterFieldDescription('baz'));
1862
    }
1863
1864
    public function testGetSubjectNoRequest(): void
1865
    {
1866
        $modelManager = $this->createMock(ModelManagerInterface::class);
1867
        $modelManager
1868
            ->expects($this->never())
1869
            ->method('find');
1870
1871
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'Sonata\NewsBundle\Controller\PostAdminController');
1872
        $admin->setModelManager($modelManager);
1873
1874
        $this->assertFalse($admin->hasSubject());
1875
    }
1876
1877
    public function testGetSideMenu(): void
1878
    {
1879
        $item = $this->createMock(ItemInterface::class);
1880
        $item
1881
            ->expects($this->once())
1882
            ->method('setChildrenAttribute')
1883
            ->with('class', 'nav navbar-nav');
1884
        $item
1885
            ->expects($this->once())
1886
            ->method('setExtra')
1887
            ->with('translation_domain', 'foo_bar_baz');
1888
1889
        $menuFactory = $this->createMock(FactoryInterface::class);
1890
        $menuFactory
1891
            ->expects($this->once())
1892
            ->method('createItem')
1893
            ->willReturn($item);
1894
1895
        $modelAdmin = new ModelAdmin('sonata.post.admin.model', 'Application\Sonata\FooBundle\Entity\Model', 'Sonata\FooBundle\Controller\ModelAdminController');
1896
        $modelAdmin->setMenuFactory($menuFactory);
1897
        $modelAdmin->setTranslationDomain('foo_bar_baz');
1898
1899
        $modelAdmin->getSideMenu('foo');
1900
    }
1901
1902
    /**
1903
     * @return array
1904
     */
1905
    public function provideGetSubject()
1906
    {
1907
        return [
1908
            [23],
1909
            ['azerty'],
1910
            ['4f69bbb5f14a13347f000092'],
1911
            ['0779ca8d-e2be-11e4-ac58-0242ac11000b'],
1912
            [sprintf('123%smy_type', AdapterInterface::ID_SEPARATOR)], // composite keys are supported
1913
        ];
1914
    }
1915
1916
    /**
1917
     * @dataProvider provideGetSubject
1918
     */
1919
    public function testGetSubjectFailed($id): void
1920
    {
1921
        $modelManager = $this->createMock(ModelManagerInterface::class);
1922
        $modelManager
1923
            ->expects($this->once())
1924
            ->method('find')
1925
            ->with('NewsBundle\Entity\Post', $id)
1926
            ->willReturn(null); // entity not found
1927
1928
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'Sonata\NewsBundle\Controller\PostAdminController');
1929
        $admin->setModelManager($modelManager);
1930
1931
        $admin->setRequest(new Request(['id' => $id]));
1932
        $this->assertFalse($admin->hasSubject());
1933
    }
1934
1935
    /**
1936
     * @dataProvider provideGetSubject
1937
     */
1938
    public function testGetSubject($id): void
1939
    {
1940
        $model = new Post();
1941
1942
        $modelManager = $this->createMock(ModelManagerInterface::class);
1943
        $modelManager
1944
            ->expects($this->once())
1945
            ->method('find')
1946
            ->with('NewsBundle\Entity\Post', $id)
1947
            ->willReturn($model);
1948
1949
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'Sonata\NewsBundle\Controller\PostAdminController');
1950
        $admin->setModelManager($modelManager);
1951
1952
        $admin->setRequest(new Request(['id' => $id]));
1953
        $this->assertTrue($admin->hasSubject());
1954
        $this->assertSame($model, $admin->getSubject());
1955
        $this->assertSame($model, $admin->getSubject()); // model manager must be used only once
1956
    }
1957
1958
    public function testGetSubjectWithParentDescription(): void
1959
    {
1960
        $adminId = 1;
1961
1962
        $comment = new Comment();
1963
1964
        $modelManager = $this->createMock(ModelManagerInterface::class);
1965
        $modelManager
1966
            ->method('find')
1967
            ->with('NewsBundle\Entity\Comment', $adminId)
1968
            ->willReturn($comment);
1969
1970
        $request = new Request(['id' => $adminId]);
1971
1972
        $postAdmin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'Sonata\NewsBundle\Controller\PostAdminController');
1973
        $postAdmin->setRequest($request);
1974
1975
        $commentAdmin = new CommentAdmin('sonata.post.admin.comment', 'NewsBundle\Entity\Comment', 'Sonata\NewsBundle\Controller\CommentAdminController');
1976
        $commentAdmin->setRequest($request);
1977
        $commentAdmin->setModelManager($modelManager);
1978
1979
        $this->assertTrue($commentAdmin->hasSubject());
1980
        $this->assertSame($comment, $commentAdmin->getSubject());
1981
1982
        $commentAdmin->setSubject(null);
1983
        $commentAdmin->setParentFieldDescription(new FieldDescription());
1984
1985
        $this->assertFalse($commentAdmin->hasSubject());
1986
    }
1987
1988
    /**
1989
     * @covers \Sonata\AdminBundle\Admin\AbstractAdmin::configureActionButtons
1990
     */
1991
    public function testGetActionButtonsList(): void
1992
    {
1993
        $expected = [
1994
            'create' => [
1995
                'template' => 'Foo.html.twig',
1996
            ],
1997
        ];
1998
1999
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'Sonata\NewsBundle\Controller\PostAdminController');
2000
2001
        $templateRegistry = $this->prophesize(MutableTemplateRegistryInterface::class);
2002
        $templateRegistry->getTemplate('button_create')->willReturn('Foo.html.twig');
2003
2004
        $admin->setTemplateRegistry($templateRegistry->reveal());
2005
2006
        $securityHandler = $this->createMock(SecurityHandlerInterface::class);
2007
        $securityHandler
2008
            ->expects($this->once())
2009
            ->method('isGranted')
2010
            ->with($admin, 'CREATE', $admin)
2011
            ->willReturn(true);
2012
        $admin->setSecurityHandler($securityHandler);
2013
2014
        $routeGenerator = $this->createMock(RouteGeneratorInterface::class);
2015
        $routeGenerator
2016
            ->expects($this->once())
2017
            ->method('hasAdminRoute')
2018
            ->with($admin, 'create')
2019
            ->willReturn(true);
2020
        $admin->setRouteGenerator($routeGenerator);
2021
2022
        $this->assertSame($expected, $admin->getActionButtons('list', null));
2023
    }
2024
2025
    /**
2026
     * @covers \Sonata\AdminBundle\Admin\AbstractAdmin::configureActionButtons
2027
     */
2028
    public function testGetActionButtonsListCreateDisabled(): void
2029
    {
2030
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'Sonata\NewsBundle\Controller\PostAdminController');
2031
2032
        $securityHandler = $this->createMock(SecurityHandlerInterface::class);
2033
        $securityHandler
2034
            ->expects($this->once())
2035
            ->method('isGranted')
2036
            ->with($admin, 'CREATE', $admin)
2037
            ->willReturn(false);
2038
        $admin->setSecurityHandler($securityHandler);
2039
2040
        $this->assertSame([], $admin->getActionButtons('list', null));
2041
    }
2042
2043
    /**
2044
     * @covers \Sonata\AdminBundle\Admin\AbstractAdmin::configureBatchActions
2045
     */
2046
    public function testGetBatchActions(): void
2047
    {
2048
        $expected = [
2049
            'delete' => [
2050
                'label' => 'action_delete',
2051
                'translation_domain' => 'SonataAdminBundle',
2052
                'ask_confirmation' => true, // by default always true
2053
            ],
2054
            'foo' => [
2055
                'label' => 'action_foo',
2056
                'translation_domain' => 'SonataAdminBundle',
2057
            ],
2058
            'bar' => [
2059
                'label' => 'batch.label_bar',
2060
                'translation_domain' => 'SonataAdminBundle',
2061
            ],
2062
            'baz' => [
2063
                'label' => 'action_baz',
2064
                'translation_domain' => 'AcmeAdminBundle',
2065
            ],
2066
        ];
2067
2068
        $pathInfo = new PathInfoBuilder($this->createMock(AuditManagerInterface::class));
2069
2070
        $labelTranslatorStrategy = $this->createMock(LabelTranslatorStrategyInterface::class);
2071
        $labelTranslatorStrategy
2072
            ->method('getLabel')
2073
            ->willReturnCallback(static function (string $label, string $context = '', string $type = ''): string {
2074
                return sprintf('%s.%s_%s', $context, $type, $label);
2075
            });
2076
2077
        $admin = new PostAdmin('sonata.post.admin.model', 'Application\Sonata\FooBundle\Entity\Model', 'Sonata\FooBundle\Controller\ModelAdminController');
2078
        $admin->setRouteBuilder($pathInfo);
2079
        $admin->setTranslationDomain('SonataAdminBundle');
2080
        $admin->setLabelTranslatorStrategy($labelTranslatorStrategy);
2081
2082
        $routeGenerator = $this->createMock(RouteGeneratorInterface::class);
2083
        $routeGenerator
2084
            ->expects($this->once())
2085
            ->method('hasAdminRoute')
2086
            ->with($admin, 'delete')
2087
            ->willReturn(true);
2088
        $admin->setRouteGenerator($routeGenerator);
2089
2090
        $securityHandler = $this->createMock(SecurityHandlerInterface::class);
2091
        $securityHandler
2092
            ->method('isGranted')
2093
            ->willReturnCallback(static function (AdminInterface $adminIn, string $attributes, $object = null) use ($admin): bool {
0 ignored issues
show
Unused Code introduced by
The parameter $object is not used and could be removed.

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

Loading history...
2094
                return $admin === $adminIn && 'DELETE' === $attributes;
2095
            });
2096
        $admin->setSecurityHandler($securityHandler);
2097
2098
        $this->assertSame($expected, $admin->getBatchActions());
2099
    }
2100
2101
    /**
2102
     * @covers \Sonata\AdminBundle\Admin\AbstractAdmin::showMosaicButton
2103
     */
2104
    public function testShowMosaicButton(): void
2105
    {
2106
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'Sonata\NewsBundle\Controller\PostAdminController');
2107
        $listModes = $admin->getListModes();
2108
2109
        $admin->showMosaicButton(true);
2110
2111
        $this->assertSame($listModes, $admin->getListModes());
2112
    }
2113
2114
    /**
2115
     * @covers \Sonata\AdminBundle\Admin\AbstractAdmin::showMosaicButton
2116
     */
2117
    public function testShowMosaicButtonHideMosaic(): void
2118
    {
2119
        $admin = new PostAdmin('sonata.post.admin.post', 'NewsBundle\Entity\Post', 'Sonata\NewsBundle\Controller\PostAdminController');
2120
        $listModes = $admin->getListModes();
2121
        $expected['list'] = $listModes['list'];
0 ignored issues
show
Coding Style Comprehensibility introduced by
$expected was never initialized. Although not strictly required by PHP, it is generally a good practice to add $expected = array(); before regardless.

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

Let’s take a look at an example:

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

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

    // do something with $myArray
}

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

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

Loading history...
2122
2123
        $admin->showMosaicButton(false);
2124
2125
        $this->assertSame($expected, $admin->getListModes());
2126
    }
2127
2128
    /**
2129
     * @covers \Sonata\AdminBundle\Admin\AbstractAdmin::getDashboardActions
2130
     * @dataProvider provideGetBaseRouteName
2131
     */
2132
    public function testDefaultDashboardActionsArePresent(string $objFqn, string $expected): void
2133
    {
2134
        $pathInfo = new PathInfoBuilder($this->createMock(AuditManagerInterface::class));
2135
        $routerMock = $this->createMock(RouterInterface::class);
2136
2137
        $routerMock->method('generate')->willReturn('/admin/post');
2138
2139
        $routeGenerator = new DefaultRouteGenerator(
2140
            $routerMock,
2141
            new RoutesCache($this->cacheTempFolder, true)
2142
        );
2143
2144
        $admin = new PostAdmin('sonata.post.admin.post', $objFqn, 'Sonata\NewsBundle\Controller\PostAdminController');
2145
        $admin->setRouteBuilder($pathInfo);
2146
        $admin->setRouteGenerator($routeGenerator);
2147
        $admin->initialize();
2148
2149
        $templateRegistry = $this->prophesize(MutableTemplateRegistryInterface::class);
2150
        $templateRegistry->getTemplate('action_create')->willReturn('Foo.html.twig');
2151
2152
        $admin->setTemplateRegistry($templateRegistry->reveal());
2153
2154
        $securityHandler = $this->createMock(SecurityHandlerInterface::class);
2155
        $securityHandler
2156
            ->method('isGranted')
2157
            ->willReturnCallback(static function (AdminInterface $adminIn, string $attributes, $object = null) use ($admin): bool {
0 ignored issues
show
Unused Code introduced by
The parameter $object is not used and could be removed.

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

Loading history...
2158
                return $admin === $adminIn && ('CREATE' === $attributes || 'LIST' === $attributes);
2159
            });
2160
2161
        $admin->setSecurityHandler($securityHandler);
2162
2163
        $this->assertArrayHasKey('list', $admin->getDashboardActions());
2164
        $this->assertArrayHasKey('create', $admin->getDashboardActions());
2165
    }
2166
2167
    public function testDefaultFilters(): void
2168
    {
2169
        $admin = new FilteredAdmin('sonata.post.admin.model', 'Application\Sonata\FooBundle\Entity\Model', 'Sonata\FooBundle\Controller\ModelAdminController');
2170
2171
        $subjectId = uniqid();
2172
2173
        $request = $this->createMock(Request::class);
2174
        $query = $this->createMock(ParameterBag::class);
2175
        $query
2176
            ->method('get')
2177
            ->with($this->equalTo('filter'))
2178
            ->willReturn([
2179
                'a' => [
2180
                    'value' => 'b',
2181
                ],
2182
                'foo' => [
2183
                    'type' => '1',
2184
                    'value' => 'bar',
2185
                ],
2186
                'baz' => [
2187
                    'type' => '5',
2188
                    'value' => 'test',
2189
                ],
2190
            ]);
2191
        $request->query = $query;
2192
2193
        $request
2194
            ->method('get')
2195
            ->willReturn($subjectId);
2196
2197
        $admin->setRequest($request);
2198
2199
        $modelManager = $this->createMock(ModelManagerInterface::class);
2200
        $modelManager
2201
            ->method('getDefaultSortValues')
2202
            ->willReturn([]);
2203
2204
        $admin->setModelManager($modelManager);
2205
2206
        $this->assertSame([
2207
            '_page' => 1,
2208
            '_per_page' => 32,
2209
            'foo' => [
2210
                'type' => '1',
2211
                'value' => 'bar',
2212
            ],
2213
            'baz' => [
2214
                'type' => '5',
2215
                'value' => 'test',
2216
            ],
2217
            'a' => [
2218
                'value' => 'b',
2219
            ],
2220
        ], $admin->getFilterParameters());
2221
2222
        $this->assertTrue($admin->isDefaultFilter('foo'));
2223
        $this->assertFalse($admin->isDefaultFilter('bar'));
2224
        $this->assertFalse($admin->isDefaultFilter('a'));
2225
    }
2226
2227
    /**
2228
     * NEXT_MAJOR: remove this method.
2229
     *
2230
     * @group legacy
2231
     */
2232
    public function testCreateQueryLegacyCallWorks(): void
2233
    {
2234
        $admin = $this->getMockForAbstractClass(AbstractAdmin::class, [
2235
            'admin.my_code', 'My\Class', 'MyBundle\ClassAdminController',
2236
        ]);
2237
        $query = $this->createMock(ProxyQueryInterface::class);
2238
        $modelManager = $this->createMock(ModelManagerInterface::class);
2239
        $modelManager->expects($this->once())
2240
            ->method('createQuery')
2241
            ->with('My\Class')
2242
            ->willReturn($query);
2243
2244
        $admin->setModelManager($modelManager);
2245
        $this->assertSame($query, $admin->createQuery('list'));
2246
    }
2247
2248
    public function testGetDataSourceIterator(): void
2249
    {
2250
        $datagrid = $this->createMock(DatagridInterface::class);
2251
        $datagrid->method('buildPager');
2252
2253
        $modelManager = $this->createMock(ModelManagerInterface::class);
2254
        $modelManager->method('getExportFields')->willReturn([
2255
            'field',
2256
            'foo',
2257
            'bar',
2258
        ]);
2259
        $modelManager->expects($this->once())->method('getDataSourceIterator')
2260
            ->with($this->equalTo($datagrid), $this->equalTo([
2261
                'Feld' => 'field',
2262
                1 => 'foo',
2263
                2 => 'bar',
2264
            ]))
2265
            ->willReturn(new ArraySourceIterator([]));
2266
2267
        $admin = $this->getMockBuilder(AbstractAdmin::class)
2268
            ->disableOriginalConstructor()
2269
            ->setMethods(['getClass', 'getDatagrid', 'getTranslationLabel', 'trans'])
2270
            ->getMockForAbstractClass();
2271
        $admin->method('getClass')->willReturn('App\Admin\MyAdmin');
2272
        $admin->method('getDatagrid')->willReturn($datagrid);
2273
        $admin->setModelManager($modelManager);
2274
2275
        $admin
2276
            ->method('getTranslationLabel')
2277
            ->willReturnCallback(static function (string $label, string $context = '', string $type = ''): string {
2278
                return sprintf('%s.%s_%s', $context, $type, $label);
2279
            });
2280
        $admin
2281
            ->method('trans')
2282
            ->willReturnCallback(static function (string $label): string {
2283
                if ('export.label_field' === $label) {
2284
                    return 'Feld';
2285
                }
2286
2287
                return $label;
2288
            });
2289
2290
        $admin->getDataSourceIterator();
2291
    }
2292
2293
    public function testCircularChildAdmin(): void
2294
    {
2295
        $this->expectException(\RuntimeException::class);
2296
        $this->expectExceptionMessage(
2297
            'Circular reference detected! The child admin `sonata.post.admin.post` is already in the parent tree of the `sonata.post.admin.comment` admin.'
2298
        );
2299
2300
        $postAdmin = new PostAdmin(
2301
            'sonata.post.admin.post',
2302
            'Application\Sonata\NewsBundle\Entity\Post',
2303
            'Sonata\NewsBundle\Controller\PostAdminController'
2304
        );
2305
        $commentAdmin = new CommentAdmin(
2306
            'sonata.post.admin.comment',
2307
            'Application\Sonata\NewsBundle\Entity\Comment',
2308
            'Sonata\NewsBundle\Controller\CommentAdminController'
2309
        );
2310
        $postAdmin->addChild($commentAdmin, 'post');
2311
        $commentAdmin->addChild($postAdmin, 'comment');
2312
    }
2313
2314
    public function testCircularChildAdminTripleLevel(): void
2315
    {
2316
        $this->expectException(\RuntimeException::class);
2317
        $this->expectExceptionMessage(
2318
            'Circular reference detected! The child admin `sonata.post.admin.post` is already in the parent tree of the `sonata.post.admin.comment_vote` admin.'
2319
        );
2320
2321
        $postAdmin = new PostAdmin(
2322
            'sonata.post.admin.post',
2323
            'Application\Sonata\NewsBundle\Entity\Post',
2324
            'Sonata\NewsBundle\Controller\PostAdminController'
2325
        );
2326
        $commentAdmin = new CommentAdmin(
2327
            'sonata.post.admin.comment',
2328
            'Application\Sonata\NewsBundle\Entity\Comment',
2329
            'Sonata\NewsBundle\Controller\CommentAdminController'
2330
        );
2331
        $commentVoteAdmin = new CommentVoteAdmin(
2332
            'sonata.post.admin.comment_vote',
2333
            'Application\Sonata\NewsBundle\Entity\CommentVote',
2334
            'Sonata\NewsBundle\Controller\CommentVoteAdminController'
2335
        );
2336
        $postAdmin->addChild($commentAdmin, 'post');
2337
        $commentAdmin->addChild($commentVoteAdmin, 'comment');
2338
        $commentVoteAdmin->addChild($postAdmin, 'post');
2339
    }
2340
2341
    public function testCircularChildAdminWithItself(): 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.post` 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
        $postAdmin->addChild($postAdmin);
2354
    }
2355
2356
    public function testGetRootAncestor(): void
2357
    {
2358
        $postAdmin = new PostAdmin(
2359
            'sonata.post.admin.post',
2360
            'Application\Sonata\NewsBundle\Entity\Post',
2361
            'Sonata\NewsBundle\Controller\PostAdminController'
2362
        );
2363
        $commentAdmin = new CommentAdmin(
2364
            'sonata.post.admin.comment',
2365
            'Application\Sonata\NewsBundle\Entity\Comment',
2366
            'Sonata\NewsBundle\Controller\CommentAdminController'
2367
        );
2368
        $commentVoteAdmin = new CommentVoteAdmin(
2369
            'sonata.post.admin.comment_vote',
2370
            'Application\Sonata\NewsBundle\Entity\CommentVote',
2371
            'Sonata\NewsBundle\Controller\CommentVoteAdminController'
2372
        );
2373
2374
        $this->assertSame($postAdmin, $postAdmin->getRootAncestor());
2375
        $this->assertSame($commentAdmin, $commentAdmin->getRootAncestor());
2376
        $this->assertSame($commentVoteAdmin, $commentVoteAdmin->getRootAncestor());
2377
2378
        $postAdmin->addChild($commentAdmin, 'post');
2379
2380
        $this->assertSame($postAdmin, $postAdmin->getRootAncestor());
2381
        $this->assertSame($postAdmin, $commentAdmin->getRootAncestor());
2382
        $this->assertSame($commentVoteAdmin, $commentVoteAdmin->getRootAncestor());
2383
2384
        $commentAdmin->addChild($commentVoteAdmin, 'comment');
2385
2386
        $this->assertSame($postAdmin, $postAdmin->getRootAncestor());
2387
        $this->assertSame($postAdmin, $commentAdmin->getRootAncestor());
2388
        $this->assertSame($postAdmin, $commentVoteAdmin->getRootAncestor());
2389
    }
2390
2391
    public function testGetChildDepth(): void
2392
    {
2393
        $postAdmin = new PostAdmin(
2394
            'sonata.post.admin.post',
2395
            'Application\Sonata\NewsBundle\Entity\Post',
2396
            'Sonata\NewsBundle\Controller\PostAdminController'
2397
        );
2398
        $commentAdmin = new CommentAdmin(
2399
            'sonata.post.admin.comment',
2400
            'Application\Sonata\NewsBundle\Entity\Comment',
2401
            'Sonata\NewsBundle\Controller\CommentAdminController'
2402
        );
2403
        $commentVoteAdmin = new CommentVoteAdmin(
2404
            'sonata.post.admin.comment_vote',
2405
            'Application\Sonata\NewsBundle\Entity\CommentVote',
2406
            'Sonata\NewsBundle\Controller\CommentVoteAdminController'
2407
        );
2408
2409
        $this->assertSame(0, $postAdmin->getChildDepth());
2410
        $this->assertSame(0, $commentAdmin->getChildDepth());
2411
        $this->assertSame(0, $commentVoteAdmin->getChildDepth());
2412
2413
        $postAdmin->addChild($commentAdmin, 'post');
2414
2415
        $this->assertSame(0, $postAdmin->getChildDepth());
2416
        $this->assertSame(1, $commentAdmin->getChildDepth());
2417
        $this->assertSame(0, $commentVoteAdmin->getChildDepth());
2418
2419
        $commentAdmin->addChild($commentVoteAdmin, 'comment');
2420
2421
        $this->assertSame(0, $postAdmin->getChildDepth());
2422
        $this->assertSame(1, $commentAdmin->getChildDepth());
2423
        $this->assertSame(2, $commentVoteAdmin->getChildDepth());
2424
    }
2425
2426
    public function testGetCurrentLeafChildAdmin(): void
2427
    {
2428
        $postAdmin = new PostAdmin(
2429
            'sonata.post.admin.post',
2430
            'Application\Sonata\NewsBundle\Entity\Post',
2431
            'Sonata\NewsBundle\Controller\PostAdminController'
2432
        );
2433
        $commentAdmin = new CommentAdmin(
2434
            'sonata.post.admin.comment',
2435
            'Application\Sonata\NewsBundle\Entity\Comment',
2436
            'Sonata\NewsBundle\Controller\CommentAdminController'
2437
        );
2438
        $commentVoteAdmin = new CommentVoteAdmin(
2439
            'sonata.post.admin.comment_vote',
2440
            'Application\Sonata\NewsBundle\Entity\CommentVote',
2441
            'Sonata\NewsBundle\Controller\CommentVoteAdminController'
2442
        );
2443
2444
        $postAdmin->addChild($commentAdmin, 'post');
2445
        $commentAdmin->addChild($commentVoteAdmin, 'comment');
2446
2447
        $this->assertNull($postAdmin->getCurrentLeafChildAdmin());
2448
        $this->assertNull($commentAdmin->getCurrentLeafChildAdmin());
2449
        $this->assertNull($commentVoteAdmin->getCurrentLeafChildAdmin());
2450
2451
        $commentAdmin->setCurrentChild(true);
2452
2453
        $this->assertSame($commentAdmin, $postAdmin->getCurrentLeafChildAdmin());
2454
        $this->assertNull($commentAdmin->getCurrentLeafChildAdmin());
2455
        $this->assertNull($commentVoteAdmin->getCurrentLeafChildAdmin());
2456
2457
        $commentVoteAdmin->setCurrentChild(true);
2458
2459
        $this->assertSame($commentVoteAdmin, $postAdmin->getCurrentLeafChildAdmin());
2460
        $this->assertSame($commentVoteAdmin, $commentAdmin->getCurrentLeafChildAdmin());
2461
        $this->assertNull($commentVoteAdmin->getCurrentLeafChildAdmin());
2462
    }
2463
2464
    public function testAdminAvoidInifiniteLoop(): void
2465
    {
2466
        $this->expectNotToPerformAssertions();
2467
2468
        $formFactory = new FormFactory(new FormRegistry([], new ResolvedFormTypeFactory()));
2469
2470
        $admin = new AvoidInfiniteLoopAdmin('code', \stdClass::class, null);
2471
        $admin->setSubject(new \stdClass());
2472
2473
        $admin->setFormContractor(new FormContractor($formFactory));
2474
2475
        $admin->setShowBuilder(new ShowBuilder());
2476
2477
        $admin->setListBuilder(new ListBuilder());
2478
2479
        $pager = $this->createStub(PagerInterface::class);
2480
        $admin->setDatagridBuilder(new DatagridBuilder($formFactory, $pager));
2481
2482
        $validator = $this->createMock(ValidatorInterface::class);
2483
        $validator->method('getMetadataFor')->willReturn($this->createStub(MemberMetadata::class));
2484
        $admin->setValidator($validator);
2485
2486
        $routeGenerator = $this->createStub(RouteGeneratorInterface::class);
2487
        $routeGenerator->method('hasAdminRoute')->willReturn(false);
2488
        $admin->setRouteGenerator($routeGenerator);
2489
2490
        $admin->getForm();
2491
        $admin->getShow();
2492
        $admin->getList();
2493
        $admin->getDatagrid();
2494
    }
2495
2496
    /**
2497
     * NEXT_MAJOR: Remove this test and its data provider.
2498
     *
2499
     * @group legacy
2500
     *
2501
     * @dataProvider getDeprecatedAbstractAdminConstructorArgs
2502
     *
2503
     * @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.
2504
     */
2505
    public function testDeprecatedAbstractAdminConstructorArgs($code, $class, $baseControllerName): void
2506
    {
2507
        new PostAdmin($code, $class, $baseControllerName);
2508
    }
2509
2510
    public function getDeprecatedAbstractAdminConstructorArgs(): iterable
2511
    {
2512
        yield from [
2513
            ['sonata.post.admin.post', null, null],
2514
            [null, null, null],
2515
            ['sonata.post.admin.post', 'Application\Sonata\NewsBundle\Entity\Post', false],
2516
            ['sonata.post.admin.post', false, false],
2517
            [false, false, false],
2518
            [true, true, true],
2519
            [new \stdClass(), new \stdClass(), new \stdClass()],
2520
            [0, 0, 0],
2521
            [1, 1, 1],
2522
        ];
2523
    }
2524
}
2525