Completed
Push — master ( 3fd2dd...aba624 )
by Grégoire
04:19
created

tests/Controller/CRUDControllerTest.php (4 issues)

Upgrade to new PHP Analysis Engine

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

1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of the Sonata Project package.
7
 *
8
 * (c) Thomas Rabaix <[email protected]>
9
 *
10
 * For the full copyright and license information, please view the LICENSE
11
 * file that was distributed with this source code.
12
 */
13
14
namespace Sonata\AdminBundle\Tests\Controller;
15
16
use PHPUnit\Framework\TestCase;
17
use Psr\Log\LoggerInterface;
18
use Sonata\AdminBundle\Admin\AdminInterface;
19
use Sonata\AdminBundle\Admin\FieldDescriptionCollection;
20
use Sonata\AdminBundle\Admin\Pool;
21
use Sonata\AdminBundle\Controller\CRUDController;
22
use Sonata\AdminBundle\Datagrid\DatagridInterface;
23
use Sonata\AdminBundle\Datagrid\ProxyQueryInterface;
24
use Sonata\AdminBundle\Exception\LockException;
25
use Sonata\AdminBundle\Exception\ModelManagerException;
26
use Sonata\AdminBundle\Export\Exporter as SonataExporter;
27
use Sonata\AdminBundle\Model\AuditManager;
28
use Sonata\AdminBundle\Model\AuditReaderInterface;
29
use Sonata\AdminBundle\Model\ModelManagerInterface;
30
use Sonata\AdminBundle\Security\Acl\Permission\AdminPermissionMap;
31
use Sonata\AdminBundle\Security\Handler\AclSecurityHandler;
32
use Sonata\AdminBundle\Templating\TemplateRegistryInterface;
33
use Sonata\AdminBundle\Tests\Fixtures\Controller\BatchAdminController;
34
use Sonata\AdminBundle\Tests\Fixtures\Controller\PreCRUDController;
35
use Sonata\AdminBundle\Util\AdminObjectAclData;
36
use Sonata\AdminBundle\Util\AdminObjectAclManipulator;
37
use Sonata\Exporter\Exporter;
38
use Sonata\Exporter\Source\SourceIteratorInterface;
39
use Sonata\Exporter\Writer\JsonWriter;
40
use Symfony\Bridge\Twig\Extension\FormExtension;
41
use Symfony\Bridge\Twig\Form\TwigRenderer;
42
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
43
use Symfony\Bundle\FrameworkBundle\Templating\DelegatingEngine;
44
use Symfony\Component\DependencyInjection\ContainerInterface;
45
use Symfony\Component\Form\Form;
46
use Symfony\Component\Form\FormRenderer;
47
use Symfony\Component\Form\FormView;
48
use Symfony\Component\HttpFoundation\RedirectResponse;
49
use Symfony\Component\HttpFoundation\Request;
50
use Symfony\Component\HttpFoundation\RequestStack;
51
use Symfony\Component\HttpFoundation\Response;
52
use Symfony\Component\HttpFoundation\Session\Session;
53
use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage;
54
use Symfony\Component\HttpFoundation\StreamedResponse;
55
use Symfony\Component\HttpKernel\Exception\HttpException;
56
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
57
use Symfony\Component\HttpKernel\KernelInterface;
58
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
59
use Symfony\Component\Security\Csrf\CsrfToken;
60
use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface;
61
use Symfony\Component\Translation\TranslatorInterface;
62
63
/**
64
 * Test for CRUDController.
65
 *
66
 * @author Andrej Hudec <[email protected]>
67
 *
68
 * @group legacy
69
 */
70
class CRUDControllerTest extends TestCase
71
{
72
    /**
73
     * @var CRUDController
74
     */
75
    private $controller;
76
77
    /**
78
     * @var Request
79
     */
80
    private $request;
81
82
    /**
83
     * @var AdminInterface
84
     */
85
    private $admin;
86
87
    /**
88
     * @var TemplateRegistryInterface
89
     */
90
    private $templateRegistry;
91
92
    /**
93
     * @var Pool
94
     */
95
    private $pool;
96
97
    /**
98
     * @var array
99
     */
100
    private $parameters;
101
102
    /**
103
     * @var Session
104
     */
105
    private $session;
106
107
    /**
108
     * @var AuditManager
109
     */
110
    private $auditManager;
111
112
    /**
113
     * @var ContainerInterface
114
     */
115
    private $container;
116
117
    /**
118
     * @var AdminObjectAclManipulator
119
     */
120
    private $adminObjectAclManipulator;
121
122
    /**
123
     * @var string
124
     */
125
    private $template;
126
127
    /**
128
     * @var array
129
     */
130
    private $protectedTestedMethods;
131
132
    /**
133
     * @var CsrfTokenManagerInterface
134
     */
135
    private $csrfProvider;
136
137
    /**
138
     * @var KernelInterface
139
     */
140
    private $kernel;
141
142
    /**
143
     * @var TranslatorInterface
144
     */
145
    private $translator;
146
147
    /**
148
     * {@inheritdoc}
149
     */
150
    protected function setUp(): void
151
    {
152
        $this->container = $this->createMock(ContainerInterface::class);
153
154
        $this->request = new Request();
155
        $this->pool = new Pool($this->container, 'title', 'logo.png');
156
        $this->pool->setAdminServiceIds(['foo.admin']);
157
        $this->request->attributes->set('_sonata_admin', 'foo.admin');
158
        $this->admin = $this->getMockBuilder(AdminInterface::class)
159
            ->disableOriginalConstructor()
160
            ->getMock();
161
        $this->translator = $this->createMock(TranslatorInterface::class);
162
        $this->parameters = [];
163
        $this->template = '';
164
165
        $this->templateRegistry = $this->prophesize(TemplateRegistryInterface::class);
166
167
        $templating = $this->getMockBuilder(DelegatingEngine::class)
168
            ->setConstructorArgs([$this->container, []])
169
            ->getMock();
170
171
        $templatingRenderReturnCallback = $this->returnCallback(function (
172
            $view,
173
            array $parameters = [],
174
            Response $response = null
175
        ) {
176
            $this->template = $view;
177
178
            if (null === $response) {
179
                $response = new Response();
180
            }
181
182
            $this->parameters = $parameters;
183
184
            return $response;
185
        });
186
187
        // SF < 3.3.10 BC
188
        $templating->expects($this->any())
189
            ->method('renderResponse')
190
            ->will($templatingRenderReturnCallback);
191
192
        $templating->expects($this->any())
193
            ->method('render')
194
            ->will($templatingRenderReturnCallback);
195
196
        $this->session = new Session(new MockArraySessionStorage());
197
198
        $twig = $this->getMockBuilder(\Twig_Environment::class)
199
            ->disableOriginalConstructor()
200
            ->getMock();
201
202
        $twig->expects($this->any())
203
            ->method('getExtension')
204
            ->will($this->returnCallback(function ($name) {
205
                switch ($name) {
206
                    case FormExtension::class:
207
                        return new FormExtension($this->createMock(TwigRenderer::class));
208
                }
209
            }));
210
211
        $twig->expects($this->any())
212
            ->method('getRuntime')
213
            ->will($this->returnCallback(function ($name) {
214
                switch ($name) {
215
                    case TwigRenderer::class:
216
                        return $this->createMock(TwigRenderer::class);
217
                    case FormRenderer::class:
218
                        return $this->createMock(FormRenderer::class);
219
                }
220
            }));
221
222
        // NEXT_MAJOR : require sonata/exporter ^1.7 and remove conditional
223
        if (class_exists(Exporter::class)) {
224
            $exporter = new Exporter([new JsonWriter('/tmp/sonataadmin/export.json')]);
225
        } else {
226
            $exporter = $this->createMock(SonataExporter::class);
227
228
            $exporter->expects($this->any())
229
                ->method('getResponse')
230
                ->will($this->returnValue(new StreamedResponse()));
231
        }
232
233
        $this->auditManager = $this->getMockBuilder(AuditManager::class)
234
            ->disableOriginalConstructor()
235
            ->getMock();
236
237
        $this->adminObjectAclManipulator = $this->getMockBuilder(AdminObjectAclManipulator::class)
238
            ->disableOriginalConstructor()
239
            ->getMock();
240
241
        $this->csrfProvider = $this->getMockBuilder(CsrfTokenManagerInterface::class)
242
            ->getMock();
243
244
        $this->csrfProvider->expects($this->any())
245
            ->method('getToken')
246
            ->will($this->returnCallback(static function ($intention) {
247
                return new CsrfToken($intention, 'csrf-token-123_'.$intention);
248
            }));
249
250
        $this->csrfProvider->expects($this->any())
251
            ->method('isTokenValid')
252
            ->will($this->returnCallback(static function (CsrfToken $token) {
253
                if ($token->getValue() === 'csrf-token-123_'.$token->getId()) {
254
                    return true;
255
                }
256
257
                return false;
258
            }));
259
260
        $this->logger = $this->createMock(LoggerInterface::class);
261
262
        $requestStack = new RequestStack();
263
        $requestStack->push($this->request);
264
265
        $this->kernel = $this->createMock(KernelInterface::class);
266
267
        $this->container->expects($this->any())
268
            ->method('get')
269
            ->will($this->returnCallback(function ($id) use (
270
                $templating,
271
                $twig,
272
                $exporter,
273
                $requestStack
274
            ) {
275
                switch ($id) {
276
                    case 'sonata.admin.pool':
277
                        return $this->pool;
278
                    case 'request_stack':
279
                        return $requestStack;
280
                    case 'foo.admin':
281
                        return $this->admin;
282
                    case 'foo.admin.template_registry':
283
                        return $this->templateRegistry->reveal();
284
                    case 'templating':
285
                        return $templating;
286
                    case 'twig':
287
                        return $twig;
288
                    case 'session':
289
                        return $this->session;
290
                    case 'sonata.admin.exporter':
291
                        return $exporter;
292
                    case 'sonata.admin.audit.manager':
293
                        return $this->auditManager;
294
                    case 'sonata.admin.object.manipulator.acl.admin':
295
                        return $this->adminObjectAclManipulator;
296
                    case 'security.csrf.token_manager':
297
                        return $this->csrfProvider;
298
                    case 'logger':
299
                        return $this->logger;
300
                    case 'kernel':
301
                        return $this->kernel;
302
                    case 'translator':
303
                        return $this->translator;
304
                }
305
            }));
306
307
        $this->container->expects($this->any())
308
            ->method('has')
309
            ->will($this->returnCallback(function ($id) {
310
                if ('security.csrf.token_manager' === $id && null !== $this->getCsrfProvider()) {
311
                    return true;
312
                }
313
314
                if ('logger' === $id) {
315
                    return true;
316
                }
317
318
                if ('session' === $id) {
319
                    return true;
320
                }
321
322
                if ('templating' === $id) {
323
                    return true;
324
                }
325
326
                if ('translator' === $id) {
327
                    return true;
328
                }
329
330
                return false;
331
            }));
332
333
        $this->container->expects($this->any())
334
            ->method('getParameter')
335
            ->will($this->returnCallback(static function ($name) {
336
                switch ($name) {
337
                    case 'security.role_hierarchy.roles':
338
                       return ['ROLE_SUPER_ADMIN' => ['ROLE_USER', 'ROLE_SONATA_ADMIN', 'ROLE_ADMIN']];
339
                }
340
            }));
341
342
        $this->templateRegistry->getTemplate('ajax')->willReturn('@SonataAdmin/ajax_layout.html.twig');
343
        $this->templateRegistry->getTemplate('layout')->willReturn('@SonataAdmin/standard_layout.html.twig');
344
        $this->templateRegistry->getTemplate('show')->willReturn('@SonataAdmin/CRUD/show.html.twig');
345
        $this->templateRegistry->getTemplate('show_compare')->willReturn('@SonataAdmin/CRUD/show_compare.html.twig');
346
        $this->templateRegistry->getTemplate('edit')->willReturn('@SonataAdmin/CRUD/edit.html.twig');
347
        $this->templateRegistry->getTemplate('dashboard')->willReturn('@SonataAdmin/Core/dashboard.html.twig');
348
        $this->templateRegistry->getTemplate('search')->willReturn('@SonataAdmin/Core/search.html.twig');
349
        $this->templateRegistry->getTemplate('list')->willReturn('@SonataAdmin/CRUD/list.html.twig');
350
        $this->templateRegistry->getTemplate('preview')->willReturn('@SonataAdmin/CRUD/preview.html.twig');
351
        $this->templateRegistry->getTemplate('history')->willReturn('@SonataAdmin/CRUD/history.html.twig');
352
        $this->templateRegistry->getTemplate('acl')->willReturn('@SonataAdmin/CRUD/acl.html.twig');
353
        $this->templateRegistry->getTemplate('delete')->willReturn('@SonataAdmin/CRUD/delete.html.twig');
354
        $this->templateRegistry->getTemplate('batch')->willReturn('@SonataAdmin/CRUD/list__batch.html.twig');
355
        $this->templateRegistry->getTemplate('batch_confirmation')->willReturn('@SonataAdmin/CRUD/batch_confirmation.html.twig');
356
357
        // NEXT_MAJOR: Remove this call
358
        $this->admin->method('getTemplate')->willReturnMap([
359
            ['ajax', '@SonataAdmin/ajax_layout.html.twig'],
360
            ['layout', '@SonataAdmin/standard_layout.html.twig'],
361
            ['show', '@SonataAdmin/CRUD/show.html.twig'],
362
            ['show_compare', '@SonataAdmin/CRUD/show_compare.html.twig'],
363
            ['edit', '@SonataAdmin/CRUD/edit.html.twig'],
364
            ['dashboard', '@SonataAdmin/Core/dashboard.html.twig'],
365
            ['search', '@SonataAdmin/Core/search.html.twig'],
366
            ['list', '@SonataAdmin/CRUD/list.html.twig'],
367
            ['preview', '@SonataAdmin/CRUD/preview.html.twig'],
368
            ['history', '@SonataAdmin/CRUD/history.html.twig'],
369
            ['acl', '@SonataAdmin/CRUD/acl.html.twig'],
370
            ['delete', '@SonataAdmin/CRUD/delete.html.twig'],
371
            ['batch', '@SonataAdmin/CRUD/list__batch.html.twig'],
372
            ['batch_confirmation', '@SonataAdmin/CRUD/batch_confirmation.html.twig'],
373
        ]);
374
375
        $this->admin->expects($this->any())
376
            ->method('getIdParameter')
377
            ->will($this->returnValue('id'));
378
379
        $this->admin->expects($this->any())
380
            ->method('getAccessMapping')
381
            ->will($this->returnValue([]));
382
383
        $this->admin->expects($this->any())
384
            ->method('generateUrl')
385
            ->will(
386
                $this->returnCallback(
387
                    static function ($name, array $parameters = [], $absolute = false) {
388
                        $result = $name;
389
                        if (!empty($parameters)) {
390
                            $result .= '?'.http_build_query($parameters);
391
                        }
392
393
                        return $result;
394
                    }
395
                )
396
            );
397
398
        $this->admin->expects($this->any())
399
            ->method('generateObjectUrl')
400
            ->will(
401
                $this->returnCallback(
402
                    static function ($name, $object, array $parameters = [], $absolute = false) {
403
                        $result = \get_class($object).'_'.$name;
404
                        if (!empty($parameters)) {
405
                            $result .= '?'.http_build_query($parameters);
406
                        }
407
408
                        return $result;
409
                    }
410
                )
411
            );
412
413
        $this->admin->expects($this->any())
414
            ->method('getCode')
415
            ->willReturn('foo.admin');
416
417
        $this->controller = new CRUDController();
418
        $this->controller->setContainer($this->container);
419
420
        // Make some methods public to test them
421
        $testedMethods = [
422
            'renderJson',
423
            'isXmlHttpRequest',
424
            'configure',
425
            'getBaseTemplate',
426
            'redirectTo',
427
            'addFlash',
428
        ];
429
        foreach ($testedMethods as $testedMethod) {
430
            // NEXT_MAJOR: Remove this check and only use CRUDController
431
            if (method_exists(CRUDController::class, $testedMethod)) {
432
                $method = new \ReflectionMethod(CRUDController::class, $testedMethod);
433
            } else {
434
                $method = new \ReflectionMethod(Controller::class, $testedMethod);
435
            }
436
437
            $method->setAccessible(true);
438
            $this->protectedTestedMethods[$testedMethod] = $method;
439
        }
440
    }
441
442
    public function testRenderJson1(): void
443
    {
444
        $data = ['example' => '123', 'foo' => 'bar'];
445
446
        $this->request->headers->set('Content-Type', 'application/x-www-form-urlencoded');
447
        $response = $this->protectedTestedMethods['renderJson']->invoke($this->controller, $data, 200, [], $this->request);
448
449
        $this->assertSame($response->headers->get('Content-Type'), 'application/json');
450
        $this->assertSame(json_encode($data), $response->getContent());
451
    }
452
453
    public function testRenderJson2(): void
454
    {
455
        $data = ['example' => '123', 'foo' => 'bar'];
456
457
        $this->request->headers->set('Content-Type', 'multipart/form-data');
458
        $response = $this->protectedTestedMethods['renderJson']->invoke($this->controller, $data, 200, [], $this->request);
459
460
        $this->assertSame($response->headers->get('Content-Type'), 'application/json');
461
        $this->assertSame(json_encode($data), $response->getContent());
462
    }
463
464
    public function testRenderJsonAjax(): void
465
    {
466
        $data = ['example' => '123', 'foo' => 'bar'];
467
468
        $this->request->attributes->set('_xml_http_request', true);
469
        $this->request->headers->set('Content-Type', 'multipart/form-data');
470
        $response = $this->protectedTestedMethods['renderJson']->invoke($this->controller, $data, 200, [], $this->request);
471
472
        $this->assertSame($response->headers->get('Content-Type'), 'application/json');
473
        $this->assertSame(json_encode($data), $response->getContent());
474
    }
475
476
    public function testIsXmlHttpRequest(): void
477
    {
478
        $this->assertFalse($this->protectedTestedMethods['isXmlHttpRequest']->invoke($this->controller, $this->request));
479
480
        $this->request->headers->set('X-Requested-With', 'XMLHttpRequest');
481
482
        $this->assertTrue($this->protectedTestedMethods['isXmlHttpRequest']->invoke($this->controller, $this->request));
483
484
        $this->request->headers->remove('X-Requested-With');
485
        $this->assertFalse($this->protectedTestedMethods['isXmlHttpRequest']->invoke($this->controller, $this->request));
486
487
        $this->request->attributes->set('_xml_http_request', true);
488
        $this->assertTrue($this->protectedTestedMethods['isXmlHttpRequest']->invoke($this->controller, $this->request));
489
    }
490
491
    public function testConfigure(): void
492
    {
493
        $uniqueId = '';
494
495
        $this->admin->expects($this->once())
496
            ->method('setUniqid')
497
            ->will($this->returnCallback(static function ($uniqid) use (&$uniqueId): void {
498
                $uniqueId = $uniqid;
499
            }));
500
501
        $this->request->query->set('uniqid', 123456);
502
        $this->protectedTestedMethods['configure']->invoke($this->controller);
503
504
        $this->assertSame(123456, $uniqueId);
505
        $this->assertAttributeSame($this->admin, 'admin', $this->controller);
506
    }
507
508
    public function testConfigureChild(): void
509
    {
510
        $uniqueId = '';
511
512
        $this->admin->expects($this->once())
513
            ->method('setUniqid')
514
            ->will($this->returnCallback(static function ($uniqid) use (&$uniqueId): void {
515
                $uniqueId = $uniqid;
516
            }));
517
518
        $this->admin->expects($this->once())
519
            ->method('isChild')
520
            ->will($this->returnValue(true));
521
522
        $adminParent = $this->getMockBuilder(AdminInterface::class)
523
            ->disableOriginalConstructor()
524
            ->getMock();
525
        $this->admin->expects($this->once())
526
            ->method('getParent')
527
            ->will($this->returnValue($adminParent));
528
529
        $this->request->query->set('uniqid', 123456);
530
        $this->protectedTestedMethods['configure']->invoke($this->controller);
531
532
        $this->assertSame(123456, $uniqueId);
533
        $this->assertAttributeInstanceOf(\get_class($adminParent), 'admin', $this->controller);
534
    }
535
536
    public function testConfigureWithException(): void
537
    {
538
        $this->expectException(
539
            \RuntimeException::class,
540
            'There is no `_sonata_admin` defined for the controller `Sonata\AdminBundle\Controller\CRUDController`'
541
        );
542
543
        $this->request->attributes->remove('_sonata_admin');
544
        $this->protectedTestedMethods['configure']->invoke($this->controller);
545
    }
546
547
    public function testConfigureWithException2(): void
548
    {
549
        $this->expectException(
550
            \InvalidArgumentException::class,
551
            'Found service "nonexistent.admin" is not a valid admin service'
552
        );
553
554
        $this->pool->setAdminServiceIds(['nonexistent.admin']);
555
        $this->request->attributes->set('_sonata_admin', 'nonexistent.admin');
556
        $this->protectedTestedMethods['configure']->invoke($this->controller);
557
    }
558
559
    public function testGetBaseTemplate(): void
560
    {
561
        $this->assertSame(
562
            '@SonataAdmin/standard_layout.html.twig',
563
            $this->protectedTestedMethods['getBaseTemplate']->invoke($this->controller, $this->request)
564
        );
565
566
        $this->request->headers->set('X-Requested-With', 'XMLHttpRequest');
567
        $this->assertSame(
568
            '@SonataAdmin/ajax_layout.html.twig',
569
            $this->protectedTestedMethods['getBaseTemplate']->invoke($this->controller, $this->request)
570
        );
571
572
        $this->request->headers->remove('X-Requested-With');
573
        $this->assertSame(
574
            '@SonataAdmin/standard_layout.html.twig',
575
            $this->protectedTestedMethods['getBaseTemplate']->invoke($this->controller, $this->request)
576
        );
577
578
        $this->request->attributes->set('_xml_http_request', true);
579
        $this->assertSame(
580
            '@SonataAdmin/ajax_layout.html.twig',
581
            $this->protectedTestedMethods['getBaseTemplate']->invoke($this->controller, $this->request)
582
        );
583
    }
584
585
    public function testRender(): void
586
    {
587
        $this->parameters = [];
588
        $this->assertInstanceOf(
589
            Response::class,
590
            $this->controller->renderWithExtraParams('@FooAdmin/foo.html.twig', [], null)
591
        );
592
        $this->assertSame($this->admin, $this->parameters['admin']);
593
        $this->assertSame('@SonataAdmin/standard_layout.html.twig', $this->parameters['base_template']);
594
        $this->assertSame($this->pool, $this->parameters['admin_pool']);
595
        $this->assertSame('@FooAdmin/foo.html.twig', $this->template);
596
    }
597
598
    public function testRenderWithResponse(): void
599
    {
600
        $this->parameters = [];
601
        $response = $response = new Response();
602
        $response->headers->set('X-foo', 'bar');
603
        $responseResult = $this->controller->renderWithExtraParams('@FooAdmin/foo.html.twig', [], $response);
604
605
        $this->assertSame($response, $responseResult);
606
        $this->assertSame('bar', $responseResult->headers->get('X-foo'));
607
        $this->assertSame($this->admin, $this->parameters['admin']);
608
        $this->assertSame('@SonataAdmin/standard_layout.html.twig', $this->parameters['base_template']);
609
        $this->assertSame($this->pool, $this->parameters['admin_pool']);
610
        $this->assertSame('@FooAdmin/foo.html.twig', $this->template);
611
    }
612
613
    public function testRenderCustomParams(): void
614
    {
615
        $this->parameters = [];
616
        $this->assertInstanceOf(
617
            Response::class,
618
            $this->controller->renderWithExtraParams(
619
                '@FooAdmin/foo.html.twig',
620
                ['foo' => 'bar'],
621
                null
622
            )
623
        );
624
        $this->assertSame($this->admin, $this->parameters['admin']);
625
        $this->assertSame('@SonataAdmin/standard_layout.html.twig', $this->parameters['base_template']);
626
        $this->assertSame($this->pool, $this->parameters['admin_pool']);
627
        $this->assertSame('bar', $this->parameters['foo']);
628
        $this->assertSame('@FooAdmin/foo.html.twig', $this->template);
629
    }
630
631
    public function testRenderAjax(): void
632
    {
633
        $this->parameters = [];
634
        $this->request->headers->set('X-Requested-With', 'XMLHttpRequest');
635
        $this->assertInstanceOf(
636
            Response::class,
637
            $this->controller->renderWithExtraParams(
638
                '@FooAdmin/foo.html.twig',
639
                ['foo' => 'bar'],
640
                null
641
            )
642
        );
643
        $this->assertSame($this->admin, $this->parameters['admin']);
644
        $this->assertSame('@SonataAdmin/ajax_layout.html.twig', $this->parameters['base_template']);
645
        $this->assertSame($this->pool, $this->parameters['admin_pool']);
646
        $this->assertSame('bar', $this->parameters['foo']);
647
        $this->assertSame('@FooAdmin/foo.html.twig', $this->template);
648
    }
649
650
    public function testListActionAccessDenied(): void
651
    {
652
        $this->expectException(AccessDeniedException::class);
653
654
        $this->admin->expects($this->once())
655
            ->method('checkAccess')
656
            ->with($this->equalTo('list'))
657
            ->will($this->throwException(new AccessDeniedException()));
658
659
        $this->controller->listAction($this->request);
660
    }
661
662
    public function testPreList(): void
663
    {
664
        $this->admin->expects($this->any())
665
            ->method('hasRoute')
666
            ->with($this->equalTo('list'))
667
            ->will($this->returnValue(true));
668
669
        $this->admin->expects($this->once())
670
            ->method('checkAccess')
671
            ->with($this->equalTo('list'))
672
            ->will($this->returnValue(true));
673
674
        $controller = new PreCRUDController();
675
        $controller->setContainer($this->container);
676
677
        $response = $controller->listAction($this->request);
678
        $this->assertInstanceOf(Response::class, $response);
679
        $this->assertSame('preList called', $response->getContent());
680
    }
681
682
    public function testListAction(): void
683
    {
684
        $datagrid = $this->createMock(DatagridInterface::class);
685
686
        $this->admin->expects($this->any())
687
            ->method('hasRoute')
688
            ->with($this->equalTo('list'))
689
            ->will($this->returnValue(true));
690
691
        $this->admin->expects($this->once())
692
            ->method('checkAccess')
693
            ->with($this->equalTo('list'))
694
            ->will($this->returnValue(true));
695
696
        $form = $this->getMockBuilder(Form::class)
697
            ->disableOriginalConstructor()
698
            ->getMock();
699
700
        $form->expects($this->once())
701
            ->method('createView')
702
            ->will($this->returnValue($this->createMock(FormView::class)));
703
704
        $this->admin->expects($this->once())
705
            ->method('getDatagrid')
706
            ->will($this->returnValue($datagrid));
707
708
        $datagrid->expects($this->once())
709
            ->method('getForm')
710
            ->will($this->returnValue($form));
711
712
        $this->parameters = [];
713
        $this->assertInstanceOf(Response::class, $this->controller->listAction($this->request));
714
715
        $this->assertSame($this->admin, $this->parameters['admin']);
716
        $this->assertSame('@SonataAdmin/standard_layout.html.twig', $this->parameters['base_template']);
717
        $this->assertSame($this->pool, $this->parameters['admin_pool']);
718
719
        $this->assertSame('list', $this->parameters['action']);
720
        $this->assertInstanceOf(FormView::class, $this->parameters['form']);
721
        $this->assertInstanceOf(DatagridInterface::class, $this->parameters['datagrid']);
722
        $this->assertSame('csrf-token-123_sonata.batch', $this->parameters['csrf_token']);
723
        $this->assertSame([], $this->session->getFlashBag()->all());
724
        $this->assertSame('@SonataAdmin/CRUD/list.html.twig', $this->template);
725
    }
726
727
    public function testBatchActionDeleteAccessDenied(): void
728
    {
729
        $this->expectException(AccessDeniedException::class);
730
731
        $this->admin->expects($this->once())
732
            ->method('checkAccess')
733
            ->with($this->equalTo('batchDelete'))
734
            ->will($this->throwException(new AccessDeniedException()));
735
736
        $this->controller->batchActionDelete($this->createMock(ProxyQueryInterface::class));
737
    }
738
739
    public function testBatchActionDelete(): void
740
    {
741
        $modelManager = $this->createMock(ModelManagerInterface::class);
742
743
        $this->admin->expects($this->once())
744
            ->method('checkAccess')
745
            ->with($this->equalTo('batchDelete'))
746
            ->will($this->returnValue(true));
747
748
        $this->admin->expects($this->once())
749
            ->method('getModelManager')
750
            ->will($this->returnValue($modelManager));
751
752
        $this->admin->expects($this->once())
753
            ->method('getFilterParameters')
754
            ->will($this->returnValue(['foo' => 'bar']));
755
756
        $this->expectTranslate('flash_batch_delete_success', [], 'SonataAdminBundle');
757
758
        $result = $this->controller->batchActionDelete($this->createMock(ProxyQueryInterface::class));
759
760
        $this->assertInstanceOf(RedirectResponse::class, $result);
761
        $this->assertSame(['flash_batch_delete_success'], $this->session->getFlashBag()->get('sonata_flash_success'));
762
        $this->assertSame('list?filter%5Bfoo%5D=bar', $result->getTargetUrl());
763
    }
764
765
    public function testBatchActionDeleteWithModelManagerException(): void
766
    {
767
        $modelManager = $this->createMock(ModelManagerInterface::class);
768
        $this->assertLoggerLogsModelManagerException($modelManager, 'batchDelete');
769
770
        $this->admin->expects($this->once())
771
            ->method('getModelManager')
772
            ->will($this->returnValue($modelManager));
773
774
        $this->admin->expects($this->once())
775
            ->method('getFilterParameters')
776
            ->will($this->returnValue(['foo' => 'bar']));
777
778
        $this->expectTranslate('flash_batch_delete_error', [], 'SonataAdminBundle');
779
780
        $result = $this->controller->batchActionDelete($this->createMock(ProxyQueryInterface::class));
781
782
        $this->assertInstanceOf(RedirectResponse::class, $result);
783
        $this->assertSame(['flash_batch_delete_error'], $this->session->getFlashBag()->get('sonata_flash_error'));
784
        $this->assertSame('list?filter%5Bfoo%5D=bar', $result->getTargetUrl());
785
    }
786
787
    public function testBatchActionDeleteWithModelManagerExceptionInDebugMode(): void
788
    {
789
        $modelManager = $this->createMock(ModelManagerInterface::class);
790
        $this->expectException(ModelManagerException::class);
791
792
        $modelManager->expects($this->once())
793
            ->method('batchDelete')
794
            ->will($this->returnCallback(static function (): void {
795
                throw new ModelManagerException();
796
            }));
797
798
        $this->admin->expects($this->once())
799
            ->method('getModelManager')
800
            ->will($this->returnValue($modelManager));
801
802
        $this->kernel->expects($this->once())
803
            ->method('isDebug')
804
            ->will($this->returnValue(true));
805
806
        $this->controller->batchActionDelete($this->createMock(ProxyQueryInterface::class));
807
    }
808
809
    public function testShowActionNotFoundException(): void
810
    {
811
        $this->expectException(NotFoundHttpException::class);
812
813
        $this->admin->expects($this->once())
814
            ->method('getObject')
815
            ->will($this->returnValue(false));
816
817
        $this->controller->showAction(null, $this->request);
818
    }
819
820
    public function testShowActionAccessDenied(): void
821
    {
822
        $this->expectException(AccessDeniedException::class);
823
824
        $this->admin->expects($this->once())
825
            ->method('getObject')
826
            ->will($this->returnValue(new \stdClass()));
827
828
        $this->admin->expects($this->once())
829
            ->method('checkAccess')
830
            ->with($this->equalTo('show'))
831
            ->will($this->throwException(new AccessDeniedException()));
832
833
        $this->controller->showAction(null, $this->request);
834
    }
835
836
    /**
837
     * @group legacy
838
     * @expectedDeprecation Calling this method without implementing "configureShowFields" is not supported since 3.40.0 and will no longer be possible in 4.0
839
     */
840
    public function testShowActionDeprecation(): void
841
    {
842
        $object = new \stdClass();
843
844
        $this->admin->expects($this->once())
845
            ->method('getObject')
846
            ->will($this->returnValue($object));
847
848
        $this->admin->expects($this->once())
849
            ->method('checkAccess')
850
            ->with($this->equalTo('show'))
851
            ->will($this->returnValue(true));
852
853
        $show = $this->createMock(FieldDescriptionCollection::class);
854
855
        $this->admin->expects($this->once())
856
            ->method('getShow')
857
            ->will($this->returnValue($show));
858
859
        $show->expects($this->once())
860
            ->method('getElements')
861
            ->willReturn([]);
862
863
        $show->expects($this->once())
864
            ->method('count')
865
            ->willReturn(0);
866
867
        $this->controller->showAction(null, $this->request);
868
    }
869
870
    public function testPreShow(): void
871
    {
872
        $object = new \stdClass();
873
        $object->foo = 123456;
874
875
        $this->admin->expects($this->once())
876
            ->method('getObject')
877
            ->will($this->returnValue($object));
878
879
        $this->admin->expects($this->once())
880
            ->method('checkAccess')
881
            ->with($this->equalTo('show'))
882
            ->will($this->returnValue(true));
883
884
        $controller = new PreCRUDController();
885
        $controller->setContainer($this->container);
886
887
        $response = $controller->showAction(null, $this->request);
888
        $this->assertInstanceOf(Response::class, $response);
889
        $this->assertSame('preShow called: 123456', $response->getContent());
890
    }
891
892
    public function testShowAction(): void
893
    {
894
        $object = new \stdClass();
895
896
        $this->admin->expects($this->once())
897
            ->method('getObject')
898
            ->will($this->returnValue($object));
899
900
        $this->admin->expects($this->once())
901
            ->method('checkAccess')
902
            ->with($this->equalTo('show'))
903
            ->will($this->returnValue(true));
904
905
        $show = $this->createMock(FieldDescriptionCollection::class);
906
907
        $this->admin->expects($this->once())
908
            ->method('getShow')
909
            ->will($this->returnValue($show));
910
911
        $show->expects($this->once())
912
            ->method('getElements')
913
            ->willReturn(['field' => 'fielddata']);
914
915
        $this->assertInstanceOf(Response::class, $this->controller->showAction(null, $this->request));
916
917
        $this->assertSame($this->admin, $this->parameters['admin']);
918
        $this->assertSame('@SonataAdmin/standard_layout.html.twig', $this->parameters['base_template']);
919
        $this->assertSame($this->pool, $this->parameters['admin_pool']);
920
921
        $this->assertSame('show', $this->parameters['action']);
922
        $this->assertInstanceOf(FieldDescriptionCollection::class, $this->parameters['elements']);
923
        $this->assertSame($object, $this->parameters['object']);
924
925
        $this->assertSame([], $this->session->getFlashBag()->all());
926
        $this->assertSame('@SonataAdmin/CRUD/show.html.twig', $this->template);
927
    }
928
929
    /**
930
     * @dataProvider getRedirectToTests
931
     */
932
    public function testRedirectTo($expected, $route, $queryParams, $requestParams, $hasActiveSubclass): void
933
    {
934
        $this->admin->expects($this->any())
935
            ->method('hasActiveSubclass')
936
            ->will($this->returnValue($hasActiveSubclass));
937
938
        $object = new \stdClass();
939
940
        foreach ($queryParams as $key => $value) {
941
            $this->request->query->set($key, $value);
942
        }
943
944
        foreach ($requestParams as $key => $value) {
945
            $this->request->request->set($key, $value);
946
        }
947
948
        $this->admin->expects($this->any())
949
            ->method('hasRoute')
950
            ->with($this->equalTo($route))
951
            ->will($this->returnValue(true));
952
953
        $this->admin->expects($this->any())
954
            ->method('hasAccess')
955
            ->with($this->equalTo($route))
956
            ->will($this->returnValue(true));
957
958
        $response = $this->protectedTestedMethods['redirectTo']->invoke($this->controller, $object, $this->request);
959
        $this->assertInstanceOf(RedirectResponse::class, $response);
960
        $this->assertSame($expected, $response->getTargetUrl());
961
    }
962
963
    public function testRedirectToWithObject(): void
964
    {
965
        $this->admin->expects($this->any())
966
            ->method('hasActiveSubclass')
967
            ->will($this->returnValue(false));
968
969
        $object = new \stdClass();
970
971
        $this->admin->expects($this->at(0))
972
            ->method('hasRoute')
973
            ->with($this->equalTo('edit'))
974
            ->will($this->returnValue(true));
975
976
        $this->admin->expects($this->any())
977
            ->method('hasAccess')
978
            ->with($this->equalTo('edit'), $object)
979
            ->will($this->returnValue(false));
980
981
        $response = $this->protectedTestedMethods['redirectTo']->invoke($this->controller, $object, $this->request);
982
        $this->assertInstanceOf(RedirectResponse::class, $response);
983
        $this->assertSame('list', $response->getTargetUrl());
984
    }
985
986
    public function getRedirectToTests()
987
    {
988
        return [
989
            ['stdClass_edit', 'edit', [], [], false],
990
            ['list', 'list', ['btn_update_and_list' => true], [], false],
991
            ['list', 'list', ['btn_create_and_list' => true], [], false],
992
            ['create', 'create', ['btn_create_and_create' => true], [], false],
993
            ['create?subclass=foo', 'create', ['btn_create_and_create' => true, 'subclass' => 'foo'], [], true],
994
            ['stdClass_edit?_tab=first_tab', 'edit', ['btn_update_and_edit' => true], ['_tab' => 'first_tab'], false],
995
        ];
996
    }
997
998
    public function testDeleteActionNotFoundException(): void
999
    {
1000
        $this->expectException(NotFoundHttpException::class);
1001
1002
        $this->admin->expects($this->once())
1003
            ->method('getObject')
1004
            ->will($this->returnValue(false));
1005
1006
        $this->controller->deleteAction(1, $this->request);
1007
    }
1008
1009
    public function testDeleteActionAccessDenied(): void
1010
    {
1011
        $this->expectException(AccessDeniedException::class);
1012
1013
        $this->admin->expects($this->once())
1014
            ->method('getObject')
1015
            ->will($this->returnValue(new \stdClass()));
1016
1017
        $this->admin->expects($this->once())
1018
            ->method('checkAccess')
1019
            ->with($this->equalTo('delete'))
1020
            ->will($this->throwException(new AccessDeniedException()));
1021
1022
        $this->controller->deleteAction(1, $this->request);
1023
    }
1024
1025
    public function testPreDelete(): void
1026
    {
1027
        $object = new \stdClass();
1028
        $object->foo = 123456;
1029
1030
        $this->admin->expects($this->once())
1031
            ->method('getObject')
1032
            ->will($this->returnValue($object));
1033
1034
        $this->admin->expects($this->once())
1035
            ->method('checkAccess')
1036
            ->with($this->equalTo('delete'))
1037
            ->will($this->returnValue(true));
1038
1039
        $controller = new PreCRUDController();
1040
        $controller->setContainer($this->container);
1041
1042
        $response = $controller->deleteAction(null, $this->request);
1043
        $this->assertInstanceOf(Response::class, $response);
1044
        $this->assertSame('preDelete called: 123456', $response->getContent());
1045
    }
1046
1047
    public function testDeleteAction(): void
1048
    {
1049
        $object = new \stdClass();
1050
1051
        $this->admin->expects($this->once())
1052
            ->method('getObject')
1053
            ->will($this->returnValue($object));
1054
1055
        $this->admin->expects($this->once())
1056
            ->method('checkAccess')
1057
            ->with($this->equalTo('delete'))
1058
            ->will($this->returnValue(true));
1059
1060
        $this->assertInstanceOf(Response::class, $this->controller->deleteAction(1, $this->request));
1061
1062
        $this->assertSame($this->admin, $this->parameters['admin']);
1063
        $this->assertSame('@SonataAdmin/standard_layout.html.twig', $this->parameters['base_template']);
1064
        $this->assertSame($this->pool, $this->parameters['admin_pool']);
1065
1066
        $this->assertSame('delete', $this->parameters['action']);
1067
        $this->assertSame($object, $this->parameters['object']);
1068
        $this->assertSame('csrf-token-123_sonata.delete', $this->parameters['csrf_token']);
1069
1070
        $this->assertSame([], $this->session->getFlashBag()->all());
1071
        $this->assertSame('@SonataAdmin/CRUD/delete.html.twig', $this->template);
1072
    }
1073
1074
    public function testDeleteActionNoCsrfToken(): void
1075
    {
1076
        $this->csrfProvider = null;
1077
1078
        $object = new \stdClass();
1079
1080
        $this->admin->expects($this->once())
1081
            ->method('getObject')
1082
            ->will($this->returnValue($object));
1083
1084
        $this->admin->expects($this->once())
1085
            ->method('checkAccess')
1086
            ->with($this->equalTo('delete'))
1087
            ->will($this->returnValue(true));
1088
1089
        $this->assertInstanceOf(Response::class, $this->controller->deleteAction(1, $this->request));
1090
1091
        $this->assertSame($this->admin, $this->parameters['admin']);
1092
        $this->assertSame('@SonataAdmin/standard_layout.html.twig', $this->parameters['base_template']);
1093
        $this->assertSame($this->pool, $this->parameters['admin_pool']);
1094
1095
        $this->assertSame('delete', $this->parameters['action']);
1096
        $this->assertSame($object, $this->parameters['object']);
1097
        $this->assertFalse($this->parameters['csrf_token']);
1098
1099
        $this->assertSame([], $this->session->getFlashBag()->all());
1100
        $this->assertSame('@SonataAdmin/CRUD/delete.html.twig', $this->template);
1101
    }
1102
1103
    public function testDeleteActionAjaxSuccess1(): void
1104
    {
1105
        $object = new \stdClass();
1106
1107
        $this->admin->expects($this->once())
1108
            ->method('getObject')
1109
            ->will($this->returnValue($object));
1110
1111
        $this->admin->expects($this->once())
1112
            ->method('checkAccess')
1113
            ->with($this->equalTo('delete'))
1114
            ->will($this->returnValue(true));
1115
1116
        $this->request->setMethod('DELETE');
1117
1118
        $this->request->headers->set('X-Requested-With', 'XMLHttpRequest');
1119
        $this->request->request->set('_sonata_csrf_token', 'csrf-token-123_sonata.delete');
1120
1121
        $response = $this->controller->deleteAction(1, $this->request);
1122
1123
        $this->assertInstanceOf(Response::class, $response);
1124
        $this->assertSame(json_encode(['result' => 'ok']), $response->getContent());
1125
        $this->assertSame([], $this->session->getFlashBag()->all());
1126
    }
1127
1128
    public function testDeleteActionAjaxSuccess2(): void
1129
    {
1130
        $object = new \stdClass();
1131
1132
        $this->admin->expects($this->once())
1133
            ->method('getObject')
1134
            ->will($this->returnValue($object));
1135
1136
        $this->admin->expects($this->once())
1137
            ->method('checkAccess')
1138
            ->with($this->equalTo('delete'))
1139
            ->will($this->returnValue(true));
1140
1141
        $this->request->setMethod('POST');
1142
        $this->request->request->set('_method', 'DELETE');
1143
        $this->request->request->set('_sonata_csrf_token', 'csrf-token-123_sonata.delete');
1144
1145
        $this->request->headers->set('X-Requested-With', 'XMLHttpRequest');
1146
1147
        $response = $this->controller->deleteAction(1, $this->request);
1148
1149
        $this->assertInstanceOf(Response::class, $response);
1150
        $this->assertSame(json_encode(['result' => 'ok']), $response->getContent());
1151
        $this->assertSame([], $this->session->getFlashBag()->all());
1152
    }
1153
1154
    public function testDeleteActionAjaxError(): void
1155
    {
1156
        $object = new \stdClass();
1157
1158
        $this->admin->expects($this->once())
1159
            ->method('getObject')
1160
            ->will($this->returnValue($object));
1161
1162
        $this->admin->expects($this->once())
1163
            ->method('checkAccess')
1164
            ->with($this->equalTo('delete'))
1165
            ->will($this->returnValue(true));
1166
1167
        $this->admin->expects($this->any())
1168
            ->method('getClass')
1169
            ->will($this->returnValue('stdClass'));
1170
1171
        $this->assertLoggerLogsModelManagerException($this->admin, 'delete');
1172
1173
        $this->request->setMethod('DELETE');
1174
1175
        $this->request->request->set('_sonata_csrf_token', 'csrf-token-123_sonata.delete');
1176
        $this->request->headers->set('X-Requested-With', 'XMLHttpRequest');
1177
1178
        $response = $this->controller->deleteAction(1, $this->request);
1179
1180
        $this->assertInstanceOf(Response::class, $response);
1181
        $this->assertSame(json_encode(['result' => 'error']), $response->getContent());
1182
        $this->assertSame([], $this->session->getFlashBag()->all());
1183
    }
1184
1185
    public function testDeleteActionWithModelManagerExceptionInDebugMode(): void
1186
    {
1187
        $this->expectException(ModelManagerException::class);
1188
1189
        $object = new \stdClass();
1190
1191
        $this->admin->expects($this->once())
1192
            ->method('getObject')
1193
            ->will($this->returnValue($object));
1194
1195
        $this->admin->expects($this->once())
1196
            ->method('checkAccess')
1197
            ->with($this->equalTo('delete'))
1198
            ->will($this->returnValue(true));
1199
1200
        $this->admin->expects($this->once())
1201
            ->method('delete')
1202
            ->will($this->returnCallback(static function (): void {
1203
                throw new ModelManagerException();
1204
            }));
1205
1206
        $this->kernel->expects($this->once())
1207
            ->method('isDebug')
1208
            ->will($this->returnValue(true));
1209
1210
        $this->request->setMethod('DELETE');
1211
        $this->request->request->set('_sonata_csrf_token', 'csrf-token-123_sonata.delete');
1212
1213
        $this->controller->deleteAction(1, $this->request);
1214
    }
1215
1216
    /**
1217
     * @dataProvider getToStringValues
1218
     */
1219
    public function testDeleteActionSuccess1($expectedToStringValue, $toStringValue): void
1220
    {
1221
        $object = new \stdClass();
1222
1223
        $this->admin->expects($this->once())
1224
            ->method('getObject')
1225
            ->will($this->returnValue($object));
1226
1227
        $this->admin->expects($this->once())
1228
            ->method('toString')
1229
            ->with($this->equalTo($object))
1230
            ->will($this->returnValue($toStringValue));
1231
1232
        $this->expectTranslate('flash_delete_success', ['%name%' => $expectedToStringValue], 'SonataAdminBundle');
1233
1234
        $this->admin->expects($this->once())
1235
            ->method('checkAccess')
1236
            ->with($this->equalTo('delete'))
1237
            ->will($this->returnValue(true));
1238
1239
        $this->request->setMethod('DELETE');
1240
1241
        $this->request->request->set('_sonata_csrf_token', 'csrf-token-123_sonata.delete');
1242
1243
        $response = $this->controller->deleteAction(1, $this->request);
1244
1245
        $this->assertInstanceOf(RedirectResponse::class, $response);
1246
        $this->assertSame(['flash_delete_success'], $this->session->getFlashBag()->get('sonata_flash_success'));
1247
        $this->assertSame('list', $response->getTargetUrl());
1248
    }
1249
1250
    /**
1251
     * @dataProvider getToStringValues
1252
     */
1253
    public function testDeleteActionSuccess2($expectedToStringValue, $toStringValue): void
1254
    {
1255
        $object = new \stdClass();
1256
1257
        $this->admin->expects($this->once())
1258
            ->method('getObject')
1259
            ->will($this->returnValue($object));
1260
1261
        $this->admin->expects($this->once())
1262
            ->method('checkAccess')
1263
            ->with($this->equalTo('delete'))
1264
            ->will($this->returnValue(true));
1265
1266
        $this->admin->expects($this->once())
1267
            ->method('toString')
1268
            ->with($this->equalTo($object))
1269
            ->will($this->returnValue($toStringValue));
1270
1271
        $this->expectTranslate('flash_delete_success', ['%name%' => $expectedToStringValue], 'SonataAdminBundle');
1272
1273
        $this->request->setMethod('POST');
1274
        $this->request->request->set('_method', 'DELETE');
1275
1276
        $this->request->request->set('_sonata_csrf_token', 'csrf-token-123_sonata.delete');
1277
1278
        $response = $this->controller->deleteAction(1, $this->request);
1279
1280
        $this->assertInstanceOf(RedirectResponse::class, $response);
1281
        $this->assertSame(['flash_delete_success'], $this->session->getFlashBag()->get('sonata_flash_success'));
1282
        $this->assertSame('list', $response->getTargetUrl());
1283
    }
1284
1285
    /**
1286
     * @dataProvider getToStringValues
1287
     */
1288
    public function testDeleteActionSuccessNoCsrfTokenProvider($expectedToStringValue, $toStringValue): void
1289
    {
1290
        $this->csrfProvider = null;
1291
1292
        $object = new \stdClass();
1293
1294
        $this->admin->expects($this->once())
1295
            ->method('getObject')
1296
            ->will($this->returnValue($object));
1297
1298
        $this->admin->expects($this->once())
1299
            ->method('checkAccess')
1300
            ->with($this->equalTo('delete'))
1301
            ->will($this->returnValue(true));
1302
1303
        $this->admin->expects($this->once())
1304
            ->method('toString')
1305
            ->with($this->equalTo($object))
1306
            ->will($this->returnValue($toStringValue));
1307
1308
        $this->expectTranslate('flash_delete_success', ['%name%' => $expectedToStringValue], 'SonataAdminBundle');
1309
1310
        $this->request->setMethod('POST');
1311
        $this->request->request->set('_method', 'DELETE');
1312
1313
        $response = $this->controller->deleteAction(1, $this->request);
1314
1315
        $this->assertInstanceOf(RedirectResponse::class, $response);
1316
        $this->assertSame(['flash_delete_success'], $this->session->getFlashBag()->get('sonata_flash_success'));
1317
        $this->assertSame('list', $response->getTargetUrl());
1318
    }
1319
1320
    public function testDeleteActionWrongRequestMethod(): void
1321
    {
1322
        $object = new \stdClass();
1323
1324
        $this->admin->expects($this->once())
1325
            ->method('getObject')
1326
            ->will($this->returnValue($object));
1327
1328
        $this->admin->expects($this->once())
1329
            ->method('checkAccess')
1330
            ->with($this->equalTo('delete'))
1331
            ->will($this->returnValue(true));
1332
1333
        //without POST request parameter "_method" should not be used as real REST method
1334
        $this->request->query->set('_method', 'DELETE');
1335
1336
        $this->assertInstanceOf(Response::class, $this->controller->deleteAction(1, $this->request));
1337
1338
        $this->assertSame($this->admin, $this->parameters['admin']);
1339
        $this->assertSame('@SonataAdmin/standard_layout.html.twig', $this->parameters['base_template']);
1340
        $this->assertSame($this->pool, $this->parameters['admin_pool']);
1341
1342
        $this->assertSame('delete', $this->parameters['action']);
1343
        $this->assertSame($object, $this->parameters['object']);
1344
        $this->assertSame('csrf-token-123_sonata.delete', $this->parameters['csrf_token']);
1345
1346
        $this->assertSame([], $this->session->getFlashBag()->all());
1347
        $this->assertSame('@SonataAdmin/CRUD/delete.html.twig', $this->template);
1348
    }
1349
1350
    /**
1351
     * @dataProvider getToStringValues
1352
     */
1353
    public function testDeleteActionError($expectedToStringValue, $toStringValue): void
1354
    {
1355
        $object = new \stdClass();
1356
1357
        $this->admin->expects($this->once())
1358
            ->method('getObject')
1359
            ->will($this->returnValue($object));
1360
1361
        $this->admin->expects($this->once())
1362
            ->method('checkAccess')
1363
            ->with($this->equalTo('delete'))
1364
            ->will($this->returnValue(true));
1365
1366
        $this->admin->expects($this->once())
1367
            ->method('toString')
1368
            ->with($this->equalTo($object))
1369
            ->will($this->returnValue($toStringValue));
1370
1371
        $this->expectTranslate('flash_delete_error', ['%name%' => $expectedToStringValue], 'SonataAdminBundle');
1372
1373
        $this->assertLoggerLogsModelManagerException($this->admin, 'delete');
1374
1375
        $this->request->setMethod('DELETE');
1376
        $this->request->request->set('_sonata_csrf_token', 'csrf-token-123_sonata.delete');
1377
1378
        $response = $this->controller->deleteAction(1, $this->request);
1379
1380
        $this->assertInstanceOf(RedirectResponse::class, $response);
1381
        $this->assertSame(['flash_delete_error'], $this->session->getFlashBag()->get('sonata_flash_error'));
1382
        $this->assertSame('list', $response->getTargetUrl());
1383
    }
1384
1385
    public function testDeleteActionInvalidCsrfToken(): void
1386
    {
1387
        $object = new \stdClass();
1388
1389
        $this->admin->expects($this->once())
1390
            ->method('getObject')
1391
            ->will($this->returnValue($object));
1392
1393
        $this->admin->expects($this->once())
1394
            ->method('checkAccess')
1395
            ->with($this->equalTo('delete'))
1396
            ->will($this->returnValue(true));
1397
1398
        $this->request->setMethod('POST');
1399
        $this->request->request->set('_method', 'DELETE');
1400
        $this->request->request->set('_sonata_csrf_token', 'CSRF-INVALID');
1401
1402
        try {
1403
            $this->controller->deleteAction(1, $this->request);
1404
        } catch (HttpException $e) {
1405
            $this->assertSame('The csrf token is not valid, CSRF attack?', $e->getMessage());
1406
            $this->assertSame(400, $e->getStatusCode());
1407
        }
1408
    }
1409
1410
    public function testEditActionNotFoundException(): void
1411
    {
1412
        $this->expectException(NotFoundHttpException::class);
1413
1414
        $this->admin->expects($this->once())
1415
            ->method('getObject')
1416
            ->will($this->returnValue(false));
1417
1418
        $this->controller->editAction(null, $this->request);
1419
    }
1420
1421
    public function testEditActionRuntimeException(): void
1422
    {
1423
        $this->expectException(\RuntimeException::class);
1424
1425
        $this->admin->expects($this->once())
1426
            ->method('getObject')
1427
            ->will($this->returnValue(new \stdClass()));
1428
1429
        $this->admin->expects($this->once())
1430
            ->method('checkAccess')
1431
            ->with($this->equalTo('edit'))
1432
            ->will($this->returnValue(true));
1433
1434
        $form = $this->createMock(Form::class);
1435
1436
        $this->admin->expects($this->once())
1437
            ->method('getForm')
1438
            ->will($this->returnValue($form));
1439
1440
        $form->expects($this->once())
1441
            ->method('all')
1442
            ->willReturn([]);
1443
1444
        $this->controller->editAction(null, $this->request);
1445
    }
1446
1447
    public function testEditActionAccessDenied(): void
1448
    {
1449
        $this->expectException(AccessDeniedException::class);
1450
1451
        $this->admin->expects($this->once())
1452
            ->method('getObject')
1453
            ->will($this->returnValue(new \stdClass()));
1454
1455
        $this->admin->expects($this->once())
1456
            ->method('checkAccess')
1457
            ->with($this->equalTo('edit'))
1458
            ->will($this->throwException(new AccessDeniedException()));
1459
1460
        $this->controller->editAction(null, $this->request);
1461
    }
1462
1463
    public function testPreEdit(): void
1464
    {
1465
        $object = new \stdClass();
1466
        $object->foo = 123456;
1467
1468
        $this->admin->expects($this->once())
1469
            ->method('getObject')
1470
            ->will($this->returnValue($object));
1471
1472
        $this->admin->expects($this->once())
1473
            ->method('checkAccess')
1474
            ->with($this->equalTo('edit'))
1475
            ->will($this->returnValue(true));
1476
1477
        $controller = new PreCRUDController();
1478
        $controller->setContainer($this->container);
1479
1480
        $response = $controller->editAction(null, $this->request);
1481
        $this->assertInstanceOf(Response::class, $response);
1482
        $this->assertSame('preEdit called: 123456', $response->getContent());
1483
    }
1484
1485
    public function testEditAction(): void
1486
    {
1487
        $object = new \stdClass();
1488
1489
        $this->admin->expects($this->once())
1490
            ->method('getObject')
1491
            ->will($this->returnValue($object));
1492
1493
        $this->admin->expects($this->once())
1494
            ->method('checkAccess')
1495
            ->with($this->equalTo('edit'))
1496
            ->will($this->returnValue(true));
1497
1498
        $form = $this->createMock(Form::class);
1499
1500
        $this->admin->expects($this->once())
1501
            ->method('getForm')
1502
            ->will($this->returnValue($form));
1503
1504
        $formView = $this->createMock(FormView::class);
1505
1506
        $form->expects($this->any())
1507
            ->method('createView')
1508
            ->will($this->returnValue($formView));
1509
1510
        $form->expects($this->once())
1511
            ->method('all')
1512
            ->willReturn(['field' => 'fielddata']);
1513
1514
        $this->assertInstanceOf(Response::class, $this->controller->editAction(null, $this->request));
1515
1516
        $this->assertSame($this->admin, $this->parameters['admin']);
1517
        $this->assertSame('@SonataAdmin/standard_layout.html.twig', $this->parameters['base_template']);
1518
        $this->assertSame($this->pool, $this->parameters['admin_pool']);
1519
1520
        $this->assertSame('edit', $this->parameters['action']);
1521
        $this->assertInstanceOf(FormView::class, $this->parameters['form']);
1522
        $this->assertSame($object, $this->parameters['object']);
1523
        $this->assertSame([], $this->session->getFlashBag()->all());
1524
        $this->assertSame('@SonataAdmin/CRUD/edit.html.twig', $this->template);
1525
    }
1526
1527
    /**
1528
     * @dataProvider getToStringValues
1529
     */
1530
    public function testEditActionSuccess($expectedToStringValue, $toStringValue): void
1531
    {
1532
        $object = new \stdClass();
1533
1534
        $this->admin->expects($this->once())
1535
            ->method('getObject')
1536
            ->will($this->returnValue($object));
1537
1538
        $this->admin->expects($this->once())
1539
            ->method('update')
1540
            ->will($this->returnArgument(0));
1541
1542
        $this->admin->expects($this->once())
0 ignored issues
show
The method expects() does not seem to exist on object<Sonata\AdminBundle\Admin\AdminInterface>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
1543
            ->method('checkAccess')
1544
            ->with($this->equalTo('edit'));
1545
1546
        $this->admin->expects($this->once())
1547
            ->method('hasRoute')
1548
            ->with($this->equalTo('edit'))
1549
            ->will($this->returnValue(true));
1550
1551
        $this->admin->expects($this->once())
1552
            ->method('hasAccess')
1553
            ->with($this->equalTo('edit'))
1554
            ->will($this->returnValue(true));
1555
1556
        $form = $this->createMock(Form::class);
1557
1558
        $form->expects($this->once())
1559
            ->method('getData')
1560
            ->will($this->returnValue($object));
1561
1562
        $this->admin->expects($this->once())
1563
            ->method('getForm')
1564
            ->will($this->returnValue($form));
1565
1566
        $form->expects($this->once())
1567
            ->method('isSubmitted')
1568
            ->will($this->returnValue(true));
1569
1570
        $form->expects($this->once())
1571
            ->method('isValid')
1572
            ->will($this->returnValue(true));
1573
1574
        $form->expects($this->once())
1575
            ->method('all')
1576
            ->willReturn(['field' => 'fielddata']);
1577
1578
        $this->admin->expects($this->once())
1579
            ->method('toString')
1580
            ->with($this->equalTo($object))
1581
            ->will($this->returnValue($toStringValue));
1582
1583
        $this->expectTranslate('flash_edit_success', ['%name%' => $expectedToStringValue], 'SonataAdminBundle');
1584
1585
        $this->request->setMethod('POST');
1586
1587
        $response = $this->controller->editAction(null, $this->request);
1588
1589
        $this->assertInstanceOf(RedirectResponse::class, $response);
1590
        $this->assertSame(['flash_edit_success'], $this->session->getFlashBag()->get('sonata_flash_success'));
1591
        $this->assertSame('stdClass_edit', $response->getTargetUrl());
1592
    }
1593
1594
    /**
1595
     * @dataProvider getToStringValues
1596
     */
1597
    public function testEditActionError($expectedToStringValue, $toStringValue): void
1598
    {
1599
        $object = new \stdClass();
1600
1601
        $this->admin->expects($this->once())
1602
            ->method('getObject')
1603
            ->will($this->returnValue($object));
1604
1605
        $this->admin->expects($this->once())
1606
            ->method('checkAccess')
1607
            ->with($this->equalTo('edit'))
1608
            ->will($this->returnValue(true));
1609
1610
        $form = $this->createMock(Form::class);
1611
1612
        $this->admin->expects($this->once())
1613
            ->method('getForm')
1614
            ->will($this->returnValue($form));
1615
1616
        $form->expects($this->once())
1617
            ->method('isSubmitted')
1618
            ->will($this->returnValue(true));
1619
1620
        $form->expects($this->once())
1621
            ->method('isValid')
1622
            ->will($this->returnValue(false));
1623
1624
        $form->expects($this->once())
1625
            ->method('all')
1626
            ->willReturn(['field' => 'fielddata']);
1627
1628
        $this->admin->expects($this->once())
1629
            ->method('toString')
1630
            ->with($this->equalTo($object))
1631
            ->will($this->returnValue($toStringValue));
1632
1633
        $this->expectTranslate('flash_edit_error', ['%name%' => $expectedToStringValue], 'SonataAdminBundle');
1634
1635
        $this->request->setMethod('POST');
1636
1637
        $formView = $this->createMock(FormView::class);
1638
1639
        $form->expects($this->any())
1640
            ->method('createView')
1641
            ->will($this->returnValue($formView));
1642
1643
        $this->assertInstanceOf(Response::class, $this->controller->editAction(null, $this->request));
1644
1645
        $this->assertSame($this->admin, $this->parameters['admin']);
1646
        $this->assertSame('@SonataAdmin/standard_layout.html.twig', $this->parameters['base_template']);
1647
        $this->assertSame($this->pool, $this->parameters['admin_pool']);
1648
1649
        $this->assertSame('edit', $this->parameters['action']);
1650
        $this->assertInstanceOf(FormView::class, $this->parameters['form']);
1651
        $this->assertSame($object, $this->parameters['object']);
1652
1653
        $this->assertSame(['sonata_flash_error' => ['flash_edit_error']], $this->session->getFlashBag()->all());
1654
        $this->assertSame('@SonataAdmin/CRUD/edit.html.twig', $this->template);
1655
    }
1656
1657
    public function testEditActionAjaxSuccess(): void
1658
    {
1659
        $object = new \stdClass();
1660
1661
        $this->admin->expects($this->once())
1662
            ->method('getObject')
1663
            ->will($this->returnValue($object));
1664
1665
        $this->admin->expects($this->once())
1666
            ->method('update')
1667
            ->will($this->returnArgument(0));
1668
1669
        $this->admin->expects($this->once())
0 ignored issues
show
The method expects() does not seem to exist on object<Sonata\AdminBundle\Admin\AdminInterface>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
1670
            ->method('checkAccess')
1671
            ->with($this->equalTo('edit'))
1672
            ->will($this->returnValue(true));
1673
1674
        $form = $this->createMock(Form::class);
1675
1676
        $this->admin->expects($this->once())
1677
            ->method('getForm')
1678
            ->will($this->returnValue($form));
1679
1680
        $form->expects($this->once())
1681
            ->method('isSubmitted')
1682
            ->will($this->returnValue(true));
1683
1684
        $form->expects($this->once())
1685
            ->method('isValid')
1686
            ->will($this->returnValue(true));
1687
1688
        $form->expects($this->once())
1689
            ->method('getData')
1690
            ->will($this->returnValue($object));
1691
1692
        $form->expects($this->once())
1693
            ->method('all')
1694
            ->willReturn(['field' => 'fielddata']);
1695
1696
        $this->admin->expects($this->once())
1697
            ->method('getNormalizedIdentifier')
1698
            ->with($this->equalTo($object))
1699
            ->will($this->returnValue('foo_normalized'));
1700
1701
        $this->admin->expects($this->once())
1702
            ->method('toString')
1703
            ->will($this->returnValue('foo'));
1704
1705
        $this->request->setMethod('POST');
1706
        $this->request->headers->set('X-Requested-With', 'XMLHttpRequest');
1707
1708
        $response = $this->controller->editAction(null, $this->request);
1709
1710
        $this->assertInstanceOf(Response::class, $response);
1711
        $this->assertSame(json_encode(['result' => 'ok', 'objectId' => 'foo_normalized', 'objectName' => 'foo']), $response->getContent());
1712
        $this->assertSame([], $this->session->getFlashBag()->all());
1713
    }
1714
1715
    public function testEditActionAjaxError(): void
1716
    {
1717
        $object = new \stdClass();
1718
1719
        $this->admin->expects($this->once())
1720
            ->method('getObject')
1721
            ->will($this->returnValue($object));
1722
1723
        $this->admin->expects($this->once())
1724
            ->method('checkAccess')
1725
            ->with($this->equalTo('edit'))
1726
            ->will($this->returnValue(true));
1727
1728
        $form = $this->createMock(Form::class);
1729
1730
        $this->admin->expects($this->once())
1731
            ->method('getForm')
1732
            ->will($this->returnValue($form));
1733
1734
        $form->expects($this->once())
1735
            ->method('isSubmitted')
1736
            ->will($this->returnValue(true));
1737
1738
        $form->expects($this->once())
1739
            ->method('isValid')
1740
            ->will($this->returnValue(false));
1741
1742
        $form->expects($this->once())
1743
            ->method('all')
1744
            ->willReturn(['field' => 'fielddata']);
1745
1746
        $this->request->setMethod('POST');
1747
        $this->request->headers->set('X-Requested-With', 'XMLHttpRequest');
1748
1749
        $formView = $this->createMock(FormView::class);
1750
1751
        $form->expects($this->any())
1752
            ->method('createView')
1753
            ->will($this->returnValue($formView));
1754
1755
        $this->assertInstanceOf(Response::class, $this->controller->editAction(null, $this->request));
1756
1757
        $this->assertSame($this->admin, $this->parameters['admin']);
1758
        $this->assertSame('@SonataAdmin/ajax_layout.html.twig', $this->parameters['base_template']);
1759
        $this->assertSame($this->pool, $this->parameters['admin_pool']);
1760
1761
        $this->assertSame('edit', $this->parameters['action']);
1762
        $this->assertInstanceOf(FormView::class, $this->parameters['form']);
1763
        $this->assertSame($object, $this->parameters['object']);
1764
1765
        $this->assertSame([], $this->session->getFlashBag()->all());
1766
        $this->assertSame('@SonataAdmin/CRUD/edit.html.twig', $this->template);
1767
    }
1768
1769
    /**
1770
     * @dataProvider getToStringValues
1771
     */
1772
    public function testEditActionWithModelManagerException($expectedToStringValue, $toStringValue): void
1773
    {
1774
        $object = new \stdClass();
1775
1776
        $this->admin->expects($this->once())
1777
            ->method('getObject')
1778
            ->will($this->returnValue($object));
1779
1780
        $this->admin->expects($this->once())
1781
            ->method('checkAccess')
1782
            ->with($this->equalTo('edit'))
1783
            ->will($this->returnValue(true));
1784
1785
        $this->admin->expects($this->any())
1786
            ->method('getClass')
1787
            ->will($this->returnValue('stdClass'));
1788
1789
        $form = $this->createMock(Form::class);
1790
1791
        $this->admin->expects($this->once())
1792
            ->method('getForm')
1793
            ->will($this->returnValue($form));
1794
1795
        $form->expects($this->once())
1796
            ->method('isValid')
1797
            ->will($this->returnValue(true));
1798
1799
        $form->expects($this->once())
1800
            ->method('getData')
1801
            ->will($this->returnValue($object));
1802
1803
        $form->expects($this->once())
1804
            ->method('all')
1805
            ->willReturn(['field' => 'fielddata']);
1806
1807
        $this->admin->expects($this->once())
1808
            ->method('toString')
1809
            ->with($this->equalTo($object))
1810
            ->will($this->returnValue($toStringValue));
1811
1812
        $this->expectTranslate('flash_edit_error', ['%name%' => $expectedToStringValue], 'SonataAdminBundle');
1813
1814
        $form->expects($this->once())
1815
            ->method('isSubmitted')
1816
            ->will($this->returnValue(true));
1817
        $this->request->setMethod('POST');
1818
1819
        $formView = $this->createMock(FormView::class);
1820
1821
        $form->expects($this->any())
1822
            ->method('createView')
1823
            ->will($this->returnValue($formView));
1824
1825
        $this->assertLoggerLogsModelManagerException($this->admin, 'update');
1826
        $this->assertInstanceOf(Response::class, $this->controller->editAction(null, $this->request));
1827
1828
        $this->assertSame($this->admin, $this->parameters['admin']);
1829
        $this->assertSame('@SonataAdmin/standard_layout.html.twig', $this->parameters['base_template']);
1830
        $this->assertSame($this->pool, $this->parameters['admin_pool']);
1831
1832
        $this->assertSame('edit', $this->parameters['action']);
1833
        $this->assertInstanceOf(FormView::class, $this->parameters['form']);
1834
        $this->assertSame($object, $this->parameters['object']);
1835
1836
        $this->assertSame(['sonata_flash_error' => ['flash_edit_error']], $this->session->getFlashBag()->all());
1837
        $this->assertSame('@SonataAdmin/CRUD/edit.html.twig', $this->template);
1838
    }
1839
1840
    public function testEditActionWithPreview(): void
1841
    {
1842
        $object = new \stdClass();
1843
1844
        $this->admin->expects($this->once())
1845
            ->method('getObject')
1846
            ->will($this->returnValue($object));
1847
1848
        $this->admin->expects($this->once())
0 ignored issues
show
The method expects() does not seem to exist on object<Sonata\AdminBundle\Admin\AdminInterface>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
1849
            ->method('checkAccess')
1850
            ->with($this->equalTo('edit'))
1851
            ->will($this->returnValue(true));
1852
1853
        $form = $this->createMock(Form::class);
1854
1855
        $this->admin->expects($this->once())
1856
            ->method('getForm')
1857
            ->will($this->returnValue($form));
1858
1859
        $this->admin->expects($this->once())
1860
            ->method('supportsPreviewMode')
1861
            ->will($this->returnValue(true));
1862
1863
        $formView = $this->createMock(FormView::class);
1864
1865
        $form->expects($this->any())
1866
            ->method('createView')
1867
            ->will($this->returnValue($formView));
1868
1869
        $form->expects($this->once())
1870
            ->method('isSubmitted')
1871
            ->will($this->returnValue(true));
1872
1873
        $form->expects($this->once())
1874
            ->method('isValid')
1875
            ->will($this->returnValue(true));
1876
1877
        $form->expects($this->once())
1878
            ->method('all')
1879
            ->willReturn(['field' => 'fielddata']);
1880
1881
        $this->request->setMethod('POST');
1882
        $this->request->request->set('btn_preview', 'Preview');
1883
1884
        $this->assertInstanceOf(Response::class, $this->controller->editAction(null, $this->request));
1885
1886
        $this->assertSame($this->admin, $this->parameters['admin']);
1887
        $this->assertSame('@SonataAdmin/standard_layout.html.twig', $this->parameters['base_template']);
1888
        $this->assertSame($this->pool, $this->parameters['admin_pool']);
1889
1890
        $this->assertSame('edit', $this->parameters['action']);
1891
        $this->assertInstanceOf(FormView::class, $this->parameters['form']);
1892
        $this->assertSame($object, $this->parameters['object']);
1893
1894
        $this->assertSame([], $this->session->getFlashBag()->all());
1895
        $this->assertSame('@SonataAdmin/CRUD/preview.html.twig', $this->template);
1896
    }
1897
1898
    public function testEditActionWithLockException(): void
1899
    {
1900
        $object = new \stdClass();
1901
        $class = \get_class($object);
1902
1903
        $this->admin->expects($this->any())
1904
            ->method('getObject')
1905
            ->will($this->returnValue($object));
1906
1907
        $this->admin->expects($this->any())
1908
            ->method('checkAccess')
1909
            ->with($this->equalTo('edit'))
1910
            ->will($this->returnValue(true));
1911
1912
        $this->admin->expects($this->any())
1913
            ->method('getClass')
1914
            ->will($this->returnValue($class));
1915
1916
        $form = $this->createMock(Form::class);
1917
1918
        $form->expects($this->any())
1919
            ->method('isValid')
1920
            ->will($this->returnValue(true));
1921
1922
        $form->expects($this->once())
1923
            ->method('getData')
1924
            ->will($this->returnValue($object));
1925
1926
        $form->expects($this->once())
1927
            ->method('all')
1928
            ->willReturn(['field' => 'fielddata']);
1929
1930
        $this->admin->expects($this->any())
1931
            ->method('getForm')
1932
            ->will($this->returnValue($form));
1933
1934
        $form->expects($this->any())
1935
            ->method('isSubmitted')
1936
            ->will($this->returnValue(true));
1937
        $this->request->setMethod('POST');
1938
1939
        $this->admin->expects($this->any())
1940
            ->method('update')
1941
            ->will($this->throwException(new LockException()));
1942
1943
        $this->admin->expects($this->any())
1944
            ->method('toString')
1945
            ->with($this->equalTo($object))
1946
            ->will($this->returnValue($class));
1947
1948
        $formView = $this->createMock(FormView::class);
1949
1950
        $form->expects($this->any())
1951
            ->method('createView')
1952
            ->will($this->returnValue($formView));
1953
1954
        $this->expectTranslate('flash_lock_error', [
1955
            '%name%' => $class,
1956
            '%link_start%' => '<a href="stdClass_edit">',
1957
            '%link_end%' => '</a>',
1958
        ], 'SonataAdminBundle');
1959
1960
        $this->assertInstanceOf(Response::class, $this->controller->editAction(null, $this->request));
1961
    }
1962
1963
    public function testCreateActionAccessDenied(): void
1964
    {
1965
        $this->expectException(AccessDeniedException::class);
1966
1967
        $this->admin->expects($this->once())
1968
            ->method('checkAccess')
1969
            ->with($this->equalTo('create'))
1970
            ->will($this->throwException(new AccessDeniedException()));
1971
1972
        $this->controller->createAction($this->request);
1973
    }
1974
1975
    public function testCreateActionRuntimeException(): void
1976
    {
1977
        $this->expectException(\RuntimeException::class);
1978
1979
        $this->admin->expects($this->once())
1980
            ->method('checkAccess')
1981
            ->with($this->equalTo('create'))
1982
            ->will($this->returnValue(true));
1983
1984
        $this->admin->expects($this->any())
1985
            ->method('getClass')
1986
            ->will($this->returnValue('stdClass'));
1987
1988
        $this->admin->expects($this->once())
1989
            ->method('getNewInstance')
1990
            ->will($this->returnValue(new \stdClass()));
1991
1992
        $form = $this->createMock(Form::class);
1993
1994
        $this->admin->expects($this->once())
1995
            ->method('getForm')
1996
            ->will($this->returnValue($form));
1997
1998
        $form->expects($this->once())
1999
            ->method('all')
2000
            ->willReturn([]);
2001
2002
        $this->controller->createAction($this->request);
2003
    }
2004
2005
    public function testPreCreate(): void
2006
    {
2007
        $object = new \stdClass();
2008
        $object->foo = 123456;
2009
2010
        $this->admin->expects($this->once())
2011
            ->method('checkAccess')
2012
            ->with($this->equalTo('create'))
2013
            ->will($this->returnValue(true));
2014
2015
        $this->admin->expects($this->any())
2016
            ->method('getClass')
2017
            ->will($this->returnValue('stdClass'));
2018
2019
        $this->admin->expects($this->once())
2020
            ->method('getNewInstance')
2021
            ->will($this->returnValue($object));
2022
2023
        $controller = new PreCRUDController();
2024
        $controller->setContainer($this->container);
2025
2026
        $response = $controller->createAction($this->request);
2027
        $this->assertInstanceOf(Response::class, $response);
2028
        $this->assertSame('preCreate called: 123456', $response->getContent());
2029
    }
2030
2031
    public function testCreateAction(): void
2032
    {
2033
        $this->admin->expects($this->once())
2034
            ->method('checkAccess')
2035
            ->with($this->equalTo('create'))
2036
            ->will($this->returnValue(true));
2037
2038
        $object = new \stdClass();
2039
2040
        $this->admin->expects($this->any())
2041
            ->method('getClass')
2042
            ->will($this->returnValue('stdClass'));
2043
2044
        $this->admin->expects($this->once())
2045
            ->method('getNewInstance')
2046
            ->will($this->returnValue($object));
2047
2048
        $form = $this->createMock(Form::class);
2049
2050
        $this->admin->expects($this->once())
2051
            ->method('getForm')
2052
            ->will($this->returnValue($form));
2053
2054
        $form->expects($this->once())
2055
            ->method('all')
2056
            ->willReturn(['field' => 'fielddata']);
2057
2058
        $formView = $this->createMock(FormView::class);
2059
2060
        $form->expects($this->any())
2061
            ->method('createView')
2062
            ->will($this->returnValue($formView));
2063
2064
        $this->assertInstanceOf(Response::class, $this->controller->createAction($this->request));
2065
2066
        $this->assertSame($this->admin, $this->parameters['admin']);
2067
        $this->assertSame('@SonataAdmin/standard_layout.html.twig', $this->parameters['base_template']);
2068
        $this->assertSame($this->pool, $this->parameters['admin_pool']);
2069
2070
        $this->assertSame('create', $this->parameters['action']);
2071
        $this->assertInstanceOf(FormView::class, $this->parameters['form']);
2072
        $this->assertSame($object, $this->parameters['object']);
2073
2074
        $this->assertSame([], $this->session->getFlashBag()->all());
2075
        $this->assertSame('@SonataAdmin/CRUD/edit.html.twig', $this->template);
2076
    }
2077
2078
    /**
2079
     * @dataProvider getToStringValues
2080
     */
2081
    public function testCreateActionSuccess($expectedToStringValue, $toStringValue): void
2082
    {
2083
        $object = new \stdClass();
2084
2085
        $this->admin->expects($this->exactly(2))
2086
            ->method('checkAccess')
2087
            ->will($this->returnCallback(static function ($name, $objectIn = null) use ($object) {
2088
                if ('edit' === $name) {
2089
                    return true;
2090
                }
2091
2092
                if ('create' !== $name) {
2093
                    return false;
2094
                }
2095
2096
                if (null === $objectIn) {
2097
                    return true;
2098
                }
2099
2100
                return $objectIn === $object;
2101
            }));
2102
2103
        $this->admin->expects($this->once())
2104
            ->method('hasRoute')
2105
            ->with($this->equalTo('edit'))
2106
            ->will($this->returnValue(true));
2107
2108
        $this->admin->expects($this->once())
2109
            ->method('hasAccess')
2110
            ->with($this->equalTo('edit'))
2111
            ->will($this->returnValue(true));
2112
2113
        $this->admin->expects($this->once())
2114
            ->method('getNewInstance')
2115
            ->will($this->returnValue($object));
2116
2117
        $this->admin->expects($this->once())
2118
            ->method('create')
2119
            ->will($this->returnArgument(0));
2120
2121
        $form = $this->createMock(Form::class);
2122
2123
        $this->admin->expects($this->any())
2124
            ->method('getClass')
2125
            ->will($this->returnValue('stdClass'));
2126
2127
        $this->admin->expects($this->once())
2128
            ->method('getForm')
2129
            ->will($this->returnValue($form));
2130
2131
        $form->expects($this->once())
2132
            ->method('all')
2133
            ->willReturn(['field' => 'fielddata']);
2134
2135
        $form->expects($this->once())
2136
            ->method('isSubmitted')
2137
            ->will($this->returnValue(true));
2138
2139
        $form->expects($this->once())
2140
            ->method('isValid')
2141
            ->will($this->returnValue(true));
2142
2143
        $form->expects($this->once())
2144
            ->method('getData')
2145
            ->will($this->returnValue($object));
2146
2147
        $this->admin->expects($this->once())
2148
            ->method('toString')
2149
            ->with($this->equalTo($object))
2150
            ->will($this->returnValue($toStringValue));
2151
2152
        $this->expectTranslate('flash_create_success', ['%name%' => $expectedToStringValue], 'SonataAdminBundle');
2153
2154
        $this->request->setMethod('POST');
2155
2156
        $response = $this->controller->createAction($this->request);
2157
2158
        $this->assertInstanceOf(RedirectResponse::class, $response);
2159
        $this->assertSame(['flash_create_success'], $this->session->getFlashBag()->get('sonata_flash_success'));
2160
        $this->assertSame('stdClass_edit', $response->getTargetUrl());
2161
    }
2162
2163
    public function testCreateActionAccessDenied2(): void
2164
    {
2165
        $this->expectException(AccessDeniedException::class);
2166
2167
        $object = new \stdClass();
2168
2169
        $this->admin->expects($this->any())
2170
            ->method('checkAccess')
2171
            ->will($this->returnCallback(static function ($name, $object = null) {
2172
                if ('create' !== $name) {
2173
                    throw new AccessDeniedException();
2174
                }
2175
                if (null === $object) {
2176
                    return true;
2177
                }
2178
2179
                throw new AccessDeniedException();
2180
            }));
2181
2182
        $this->admin->expects($this->once())
2183
            ->method('getNewInstance')
2184
            ->will($this->returnValue($object));
2185
2186
        $form = $this->createMock(Form::class);
2187
2188
        $this->admin->expects($this->any())
2189
            ->method('getClass')
2190
            ->will($this->returnValue('stdClass'));
2191
2192
        $this->admin->expects($this->once())
2193
            ->method('getForm')
2194
            ->will($this->returnValue($form));
2195
2196
        $form->expects($this->once())
2197
            ->method('all')
2198
            ->willReturn(['field' => 'fielddata']);
2199
2200
        $form->expects($this->once())
2201
            ->method('isSubmitted')
2202
            ->will($this->returnValue(true));
2203
2204
        $form->expects($this->once())
2205
            ->method('getData')
2206
            ->will($this->returnValue($object));
2207
2208
        $form->expects($this->once())
2209
            ->method('isValid')
2210
            ->will($this->returnValue(true));
2211
2212
        $this->request->setMethod('POST');
2213
2214
        $this->controller->createAction($this->request);
2215
    }
2216
2217
    /**
2218
     * @dataProvider getToStringValues
2219
     */
2220
    public function testCreateActionError($expectedToStringValue, $toStringValue): void
2221
    {
2222
        $this->admin->expects($this->once())
2223
            ->method('checkAccess')
2224
            ->with($this->equalTo('create'))
2225
            ->will($this->returnValue(true));
2226
2227
        $object = new \stdClass();
2228
2229
        $this->admin->expects($this->any())
2230
            ->method('getClass')
2231
            ->will($this->returnValue('stdClass'));
2232
2233
        $this->admin->expects($this->once())
2234
            ->method('getNewInstance')
2235
            ->will($this->returnValue($object));
2236
2237
        $form = $this->createMock(Form::class);
2238
2239
        $this->admin->expects($this->once())
2240
            ->method('getForm')
2241
            ->will($this->returnValue($form));
2242
2243
        $form->expects($this->once())
2244
            ->method('all')
2245
            ->willReturn(['field' => 'fielddata']);
2246
2247
        $form->expects($this->once())
2248
            ->method('isSubmitted')
2249
            ->will($this->returnValue(true));
2250
2251
        $form->expects($this->once())
2252
            ->method('isValid')
2253
            ->will($this->returnValue(false));
2254
2255
        $this->admin->expects($this->once())
2256
            ->method('toString')
2257
            ->with($this->equalTo($object))
2258
            ->will($this->returnValue($toStringValue));
2259
2260
        $this->expectTranslate('flash_create_error', ['%name%' => $expectedToStringValue], 'SonataAdminBundle');
2261
2262
        $this->request->setMethod('POST');
2263
2264
        $formView = $this->createMock(FormView::class);
2265
2266
        $form->expects($this->any())
2267
            ->method('createView')
2268
            ->will($this->returnValue($formView));
2269
2270
        $this->assertInstanceOf(Response::class, $this->controller->createAction($this->request));
2271
2272
        $this->assertSame($this->admin, $this->parameters['admin']);
2273
        $this->assertSame('@SonataAdmin/standard_layout.html.twig', $this->parameters['base_template']);
2274
        $this->assertSame($this->pool, $this->parameters['admin_pool']);
2275
2276
        $this->assertSame('create', $this->parameters['action']);
2277
        $this->assertInstanceOf(FormView::class, $this->parameters['form']);
2278
        $this->assertSame($object, $this->parameters['object']);
2279
2280
        $this->assertSame(['sonata_flash_error' => ['flash_create_error']], $this->session->getFlashBag()->all());
2281
        $this->assertSame('@SonataAdmin/CRUD/edit.html.twig', $this->template);
2282
    }
2283
2284
    /**
2285
     * @dataProvider getToStringValues
2286
     */
2287
    public function testCreateActionWithModelManagerException($expectedToStringValue, $toStringValue): void
2288
    {
2289
        $this->admin->expects($this->exactly(2))
2290
            ->method('checkAccess')
2291
            ->with($this->equalTo('create'))
2292
            ->will($this->returnValue(true));
2293
2294
        $this->admin->expects($this->any())
2295
            ->method('getClass')
2296
            ->will($this->returnValue('stdClass'));
2297
2298
        $object = new \stdClass();
2299
2300
        $this->admin->expects($this->once())
2301
            ->method('getNewInstance')
2302
            ->will($this->returnValue($object));
2303
2304
        $form = $this->createMock(Form::class);
2305
2306
        $this->admin->expects($this->once())
2307
            ->method('getForm')
2308
            ->will($this->returnValue($form));
2309
2310
        $form->expects($this->once())
2311
            ->method('all')
2312
            ->willReturn(['field' => 'fielddata']);
2313
2314
        $form->expects($this->once())
2315
            ->method('isValid')
2316
            ->will($this->returnValue(true));
2317
2318
        $this->admin->expects($this->once())
2319
            ->method('toString')
2320
            ->with($this->equalTo($object))
2321
            ->will($this->returnValue($toStringValue));
2322
2323
        $this->expectTranslate('flash_create_error', ['%name%' => $expectedToStringValue], 'SonataAdminBundle');
2324
2325
        $form->expects($this->once())
2326
            ->method('isSubmitted')
2327
            ->will($this->returnValue(true));
2328
2329
        $form->expects($this->once())
2330
            ->method('getData')
2331
            ->will($this->returnValue($object));
2332
2333
        $this->request->setMethod('POST');
2334
2335
        $formView = $this->createMock(FormView::class);
2336
2337
        $form->expects($this->any())
2338
            ->method('createView')
2339
            ->will($this->returnValue($formView));
2340
2341
        $this->assertLoggerLogsModelManagerException($this->admin, 'create');
2342
2343
        $this->assertInstanceOf(Response::class, $this->controller->createAction($this->request));
2344
2345
        $this->assertSame($this->admin, $this->parameters['admin']);
2346
        $this->assertSame('@SonataAdmin/standard_layout.html.twig', $this->parameters['base_template']);
2347
        $this->assertSame($this->pool, $this->parameters['admin_pool']);
2348
2349
        $this->assertSame('create', $this->parameters['action']);
2350
        $this->assertInstanceOf(FormView::class, $this->parameters['form']);
2351
        $this->assertSame($object, $this->parameters['object']);
2352
2353
        $this->assertSame(['sonata_flash_error' => ['flash_create_error']], $this->session->getFlashBag()->all());
2354
        $this->assertSame('@SonataAdmin/CRUD/edit.html.twig', $this->template);
2355
    }
2356
2357
    public function testCreateActionAjaxSuccess(): void
2358
    {
2359
        $object = new \stdClass();
2360
2361
        $this->admin->expects($this->exactly(2))
2362
            ->method('checkAccess')
2363
            ->will($this->returnCallback(static function ($name, $objectIn = null) use ($object) {
2364
                if ('create' !== $name) {
2365
                    return false;
2366
                }
2367
2368
                if (null === $objectIn) {
2369
                    return true;
2370
                }
2371
2372
                return $objectIn === $object;
2373
            }));
2374
2375
        $this->admin->expects($this->once())
2376
            ->method('getNewInstance')
2377
            ->will($this->returnValue($object));
2378
2379
        $this->admin->expects($this->once())
2380
            ->method('create')
2381
            ->will($this->returnArgument(0));
2382
2383
        $form = $this->createMock(Form::class);
2384
2385
        $this->admin->expects($this->once())
2386
            ->method('getForm')
2387
            ->will($this->returnValue($form));
2388
2389
        $form->expects($this->once())
2390
            ->method('all')
2391
            ->willReturn(['field' => 'fielddata']);
2392
2393
        $form->expects($this->once())
2394
            ->method('isSubmitted')
2395
            ->will($this->returnValue(true));
2396
2397
        $form->expects($this->once())
2398
            ->method('isValid')
2399
            ->will($this->returnValue(true));
2400
2401
        $form->expects($this->once())
2402
            ->method('getData')
2403
            ->will($this->returnValue($object));
2404
2405
        $this->admin->expects($this->any())
2406
            ->method('getClass')
2407
            ->will($this->returnValue('stdClass'));
2408
2409
        $this->admin->expects($this->once())
2410
            ->method('getNormalizedIdentifier')
2411
            ->with($this->equalTo($object))
2412
            ->will($this->returnValue('foo_normalized'));
2413
2414
        $this->admin->expects($this->once())
2415
            ->method('toString')
2416
            ->will($this->returnValue('foo'));
2417
2418
        $this->request->setMethod('POST');
2419
        $this->request->headers->set('X-Requested-With', 'XMLHttpRequest');
2420
2421
        $response = $this->controller->createAction($this->request);
2422
2423
        $this->assertInstanceOf(Response::class, $response);
2424
        $this->assertSame(json_encode(['result' => 'ok', 'objectId' => 'foo_normalized', 'objectName' => 'foo']), $response->getContent());
2425
        $this->assertSame([], $this->session->getFlashBag()->all());
2426
    }
2427
2428
    public function testCreateActionAjaxError(): void
2429
    {
2430
        $this->admin->expects($this->once())
2431
            ->method('checkAccess')
2432
            ->with($this->equalTo('create'))
2433
            ->will($this->returnValue(true));
2434
2435
        $object = new \stdClass();
2436
2437
        $this->admin->expects($this->once())
2438
            ->method('getNewInstance')
2439
            ->will($this->returnValue($object));
2440
2441
        $form = $this->createMock(Form::class);
2442
2443
        $this->admin->expects($this->any())
2444
            ->method('getClass')
2445
            ->will($this->returnValue('stdClass'));
2446
2447
        $this->admin->expects($this->once())
2448
            ->method('getForm')
2449
            ->will($this->returnValue($form));
2450
2451
        $form->expects($this->once())
2452
            ->method('all')
2453
            ->willReturn(['field' => 'fielddata']);
2454
2455
        $form->expects($this->once())
2456
            ->method('isSubmitted')
2457
            ->will($this->returnValue(true));
2458
2459
        $form->expects($this->once())
2460
            ->method('isValid')
2461
            ->will($this->returnValue(false));
2462
2463
        $this->request->setMethod('POST');
2464
        $this->request->headers->set('X-Requested-With', 'XMLHttpRequest');
2465
2466
        $formView = $this->createMock(FormView::class);
2467
2468
        $form->expects($this->any())
2469
            ->method('createView')
2470
            ->will($this->returnValue($formView));
2471
2472
        $this->assertInstanceOf(Response::class, $this->controller->createAction($this->request));
2473
2474
        $this->assertSame($this->admin, $this->parameters['admin']);
2475
        $this->assertSame('@SonataAdmin/ajax_layout.html.twig', $this->parameters['base_template']);
2476
        $this->assertSame($this->pool, $this->parameters['admin_pool']);
2477
2478
        $this->assertSame('create', $this->parameters['action']);
2479
        $this->assertInstanceOf(FormView::class, $this->parameters['form']);
2480
        $this->assertSame($object, $this->parameters['object']);
2481
2482
        $this->assertSame([], $this->session->getFlashBag()->all());
2483
        $this->assertSame('@SonataAdmin/CRUD/edit.html.twig', $this->template);
2484
    }
2485
2486
    public function testCreateActionWithPreview(): void
2487
    {
2488
        $this->admin->expects($this->once())
2489
            ->method('checkAccess')
2490
            ->with($this->equalTo('create'))
2491
            ->will($this->returnValue(true));
2492
2493
        $object = new \stdClass();
2494
2495
        $this->admin->expects($this->once())
2496
            ->method('getNewInstance')
2497
            ->will($this->returnValue($object));
2498
2499
        $form = $this->createMock(Form::class);
2500
2501
        $this->admin->expects($this->any())
2502
            ->method('getClass')
2503
            ->will($this->returnValue('stdClass'));
2504
2505
        $this->admin->expects($this->once())
2506
            ->method('getForm')
2507
            ->will($this->returnValue($form));
2508
2509
        $form->expects($this->once())
2510
            ->method('all')
2511
            ->willReturn(['field' => 'fielddata']);
2512
2513
        $this->admin->expects($this->once())
2514
            ->method('supportsPreviewMode')
2515
            ->will($this->returnValue(true));
2516
2517
        $formView = $this->createMock(FormView::class);
2518
2519
        $form->expects($this->any())
2520
            ->method('createView')
2521
            ->will($this->returnValue($formView));
2522
2523
        $form->expects($this->once())
2524
            ->method('isSubmitted')
2525
            ->will($this->returnValue(true));
2526
2527
        $form->expects($this->once())
2528
            ->method('isValid')
2529
            ->will($this->returnValue(true));
2530
2531
        $this->request->setMethod('POST');
2532
        $this->request->request->set('btn_preview', 'Preview');
2533
2534
        $this->assertInstanceOf(Response::class, $this->controller->createAction($this->request));
2535
2536
        $this->assertSame($this->admin, $this->parameters['admin']);
2537
        $this->assertSame('@SonataAdmin/standard_layout.html.twig', $this->parameters['base_template']);
2538
        $this->assertSame($this->pool, $this->parameters['admin_pool']);
2539
2540
        $this->assertSame('create', $this->parameters['action']);
2541
        $this->assertInstanceOf(FormView::class, $this->parameters['form']);
2542
        $this->assertSame($object, $this->parameters['object']);
2543
2544
        $this->assertSame([], $this->session->getFlashBag()->all());
2545
        $this->assertSame('@SonataAdmin/CRUD/preview.html.twig', $this->template);
2546
    }
2547
2548
    public function testExportActionAccessDenied(): void
2549
    {
2550
        $this->expectException(AccessDeniedException::class);
2551
2552
        $this->admin->expects($this->once())
2553
            ->method('checkAccess')
2554
            ->with($this->equalTo('export'))
2555
            ->will($this->throwException(new AccessDeniedException()));
2556
2557
        $this->controller->exportAction($this->request);
2558
    }
2559
2560
    public function testExportActionWrongFormat(): void
2561
    {
2562
        $this->expectException(\RuntimeException::class, 'Export in format `csv` is not allowed for class: `Foo`. Allowed formats are: `json`');
2563
2564
        $this->admin->expects($this->once())
2565
            ->method('checkAccess')
2566
            ->with($this->equalTo('export'))
2567
            ->will($this->returnValue(true));
2568
2569
        $this->admin->expects($this->once())
2570
            ->method('getExportFormats')
2571
            ->will($this->returnValue(['json']));
2572
2573
        $this->admin->expects($this->any())
2574
            ->method('getClass')
2575
            ->will($this->returnValue('Foo'));
2576
2577
        $this->request->query->set('format', 'csv');
2578
2579
        $this->controller->exportAction($this->request);
2580
    }
2581
2582
    public function testExportAction(): void
2583
    {
2584
        $this->admin->expects($this->once())
2585
            ->method('checkAccess')
2586
            ->with($this->equalTo('export'))
2587
            ->will($this->returnValue(true));
2588
2589
        $this->admin->expects($this->once())
2590
            ->method('getExportFormats')
2591
            ->will($this->returnValue(['json']));
2592
2593
        $this->admin->expects($this->once())
2594
            ->method('getClass')
2595
            ->will($this->returnValue(\stdClass::class));
2596
2597
        $dataSourceIterator = $this->createMock(SourceIteratorInterface::class);
2598
2599
        $this->admin->expects($this->once())
2600
            ->method('getDataSourceIterator')
2601
            ->will($this->returnValue($dataSourceIterator));
2602
2603
        $this->request->query->set('format', 'json');
2604
2605
        $response = $this->controller->exportAction($this->request);
2606
        $this->assertInstanceOf(StreamedResponse::class, $response);
2607
        $this->assertSame(200, $response->getStatusCode());
2608
        $this->assertSame([], $this->session->getFlashBag()->all());
2609
    }
2610
2611
    public function testHistoryActionAccessDenied(): void
2612
    {
2613
        $this->expectException(AccessDeniedException::class);
2614
2615
        $this->admin->expects($this->any())
2616
            ->method('getObject')
2617
            ->will($this->returnValue(new \StdClass()));
2618
2619
        $this->admin->expects($this->once())
2620
            ->method('checkAccess')
2621
            ->with($this->equalTo('history'))
2622
            ->will($this->throwException(new AccessDeniedException()));
2623
2624
        $this->controller->historyAction(null, $this->request);
2625
    }
2626
2627
    public function testHistoryActionNotFoundException(): void
2628
    {
2629
        $this->expectException(NotFoundHttpException::class);
2630
2631
        $this->admin->expects($this->once())
2632
            ->method('getObject')
2633
            ->will($this->returnValue(false));
2634
2635
        $this->controller->historyAction(null, $this->request);
2636
    }
2637
2638
    public function testHistoryActionNoReader(): void
2639
    {
2640
        $this->expectException(NotFoundHttpException::class, 'unable to find the audit reader for class : Foo');
2641
2642
        $this->request->query->set('id', 123);
2643
2644
        $this->admin->expects($this->once())
2645
            ->method('checkAccess')
2646
            ->with($this->equalTo('history'))
2647
            ->will($this->returnValue(true));
2648
2649
        $object = new \stdClass();
2650
2651
        $this->admin->expects($this->once())
2652
            ->method('getObject')
2653
            ->will($this->returnValue($object));
2654
2655
        $this->admin->expects($this->any())
2656
            ->method('getClass')
2657
            ->will($this->returnValue('Foo'));
2658
2659
        $this->auditManager->expects($this->once())
2660
            ->method('hasReader')
2661
            ->with($this->equalTo('Foo'))
2662
            ->will($this->returnValue(false));
2663
2664
        $this->controller->historyAction(null, $this->request);
2665
    }
2666
2667
    public function testHistoryAction(): void
2668
    {
2669
        $this->request->query->set('id', 123);
2670
2671
        $this->admin->expects($this->once())
2672
            ->method('checkAccess')
2673
            ->with($this->equalTo('history'))
2674
            ->will($this->returnValue(true));
2675
2676
        $object = new \stdClass();
2677
2678
        $this->admin->expects($this->once())
2679
            ->method('getObject')
2680
            ->will($this->returnValue($object));
2681
2682
        $this->admin->expects($this->any())
2683
            ->method('getClass')
2684
            ->will($this->returnValue('Foo'));
2685
2686
        $this->auditManager->expects($this->once())
2687
            ->method('hasReader')
2688
            ->with($this->equalTo('Foo'))
2689
            ->will($this->returnValue(true));
2690
2691
        $reader = $this->createMock(AuditReaderInterface::class);
2692
2693
        $this->auditManager->expects($this->once())
2694
            ->method('getReader')
2695
            ->with($this->equalTo('Foo'))
2696
            ->will($this->returnValue($reader));
2697
2698
        $reader->expects($this->once())
2699
            ->method('findRevisions')
2700
            ->with($this->equalTo('Foo'), $this->equalTo(123))
2701
            ->will($this->returnValue([]));
2702
2703
        $this->assertInstanceOf(Response::class, $this->controller->historyAction(null, $this->request));
2704
2705
        $this->assertSame($this->admin, $this->parameters['admin']);
2706
        $this->assertSame('@SonataAdmin/standard_layout.html.twig', $this->parameters['base_template']);
2707
        $this->assertSame($this->pool, $this->parameters['admin_pool']);
2708
2709
        $this->assertSame('history', $this->parameters['action']);
2710
        $this->assertSame([], $this->parameters['revisions']);
2711
        $this->assertSame($object, $this->parameters['object']);
2712
2713
        $this->assertSame([], $this->session->getFlashBag()->all());
2714
        $this->assertSame('@SonataAdmin/CRUD/history.html.twig', $this->template);
2715
    }
2716
2717
    public function testAclActionAclNotEnabled(): void
2718
    {
2719
        $this->expectException(NotFoundHttpException::class, 'ACL are not enabled for this admin');
2720
2721
        $this->controller->aclAction(null, $this->request);
2722
    }
2723
2724
    public function testAclActionNotFoundException(): void
2725
    {
2726
        $this->expectException(NotFoundHttpException::class);
2727
2728
        $this->admin->expects($this->once())
2729
            ->method('isAclEnabled')
2730
            ->will($this->returnValue(true));
2731
2732
        $this->admin->expects($this->once())
2733
            ->method('getObject')
2734
            ->will($this->returnValue(false));
2735
2736
        $this->controller->aclAction(null, $this->request);
2737
    }
2738
2739
    public function testAclActionAccessDenied(): void
2740
    {
2741
        $this->expectException(AccessDeniedException::class);
2742
2743
        $this->admin->expects($this->once())
2744
            ->method('isAclEnabled')
2745
            ->will($this->returnValue(true));
2746
2747
        $object = new \stdClass();
2748
2749
        $this->admin->expects($this->once())
2750
            ->method('getObject')
2751
            ->will($this->returnValue($object));
2752
2753
        $this->admin->expects($this->once())
2754
            ->method('checkAccess')
2755
            ->with($this->equalTo('acl'), $this->equalTo($object))
2756
            ->will($this->throwException(new AccessDeniedException()));
2757
2758
        $this->controller->aclAction(null, $this->request);
2759
    }
2760
2761
    public function testAclAction(): void
2762
    {
2763
        $this->request->query->set('id', 123);
2764
2765
        $this->admin->expects($this->once())
2766
            ->method('isAclEnabled')
2767
            ->will($this->returnValue(true));
2768
2769
        $object = new \stdClass();
2770
2771
        $this->admin->expects($this->once())
2772
            ->method('getObject')
2773
            ->will($this->returnValue($object));
2774
2775
        $this->admin->expects($this->any())
2776
            ->method('checkAccess')
2777
            ->will($this->returnValue(true));
2778
2779
        $this->admin->expects($this->any())
2780
            ->method('getSecurityInformation')
2781
            ->will($this->returnValue([]));
2782
2783
        $this->adminObjectAclManipulator->expects($this->once())
2784
            ->method('getMaskBuilderClass')
2785
            ->will($this->returnValue(AdminPermissionMap::class));
2786
2787
        $aclUsersForm = $this->getMockBuilder(Form::class)
2788
            ->disableOriginalConstructor()
2789
            ->getMock();
2790
2791
        $aclUsersForm->expects($this->once())
2792
            ->method('createView')
2793
            ->will($this->returnValue($this->createMock(FormView::class)));
2794
2795
        $aclRolesForm = $this->getMockBuilder(Form::class)
2796
            ->disableOriginalConstructor()
2797
            ->getMock();
2798
2799
        $aclRolesForm->expects($this->once())
2800
            ->method('createView')
2801
            ->will($this->returnValue($this->createMock(FormView::class)));
2802
2803
        $this->adminObjectAclManipulator->expects($this->once())
2804
            ->method('createAclUsersForm')
2805
            ->with($this->isInstanceOf(AdminObjectAclData::class))
2806
            ->will($this->returnValue($aclUsersForm));
2807
2808
        $this->adminObjectAclManipulator->expects($this->once())
2809
            ->method('createAclRolesForm')
2810
            ->with($this->isInstanceOf(AdminObjectAclData::class))
2811
            ->will($this->returnValue($aclRolesForm));
2812
2813
        $aclSecurityHandler = $this->getMockBuilder(AclSecurityHandler::class)
2814
            ->disableOriginalConstructor()
2815
            ->getMock();
2816
2817
        $aclSecurityHandler->expects($this->any())
2818
            ->method('getObjectPermissions')
2819
            ->will($this->returnValue([]));
2820
2821
        $this->admin->expects($this->any())
2822
            ->method('getSecurityHandler')
2823
            ->will($this->returnValue($aclSecurityHandler));
2824
2825
        $this->assertInstanceOf(Response::class, $this->controller->aclAction(null, $this->request));
2826
2827
        $this->assertSame($this->admin, $this->parameters['admin']);
2828
        $this->assertSame('@SonataAdmin/standard_layout.html.twig', $this->parameters['base_template']);
2829
        $this->assertSame($this->pool, $this->parameters['admin_pool']);
2830
2831
        $this->assertSame('acl', $this->parameters['action']);
2832
        $this->assertSame([], $this->parameters['permissions']);
2833
        $this->assertSame($object, $this->parameters['object']);
2834
        $this->assertInstanceOf(\ArrayIterator::class, $this->parameters['users']);
2835
        $this->assertInstanceOf(\ArrayIterator::class, $this->parameters['roles']);
2836
        $this->assertInstanceOf(FormView::class, $this->parameters['aclUsersForm']);
2837
        $this->assertInstanceOf(FormView::class, $this->parameters['aclRolesForm']);
2838
2839
        $this->assertSame([], $this->session->getFlashBag()->all());
2840
        $this->assertSame('@SonataAdmin/CRUD/acl.html.twig', $this->template);
2841
    }
2842
2843
    public function testAclActionInvalidUpdate(): void
2844
    {
2845
        $this->request->query->set('id', 123);
2846
        $this->request->request->set(AdminObjectAclManipulator::ACL_USERS_FORM_NAME, []);
2847
2848
        $this->admin->expects($this->once())
2849
            ->method('isAclEnabled')
2850
            ->will($this->returnValue(true));
2851
2852
        $object = new \stdClass();
2853
2854
        $this->admin->expects($this->once())
2855
            ->method('getObject')
2856
            ->will($this->returnValue($object));
2857
2858
        $this->admin->expects($this->any())
2859
            ->method('checkAccess')
2860
            ->will($this->returnValue(true));
2861
2862
        $this->admin->expects($this->any())
2863
            ->method('getSecurityInformation')
2864
            ->will($this->returnValue([]));
2865
2866
        $this->adminObjectAclManipulator->expects($this->once())
2867
            ->method('getMaskBuilderClass')
2868
            ->will($this->returnValue(AdminPermissionMap::class));
2869
2870
        $aclUsersForm = $this->getMockBuilder(Form::class)
2871
            ->disableOriginalConstructor()
2872
            ->getMock();
2873
2874
        $aclUsersForm->expects($this->once())
2875
            ->method('isValid')
2876
            ->will($this->returnValue(false));
2877
2878
        $aclUsersForm->expects($this->once())
2879
            ->method('createView')
2880
            ->will($this->returnValue($this->createMock(FormView::class)));
2881
2882
        $aclRolesForm = $this->getMockBuilder(Form::class)
2883
            ->disableOriginalConstructor()
2884
            ->getMock();
2885
2886
        $aclRolesForm->expects($this->once())
2887
            ->method('createView')
2888
            ->will($this->returnValue($this->createMock(FormView::class)));
2889
2890
        $this->adminObjectAclManipulator->expects($this->once())
2891
            ->method('createAclUsersForm')
2892
            ->with($this->isInstanceOf(AdminObjectAclData::class))
2893
            ->will($this->returnValue($aclUsersForm));
2894
2895
        $this->adminObjectAclManipulator->expects($this->once())
2896
            ->method('createAclRolesForm')
2897
            ->with($this->isInstanceOf(AdminObjectAclData::class))
2898
            ->will($this->returnValue($aclRolesForm));
2899
2900
        $aclSecurityHandler = $this->getMockBuilder(AclSecurityHandler::class)
2901
            ->disableOriginalConstructor()
2902
            ->getMock();
2903
2904
        $aclSecurityHandler->expects($this->any())
2905
            ->method('getObjectPermissions')
2906
            ->will($this->returnValue([]));
2907
2908
        $this->admin->expects($this->any())
2909
            ->method('getSecurityHandler')
2910
            ->will($this->returnValue($aclSecurityHandler));
2911
2912
        $this->request->setMethod('POST');
2913
2914
        $this->assertInstanceOf(Response::class, $this->controller->aclAction(null, $this->request));
2915
2916
        $this->assertSame($this->admin, $this->parameters['admin']);
2917
        $this->assertSame('@SonataAdmin/standard_layout.html.twig', $this->parameters['base_template']);
2918
        $this->assertSame($this->pool, $this->parameters['admin_pool']);
2919
2920
        $this->assertSame('acl', $this->parameters['action']);
2921
        $this->assertSame([], $this->parameters['permissions']);
2922
        $this->assertSame($object, $this->parameters['object']);
2923
        $this->assertInstanceOf(\ArrayIterator::class, $this->parameters['users']);
2924
        $this->assertInstanceOf(\ArrayIterator::class, $this->parameters['roles']);
2925
        $this->assertInstanceOf(FormView::class, $this->parameters['aclUsersForm']);
2926
        $this->assertInstanceOf(FormView::class, $this->parameters['aclRolesForm']);
2927
2928
        $this->assertSame([], $this->session->getFlashBag()->all());
2929
        $this->assertSame('@SonataAdmin/CRUD/acl.html.twig', $this->template);
2930
    }
2931
2932
    public function testAclActionSuccessfulUpdate(): void
2933
    {
2934
        $this->request->query->set('id', 123);
2935
        $this->request->request->set(AdminObjectAclManipulator::ACL_ROLES_FORM_NAME, []);
2936
2937
        $this->admin->expects($this->once())
2938
            ->method('isAclEnabled')
2939
            ->will($this->returnValue(true));
2940
2941
        $object = new \stdClass();
2942
2943
        $this->admin->expects($this->once())
2944
            ->method('getObject')
2945
            ->will($this->returnValue($object));
2946
2947
        $this->admin->expects($this->any())
2948
            ->method('checkAccess')
2949
            ->will($this->returnValue(true));
2950
2951
        $this->admin->expects($this->any())
2952
            ->method('getSecurityInformation')
2953
            ->will($this->returnValue([]));
2954
2955
        $this->adminObjectAclManipulator->expects($this->once())
2956
            ->method('getMaskBuilderClass')
2957
            ->will($this->returnValue(AdminPermissionMap::class));
2958
2959
        $aclUsersForm = $this->getMockBuilder(Form::class)
2960
            ->disableOriginalConstructor()
2961
            ->getMock();
2962
2963
        $aclUsersForm->expects($this->any())
2964
            ->method('createView')
2965
            ->will($this->returnValue($this->createMock(FormView::class)));
2966
2967
        $aclRolesForm = $this->getMockBuilder(Form::class)
2968
            ->disableOriginalConstructor()
2969
            ->getMock();
2970
2971
        $aclRolesForm->expects($this->any())
2972
            ->method('createView')
2973
            ->will($this->returnValue($this->createMock(FormView::class)));
2974
2975
        $aclRolesForm->expects($this->once())
2976
            ->method('isValid')
2977
            ->will($this->returnValue(true));
2978
2979
        $this->adminObjectAclManipulator->expects($this->once())
2980
            ->method('createAclUsersForm')
2981
            ->with($this->isInstanceOf(AdminObjectAclData::class))
2982
            ->will($this->returnValue($aclUsersForm));
2983
2984
        $this->adminObjectAclManipulator->expects($this->once())
2985
            ->method('createAclRolesForm')
2986
            ->with($this->isInstanceOf(AdminObjectAclData::class))
2987
            ->will($this->returnValue($aclRolesForm));
2988
2989
        $aclSecurityHandler = $this->getMockBuilder(AclSecurityHandler::class)
2990
            ->disableOriginalConstructor()
2991
            ->getMock();
2992
2993
        $aclSecurityHandler->expects($this->any())
2994
            ->method('getObjectPermissions')
2995
            ->will($this->returnValue([]));
2996
2997
        $this->admin->expects($this->any())
2998
            ->method('getSecurityHandler')
2999
            ->will($this->returnValue($aclSecurityHandler));
3000
3001
        $this->expectTranslate('flash_acl_edit_success', [], 'SonataAdminBundle');
3002
3003
        $this->request->setMethod('POST');
3004
3005
        $response = $this->controller->aclAction(null, $this->request);
3006
3007
        $this->assertInstanceOf(RedirectResponse::class, $response);
3008
3009
        $this->assertSame(['flash_acl_edit_success'], $this->session->getFlashBag()->get('sonata_flash_success'));
3010
        $this->assertSame('stdClass_acl', $response->getTargetUrl());
3011
    }
3012
3013
    public function testHistoryViewRevisionActionAccessDenied(): void
3014
    {
3015
        $this->expectException(AccessDeniedException::class);
3016
3017
        $this->admin->expects($this->any())
3018
            ->method('getObject')
3019
            ->will($this->returnValue(new \StdClass()));
3020
3021
        $this->admin->expects($this->once())
3022
            ->method('checkAccess')
3023
            ->with($this->equalTo('historyViewRevision'))
3024
            ->will($this->throwException(new AccessDeniedException()));
3025
3026
        $this->controller->historyViewRevisionAction(null, null, $this->request);
3027
    }
3028
3029
    public function testHistoryViewRevisionActionNotFoundException(): void
3030
    {
3031
        $this->expectException(NotFoundHttpException::class, 'unable to find the object with id: 123');
3032
3033
        $this->request->query->set('id', 123);
3034
3035
        $this->admin->expects($this->once())
3036
            ->method('getObject')
3037
            ->will($this->returnValue(false));
3038
3039
        $this->controller->historyViewRevisionAction(null, null, $this->request);
3040
    }
3041
3042
    public function testHistoryViewRevisionActionNoReader(): void
3043
    {
3044
        $this->expectException(NotFoundHttpException::class, 'unable to find the audit reader for class : Foo');
3045
3046
        $this->request->query->set('id', 123);
3047
3048
        $this->admin->expects($this->once())
3049
            ->method('checkAccess')
3050
            ->with($this->equalTo('historyViewRevision'))
3051
            ->will($this->returnValue(true));
3052
3053
        $object = new \stdClass();
3054
3055
        $this->admin->expects($this->once())
3056
            ->method('getObject')
3057
            ->will($this->returnValue($object));
3058
3059
        $this->admin->expects($this->any())
3060
            ->method('getClass')
3061
            ->will($this->returnValue('Foo'));
3062
3063
        $this->auditManager->expects($this->once())
3064
            ->method('hasReader')
3065
            ->with($this->equalTo('Foo'))
3066
            ->will($this->returnValue(false));
3067
3068
        $this->controller->historyViewRevisionAction(null, null, $this->request);
3069
    }
3070
3071
    public function testHistoryViewRevisionActionNotFoundRevision(): void
3072
    {
3073
        $this->expectException(NotFoundHttpException::class, 'unable to find the targeted object `123` from the revision `456` with classname : `Foo`');
3074
3075
        $this->request->query->set('id', 123);
3076
3077
        $this->admin->expects($this->once())
3078
            ->method('checkAccess')
3079
            ->with($this->equalTo('historyViewRevision'))
3080
            ->will($this->returnValue(true));
3081
3082
        $object = new \stdClass();
3083
3084
        $this->admin->expects($this->once())
3085
            ->method('getObject')
3086
            ->will($this->returnValue($object));
3087
3088
        $this->admin->expects($this->any())
3089
            ->method('getClass')
3090
            ->will($this->returnValue('Foo'));
3091
3092
        $this->auditManager->expects($this->once())
3093
            ->method('hasReader')
3094
            ->with($this->equalTo('Foo'))
3095
            ->will($this->returnValue(true));
3096
3097
        $reader = $this->createMock(AuditReaderInterface::class);
3098
3099
        $this->auditManager->expects($this->once())
3100
            ->method('getReader')
3101
            ->with($this->equalTo('Foo'))
3102
            ->will($this->returnValue($reader));
3103
3104
        $reader->expects($this->once())
3105
            ->method('find')
3106
            ->with($this->equalTo('Foo'), $this->equalTo(123), $this->equalTo(456))
3107
            ->will($this->returnValue(null));
3108
3109
        $this->controller->historyViewRevisionAction(123, 456, $this->request);
3110
    }
3111
3112
    public function testHistoryViewRevisionAction(): void
3113
    {
3114
        $this->request->query->set('id', 123);
3115
3116
        $this->admin->expects($this->once())
3117
            ->method('checkAccess')
3118
            ->with($this->equalTo('historyViewRevision'))
3119
            ->will($this->returnValue(true));
3120
3121
        $object = new \stdClass();
3122
3123
        $this->admin->expects($this->once())
3124
            ->method('getObject')
3125
            ->will($this->returnValue($object));
3126
3127
        $this->admin->expects($this->any())
3128
            ->method('getClass')
3129
            ->will($this->returnValue('Foo'));
3130
3131
        $this->auditManager->expects($this->once())
3132
            ->method('hasReader')
3133
            ->with($this->equalTo('Foo'))
3134
            ->will($this->returnValue(true));
3135
3136
        $reader = $this->createMock(AuditReaderInterface::class);
3137
3138
        $this->auditManager->expects($this->once())
3139
            ->method('getReader')
3140
            ->with($this->equalTo('Foo'))
3141
            ->will($this->returnValue($reader));
3142
3143
        $objectRevision = new \stdClass();
3144
        $objectRevision->revision = 456;
3145
3146
        $reader->expects($this->once())
3147
            ->method('find')
3148
            ->with($this->equalTo('Foo'), $this->equalTo(123), $this->equalTo(456))
3149
            ->will($this->returnValue($objectRevision));
3150
3151
        $this->admin->expects($this->once())
3152
            ->method('setSubject')
3153
            ->with($this->equalTo($objectRevision))
3154
            ->will($this->returnValue(null));
3155
3156
        $fieldDescriptionCollection = new FieldDescriptionCollection();
3157
        $this->admin->expects($this->once())
3158
            ->method('getShow')
3159
            ->will($this->returnValue($fieldDescriptionCollection));
3160
3161
        $this->assertInstanceOf(Response::class, $this->controller->historyViewRevisionAction(123, 456, $this->request));
3162
3163
        $this->assertSame($this->admin, $this->parameters['admin']);
3164
        $this->assertSame('@SonataAdmin/standard_layout.html.twig', $this->parameters['base_template']);
3165
        $this->assertSame($this->pool, $this->parameters['admin_pool']);
3166
3167
        $this->assertSame('show', $this->parameters['action']);
3168
        $this->assertSame($objectRevision, $this->parameters['object']);
3169
        $this->assertSame($fieldDescriptionCollection, $this->parameters['elements']);
3170
3171
        $this->assertSame([], $this->session->getFlashBag()->all());
3172
        $this->assertSame('@SonataAdmin/CRUD/show.html.twig', $this->template);
3173
    }
3174
3175
    public function testHistoryCompareRevisionsActionAccessDenied(): void
3176
    {
3177
        $this->expectException(AccessDeniedException::class);
3178
3179
        $this->admin->expects($this->once())
3180
            ->method('checkAccess')
3181
            ->with($this->equalTo('historyCompareRevisions'))
3182
            ->will($this->throwException(new AccessDeniedException()));
3183
3184
        $this->controller->historyCompareRevisionsAction(null, null, null, $this->request);
3185
    }
3186
3187
    public function testHistoryCompareRevisionsActionNotFoundException(): void
3188
    {
3189
        $this->expectException(NotFoundHttpException::class, 'unable to find the object with id: 123');
3190
3191
        $this->request->query->set('id', 123);
3192
3193
        $this->admin->expects($this->once())
3194
            ->method('checkAccess')
3195
            ->with($this->equalTo('historyCompareRevisions'))
3196
            ->will($this->returnValue(true));
3197
3198
        $this->admin->expects($this->once())
3199
            ->method('getObject')
3200
            ->will($this->returnValue(false));
3201
3202
        $this->controller->historyCompareRevisionsAction(null, null, null, $this->request);
3203
    }
3204
3205
    public function testHistoryCompareRevisionsActionNoReader(): void
3206
    {
3207
        $this->expectException(NotFoundHttpException::class, 'unable to find the audit reader for class : Foo');
3208
3209
        $this->request->query->set('id', 123);
3210
3211
        $this->admin->expects($this->once())
3212
            ->method('checkAccess')
3213
            ->with($this->equalTo('historyCompareRevisions'))
3214
            ->will($this->returnValue(true));
3215
3216
        $object = new \stdClass();
3217
3218
        $this->admin->expects($this->once())
3219
            ->method('getObject')
3220
            ->will($this->returnValue($object));
3221
3222
        $this->admin->expects($this->any())
3223
            ->method('getClass')
3224
            ->will($this->returnValue('Foo'));
3225
3226
        $this->auditManager->expects($this->once())
3227
            ->method('hasReader')
3228
            ->with($this->equalTo('Foo'))
3229
            ->will($this->returnValue(false));
3230
3231
        $this->controller->historyCompareRevisionsAction(null, null, null, $this->request);
3232
    }
3233
3234
    public function testHistoryCompareRevisionsActionNotFoundBaseRevision(): void
3235
    {
3236
        $this->expectException(NotFoundHttpException::class, 'unable to find the targeted object `123` from the revision `456` with classname : `Foo`');
3237
3238
        $this->request->query->set('id', 123);
3239
3240
        $this->admin->expects($this->once())
3241
            ->method('checkAccess')
3242
            ->with($this->equalTo('historyCompareRevisions'))
3243
            ->will($this->returnValue(true));
3244
3245
        $object = new \stdClass();
3246
3247
        $this->admin->expects($this->once())
0 ignored issues
show
The method expects() does not seem to exist on object<Sonata\AdminBundle\Admin\AdminInterface>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
3248
            ->method('getObject')
3249
            ->will($this->returnValue($object));
3250
3251
        $this->admin->expects($this->any())
3252
            ->method('getClass')
3253
            ->will($this->returnValue('Foo'));
3254
3255
        $this->auditManager->expects($this->once())
3256
            ->method('hasReader')
3257
            ->with($this->equalTo('Foo'))
3258
            ->will($this->returnValue(true));
3259
3260
        $reader = $this->createMock(AuditReaderInterface::class);
3261
3262
        $this->auditManager->expects($this->once())
3263
            ->method('getReader')
3264
            ->with($this->equalTo('Foo'))
3265
            ->will($this->returnValue($reader));
3266
3267
        // once because it will not be found and therefore the second call won't be executed
3268
        $reader->expects($this->once())
3269
            ->method('find')
3270
            ->with($this->equalTo('Foo'), $this->equalTo(123), $this->equalTo(456))
3271
            ->will($this->returnValue(null));
3272
3273
        $this->controller->historyCompareRevisionsAction(123, 456, 789, $this->request);
3274
    }
3275
3276
    public function testHistoryCompareRevisionsActionNotFoundCompareRevision(): void
3277
    {
3278
        $this->expectException(NotFoundHttpException::class, 'unable to find the targeted object `123` from the revision `789` with classname : `Foo`');
3279
3280
        $this->request->query->set('id', 123);
3281
3282
        $this->admin->expects($this->once())
3283
            ->method('checkAccess')
3284
            ->with($this->equalTo('historyCompareRevisions'))
3285
            ->will($this->returnValue(true));
3286
3287
        $object = new \stdClass();
3288
3289
        $this->admin->expects($this->once())
3290
            ->method('getObject')
3291
            ->will($this->returnValue($object));
3292
3293
        $this->admin->expects($this->any())
3294
            ->method('getClass')
3295
            ->will($this->returnValue('Foo'));
3296
3297
        $this->auditManager->expects($this->once())
3298
            ->method('hasReader')
3299
            ->with($this->equalTo('Foo'))
3300
            ->will($this->returnValue(true));
3301
3302
        $reader = $this->createMock(AuditReaderInterface::class);
3303
3304
        $this->auditManager->expects($this->once())
3305
            ->method('getReader')
3306
            ->with($this->equalTo('Foo'))
3307
            ->will($this->returnValue($reader));
3308
3309
        $objectRevision = new \stdClass();
3310
        $objectRevision->revision = 456;
3311
3312
        // first call should return, so the second call will throw an exception
3313
        $reader->expects($this->at(0))
3314
            ->method('find')
3315
            ->with($this->equalTo('Foo'), $this->equalTo(123), $this->equalTo(456))
3316
            ->will($this->returnValue($objectRevision));
3317
3318
        $reader->expects($this->at(1))
3319
            ->method('find')
3320
            ->with($this->equalTo('Foo'), $this->equalTo(123), $this->equalTo(789))
3321
            ->will($this->returnValue(null));
3322
3323
        $this->controller->historyCompareRevisionsAction(123, 456, 789, $this->request);
3324
    }
3325
3326
    public function testHistoryCompareRevisionsActionAction(): void
3327
    {
3328
        $this->request->query->set('id', 123);
3329
3330
        $this->admin->expects($this->once())
3331
            ->method('checkAccess')
3332
            ->with($this->equalTo('historyCompareRevisions'))
3333
            ->will($this->returnValue(true));
3334
3335
        $object = new \stdClass();
3336
3337
        $this->admin->expects($this->once())
3338
            ->method('getObject')
3339
            ->will($this->returnValue($object));
3340
3341
        $this->admin->expects($this->any())
3342
            ->method('getClass')
3343
            ->will($this->returnValue('Foo'));
3344
3345
        $this->auditManager->expects($this->once())
3346
            ->method('hasReader')
3347
            ->with($this->equalTo('Foo'))
3348
            ->will($this->returnValue(true));
3349
3350
        $reader = $this->createMock(AuditReaderInterface::class);
3351
3352
        $this->auditManager->expects($this->once())
3353
            ->method('getReader')
3354
            ->with($this->equalTo('Foo'))
3355
            ->will($this->returnValue($reader));
3356
3357
        $objectRevision = new \stdClass();
3358
        $objectRevision->revision = 456;
3359
3360
        $compareObjectRevision = new \stdClass();
3361
        $compareObjectRevision->revision = 789;
3362
3363
        $reader->expects($this->at(0))
3364
            ->method('find')
3365
            ->with($this->equalTo('Foo'), $this->equalTo(123), $this->equalTo(456))
3366
            ->will($this->returnValue($objectRevision));
3367
3368
        $reader->expects($this->at(1))
3369
            ->method('find')
3370
            ->with($this->equalTo('Foo'), $this->equalTo(123), $this->equalTo(789))
3371
            ->will($this->returnValue($compareObjectRevision));
3372
3373
        $this->admin->expects($this->once())
3374
            ->method('setSubject')
3375
            ->with($this->equalTo($objectRevision))
3376
            ->will($this->returnValue(null));
3377
3378
        $fieldDescriptionCollection = new FieldDescriptionCollection();
3379
        $this->admin->expects($this->once())
3380
            ->method('getShow')
3381
            ->will($this->returnValue($fieldDescriptionCollection));
3382
3383
        $this->assertInstanceOf(Response::class, $this->controller->historyCompareRevisionsAction(123, 456, 789, $this->request));
3384
3385
        $this->assertSame($this->admin, $this->parameters['admin']);
3386
        $this->assertSame('@SonataAdmin/standard_layout.html.twig', $this->parameters['base_template']);
3387
        $this->assertSame($this->pool, $this->parameters['admin_pool']);
3388
3389
        $this->assertSame('show', $this->parameters['action']);
3390
        $this->assertSame($objectRevision, $this->parameters['object']);
3391
        $this->assertSame($compareObjectRevision, $this->parameters['object_compare']);
3392
        $this->assertSame($fieldDescriptionCollection, $this->parameters['elements']);
3393
3394
        $this->assertSame([], $this->session->getFlashBag()->all());
3395
        $this->assertSame('@SonataAdmin/CRUD/show_compare.html.twig', $this->template);
3396
    }
3397
3398
    public function testBatchActionWrongMethod(): void
3399
    {
3400
        $this->expectException(NotFoundHttpException::class, 'Invalid request type "GET", POST expected');
3401
3402
        $this->controller->batchAction($this->request);
3403
    }
3404
3405
    public function testBatchActionActionNotDefined(): void
3406
    {
3407
        $this->expectException(\RuntimeException::class, 'The `foo` batch action is not defined');
3408
3409
        $batchActions = [];
3410
3411
        $this->admin->expects($this->once())
3412
            ->method('getBatchActions')
3413
            ->will($this->returnValue($batchActions));
3414
3415
        $this->request->setMethod('POST');
3416
        $this->request->request->set('data', json_encode(['action' => 'foo', 'idx' => ['123', '456'], 'all_elements' => false]));
3417
        $this->request->request->set('_sonata_csrf_token', 'csrf-token-123_sonata.batch');
3418
3419
        $this->controller->batchAction($this->request);
3420
    }
3421
3422
    public function testBatchActionActionInvalidCsrfToken(): void
3423
    {
3424
        $this->request->setMethod('POST');
3425
        $this->request->request->set('data', json_encode(['action' => 'foo', 'idx' => ['123', '456'], 'all_elements' => false]));
3426
        $this->request->request->set('_sonata_csrf_token', 'CSRF-INVALID');
3427
3428
        try {
3429
            $this->controller->batchAction($this->request);
3430
        } catch (HttpException $e) {
3431
            $this->assertSame('The csrf token is not valid, CSRF attack?', $e->getMessage());
3432
            $this->assertSame(400, $e->getStatusCode());
3433
        }
3434
    }
3435
3436
    public function testBatchActionMethodNotExist(): void
3437
    {
3438
        $this->expectException(\RuntimeException::class, 'A `Sonata\AdminBundle\Controller\CRUDController::batchActionFoo` method must be callable');
3439
3440
        $batchActions = ['foo' => ['label' => 'Foo Bar', 'ask_confirmation' => false]];
3441
3442
        $this->admin->expects($this->once())
3443
            ->method('getBatchActions')
3444
            ->will($this->returnValue($batchActions));
3445
3446
        $datagrid = $this->createMock(DatagridInterface::class);
3447
        $this->admin->expects($this->once())
3448
            ->method('getDatagrid')
3449
            ->will($this->returnValue($datagrid));
3450
3451
        $this->request->setMethod('POST');
3452
        $this->request->request->set('data', json_encode(['action' => 'foo', 'idx' => ['123', '456'], 'all_elements' => false]));
3453
        $this->request->request->set('_sonata_csrf_token', 'csrf-token-123_sonata.batch');
3454
3455
        $this->controller->batchAction($this->request);
3456
    }
3457
3458
    public function testBatchActionWithoutConfirmation(): void
3459
    {
3460
        $batchActions = ['delete' => ['label' => 'Foo Bar', 'ask_confirmation' => false]];
3461
3462
        $this->admin->expects($this->once())
3463
            ->method('getBatchActions')
3464
            ->will($this->returnValue($batchActions));
3465
3466
        $datagrid = $this->createMock(DatagridInterface::class);
3467
3468
        $query = $this->createMock(ProxyQueryInterface::class);
3469
        $datagrid->expects($this->once())
3470
            ->method('getQuery')
3471
            ->will($this->returnValue($query));
3472
3473
        $this->admin->expects($this->once())
3474
            ->method('getDatagrid')
3475
            ->will($this->returnValue($datagrid));
3476
3477
        $modelManager = $this->createMock(ModelManagerInterface::class);
3478
3479
        $this->admin->expects($this->once())
3480
            ->method('checkAccess')
3481
            ->with($this->equalTo('batchDelete'))
3482
            ->will($this->returnValue(true));
3483
3484
        $this->admin->expects($this->any())
3485
            ->method('getModelManager')
3486
            ->will($this->returnValue($modelManager));
3487
3488
        $this->admin->expects($this->any())
3489
            ->method('getClass')
3490
            ->will($this->returnValue('Foo'));
3491
3492
        $modelManager->expects($this->once())
3493
            ->method('addIdentifiersToQuery')
3494
            ->with($this->equalTo('Foo'), $this->equalTo($query), $this->equalTo(['123', '456']))
3495
            ->will($this->returnValue(true));
3496
3497
        $this->expectTranslate('flash_batch_delete_success', [], 'SonataAdminBundle');
3498
3499
        $this->request->setMethod('POST');
3500
        $this->request->request->set('data', json_encode(['action' => 'delete', 'idx' => ['123', '456'], 'all_elements' => false]));
3501
        $this->request->request->set('_sonata_csrf_token', 'csrf-token-123_sonata.batch');
3502
3503
        $result = $this->controller->batchAction($this->request);
3504
3505
        $this->assertInstanceOf(RedirectResponse::class, $result);
3506
        $this->assertSame(['flash_batch_delete_success'], $this->session->getFlashBag()->get('sonata_flash_success'));
3507
        $this->assertSame('list', $result->getTargetUrl());
3508
    }
3509
3510
    public function testBatchActionWithoutConfirmation2(): void
3511
    {
3512
        $batchActions = ['delete' => ['label' => 'Foo Bar', 'ask_confirmation' => false]];
3513
3514
        $this->admin->expects($this->once())
3515
            ->method('getBatchActions')
3516
            ->will($this->returnValue($batchActions));
3517
3518
        $datagrid = $this->createMock(DatagridInterface::class);
3519
3520
        $query = $this->createMock(ProxyQueryInterface::class);
3521
        $datagrid->expects($this->once())
3522
            ->method('getQuery')
3523
            ->will($this->returnValue($query));
3524
3525
        $this->admin->expects($this->once())
3526
            ->method('getDatagrid')
3527
            ->will($this->returnValue($datagrid));
3528
3529
        $modelManager = $this->createMock(ModelManagerInterface::class);
3530
3531
        $this->admin->expects($this->once())
3532
            ->method('checkAccess')
3533
            ->with($this->equalTo('batchDelete'))
3534
            ->will($this->returnValue(true));
3535
3536
        $this->admin->expects($this->any())
3537
            ->method('getModelManager')
3538
            ->will($this->returnValue($modelManager));
3539
3540
        $this->admin->expects($this->any())
3541
            ->method('getClass')
3542
            ->will($this->returnValue('Foo'));
3543
3544
        $modelManager->expects($this->once())
3545
            ->method('addIdentifiersToQuery')
3546
            ->with($this->equalTo('Foo'), $this->equalTo($query), $this->equalTo(['123', '456']))
3547
            ->will($this->returnValue(true));
3548
3549
        $this->expectTranslate('flash_batch_delete_success', [], 'SonataAdminBundle');
3550
3551
        $this->request->setMethod('POST');
3552
        $this->request->request->set('action', 'delete');
3553
        $this->request->request->set('idx', ['123', '456']);
3554
        $this->request->request->set('_sonata_csrf_token', 'csrf-token-123_sonata.batch');
3555
3556
        $result = $this->controller->batchAction($this->request);
3557
3558
        $this->assertInstanceOf(RedirectResponse::class, $result);
3559
        $this->assertSame(['flash_batch_delete_success'], $this->session->getFlashBag()->get('sonata_flash_success'));
3560
        $this->assertSame('list', $result->getTargetUrl());
3561
    }
3562
3563
    public function testBatchActionWithConfirmation(): void
3564
    {
3565
        $batchActions = ['delete' => ['label' => 'Foo Bar', 'translation_domain' => 'FooBarBaz', 'ask_confirmation' => true]];
3566
3567
        $this->admin->expects($this->once())
3568
            ->method('getBatchActions')
3569
            ->will($this->returnValue($batchActions));
3570
3571
        $data = ['action' => 'delete', 'idx' => ['123', '456'], 'all_elements' => false];
3572
3573
        $this->request->setMethod('POST');
3574
        $this->request->request->set('data', json_encode($data));
3575
        $this->request->request->set('_sonata_csrf_token', 'csrf-token-123_sonata.batch');
3576
3577
        $datagrid = $this->createMock(DatagridInterface::class);
3578
3579
        $this->admin->expects($this->once())
3580
            ->method('getDatagrid')
3581
            ->will($this->returnValue($datagrid));
3582
3583
        $form = $this->getMockBuilder(Form::class)
3584
            ->disableOriginalConstructor()
3585
            ->getMock();
3586
3587
        $form->expects($this->once())
3588
            ->method('createView')
3589
            ->will($this->returnValue($this->createMock(FormView::class)));
3590
3591
        $datagrid->expects($this->once())
3592
            ->method('getForm')
3593
            ->will($this->returnValue($form));
3594
3595
        $this->assertInstanceOf(Response::class, $this->controller->batchAction($this->request));
3596
3597
        $this->assertSame($this->admin, $this->parameters['admin']);
3598
        $this->assertSame('@SonataAdmin/standard_layout.html.twig', $this->parameters['base_template']);
3599
        $this->assertSame($this->pool, $this->parameters['admin_pool']);
3600
3601
        $this->assertSame('list', $this->parameters['action']);
3602
        $this->assertSame($datagrid, $this->parameters['datagrid']);
3603
        $this->assertInstanceOf(FormView::class, $this->parameters['form']);
3604
        $this->assertSame($data, $this->parameters['data']);
3605
        $this->assertSame('csrf-token-123_sonata.batch', $this->parameters['csrf_token']);
3606
        $this->assertSame('Foo Bar', $this->parameters['action_label']);
3607
3608
        $this->assertSame([], $this->session->getFlashBag()->all());
3609
        $this->assertSame('@SonataAdmin/CRUD/batch_confirmation.html.twig', $this->template);
3610
    }
3611
3612
    public function testBatchActionNonRelevantAction(): void
3613
    {
3614
        $controller = new BatchAdminController();
3615
        $controller->setContainer($this->container);
3616
3617
        $batchActions = ['foo' => ['label' => 'Foo Bar', 'ask_confirmation' => false]];
3618
3619
        $this->admin->expects($this->once())
3620
            ->method('getBatchActions')
3621
            ->will($this->returnValue($batchActions));
3622
3623
        $datagrid = $this->createMock(DatagridInterface::class);
3624
3625
        $this->admin->expects($this->once())
3626
            ->method('getDatagrid')
3627
            ->will($this->returnValue($datagrid));
3628
3629
        $this->expectTranslate('flash_batch_empty', [], 'SonataAdminBundle');
3630
3631
        $this->request->setMethod('POST');
3632
        $this->request->request->set('action', 'foo');
3633
        $this->request->request->set('idx', ['789']);
3634
        $this->request->request->set('_sonata_csrf_token', 'csrf-token-123_sonata.batch');
3635
3636
        $result = $controller->batchAction($this->request);
3637
3638
        $this->assertInstanceOf(RedirectResponse::class, $result);
3639
        $this->assertSame(['flash_batch_empty'], $this->session->getFlashBag()->get('sonata_flash_info'));
3640
        $this->assertSame('list', $result->getTargetUrl());
3641
    }
3642
3643
    public function testBatchActionWithCustomConfirmationTemplate(): void
3644
    {
3645
        $batchActions = ['delete' => ['label' => 'Foo Bar', 'ask_confirmation' => true, 'template' => 'custom_template.html.twig']];
3646
3647
        $this->admin->expects($this->once())
3648
            ->method('getBatchActions')
3649
            ->will($this->returnValue($batchActions));
3650
3651
        $data = ['action' => 'delete', 'idx' => ['123', '456'], 'all_elements' => false];
3652
3653
        $this->request->setMethod('POST');
3654
        $this->request->request->set('data', json_encode($data));
3655
        $this->request->request->set('_sonata_csrf_token', 'csrf-token-123_sonata.batch');
3656
3657
        $datagrid = $this->createMock(DatagridInterface::class);
3658
3659
        $this->admin->expects($this->once())
3660
            ->method('getDatagrid')
3661
            ->will($this->returnValue($datagrid));
3662
3663
        $form = $this->createMock(Form::class);
3664
3665
        $form->expects($this->once())
3666
            ->method('createView')
3667
            ->will($this->returnValue($this->createMock(FormView::class)));
3668
3669
        $datagrid->expects($this->once())
3670
            ->method('getForm')
3671
            ->will($this->returnValue($form));
3672
3673
        $this->controller->batchAction($this->request);
3674
3675
        $this->assertSame('custom_template.html.twig', $this->template);
3676
    }
3677
3678
    public function testBatchActionNonRelevantAction2(): void
3679
    {
3680
        $controller = new BatchAdminController();
3681
        $controller->setContainer($this->container);
3682
3683
        $batchActions = ['foo' => ['label' => 'Foo Bar', 'ask_confirmation' => false]];
3684
3685
        $this->admin->expects($this->once())
3686
            ->method('getBatchActions')
3687
            ->will($this->returnValue($batchActions));
3688
3689
        $datagrid = $this->createMock(DatagridInterface::class);
3690
3691
        $this->admin->expects($this->once())
3692
            ->method('getDatagrid')
3693
            ->will($this->returnValue($datagrid));
3694
3695
        $this->expectTranslate('flash_foo_error', [], 'SonataAdminBundle');
3696
3697
        $this->request->setMethod('POST');
3698
        $this->request->request->set('action', 'foo');
3699
        $this->request->request->set('idx', ['999']);
3700
        $this->request->request->set('_sonata_csrf_token', 'csrf-token-123_sonata.batch');
3701
3702
        $result = $controller->batchAction($this->request);
3703
3704
        $this->assertInstanceOf(RedirectResponse::class, $result);
3705
        $this->assertSame(['flash_foo_error'], $this->session->getFlashBag()->get('sonata_flash_info'));
3706
        $this->assertSame('list', $result->getTargetUrl());
3707
    }
3708
3709
    public function testBatchActionNoItems(): void
3710
    {
3711
        $batchActions = ['delete' => ['label' => 'Foo Bar', 'ask_confirmation' => true]];
3712
3713
        $this->admin->expects($this->once())
3714
            ->method('getBatchActions')
3715
            ->will($this->returnValue($batchActions));
3716
3717
        $datagrid = $this->createMock(DatagridInterface::class);
3718
3719
        $this->admin->expects($this->once())
3720
            ->method('getDatagrid')
3721
            ->will($this->returnValue($datagrid));
3722
3723
        $this->expectTranslate('flash_batch_empty', [], 'SonataAdminBundle');
3724
3725
        $this->request->setMethod('POST');
3726
        $this->request->request->set('action', 'delete');
3727
        $this->request->request->set('idx', []);
3728
        $this->request->request->set('_sonata_csrf_token', 'csrf-token-123_sonata.batch');
3729
3730
        $result = $this->controller->batchAction($this->request);
3731
3732
        $this->assertInstanceOf(RedirectResponse::class, $result);
3733
        $this->assertSame(['flash_batch_empty'], $this->session->getFlashBag()->get('sonata_flash_info'));
3734
        $this->assertSame('list', $result->getTargetUrl());
3735
    }
3736
3737
    public function testBatchActionNoItemsEmptyQuery(): void
3738
    {
3739
        $controller = new BatchAdminController();
3740
        $controller->setContainer($this->container);
3741
3742
        $batchActions = ['bar' => ['label' => 'Foo Bar', 'ask_confirmation' => false]];
3743
3744
        $this->admin->expects($this->once())
3745
            ->method('getBatchActions')
3746
            ->will($this->returnValue($batchActions));
3747
3748
        $datagrid = $this->createMock(DatagridInterface::class);
3749
3750
        $query = $this->createMock(ProxyQueryInterface::class);
3751
        $datagrid->expects($this->once())
3752
            ->method('getQuery')
3753
            ->will($this->returnValue($query));
3754
3755
        $this->admin->expects($this->once())
3756
            ->method('getDatagrid')
3757
            ->will($this->returnValue($datagrid));
3758
3759
        $modelManager = $this->createMock(ModelManagerInterface::class);
3760
3761
        $this->admin->expects($this->any())
3762
            ->method('getModelManager')
3763
            ->will($this->returnValue($modelManager));
3764
3765
        $this->admin->expects($this->any())
3766
            ->method('getClass')
3767
            ->will($this->returnValue('Foo'));
3768
3769
        $this->request->setMethod('POST');
3770
        $this->request->request->set('action', 'bar');
3771
        $this->request->request->set('idx', []);
3772
        $this->request->request->set('_sonata_csrf_token', 'csrf-token-123_sonata.batch');
3773
3774
        $this->expectTranslate('flash_batch_no_elements_processed', [], 'SonataAdminBundle');
3775
        $result = $controller->batchAction($this->request);
3776
3777
        $this->assertInstanceOf(Response::class, $result);
3778
        $this->assertRegExp('/Redirecting to list/', $result->getContent());
3779
    }
3780
3781
    public function testBatchActionWithRequesData(): void
3782
    {
3783
        $batchActions = ['delete' => ['label' => 'Foo Bar', 'ask_confirmation' => false]];
3784
3785
        $this->admin->expects($this->once())
3786
            ->method('getBatchActions')
3787
            ->will($this->returnValue($batchActions));
3788
3789
        $datagrid = $this->createMock(DatagridInterface::class);
3790
3791
        $query = $this->createMock(ProxyQueryInterface::class);
3792
        $datagrid->expects($this->once())
3793
            ->method('getQuery')
3794
            ->will($this->returnValue($query));
3795
3796
        $this->admin->expects($this->once())
3797
            ->method('getDatagrid')
3798
            ->will($this->returnValue($datagrid));
3799
3800
        $modelManager = $this->createMock(ModelManagerInterface::class);
3801
3802
        $this->admin->expects($this->once())
3803
            ->method('checkAccess')
3804
            ->with($this->equalTo('batchDelete'))
3805
            ->will($this->returnValue(true));
3806
3807
        $this->admin->expects($this->any())
3808
            ->method('getModelManager')
3809
            ->will($this->returnValue($modelManager));
3810
3811
        $this->admin->expects($this->any())
3812
            ->method('getClass')
3813
            ->will($this->returnValue('Foo'));
3814
3815
        $modelManager->expects($this->once())
3816
            ->method('addIdentifiersToQuery')
3817
            ->with($this->equalTo('Foo'), $this->equalTo($query), $this->equalTo(['123', '456']))
3818
            ->will($this->returnValue(true));
3819
3820
        $this->expectTranslate('flash_batch_delete_success', [], 'SonataAdminBundle');
3821
3822
        $this->request->setMethod('POST');
3823
        $this->request->request->set('data', json_encode(['action' => 'delete', 'idx' => ['123', '456'], 'all_elements' => false]));
3824
        $this->request->request->set('foo', 'bar');
3825
        $this->request->request->set('_sonata_csrf_token', 'csrf-token-123_sonata.batch');
3826
3827
        $result = $this->controller->batchAction($this->request);
3828
3829
        $this->assertInstanceOf(RedirectResponse::class, $result);
3830
        $this->assertSame(['flash_batch_delete_success'], $this->session->getFlashBag()->get('sonata_flash_success'));
3831
        $this->assertSame('list', $result->getTargetUrl());
3832
        $this->assertSame('bar', $this->request->request->get('foo'));
3833
    }
3834
3835
    public function testItThrowsWhenCallingAnUndefinedMethod(): void
3836
    {
3837
        $this->expectException(
3838
            \LogicException::class
3839
        );
3840
        $this->expectExceptionMessage(
3841
            'Call to undefined method Sonata\AdminBundle\Controller\CRUDController::doesNotExist'
3842
        );
3843
        $this->controller->doesNotExist();
3844
    }
3845
3846
    /**
3847
     * @expectedDeprecation Method Sonata\AdminBundle\Controller\CRUDController::render has been renamed to Sonata\AdminBundle\Controller\CRUDController::renderWithExtraParams.
3848
     */
3849
    public function testRenderIsDeprecated(): void
3850
    {
3851
        $this->controller->render('toto.html.twig');
3852
    }
3853
3854
    public function getCsrfProvider()
3855
    {
3856
        return $this->csrfProvider;
3857
    }
3858
3859
    public function getToStringValues()
3860
    {
3861
        return [
3862
            ['', ''],
3863
            ['Foo', 'Foo'],
3864
            ['&lt;a href=&quot;http://foo&quot;&gt;Bar&lt;/a&gt;', '<a href="http://foo">Bar</a>'],
3865
            ['&lt;&gt;&amp;&quot;&#039;abcdefghijklmnopqrstuvwxyz*-+.,?_()[]\/', '<>&"\'abcdefghijklmnopqrstuvwxyz*-+.,?_()[]\/'],
3866
        ];
3867
    }
3868
3869
    private function assertLoggerLogsModelManagerException($subject, string $method): void
3870
    {
3871
        $exception = new ModelManagerException(
3872
            $message = 'message',
3873
            1234,
3874
            new \Exception($previousExceptionMessage = 'very useful message')
3875
        );
3876
3877
        $subject->expects($this->once())
3878
            ->method($method)
3879
            ->will($this->returnCallback(static function () use ($exception): void {
3880
                throw $exception;
3881
            }));
3882
3883
        $this->logger->expects($this->once())
3884
            ->method('error')
3885
            ->with($message, [
3886
                'exception' => $exception,
3887
                'previous_exception_message' => $previousExceptionMessage,
3888
            ]);
3889
    }
3890
3891
    private function expectTranslate(
3892
        string $id,
3893
        array $parameters = [],
3894
        ?string $domain = null,
3895
        ?string $locale = null
3896
    ): void {
3897
        $this->translator->expects($this->once())
3898
            ->method('trans')
3899
            ->with($this->equalTo($id), $this->equalTo($parameters), $this->equalTo($domain), $this->equalTo($locale))
3900
            ->will($this->returnValue($id));
3901
    }
3902
}
3903