Completed
Push — master ( 28dfb2...02612b )
by Jordi Sala
17s queued 13s
created

tests/Twig/Extension/SonataAdminExtensionTest.php (2 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\Twig\Extension;
15
16
use PHPUnit\Framework\TestCase;
17
use Psr\Log\LoggerInterface;
18
use Sonata\AdminBundle\Admin\AbstractAdmin;
19
use Sonata\AdminBundle\Admin\AdminInterface;
20
use Sonata\AdminBundle\Admin\FieldDescriptionInterface;
21
use Sonata\AdminBundle\Admin\Pool;
22
use Sonata\AdminBundle\Exception\NoValueException;
23
use Sonata\AdminBundle\Templating\TemplateRegistry;
24
use Sonata\AdminBundle\Templating\TemplateRegistryInterface;
25
use Sonata\AdminBundle\Tests\Fixtures\Entity\FooToString;
26
use Sonata\AdminBundle\Tests\Fixtures\StubFilesystemLoader;
27
use Sonata\AdminBundle\Twig\Extension\SonataAdminExtension;
28
use Symfony\Bridge\Twig\AppVariable;
29
use Symfony\Bridge\Twig\Extension\RoutingExtension;
30
use Symfony\Bridge\Twig\Extension\TranslationExtension;
31
use Symfony\Component\Config\FileLocator;
32
use Symfony\Component\DependencyInjection\ContainerInterface;
33
use Symfony\Component\HttpFoundation\Request;
34
use Symfony\Component\Routing\Generator\UrlGenerator;
35
use Symfony\Component\Routing\Loader\XmlFileLoader;
36
use Symfony\Component\Routing\RequestContext;
37
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
38
use Symfony\Component\Translation\Loader\XliffFileLoader;
39
use Symfony\Component\Translation\Translator;
40
use Symfony\Contracts\Translation\TranslatorInterface;
41
use Twig\Environment;
42
use Twig\Extra\String\StringExtension;
43
use Twig\Loader\FilesystemLoader;
44
45
/**
46
 * Test for SonataAdminExtension.
47
 *
48
 * @author Andrej Hudec <[email protected]>
49
 */
50
class SonataAdminExtensionTest extends TestCase
51
{
52
    /**
53
     * @var SonataAdminExtension
54
     */
55
    private $twigExtension;
56
57
    /**
58
     * @var Environment
59
     */
60
    private $environment;
61
62
    /**
63
     * @var AdminInterface
64
     */
65
    private $admin;
66
67
    /**
68
     * @var AdminInterface
69
     */
70
    private $adminBar;
71
72
    /**
73
     * @var FieldDescriptionInterface
74
     */
75
    private $fieldDescription;
76
77
    /**
78
     * @var \stdClass
79
     */
80
    private $object;
81
82
    /**
83
     * @var Pool
84
     */
85
    private $pool;
86
87
    /**
88
     * @var LoggerInterface
89
     */
90
    private $logger;
91
92
    /**
93
     * @var string[]
94
     */
95
    private $xEditableTypeMapping;
96
97
    /**
98
     * @var TranslatorInterface
99
     */
100
    private $translator;
101
102
    /**
103
     * @var ContainerInterface
104
     */
105
    private $container;
106
107
    /**
108
     * @var TemplateRegistryInterface
109
     */
110
    private $templateRegistry;
111
112
    /**
113
     * @var AuthorizationCheckerInterface
114
     */
115
    private $securityChecker;
116
117
    protected function setUp(): void
118
    {
119
        date_default_timezone_set('Europe/London');
120
121
        $container = $this->createMock(ContainerInterface::class);
122
123
        $this->pool = new Pool($container, '', '');
124
        $this->pool->setAdminServiceIds(['sonata_admin_foo_service']);
125
        $this->pool->setAdminClasses(['fooClass' => ['sonata_admin_foo_service']]);
126
127
        $this->logger = $this->getMockForAbstractClass(LoggerInterface::class);
128
        $this->xEditableTypeMapping = [
129
            'choice' => 'select',
130
            'boolean' => 'select',
131
            'text' => 'text',
132
            'textarea' => 'textarea',
133
            'html' => 'textarea',
134
            'email' => 'email',
135
            'string' => 'text',
136
            'smallint' => 'text',
137
            'bigint' => 'text',
138
            'integer' => 'number',
139
            'decimal' => 'number',
140
            'currency' => 'number',
141
            'percent' => 'number',
142
            'url' => 'url',
143
        ];
144
145
        // translation extension
146
        $translator = new Translator('en');
147
        $translator->addLoader('xlf', new XliffFileLoader());
148
        $translator->addResource(
149
            'xlf',
150
            sprintf('%s/../../../src/Resources/translations/SonataAdminBundle.en.xliff', __DIR__),
151
            'en',
152
            'SonataAdminBundle'
153
        );
154
155
        $this->translator = $translator;
156
157
        $this->templateRegistry = new TemplateRegistry();
158
        $this->container = $this->createMock(ContainerInterface::class);
159
        $this->container
160
            ->method('get')
161
            ->with('sonata_admin_foo_service.template_registry')
162
            ->willReturn($this->templateRegistry);
163
164
        $this->securityChecker = $this->createMock(AuthorizationCheckerInterface::class);
165
        $this->securityChecker->method('isGranted')->willReturn(true);
166
167
        $this->twigExtension = new SonataAdminExtension(
168
            $this->pool,
169
            $this->logger,
170
            $this->translator,
171
            $this->container,
172
            $this->securityChecker
173
        );
174
        $this->twigExtension->setXEditableTypeMapping($this->xEditableTypeMapping);
175
176
        $request = $this->createMock(Request::class);
177
        $request->method('get')->with('_sonata_admin')->willReturn('sonata_admin_foo_service');
178
179
        $loader = new FilesystemLoader([
180
            __DIR__.'/../../../src/Resources/views/CRUD',
181
            __DIR__.'/../../Fixtures/Resources/views/CRUD',
182
        ]);
183
        $loader->addPath(__DIR__.'/../../../src/Resources/views/', 'SonataAdmin');
184
        $loader->addPath(__DIR__.'/../../Fixtures/Resources/views/', 'App');
185
186
        $this->environment = new Environment($loader, [
187
            'strict_variables' => true,
188
            'cache' => false,
189
            'autoescape' => 'html',
190
            'optimizations' => 0,
191
        ]);
192
        $this->environment->addExtension($this->twigExtension);
193
        $this->environment->addExtension(new TranslationExtension($translator));
194
        $this->environment->addExtension(new FakeTemplateRegistryExtension());
195
196
        // routing extension
197
        $xmlFileLoader = new XmlFileLoader(new FileLocator([sprintf('%s/../../../src/Resources/config/routing', __DIR__)]));
198
        $routeCollection = $xmlFileLoader->load('sonata_admin.xml');
199
200
        $xmlFileLoader = new XmlFileLoader(new FileLocator([sprintf('%s/../../Fixtures/Resources/config/routing', __DIR__)]));
201
        $testRouteCollection = $xmlFileLoader->load('routing.xml');
202
203
        $routeCollection->addCollection($testRouteCollection);
204
        $requestContext = new RequestContext();
205
        $urlGenerator = new UrlGenerator($routeCollection, $requestContext);
206
        $this->environment->addExtension(new RoutingExtension($urlGenerator));
207
        $this->environment->addExtension(new StringExtension());
208
209
        // initialize object
210
        $this->object = new \stdClass();
211
212
        // initialize admin
213
        $this->admin = $this->createMock(AbstractAdmin::class);
214
215
        $this->admin
216
            ->method('getCode')
217
            ->willReturn('sonata_admin_foo_service');
218
219
        $this->admin
220
            ->method('id')
221
            ->with($this->equalTo($this->object))
222
            ->willReturn('12345');
223
224
        $this->admin
225
            ->method('getNormalizedIdentifier')
226
            ->with($this->equalTo($this->object))
227
            ->willReturn('12345');
228
229
        $this->admin
230
            ->method('trans')
231
            ->willReturnCallback(static function ($id, $parameters = [], $domain = null) use ($translator) {
232
                return $translator->trans($id, $parameters, $domain);
233
            });
234
235
        $this->adminBar = $this->createMock(AbstractAdmin::class);
236
        $this->adminBar
237
            ->method('hasAccess')
238
            ->willReturn(true);
239
        $this->adminBar
240
            ->method('getNormalizedIdentifier')
241
            ->with($this->equalTo($this->object))
242
            ->willReturn('12345');
243
244
        $container
245
            ->method('get')
246
            ->willReturnCallback(function (string $id) {
247
                if ('sonata_admin_foo_service' === $id) {
248
                    return $this->admin;
249
                }
250
251
                if ('sonata_admin_bar_service' === $id) {
252
                    return $this->adminBar;
253
                }
254
            });
255
256
        // initialize field description
257
        $this->fieldDescription = $this->getMockForAbstractClass(FieldDescriptionInterface::class);
258
259
        $this->fieldDescription
260
            ->method('getName')
261
            ->willReturn('fd_name');
262
263
        $this->fieldDescription
264
            ->method('getAdmin')
265
            ->willReturn($this->admin);
266
267
        $this->fieldDescription
268
            ->method('getLabel')
269
            ->willReturn('Data');
270
    }
271
272
    public function getRenderListElementTests()
273
    {
274
        return [
275
            [
276
                '<td class="sonata-ba-list-field sonata-ba-list-field-string" objectId="12345"> Example </td>',
277
                'string',
278
                'Example',
279
                [],
280
            ],
281
            [
282
                '<td class="sonata-ba-list-field sonata-ba-list-field-string" objectId="12345"> </td>',
283
                'string',
284
                null,
285
                [],
286
            ],
287
            [
288
                '<td class="sonata-ba-list-field sonata-ba-list-field-text" objectId="12345"> Example </td>',
289
                'text',
290
                'Example',
291
                [],
292
            ],
293
            [
294
                '<td class="sonata-ba-list-field sonata-ba-list-field-text" objectId="12345"> </td>',
295
                'text',
296
                null,
297
                [],
298
            ],
299
            [
300
                '<td class="sonata-ba-list-field sonata-ba-list-field-textarea" objectId="12345"> Example </td>',
301
                'textarea',
302
                'Example',
303
                [],
304
            ],
305
            [
306
                '<td class="sonata-ba-list-field sonata-ba-list-field-textarea" objectId="12345"> </td>',
307
                'textarea',
308
                null,
309
                [],
310
            ],
311
            'datetime field' => [
312
                '<td class="sonata-ba-list-field sonata-ba-list-field-datetime" objectId="12345">
313
                    <time datetime="2013-12-24T10:11:12+00:00" title="2013-12-24T10:11:12+00:00">
314
                        December 24, 2013 10:11
315
                    </time>
316
                </td>',
317
                'datetime',
318
                new \DateTime('2013-12-24 10:11:12', new \DateTimeZone('Europe/London')),
319
                [],
320
            ],
321
            [
322
                '<td class="sonata-ba-list-field sonata-ba-list-field-datetime" objectId="12345">
323
                    <time datetime="2013-12-24T10:11:12+00:00" title="2013-12-24T10:11:12+00:00">
324
                        December 24, 2013 18:11
325
                    </time>
326
                </td>',
327
                'datetime',
328
                new \DateTime('2013-12-24 10:11:12', new \DateTimeZone('UTC')),
329
                ['timezone' => 'Asia/Hong_Kong'],
330
            ],
331
            [
332
                '<td class="sonata-ba-list-field sonata-ba-list-field-datetime" objectId="12345"> &nbsp; </td>',
333
                'datetime',
334
                null,
335
                [],
336
            ],
337
            [
338
                '<td class="sonata-ba-list-field sonata-ba-list-field-datetime" objectId="12345">
339
                    <time datetime="2013-12-24T10:11:12+00:00" title="2013-12-24T10:11:12+00:00">
340
                        24.12.2013 10:11:12
341
                    </time>
342
                </td>',
343
                'datetime',
344
                new \DateTime('2013-12-24 10:11:12', new \DateTimeZone('Europe/London')),
345
                ['format' => 'd.m.Y H:i:s'],
346
            ],
347
            [
348
                '<td class="sonata-ba-list-field sonata-ba-list-field-datetime" objectId="12345"> &nbsp; </td>',
349
                'datetime',
350
                null,
351
                ['format' => 'd.m.Y H:i:s'],
352
            ],
353
            [
354
                '<td class="sonata-ba-list-field sonata-ba-list-field-datetime" objectId="12345">
355
                    <time datetime="2013-12-24T10:11:12+00:00" title="2013-12-24T10:11:12+00:00">
356
                        24.12.2013 18:11:12
357
                    </time>
358
                </td>',
359
                'datetime',
360
                new \DateTime('2013-12-24 10:11:12', new \DateTimeZone('UTC')),
361
                ['format' => 'd.m.Y H:i:s', 'timezone' => 'Asia/Hong_Kong'],
362
            ],
363
            [
364
                '<td class="sonata-ba-list-field sonata-ba-list-field-datetime" objectId="12345"> &nbsp; </td>',
365
                'datetime',
366
                null,
367
                ['format' => 'd.m.Y H:i:s', 'timezone' => 'Asia/Hong_Kong'],
368
            ],
369
            [
370
                '<td class="sonata-ba-list-field sonata-ba-list-field-date" objectId="12345">
371
                    <time datetime="2013-12-24" title="2013-12-24">
372
                        December 24, 2013
373
                    </time>
374
                </td>',
375
                'date',
376
                new \DateTime('2013-12-24 10:11:12', new \DateTimeZone('Europe/London')),
377
                [],
378
            ],
379
            [
380
                '<td class="sonata-ba-list-field sonata-ba-list-field-date" objectId="12345"> &nbsp; </td>',
381
                'date',
382
                null,
383
                [],
384
            ],
385
            [
386
                '<td class="sonata-ba-list-field sonata-ba-list-field-date" objectId="12345">
387
                    <time datetime="2013-12-24" title="2013-12-24">
388
                        24.12.2013
389
                    </time>
390
                </td>',
391
                'date',
392
                new \DateTime('2013-12-24 10:11:12', new \DateTimeZone('Europe/London')),
393
                ['format' => 'd.m.Y'],
394
            ],
395
            [
396
                '<td class="sonata-ba-list-field sonata-ba-list-field-date" objectId="12345"> &nbsp; </td>',
397
                'date',
398
                null,
399
                ['format' => 'd.m.Y'],
400
            ],
401
            [
402
                '<td class="sonata-ba-list-field sonata-ba-list-field-time" objectId="12345">
403
                    <time datetime="10:11:12+00:00" title="10:11:12+00:00">
404
                        10:11:12
405
                    </time>
406
                </td>',
407
                'time',
408
                new \DateTime('2013-12-24 10:11:12', new \DateTimeZone('Europe/London')),
409
                [],
410
            ],
411
            [
412
                '<td class="sonata-ba-list-field sonata-ba-list-field-time" objectId="12345">
413
                    <time datetime="10:11:12+00:00" title="10:11:12+00:00">
414
                        18:11:12
415
                    </time>
416
                </td>',
417
                'time',
418
                new \DateTime('2013-12-24 10:11:12', new \DateTimeZone('UTC')),
419
                ['timezone' => 'Asia/Hong_Kong'],
420
            ],
421
            [
422
                '<td class="sonata-ba-list-field sonata-ba-list-field-time" objectId="12345"> &nbsp; </td>',
423
                'time',
424
                null,
425
                [],
426
            ],
427
            [
428
                '<td class="sonata-ba-list-field sonata-ba-list-field-number" objectId="12345"> 10.746135 </td>',
429
                'number', 10.746135,
430
                [],
431
            ],
432
            [
433
                '<td class="sonata-ba-list-field sonata-ba-list-field-number" objectId="12345"> </td>',
434
                'number',
435
                null,
436
                [],
437
            ],
438
            [
439
                '<td class="sonata-ba-list-field sonata-ba-list-field-integer" objectId="12345"> 5678 </td>',
440
                'integer',
441
                5678,
442
                [],
443
            ],
444
            [
445
                '<td class="sonata-ba-list-field sonata-ba-list-field-integer" objectId="12345"> </td>',
446
                'integer',
447
                null,
448
                [],
449
            ],
450
            [
451
                '<td class="sonata-ba-list-field sonata-ba-list-field-percent" objectId="12345"> 1074.6135 % </td>',
452
                'percent',
453
                10.746135,
454
                [],
455
            ],
456
            [
457
                '<td class="sonata-ba-list-field sonata-ba-list-field-percent" objectId="12345"> 0 % </td>',
458
                'percent',
459
                null,
460
                [],
461
            ],
462
            [
463
                '<td class="sonata-ba-list-field sonata-ba-list-field-currency" objectId="12345"> EUR 10.746135 </td>',
464
                'currency',
465
                10.746135,
466
                ['currency' => 'EUR'],
467
            ],
468
            [
469
                '<td class="sonata-ba-list-field sonata-ba-list-field-currency" objectId="12345"> </td>',
470
                'currency',
471
                null,
472
                ['currency' => 'EUR'],
473
            ],
474
            [
475
                '<td class="sonata-ba-list-field sonata-ba-list-field-currency" objectId="12345"> GBP 51.23456 </td>',
476
                'currency',
477
                51.23456,
478
                ['currency' => 'GBP'],
479
            ],
480
            [
481
                '<td class="sonata-ba-list-field sonata-ba-list-field-currency" objectId="12345"> </td>',
482
                'currency',
483
                null,
484
                ['currency' => 'GBP'],
485
            ],
486
            [
487
                '<td class="sonata-ba-list-field sonata-ba-list-field-email" objectId="12345"> &nbsp; </td>',
488
                'email',
489
                null,
490
                [],
491
            ],
492
            [
493
                '<td class="sonata-ba-list-field sonata-ba-list-field-email" objectId="12345"> <a href="mailto:[email protected]">[email protected]</a> </td>',
494
                'email',
495
                '[email protected]',
496
                [],
497
            ],
498
            [
499
                '<td class="sonata-ba-list-field sonata-ba-list-field-email" objectId="12345">
500
                    <a href="mailto:[email protected]">[email protected]</a> </td>',
501
                'email',
502
                '[email protected]',
503
                ['as_string' => false],
504
            ],
505
            [
506
                '<td class="sonata-ba-list-field sonata-ba-list-field-email" objectId="12345"> [email protected] </td>',
507
                'email',
508
                '[email protected]',
509
                ['as_string' => true],
510
            ],
511
            [
512
                '<td class="sonata-ba-list-field sonata-ba-list-field-email" objectId="12345">
513
                    <a href="mailto:[email protected]?'.$this->buildTwigLikeUrl(['subject' => 'Main Theme', 'body' => 'Message Body']).'">[email protected]</a>  </td>',
514
                'email',
515
                '[email protected]',
516
                ['subject' => 'Main Theme', 'body' => 'Message Body'],
517
            ],
518
            [
519
                '<td class="sonata-ba-list-field sonata-ba-list-field-email" objectId="12345">
520
                    <a href="mailto:[email protected]?'.$this->buildTwigLikeUrl(['subject' => 'Main Theme']).'">[email protected]</a>  </td>',
521
                'email',
522
                '[email protected]',
523
                ['subject' => 'Main Theme'],
524
            ],
525
            [
526
                '<td class="sonata-ba-list-field sonata-ba-list-field-email" objectId="12345">
527
                    <a href="mailto:[email protected]?'.$this->buildTwigLikeUrl(['body' => 'Message Body']).'">[email protected]</a>  </td>',
528
                'email',
529
                '[email protected]',
530
                ['body' => 'Message Body'],
531
            ],
532
            [
533
                '<td class="sonata-ba-list-field sonata-ba-list-field-email" objectId="12345"> [email protected] </td>',
534
                'email',
535
                '[email protected]',
536
                ['as_string' => true, 'subject' => 'Main Theme', 'body' => 'Message Body'],
537
            ],
538
            [
539
                '<td class="sonata-ba-list-field sonata-ba-list-field-email" objectId="12345"> [email protected] </td>',
540
                'email',
541
                '[email protected]',
542
                ['as_string' => true, 'body' => 'Message Body'],
543
            ],
544
            [
545
                '<td class="sonata-ba-list-field sonata-ba-list-field-email" objectId="12345"> [email protected] </td>',
546
                'email',
547
                '[email protected]',
548
                ['as_string' => true, 'subject' => 'Main Theme'],
549
            ],
550
            [
551
                '<td class="sonata-ba-list-field sonata-ba-list-field-array" objectId="12345">
552
                    [1&nbsp;=>&nbsp;First, 2&nbsp;=>&nbsp;Second]
553
                </td>',
554
                'array',
555
                [1 => 'First', 2 => 'Second'],
556
                [],
557
            ],
558
            [
559
                '<td class="sonata-ba-list-field sonata-ba-list-field-array" objectId="12345"> [] </td>',
560
                'array',
561
                null,
562
                [],
563
            ],
564
            [
565
                '<td class="sonata-ba-list-field sonata-ba-list-field-boolean" objectId="12345">
566
                    <span class="label label-success">yes</span>
567
                </td>',
568
                'boolean',
569
                true,
570
                ['editable' => false],
571
            ],
572
            [
573
                '<td class="sonata-ba-list-field sonata-ba-list-field-boolean" objectId="12345">
574
                    <span class="label label-danger">no</span>
575
                </td>',
576
                'boolean',
577
                false,
578
                ['editable' => false],
579
            ],
580
            [
581
                '<td class="sonata-ba-list-field sonata-ba-list-field-boolean" objectId="12345">
582
                    <span class="label label-danger">no</span>
583
                </td>',
584
                'boolean',
585
                null,
586
                ['editable' => false],
587
            ],
588
            [
589
                <<<'EOT'
590
<td class="sonata-ba-list-field sonata-ba-list-field-boolean" objectId="12345">
591
    <span
592
        class="x-editable"
593
        data-type="select"
594
        data-value="1"
595
        data-title="Data"
596
        data-pk="12345"
597
        data-url="/core/set-object-field-value?context=list&amp;field=fd_name&amp;objectId=12345&amp;code=sonata_admin_foo_service"
598
        data-source="[{value: 0, text: 'no'},{value: 1, text: 'yes'}]"
599
    >
600
        <span class="label label-success">yes</span>
601
    </span>
602
</td>
603
EOT
604
            ,
605
                'boolean',
606
                true,
607
                ['editable' => true],
608
            ],
609
            [
610
                <<<'EOT'
611
<td class="sonata-ba-list-field sonata-ba-list-field-boolean" objectId="12345">
612
    <span
613
        class="x-editable"
614
        data-type="select"
615
        data-value="0"
616
        data-title="Data"
617
        data-pk="12345"
618
        data-url="/core/set-object-field-value?context=list&amp;field=fd_name&amp;objectId=12345&amp;code=sonata_admin_foo_service"
619
        data-source="[{value: 0, text: 'no'},{value: 1, text: 'yes'}]"
620
    >
621
    <span class="label label-danger">no</span> </span>
622
</td>
623
EOT
624
                ,
625
                'boolean',
626
                false,
627
                ['editable' => true],
628
            ],
629
            [
630
                <<<'EOT'
631
<td class="sonata-ba-list-field sonata-ba-list-field-boolean" objectId="12345">
632
    <span
633
        class="x-editable"
634
        data-type="select"
635
        data-value="0"
636
        data-title="Data"
637
        data-pk="12345"
638
        data-url="/core/set-object-field-value?context=list&amp;field=fd_name&amp;objectId=12345&amp;code=sonata_admin_foo_service"
639
        data-source="[{value: 0, text: 'no'},{value: 1, text: 'yes'}]" >
640
        <span class="label label-danger">no</span> </span>
641
</td>
642
EOT
643
                ,
644
                'boolean',
645
                null,
646
                ['editable' => true],
647
            ],
648
            [
649
                '<td class="sonata-ba-list-field sonata-ba-list-field-trans" objectId="12345"> Delete </td>',
650
                'trans',
651
                'action_delete',
652
                ['catalogue' => 'SonataAdminBundle'],
653
            ],
654
            [
655
                '<td class="sonata-ba-list-field sonata-ba-list-field-trans" objectId="12345"> </td>',
656
                'trans',
657
                null,
658
                ['catalogue' => 'SonataAdminBundle'],
659
            ],
660
            [
661
                '<td class="sonata-ba-list-field sonata-ba-list-field-trans" objectId="12345"> Delete </td>',
662
                'trans',
663
                'action_delete',
664
                ['format' => '%s', 'catalogue' => 'SonataAdminBundle'],
665
            ],
666
            [
667
                '<td class="sonata-ba-list-field sonata-ba-list-field-trans" objectId="12345">
668
                action.action_delete
669
                </td>',
670
                'trans',
671
                'action_delete',
672
                ['format' => 'action.%s'],
673
            ],
674
            [
675
                '<td class="sonata-ba-list-field sonata-ba-list-field-trans" objectId="12345">
676
                action.action_delete
677
                </td>',
678
                'trans',
679
                'action_delete',
680
                ['format' => 'action.%s', 'catalogue' => 'SonataAdminBundle'],
681
            ],
682
            [
683
                '<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345"> Status1 </td>',
684
                'choice',
685
                'Status1',
686
                [],
687
            ],
688
            [
689
                '<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345"> Status1 </td>',
690
                'choice',
691
                ['Status1'],
692
                ['choices' => [], 'multiple' => true],
693
            ],
694
            [
695
                '<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345"> Alias1 </td>',
696
                'choice',
697
                'Status1',
698
                ['choices' => ['Status1' => 'Alias1', 'Status2' => 'Alias2', 'Status3' => 'Alias3']],
699
            ],
700
            [
701
                '<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345"> </td>',
702
                'choice',
703
                null,
704
                ['choices' => ['Status1' => 'Alias1', 'Status2' => 'Alias2', 'Status3' => 'Alias3']],
705
            ],
706
            [
707
                '<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345">
708
                NoValidKeyInChoices
709
                </td>',
710
                'choice',
711
                'NoValidKeyInChoices',
712
                ['choices' => ['Status1' => 'Alias1', 'Status2' => 'Alias2', 'Status3' => 'Alias3']],
713
            ],
714
            [
715
                '<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345"> Delete </td>',
716
                'choice',
717
                'Foo',
718
                ['catalogue' => 'SonataAdminBundle', 'choices' => [
719
                    'Foo' => 'action_delete',
720
                    'Status2' => 'Alias2',
721
                    'Status3' => 'Alias3',
722
                ]],
723
            ],
724
            [
725
                '<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345"> Alias1, Alias3 </td>',
726
                'choice',
727
                ['Status1', 'Status3'],
728
                ['choices' => [
729
                    'Status1' => 'Alias1',
730
                    'Status2' => 'Alias2',
731
                    'Status3' => 'Alias3',
732
                ], 'multiple' => true], ],
733
            [
734
                '<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345"> Alias1 | Alias3 </td>',
735
                'choice',
736
                ['Status1', 'Status3'],
737
                ['choices' => [
738
                    'Status1' => 'Alias1',
739
                    'Status2' => 'Alias2',
740
                    'Status3' => 'Alias3',
741
                ], 'multiple' => true, 'delimiter' => ' | '], ],
742
            [
743
                '<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345"> </td>',
744
                'choice',
745
                null,
746
                ['choices' => [
747
                    'Status1' => 'Alias1',
748
                    'Status2' => 'Alias2',
749
                    'Status3' => 'Alias3',
750
                ], 'multiple' => true],
751
            ],
752
            [
753
                '<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345">
754
                NoValidKeyInChoices
755
                </td>',
756
                'choice',
757
                ['NoValidKeyInChoices'],
758
                ['choices' => [
759
                    'Status1' => 'Alias1',
760
                    'Status2' => 'Alias2',
761
                    'Status3' => 'Alias3',
762
                ], 'multiple' => true],
763
            ],
764
            [
765
                '<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345">
766
                NoValidKeyInChoices, Alias2
767
                </td>',
768
                'choice',
769
                ['NoValidKeyInChoices', 'Status2'],
770
                ['choices' => [
771
                    'Status1' => 'Alias1',
772
                    'Status2' => 'Alias2',
773
                    'Status3' => 'Alias3',
774
                ], 'multiple' => true],
775
            ],
776
            [
777
                '<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345"> Delete, Alias3 </td>',
778
                'choice',
779
                ['Foo', 'Status3'],
780
                ['catalogue' => 'SonataAdminBundle', 'choices' => [
781
                    'Foo' => 'action_delete',
782
                    'Status2' => 'Alias2',
783
                    'Status3' => 'Alias3',
784
                ], 'multiple' => true],
785
            ],
786
            [
787
                '<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345">
788
                &lt;b&gt;Alias1&lt;/b&gt;, &lt;b&gt;Alias3&lt;/b&gt;
789
            </td>',
790
                'choice',
791
                ['Status1', 'Status3'],
792
                ['choices' => [
793
                    'Status1' => '<b>Alias1</b>',
794
                    'Status2' => '<b>Alias2</b>',
795
                    'Status3' => '<b>Alias3</b>',
796
                ], 'multiple' => true], ],
797
            [
798
                <<<'EOT'
799
<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345">
800
    <span
801
        class="x-editable"
802
        data-type="select"
803
        data-value="Status1"
804
        data-title="Data"
805
        data-pk="12345"
806
        data-url="/core/set-object-field-value?context=list&amp;field=fd_name&amp;objectId=12345&amp;code=sonata_admin_foo_service"
807
        data-source="[]"
808
    >
809
        Status1
810
    </span>
811
</td>
812
EOT
813
                ,
814
                'choice',
815
                'Status1',
816
                ['editable' => true],
817
            ],
818
            [
819
                <<<'EOT'
820
<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345">
821
    <span
822
        class="x-editable"
823
        data-type="select"
824
        data-value="Status1"
825
        data-title="Data"
826
        data-pk="12345"
827
        data-url="/core/set-object-field-value?context=list&amp;field=fd_name&amp;objectId=12345&amp;code=sonata_admin_foo_service"
828
        data-source="[{&quot;value&quot;:&quot;Status1&quot;,&quot;text&quot;:&quot;Alias1&quot;},{&quot;value&quot;:&quot;Status2&quot;,&quot;text&quot;:&quot;Alias2&quot;},{&quot;value&quot;:&quot;Status3&quot;,&quot;text&quot;:&quot;Alias3&quot;}]" >
829
        Alias1 </span>
830
</td>
831
EOT
832
                ,
833
                'choice',
834
                'Status1',
835
                [
836
                    'editable' => true,
837
                    'choices' => [
838
                        'Status1' => 'Alias1',
839
                        'Status2' => 'Alias2',
840
                        'Status3' => 'Alias3',
841
                    ],
842
                ],
843
            ],
844
            [
845
                <<<'EOT'
846
<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345">
847
    <span
848
        class="x-editable"
849
        data-type="select"
850
        data-value=""
851
        data-title="Data"
852
        data-pk="12345"
853
        data-url="/core/set-object-field-value?context=list&amp;field=fd_name&amp;objectId=12345&amp;code=sonata_admin_foo_service"
854
        data-source="[{&quot;value&quot;:&quot;Status1&quot;,&quot;text&quot;:&quot;Alias1&quot;},{&quot;value&quot;:&quot;Status2&quot;,&quot;text&quot;:&quot;Alias2&quot;},{&quot;value&quot;:&quot;Status3&quot;,&quot;text&quot;:&quot;Alias3&quot;}]" >
855
856
    </span>
857
</td>
858
EOT
859
                ,
860
                'choice',
861
                null,
862
                [
863
                    'editable' => true,
864
                    'choices' => [
865
                        'Status1' => 'Alias1',
866
                        'Status2' => 'Alias2',
867
                        'Status3' => 'Alias3',
868
                    ],
869
                ],
870
            ],
871
            [
872
                <<<'EOT'
873
<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345">
874
    <span
875
        class="x-editable"
876
        data-type="select"
877
        data-value="NoValidKeyInChoices"
878
        data-title="Data" data-pk="12345"
879
        data-url="/core/set-object-field-value?context=list&amp;field=fd_name&amp;objectId=12345&amp;code=sonata_admin_foo_service"
880
        data-source="[{&quot;value&quot;:&quot;Status1&quot;,&quot;text&quot;:&quot;Alias1&quot;},{&quot;value&quot;:&quot;Status2&quot;,&quot;text&quot;:&quot;Alias2&quot;},{&quot;value&quot;:&quot;Status3&quot;,&quot;text&quot;:&quot;Alias3&quot;}]" >
881
        NoValidKeyInChoices
882
    </span>
883
</td>
884
EOT
885
                ,
886
                'choice',
887
                'NoValidKeyInChoices',
888
                [
889
                    'editable' => true,
890
                    'choices' => [
891
                        'Status1' => 'Alias1',
892
                        'Status2' => 'Alias2',
893
                        'Status3' => 'Alias3',
894
                    ],
895
                ],
896
            ],
897
            [
898
                <<<'EOT'
899
<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345">
900
    <span
901
        class="x-editable"
902
        data-type="select"
903
        data-value="Foo"
904
        data-title="Data"
905
        data-pk="12345"
906
        data-url="/core/set-object-field-value?context=list&amp;field=fd_name&amp;objectId=12345&amp;code=sonata_admin_foo_service"
907
        data-source="[{&quot;value&quot;:&quot;Foo&quot;,&quot;text&quot;:&quot;Delete&quot;},{&quot;value&quot;:&quot;Status2&quot;,&quot;text&quot;:&quot;Alias2&quot;},{&quot;value&quot;:&quot;Status3&quot;,&quot;text&quot;:&quot;Alias3&quot;}]" >
908
         Delete
909
    </span>
910
</td>
911
EOT
912
                ,
913
                'choice',
914
                'Foo',
915
                [
916
                    'editable' => true,
917
                    'catalogue' => 'SonataAdminBundle',
918
                    'choices' => [
919
                        'Foo' => 'action_delete',
920
                        'Status2' => 'Alias2',
921
                        'Status3' => 'Alias3',
922
                    ],
923
                ],
924
            ],
925
            [
926
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345"> &nbsp; </td>',
927
                'url',
928
                null,
929
                [],
930
            ],
931
            [
932
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345"> &nbsp; </td>',
933
                'url',
934
                null,
935
                ['url' => 'http://example.com'],
936
            ],
937
            [
938
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345"> &nbsp; </td>',
939
                'url',
940
                null,
941
                ['route' => ['name' => 'sonata_admin_foo']],
942
            ],
943
            [
944
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
945
                <a href="http://example.com">http://example.com</a>
946
                </td>',
947
                'url',
948
                'http://example.com',
949
                [],
950
            ],
951
            [
952
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
953
                <a href="https://example.com">https://example.com</a>
954
                </td>',
955
                'url',
956
                'https://example.com',
957
                [],
958
            ],
959
            [
960
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
961
                <a href="https://example.com" target="_blank">https://example.com</a>
962
                </td>',
963
                'url',
964
                'https://example.com',
965
                ['attributes' => ['target' => '_blank']],
966
            ],
967
            [
968
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
969
                <a href="https://example.com" target="_blank" class="fooLink">https://example.com</a>
970
                </td>',
971
                'url',
972
                'https://example.com',
973
                ['attributes' => ['target' => '_blank', 'class' => 'fooLink']],
974
            ],
975
            [
976
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
977
                <a href="http://example.com">example.com</a>
978
                </td>',
979
                'url',
980
                'http://example.com',
981
                ['hide_protocol' => true],
982
            ],
983
            [
984
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
985
                <a href="https://example.com">example.com</a>
986
                </td>',
987
                'url',
988
                'https://example.com',
989
                ['hide_protocol' => true],
990
            ],
991
            [
992
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
993
                <a href="http://example.com">http://example.com</a>
994
                </td>',
995
                'url',
996
                'http://example.com',
997
                ['hide_protocol' => false],
998
            ],
999
            [
1000
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
1001
                <a href="https://example.com">https://example.com</a>
1002
                </td>',
1003
                'url',
1004
                'https://example.com',
1005
                ['hide_protocol' => false],
1006
            ],
1007
            [
1008
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
1009
                <a href="http://example.com">Foo</a>
1010
                </td>',
1011
                'url',
1012
                'Foo',
1013
                ['url' => 'http://example.com'],
1014
            ],
1015
            [
1016
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
1017
                <a href="http://example.com">&lt;b&gt;Foo&lt;/b&gt;</a>
1018
                </td>',
1019
                'url',
1020
                '<b>Foo</b>',
1021
                ['url' => 'http://example.com'],
1022
            ],
1023
            [
1024
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
1025
                <a href="/foo">Foo</a>
1026
                </td>',
1027
                'url',
1028
                'Foo',
1029
                ['route' => ['name' => 'sonata_admin_foo']],
1030
            ],
1031
            [
1032
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
1033
                <a href="http://localhost/foo">Foo</a>
1034
                </td>',
1035
                'url',
1036
                'Foo',
1037
                ['route' => ['name' => 'sonata_admin_foo', 'absolute' => true]],
1038
            ],
1039
            [
1040
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
1041
                <a href="/foo">foo/bar?a=b&amp;c=123456789</a>
1042
                </td>',
1043
                'url',
1044
                'http://foo/bar?a=b&c=123456789',
1045
                ['route' => ['name' => 'sonata_admin_foo'],
1046
                'hide_protocol' => true, ],
1047
            ],
1048
            [
1049
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
1050
                <a href="http://localhost/foo">foo/bar?a=b&amp;c=123456789</a>
1051
                </td>',
1052
                'url',
1053
                'http://foo/bar?a=b&c=123456789',
1054
                [
1055
                    'route' => ['name' => 'sonata_admin_foo', 'absolute' => true],
1056
                    'hide_protocol' => true,
1057
                ],
1058
            ],
1059
            [
1060
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
1061
                <a href="/foo/abcd/efgh?param3=ijkl">Foo</a>
1062
                </td>',
1063
                'url',
1064
                'Foo',
1065
                [
1066
                    'route' => ['name' => 'sonata_admin_foo_param',
1067
                    'parameters' => ['param1' => 'abcd', 'param2' => 'efgh', 'param3' => 'ijkl'], ],
1068
                ],
1069
            ],
1070
            [
1071
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
1072
                <a href="http://localhost/foo/abcd/efgh?param3=ijkl">Foo</a>
1073
                </td>',
1074
                'url',
1075
                'Foo',
1076
                [
1077
                    'route' => ['name' => 'sonata_admin_foo_param',
1078
                    'absolute' => true,
1079
                    'parameters' => ['param1' => 'abcd', 'param2' => 'efgh', 'param3' => 'ijkl'], ],
1080
                ],
1081
            ],
1082
            [
1083
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
1084
                <a href="/foo/obj/abcd/12345/efgh?param3=ijkl">Foo</a>
1085
                </td>',
1086
                'url',
1087
                'Foo',
1088
                [
1089
                    'route' => ['name' => 'sonata_admin_foo_object',
1090
                    'parameters' => ['param1' => 'abcd', 'param2' => 'efgh', 'param3' => 'ijkl'],
1091
                    'identifier_parameter_name' => 'barId', ],
1092
                ],
1093
            ],
1094
            [
1095
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
1096
                <a href="http://localhost/foo/obj/abcd/12345/efgh?param3=ijkl">Foo</a>
1097
                </td>',
1098
                'url',
1099
                'Foo',
1100
                [
1101
                    'route' => ['name' => 'sonata_admin_foo_object',
1102
                    'absolute' => true,
1103
                    'parameters' => ['param1' => 'abcd', 'param2' => 'efgh', 'param3' => 'ijkl'],
1104
                    'identifier_parameter_name' => 'barId', ],
1105
                ],
1106
            ],
1107
            [
1108
                '<td class="sonata-ba-list-field sonata-ba-list-field-html" objectId="12345">
1109
                <p><strong>Creating a Template for the Field</strong> and form</p>
1110
                </td>',
1111
                'html',
1112
                '<p><strong>Creating a Template for the Field</strong> and form</p>',
1113
                [],
1114
            ],
1115
            [
1116
                '<td class="sonata-ba-list-field sonata-ba-list-field-html" objectId="12345">
1117
                Creating a Template for the Field and form
1118
                </td>',
1119
                'html',
1120
                '<p><strong>Creating a Template for the Field</strong> and form</p>',
1121
                ['strip' => true],
1122
            ],
1123
            [
1124
                '<td class="sonata-ba-list-field sonata-ba-list-field-html" objectId="12345">
1125
                Creating a Template for the...
1126
                </td>',
1127
                'html',
1128
                '<p><strong>Creating a Template for the Field</strong> and form</p>',
1129
                ['truncate' => true],
1130
            ],
1131
            [
1132
                '<td class="sonata-ba-list-field sonata-ba-list-field-html" objectId="12345"> Creatin... </td>',
1133
                'html',
1134
                '<p><strong>Creating a Template for the Field</strong> and form</p>',
1135
                ['truncate' => ['length' => 10]],
1136
            ],
1137
            [
1138
                '<td class="sonata-ba-list-field sonata-ba-list-field-html" objectId="12345">
1139
                Creating a Template for the Field...
1140
                </td>',
1141
                'html',
1142
                '<p><strong>Creating a Template for the Field</strong> and form</p>',
1143
                ['truncate' => ['cut' => false]],
1144
            ],
1145
            [
1146
                '<td class="sonata-ba-list-field sonata-ba-list-field-html" objectId="12345">
1147
                Creating a Template for t etc.
1148
                </td>',
1149
                'html',
1150
                '<p><strong>Creating a Template for the Field</strong> and form</p>',
1151
                ['truncate' => ['ellipsis' => ' etc.']],
1152
            ],
1153
            [
1154
                '<td class="sonata-ba-list-field sonata-ba-list-field-html" objectId="12345">
1155
                Creating a Template[...]
1156
                </td>',
1157
                'html',
1158
                '<p><strong>Creating a Template for the Field</strong> and form</p>',
1159
                [
1160
                    'truncate' => [
1161
                        'length' => 20,
1162
                        'cut' => false,
1163
                        'ellipsis' => '[...]',
1164
                    ],
1165
                ],
1166
            ],
1167
1168
            [
1169
                <<<'EOT'
1170
<td class="sonata-ba-list-field sonata-ba-list-field-text" objectId="12345">
1171
<div
1172
    class="sonata-readmore"
1173
    data-readmore-height="40"
1174
    data-readmore-more="Read more"
1175
    data-readmore-less="Close">A very long string</div>
1176
</td>
1177
EOT
1178
                ,
1179
                'text',
1180
                'A very long string',
1181
                [
1182
                    'collapse' => true,
1183
                ],
1184
            ],
1185
            [
1186
                <<<'EOT'
1187
<td class="sonata-ba-list-field sonata-ba-list-field-text" objectId="12345">
1188
<div
1189
    class="sonata-readmore"
1190
    data-readmore-height="10"
1191
    data-readmore-more="More"
1192
    data-readmore-less="Less">A very long string</div>
1193
</td>
1194
EOT
1195
                ,
1196
                'text',
1197
                'A very long string',
1198
                [
1199
                    'collapse' => [
1200
                        'height' => 10,
1201
                        'more' => 'More',
1202
                        'less' => 'Less',
1203
                    ],
1204
                ],
1205
            ],
1206
            [
1207
                <<<'EOT'
1208
<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345">
1209
    <span
1210
        class="x-editable"
1211
        data-type="checklist"
1212
        data-value="[&quot;Status1&quot;,&quot;Status2&quot;]"
1213
        data-title="Data"
1214
        data-pk="12345"
1215
        data-url="/core/set-object-field-value?context=list&amp;field=fd_name&amp;objectId=12345&amp;code=sonata_admin_foo_service"
1216
        data-source="[{&quot;value&quot;:&quot;Status1&quot;,&quot;text&quot;:&quot;Delete&quot;},{&quot;value&quot;:&quot;Status2&quot;,&quot;text&quot;:&quot;Alias2&quot;},{&quot;value&quot;:&quot;Status3&quot;,&quot;text&quot;:&quot;Alias3&quot;}]" >
1217
         Delete, Alias2
1218
    </span>
1219
</td>
1220
EOT
1221
                ,
1222
                'choice',
1223
                [
1224
                    'Status1',
1225
                    'Status2',
1226
                ],
1227
                [
1228
                    'editable' => true,
1229
                    'multiple' => true,
1230
                    'catalogue' => 'SonataAdminBundle',
1231
                    'choices' => [
1232
                        'Status1' => 'action_delete',
1233
                        'Status2' => 'Alias2',
1234
                        'Status3' => 'Alias3',
1235
                    ],
1236
                ],
1237
            ],
1238
        ];
1239
    }
1240
1241
    /**
1242
     * @dataProvider getRenderViewElementTests
1243
     */
1244
    public function testRenderViewElement(string $expected, string $type, $value, array $options): void
1245
    {
1246
        $this->fieldDescription
1247
            ->method('getValue')
1248
            ->willReturn($value);
1249
1250
        $this->fieldDescription
1251
            ->method('getType')
1252
            ->willReturn($type);
1253
1254
        $this->fieldDescription
1255
            ->method('getOptions')
1256
            ->willReturn($options);
1257
1258
        $this->fieldDescription
1259
            ->method('getTemplate')
1260
            ->willReturnCallback(static function () use ($type): ?string {
1261
                switch ($type) {
1262
                    case 'boolean':
1263
                        return '@SonataAdmin/CRUD/show_boolean.html.twig';
1264
                    case 'datetime':
1265
                        return '@SonataAdmin/CRUD/show_datetime.html.twig';
1266
                    case 'date':
1267
                        return '@SonataAdmin/CRUD/show_date.html.twig';
1268
                    case 'time':
1269
                        return '@SonataAdmin/CRUD/show_time.html.twig';
1270
                    case 'currency':
1271
                        return '@SonataAdmin/CRUD/show_currency.html.twig';
1272
                    case 'percent':
1273
                        return '@SonataAdmin/CRUD/show_percent.html.twig';
1274
                    case 'email':
1275
                        return '@SonataAdmin/CRUD/show_email.html.twig';
1276
                    case 'choice':
1277
                        return '@SonataAdmin/CRUD/show_choice.html.twig';
1278
                    case 'array':
1279
                        return '@SonataAdmin/CRUD/show_array.html.twig';
1280
                    case 'trans':
1281
                        return '@SonataAdmin/CRUD/show_trans.html.twig';
1282
                    case 'url':
1283
                        return '@SonataAdmin/CRUD/show_url.html.twig';
1284
                    case 'html':
1285
                        return '@SonataAdmin/CRUD/show_html.html.twig';
1286
                    default:
1287
                        return null;
1288
                }
1289
            });
1290
1291
        $this->assertSame(
1292
            $this->removeExtraWhitespace($expected),
1293
            $this->removeExtraWhitespace(
1294
                $this->twigExtension->renderViewElement(
1295
                    $this->environment,
1296
                    $this->fieldDescription,
1297
                    $this->object
1298
                )
1299
            )
1300
        );
1301
    }
1302
1303
    public function getRenderViewElementTests()
1304
    {
1305
        return [
1306
            ['<th>Data</th> <td>Example</td>', 'string', 'Example', ['safe' => false]],
1307
            ['<th>Data</th> <td>Example</td>', 'text', 'Example', ['safe' => false]],
1308
            ['<th>Data</th> <td>Example</td>', 'textarea', 'Example', ['safe' => false]],
1309
            [
1310
                '<th>Data</th> <td><time datetime="2013-12-24T10:11:12+00:00" title="2013-12-24T10:11:12+00:00"> December 24, 2013 10:11 </time></td>',
1311
                'datetime',
1312
                new \DateTime('2013-12-24 10:11:12', new \DateTimeZone('Europe/London')), [],
1313
            ],
1314
            [
1315
                '<th>Data</th> <td><time datetime="2013-12-24T10:11:12+00:00" title="2013-12-24T10:11:12+00:00"> 24.12.2013 10:11:12 </time></td>',
1316
                'datetime',
1317
                new \DateTime('2013-12-24 10:11:12', new \DateTimeZone('Europe/London')),
1318
                ['format' => 'd.m.Y H:i:s'],
1319
            ],
1320
            [
1321
                '<th>Data</th> <td><time datetime="2013-12-24T10:11:12+00:00" title="2013-12-24T10:11:12+00:00"> December 24, 2013 18:11 </time></td>',
1322
                'datetime',
1323
                new \DateTime('2013-12-24 10:11:12', new \DateTimeZone('UTC')),
1324
                ['timezone' => 'Asia/Hong_Kong'],
1325
            ],
1326
            [
1327
                '<th>Data</th> <td><time datetime="2013-12-24" title="2013-12-24"> December 24, 2013 </time></td>',
1328
                'date',
1329
                new \DateTime('2013-12-24 10:11:12', new \DateTimeZone('Europe/London')),
1330
                [],
1331
            ],
1332
            [
1333
                '<th>Data</th> <td><time datetime="2013-12-24" title="2013-12-24"> 24.12.2013 </time></td>',
1334
                'date',
1335
                new \DateTime('2013-12-24 10:11:12', new \DateTimeZone('Europe/London')),
1336
                ['format' => 'd.m.Y'],
1337
            ],
1338
            [
1339
                '<th>Data</th> <td><time datetime="10:11:12+00:00" title="10:11:12+00:00"> 10:11:12 </time></td>',
1340
                'time',
1341
                new \DateTime('2013-12-24 10:11:12', new \DateTimeZone('Europe/London')),
1342
                [],
1343
            ],
1344
            [
1345
                '<th>Data</th> <td><time datetime="10:11:12+00:00" title="10:11:12+00:00"> 18:11:12 </time></td>',
1346
                'time',
1347
                new \DateTime('2013-12-24 10:11:12', new \DateTimeZone('UTC')),
1348
                ['timezone' => 'Asia/Hong_Kong'],
1349
            ],
1350
            ['<th>Data</th> <td>10.746135</td>', 'number', 10.746135, ['safe' => false]],
1351
            ['<th>Data</th> <td>5678</td>', 'integer', 5678, ['safe' => false]],
1352
            ['<th>Data</th> <td> 1074.6135 % </td>', 'percent', 10.746135, []],
1353
            ['<th>Data</th> <td> EUR 10.746135 </td>', 'currency', 10.746135, ['currency' => 'EUR']],
1354
            ['<th>Data</th> <td> GBP 51.23456 </td>', 'currency', 51.23456, ['currency' => 'GBP']],
1355
            [
1356
                '<th>Data</th> <td> <ul><li>1&nbsp;=>&nbsp;First</li><li>2&nbsp;=>&nbsp;Second</li></ul> </td>',
1357
                'array',
1358
                [1 => 'First', 2 => 'Second'],
1359
                ['safe' => false],
1360
            ],
1361
            [
1362
                '<th>Data</th> <td> [1&nbsp;=>&nbsp;First, 2&nbsp;=>&nbsp;Second] </td>',
1363
                'array',
1364
                [1 => 'First', 2 => 'Second'],
1365
                ['safe' => false, 'inline' => true],
1366
            ],
1367
            [
1368
                '<th>Data</th> <td><span class="label label-success">yes</span></td>',
1369
                'boolean',
1370
                true,
1371
                [],
1372
            ],
1373
            [
1374
                '<th>Data</th> <td><span class="label label-danger">yes</span></td>',
1375
                'boolean',
1376
                true,
1377
                ['inverse' => true],
1378
            ],
1379
            ['<th>Data</th> <td><span class="label label-danger">no</span></td>', 'boolean', false, []],
1380
            [
1381
                '<th>Data</th> <td><span class="label label-success">no</span></td>',
1382
                'boolean',
1383
                false,
1384
                ['inverse' => true],
1385
            ],
1386
            [
1387
                '<th>Data</th> <td> Delete </td>',
1388
                'trans',
1389
                'action_delete',
1390
                ['safe' => false, 'catalogue' => 'SonataAdminBundle'],
1391
            ],
1392
            [
1393
                '<th>Data</th> <td> Delete </td>',
1394
                'trans',
1395
                'delete',
1396
                ['safe' => false, 'catalogue' => 'SonataAdminBundle', 'format' => 'action_%s'],
1397
            ],
1398
            ['<th>Data</th> <td>Status1</td>', 'choice', 'Status1', ['safe' => false]],
1399
            [
1400
                '<th>Data</th> <td>Alias1</td>',
1401
                'choice',
1402
                'Status1',
1403
                ['safe' => false, 'choices' => [
1404
                    'Status1' => 'Alias1',
1405
                    'Status2' => 'Alias2',
1406
                    'Status3' => 'Alias3',
1407
                ]],
1408
            ],
1409
            [
1410
                '<th>Data</th> <td>NoValidKeyInChoices</td>',
1411
                'choice',
1412
                'NoValidKeyInChoices',
1413
                ['safe' => false, 'choices' => [
1414
                    'Status1' => 'Alias1',
1415
                    'Status2' => 'Alias2',
1416
                    'Status3' => 'Alias3',
1417
                ]],
1418
            ],
1419
            [
1420
                '<th>Data</th> <td>Delete</td>',
1421
                'choice',
1422
                'Foo',
1423
                ['safe' => false, 'catalogue' => 'SonataAdminBundle', 'choices' => [
1424
                    'Foo' => 'action_delete',
1425
                    'Status2' => 'Alias2',
1426
                    'Status3' => 'Alias3',
1427
                ]],
1428
            ],
1429
            [
1430
                '<th>Data</th> <td>NoValidKeyInChoices</td>',
1431
                'choice',
1432
                ['NoValidKeyInChoices'],
1433
                ['safe' => false, 'choices' => [
1434
                    'Status1' => 'Alias1',
1435
                    'Status2' => 'Alias2',
1436
                    'Status3' => 'Alias3',
1437
                ], 'multiple' => true],
1438
            ],
1439
            [
1440
                '<th>Data</th> <td>NoValidKeyInChoices, Alias2</td>',
1441
                'choice',
1442
                ['NoValidKeyInChoices', 'Status2'],
1443
                ['safe' => false, 'choices' => [
1444
                    'Status1' => 'Alias1',
1445
                    'Status2' => 'Alias2',
1446
                    'Status3' => 'Alias3',
1447
                ], 'multiple' => true],
1448
            ],
1449
            [
1450
                '<th>Data</th> <td>Alias1, Alias3</td>',
1451
                'choice',
1452
                ['Status1', 'Status3'],
1453
                ['safe' => false, 'choices' => [
1454
                    'Status1' => 'Alias1',
1455
                    'Status2' => 'Alias2',
1456
                    'Status3' => 'Alias3',
1457
                ], 'multiple' => true],
1458
            ],
1459
            [
1460
                '<th>Data</th> <td>Alias1 | Alias3</td>',
1461
                'choice',
1462
                ['Status1', 'Status3'], ['safe' => false, 'choices' => [
1463
                    'Status1' => 'Alias1',
1464
                    'Status2' => 'Alias2',
1465
                    'Status3' => 'Alias3',
1466
                ], 'multiple' => true, 'delimiter' => ' | '],
1467
            ],
1468
            [
1469
                '<th>Data</th> <td>Delete, Alias3</td>',
1470
                'choice',
1471
                ['Foo', 'Status3'],
1472
                ['safe' => false, 'catalogue' => 'SonataAdminBundle', 'choices' => [
1473
                    'Foo' => 'action_delete',
1474
                    'Status2' => 'Alias2',
1475
                    'Status3' => 'Alias3',
1476
                ], 'multiple' => true],
1477
            ],
1478
            [
1479
                '<th>Data</th> <td><b>Alias1</b>, <b>Alias3</b></td>',
1480
                'choice',
1481
                ['Status1', 'Status3'],
1482
                ['safe' => true, 'choices' => [
1483
                    'Status1' => '<b>Alias1</b>',
1484
                    'Status2' => '<b>Alias2</b>',
1485
                    'Status3' => '<b>Alias3</b>',
1486
                ], 'multiple' => true],
1487
            ],
1488
            [
1489
                '<th>Data</th> <td>&lt;b&gt;Alias1&lt;/b&gt;, &lt;b&gt;Alias3&lt;/b&gt;</td>',
1490
                'choice',
1491
                ['Status1', 'Status3'],
1492
                ['safe' => false, 'choices' => [
1493
                    'Status1' => '<b>Alias1</b>',
1494
                    'Status2' => '<b>Alias2</b>',
1495
                    'Status3' => '<b>Alias3</b>',
1496
                ], 'multiple' => true],
1497
            ],
1498
            [
1499
                '<th>Data</th> <td><a href="http://example.com">http://example.com</a></td>',
1500
                'url',
1501
                'http://example.com',
1502
                ['safe' => false],
1503
            ],
1504
            [
1505
                '<th>Data</th> <td><a href="http://example.com" target="_blank">http://example.com</a></td>',
1506
                'url',
1507
                'http://example.com',
1508
                ['safe' => false, 'attributes' => ['target' => '_blank']],
1509
            ],
1510
            [
1511
                '<th>Data</th> <td><a href="http://example.com" target="_blank" class="fooLink">http://example.com</a></td>',
1512
                'url',
1513
                'http://example.com',
1514
                ['safe' => false, 'attributes' => ['target' => '_blank', 'class' => 'fooLink']],
1515
            ],
1516
            [
1517
                '<th>Data</th> <td><a href="https://example.com">https://example.com</a></td>',
1518
                'url',
1519
                'https://example.com',
1520
                ['safe' => false],
1521
            ],
1522
            [
1523
                '<th>Data</th> <td><a href="http://example.com">example.com</a></td>',
1524
                'url',
1525
                'http://example.com',
1526
                ['safe' => false, 'hide_protocol' => true],
1527
            ],
1528
            [
1529
                '<th>Data</th> <td><a href="https://example.com">example.com</a></td>',
1530
                'url',
1531
                'https://example.com',
1532
                ['safe' => false, 'hide_protocol' => true],
1533
            ],
1534
            [
1535
                '<th>Data</th> <td><a href="http://example.com">http://example.com</a></td>',
1536
                'url',
1537
                'http://example.com',
1538
                ['safe' => false, 'hide_protocol' => false],
1539
            ],
1540
            [
1541
                '<th>Data</th> <td><a href="https://example.com">https://example.com</a></td>',
1542
                'url',
1543
                'https://example.com',
1544
                ['safe' => false,
1545
                'hide_protocol' => false, ],
1546
            ],
1547
            [
1548
                '<th>Data</th> <td><a href="http://example.com">Foo</a></td>',
1549
                'url',
1550
                'Foo',
1551
                ['safe' => false, 'url' => 'http://example.com'],
1552
            ],
1553
            [
1554
                '<th>Data</th> <td><a href="http://example.com">&lt;b&gt;Foo&lt;/b&gt;</a></td>',
1555
                'url',
1556
                '<b>Foo</b>',
1557
                ['safe' => false, 'url' => 'http://example.com'],
1558
            ],
1559
            [
1560
                '<th>Data</th> <td><a href="http://example.com"><b>Foo</b></a></td>',
1561
                'url',
1562
                '<b>Foo</b>',
1563
                ['safe' => true, 'url' => 'http://example.com'],
1564
            ],
1565
            [
1566
                '<th>Data</th> <td><a href="/foo">Foo</a></td>',
1567
                'url',
1568
                'Foo',
1569
                ['safe' => false, 'route' => ['name' => 'sonata_admin_foo']],
1570
            ],
1571
            [
1572
                '<th>Data</th> <td><a href="http://localhost/foo">Foo</a></td>',
1573
                'url',
1574
                'Foo',
1575
                ['safe' => false, 'route' => [
1576
                    'name' => 'sonata_admin_foo',
1577
                    'absolute' => true,
1578
                ]],
1579
            ],
1580
            [
1581
                '<th>Data</th> <td><a href="/foo">foo/bar?a=b&amp;c=123456789</a></td>',
1582
                'url',
1583
                'http://foo/bar?a=b&c=123456789',
1584
                [
1585
                    'safe' => false,
1586
                    'route' => ['name' => 'sonata_admin_foo'],
1587
                    'hide_protocol' => true,
1588
                ],
1589
            ],
1590
            [
1591
                '<th>Data</th> <td><a href="http://localhost/foo">foo/bar?a=b&amp;c=123456789</a></td>',
1592
                'url',
1593
                'http://foo/bar?a=b&c=123456789',
1594
                ['safe' => false, 'route' => [
1595
                    'name' => 'sonata_admin_foo',
1596
                    'absolute' => true,
1597
                ], 'hide_protocol' => true],
1598
            ],
1599
            [
1600
                '<th>Data</th> <td><a href="/foo/abcd/efgh?param3=ijkl">Foo</a></td>',
1601
                'url',
1602
                'Foo',
1603
                ['safe' => false, 'route' => [
1604
                    'name' => 'sonata_admin_foo_param',
1605
                    'parameters' => ['param1' => 'abcd', 'param2' => 'efgh', 'param3' => 'ijkl'],
1606
                ]],
1607
            ],
1608
            [
1609
                '<th>Data</th> <td><a href="http://localhost/foo/abcd/efgh?param3=ijkl">Foo</a></td>',
1610
                'url',
1611
                'Foo',
1612
                ['safe' => false, 'route' => [
1613
                    'name' => 'sonata_admin_foo_param',
1614
                    'absolute' => true,
1615
                    'parameters' => [
1616
                        'param1' => 'abcd',
1617
                        'param2' => 'efgh',
1618
                        'param3' => 'ijkl',
1619
                    ],
1620
                ]],
1621
            ],
1622
            [
1623
                '<th>Data</th> <td><a href="/foo/obj/abcd/12345/efgh?param3=ijkl">Foo</a></td>',
1624
                'url',
1625
                'Foo',
1626
                ['safe' => false, 'route' => [
1627
                    'name' => 'sonata_admin_foo_object',
1628
                    'parameters' => [
1629
                        'param1' => 'abcd',
1630
                        'param2' => 'efgh',
1631
                        'param3' => 'ijkl',
1632
                    ],
1633
                    'identifier_parameter_name' => 'barId',
1634
                ]],
1635
            ],
1636
            [
1637
                '<th>Data</th> <td><a href="http://localhost/foo/obj/abcd/12345/efgh?param3=ijkl">Foo</a></td>',
1638
                'url',
1639
                'Foo',
1640
                ['safe' => false, 'route' => [
1641
                    'name' => 'sonata_admin_foo_object',
1642
                    'absolute' => true,
1643
                    'parameters' => [
1644
                        'param1' => 'abcd',
1645
                        'param2' => 'efgh',
1646
                        'param3' => 'ijkl',
1647
                    ],
1648
                    'identifier_parameter_name' => 'barId',
1649
                ]],
1650
            ],
1651
            [
1652
                '<th>Data</th> <td> &nbsp;</td>',
1653
                'email',
1654
                null,
1655
                [],
1656
            ],
1657
            [
1658
                '<th>Data</th> <td> <a href="mailto:[email protected]">[email protected]</a></td>',
1659
                'email',
1660
                '[email protected]',
1661
                [],
1662
            ],
1663
            [
1664
                '<th>Data</th> <td> <a href="mailto:[email protected]?'.$this->buildTwigLikeUrl(['subject' => 'Main Theme', 'body' => 'Message Body']).'">[email protected]</a></td>',
1665
                'email',
1666
                '[email protected]',
1667
                ['subject' => 'Main Theme', 'body' => 'Message Body'],
1668
            ],
1669
            [
1670
                '<th>Data</th> <td> <a href="mailto:[email protected]?'.$this->buildTwigLikeUrl(['subject' => 'Main Theme']).'">[email protected]</a></td>',
1671
                'email',
1672
                '[email protected]',
1673
                ['subject' => 'Main Theme'],
1674
            ],
1675
            [
1676
                '<th>Data</th> <td> <a href="mailto:[email protected]?'.$this->buildTwigLikeUrl(['body' => 'Message Body']).'">[email protected]</a></td>',
1677
                'email',
1678
                '[email protected]',
1679
                ['body' => 'Message Body'],
1680
            ],
1681
            [
1682
                '<th>Data</th> <td> [email protected]</td>',
1683
                'email',
1684
                '[email protected]',
1685
                ['as_string' => true, 'subject' => 'Main Theme', 'body' => 'Message Body'],
1686
            ],
1687
            [
1688
                '<th>Data</th> <td> [email protected]</td>',
1689
                'email',
1690
                '[email protected]',
1691
                ['as_string' => true, 'subject' => 'Main Theme'],
1692
            ],
1693
            [
1694
                '<th>Data</th> <td> [email protected]</td>',
1695
                'email',
1696
                '[email protected]',
1697
                ['as_string' => true, 'body' => 'Message Body'],
1698
            ],
1699
            [
1700
                '<th>Data</th> <td> <a href="mailto:[email protected]">[email protected]</a></td>',
1701
                'email',
1702
                '[email protected]',
1703
                ['as_string' => false],
1704
            ],
1705
            [
1706
                '<th>Data</th> <td> [email protected]</td>',
1707
                'email',
1708
                '[email protected]',
1709
                ['as_string' => true],
1710
            ],
1711
            [
1712
                '<th>Data</th> <td><p><strong>Creating a Template for the Field</strong> and form</p> </td>',
1713
                'html',
1714
                '<p><strong>Creating a Template for the Field</strong> and form</p>',
1715
                [],
1716
            ],
1717
            [
1718
                '<th>Data</th> <td>Creating a Template for the Field and form </td>',
1719
                'html',
1720
                '<p><strong>Creating a Template for the Field</strong> and form</p>',
1721
                ['strip' => true],
1722
            ],
1723
            [
1724
                '<th>Data</th> <td> Creating a Template for the... </td>',
1725
                'html',
1726
                '<p><strong>Creating a Template for the Field</strong> and form</p>',
1727
                ['truncate' => true],
1728
            ],
1729
            [
1730
                '<th>Data</th> <td> Creatin... </td>',
1731
                'html',
1732
                '<p><strong>Creating a Template for the Field</strong> and form</p>',
1733
                ['truncate' => ['length' => 10]],
1734
            ],
1735
            [
1736
                '<th>Data</th> <td> Creating a Template for the Field... </td>',
1737
                'html',
1738
                '<p><strong>Creating a Template for the Field</strong> and form</p>',
1739
                ['truncate' => ['cut' => false]],
1740
            ],
1741
            [
1742
                '<th>Data</th> <td> Creating a Template for t etc. </td>',
1743
                'html',
1744
                '<p><strong>Creating a Template for the Field</strong> and form</p>',
1745
                ['truncate' => ['ellipsis' => ' etc.']],
1746
            ],
1747
            [
1748
                '<th>Data</th> <td> Creating a Template[...] </td>',
1749
                'html',
1750
                '<p><strong>Creating a Template for the Field</strong> and form</p>',
1751
                [
1752
                    'truncate' => [
1753
                        'length' => 20,
1754
                        'cut' => false,
1755
                        'ellipsis' => '[...]',
1756
                    ],
1757
                ],
1758
            ],
1759
            [
1760
                <<<'EOT'
1761
<th>Data</th> <td><div
1762
        class="sonata-readmore"
1763
        data-readmore-height="40"
1764
        data-readmore-more="Read more"
1765
        data-readmore-less="Close">
1766
            A very long string
1767
</div></td>
1768
EOT
1769
                ,
1770
                'text',
1771
                ' A very long string ',
1772
                [
1773
                    'collapse' => true,
1774
                    'safe' => false,
1775
                ],
1776
            ],
1777
            [
1778
                <<<'EOT'
1779
<th>Data</th> <td><div
1780
        class="sonata-readmore"
1781
        data-readmore-height="10"
1782
        data-readmore-more="More"
1783
        data-readmore-less="Less">
1784
            A very long string
1785
</div></td>
1786
EOT
1787
                ,
1788
                'text',
1789
                ' A very long string ',
1790
                [
1791
                    'collapse' => [
1792
                        'height' => 10,
1793
                        'more' => 'More',
1794
                        'less' => 'Less',
1795
                    ],
1796
                    'safe' => false,
1797
                ],
1798
            ],
1799
        ];
1800
    }
1801
1802
    public function getRenderViewElementWithNoValueTests(): iterable
1803
    {
1804
        return [
1805
            // NoValueException
1806
            ['<th>Data</th> <td></td>', 'string', ['safe' => false]],
1807
            ['<th>Data</th> <td></td>', 'text', ['safe' => false]],
1808
            ['<th>Data</th> <td></td>', 'textarea', ['safe' => false]],
1809
            ['<th>Data</th> <td>&nbsp;</td>', 'datetime', []],
1810
            [
1811
                '<th>Data</th> <td>&nbsp;</td>',
1812
                'datetime',
1813
                ['format' => 'd.m.Y H:i:s'],
1814
            ],
1815
            ['<th>Data</th> <td>&nbsp;</td>', 'date', []],
1816
            ['<th>Data</th> <td>&nbsp;</td>', 'date', ['format' => 'd.m.Y']],
1817
            ['<th>Data</th> <td>&nbsp;</td>', 'time', []],
1818
            ['<th>Data</th> <td></td>', 'number', ['safe' => false]],
1819
            ['<th>Data</th> <td></td>', 'integer', ['safe' => false]],
1820
            ['<th>Data</th> <td> 0 % </td>', 'percent', []],
1821
            ['<th>Data</th> <td> </td>', 'currency', ['currency' => 'EUR']],
1822
            ['<th>Data</th> <td> </td>', 'currency', ['currency' => 'GBP']],
1823
            ['<th>Data</th> <td> <ul></ul> </td>', 'array', ['safe' => false]],
1824
            [
1825
                '<th>Data</th> <td><span class="label label-danger">no</span></td>',
1826
                'boolean',
1827
                [],
1828
            ],
1829
            [
1830
                '<th>Data</th> <td> </td>',
1831
                'trans',
1832
                ['safe' => false, 'catalogue' => 'SonataAdminBundle'],
1833
            ],
1834
            [
1835
                '<th>Data</th> <td></td>',
1836
                'choice',
1837
                ['safe' => false, 'choices' => []],
1838
            ],
1839
            [
1840
                '<th>Data</th> <td></td>',
1841
                'choice',
1842
                ['safe' => false, 'choices' => [], 'multiple' => true],
1843
            ],
1844
            ['<th>Data</th> <td>&nbsp;</td>', 'url', []],
1845
            [
1846
                '<th>Data</th> <td>&nbsp;</td>',
1847
                'url',
1848
                ['url' => 'http://example.com'],
1849
            ],
1850
            [
1851
                '<th>Data</th> <td>&nbsp;</td>',
1852
                'url',
1853
                ['route' => ['name' => 'sonata_admin_foo']],
1854
            ],
1855
        ];
1856
    }
1857
1858
    /**
1859
     * NEXT_MAJOR: Remove this method.
1860
     *
1861
     * @group legacy
1862
     *
1863
     * @dataProvider getDeprecatedTextExtensionItems
1864
     *
1865
     * @expectedDeprecation The "truncate.preserve" option is deprecated since sonata-project/admin-bundle 3.65, to be removed in 4.0. Use "truncate.cut" instead. ("@SonataAdmin/CRUD/show_html.html.twig" at line %d).
1866
     *
1867
     * @expectedDeprecation The "truncate.separator" option is deprecated since sonata-project/admin-bundle 3.65, to be removed in 4.0. Use "truncate.ellipsis" instead. ("@SonataAdmin/CRUD/show_html.html.twig" at line %d).
1868
     */
1869
    public function testDeprecatedTextExtension(string $expected, string $type, $value, array $options): void
1870
    {
1871
        $loader = new StubFilesystemLoader([
1872
            sprintf('%s/../../../src/Resources/views/CRUD', __DIR__),
1873
        ]);
1874
        $loader->addPath(sprintf('%s/../../../src/Resources/views/', __DIR__), 'SonataAdmin');
1875
        $environment = new Environment($loader, [
1876
            'strict_variables' => true,
1877
            'cache' => false,
1878
            'autoescape' => 'html',
1879
            'optimizations' => 0,
1880
        ]);
1881
        $environment->addExtension($this->twigExtension);
1882
        $environment->addExtension(new TranslationExtension($this->translator));
1883
        $environment->addExtension(new StringExtension());
1884
1885
        $this->fieldDescription
1886
            ->method('getValue')
1887
            ->willReturn($value);
1888
1889
        $this->fieldDescription
1890
            ->method('getType')
1891
            ->willReturn($type);
1892
1893
        $this->fieldDescription
1894
            ->method('getOptions')
1895
            ->willReturn($options);
1896
1897
        $this->fieldDescription
1898
            ->method('getTemplate')
1899
            ->willReturn('@SonataAdmin/CRUD/show_html.html.twig');
1900
1901
        $this->assertSame(
1902
            $this->removeExtraWhitespace($expected),
1903
            $this->removeExtraWhitespace(
1904
                $this->twigExtension->renderViewElement(
1905
                    $environment,
1906
                    $this->fieldDescription,
1907
                    $this->object
1908
                )
1909
            )
1910
        );
1911
    }
1912
1913
    /**
1914
     * NEXT_MAJOR: Remove this method.
1915
     */
1916
    public function getDeprecatedTextExtensionItems(): iterable
1917
    {
1918
        yield 'default_separator' => [
1919
            '<th>Data</th> <td> Creating a Template for the Field... </td>',
1920
            'html',
1921
            '<p><strong>Creating a Template for the Field</strong> and form</p>',
1922
            ['truncate' => ['preserve' => true, 'separator' => '...']],
1923
        ];
1924
1925
        yield 'custom_length' => [
1926
            '<th>Data</th> <td> Creating a Template[...] </td>',
1927
            'html',
1928
            '<p><strong>Creating a Template for the Field</strong> and form</p>',
1929
            [
1930
                'truncate' => [
1931
                    'length' => 20,
1932
                    'preserve' => true,
1933
                    'separator' => '[...]',
1934
                ],
1935
            ],
1936
        ];
1937
    }
1938
1939
    /**
1940
     * NEXT_MAJOR: Remove this test.
1941
     *
1942
     * @group legacy
1943
     */
1944
    public function testGetValueFromFieldDescription(): void
1945
    {
1946
        $object = new \stdClass();
1947
        $fieldDescription = $this->getMockForAbstractClass(FieldDescriptionInterface::class);
1948
1949
        $fieldDescription
1950
            ->method('getValue')
1951
            ->willReturn('test123');
1952
1953
        $this->assertSame(
1954
            'test123',
1955
            $this->getMethodAsPublic('getValueFromFieldDescription')->invoke(
1956
                $this->twigExtension,
1957
                $object,
1958
                $fieldDescription
1959
            )
1960
        );
1961
    }
1962
1963
    /**
1964
     * NEXT_MAJOR: Remove this test.
1965
     *
1966
     * @group legacy
1967
     */
1968
    public function testGetValueFromFieldDescriptionWithRemoveLoopException(): void
1969
    {
1970
        $object = $this->createMock(\ArrayAccess::class);
1971
        $fieldDescription = $this->getMockForAbstractClass(FieldDescriptionInterface::class);
1972
1973
        $this->expectException(\RuntimeException::class);
1974
        $this->expectExceptionMessage('remove the loop requirement');
1975
1976
        $this->assertSame(
1977
            'anything',
1978
            $this->getMethodAsPublic('getValueFromFieldDescription')->invoke(
1979
                $this->twigExtension,
1980
                $object,
1981
                $fieldDescription,
1982
                ['loop' => true]
1983
            )
1984
        );
1985
    }
1986
1987
    public function testGetValueFromFieldDescriptionWithNoValueException(): void
1988
    {
1989
        $object = new \stdClass();
1990
        $fieldDescription = $this->getMockForAbstractClass(FieldDescriptionInterface::class);
1991
1992
        $fieldDescription
1993
            ->method('getValue')
1994
            ->willReturnCallback(static function (): void {
1995
                throw new NoValueException();
1996
            });
1997
1998
        $fieldDescription
1999
            ->method('getAssociationAdmin')
2000
            ->willReturn(null);
2001
2002
        $this->assertNull(
2003
            $this->getMethodAsPublic('getValueFromFieldDescription')->invoke(
2004
                $this->twigExtension,
2005
                $object,
2006
                $fieldDescription
2007
            )
2008
        );
2009
    }
2010
2011
    /**
2012
     * NEXT_MAJOR: Remove this test.
2013
     *
2014
     * @group legacy
2015
     */
2016
    public function testGetValueFromFieldDescriptionWithNoValueExceptionNewAdminInstance(): void
2017
    {
2018
        $object = new \stdClass();
2019
        $fieldDescription = $this->getMockForAbstractClass(FieldDescriptionInterface::class);
2020
2021
        $fieldDescription
2022
            ->method('getValue')
2023
            ->willReturnCallback(static function (): void {
2024
                throw new NoValueException();
2025
            });
2026
2027
        $fieldDescription
2028
            ->method('getAssociationAdmin')
2029
            ->willReturn($this->admin);
2030
2031
        $newInstance = new \stdClass();
2032
2033
        $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...
2034
            ->method('getNewInstance')
2035
            ->willReturn($newInstance);
2036
2037
        $this->assertSame(
2038
            $newInstance,
2039
            $this->getMethodAsPublic('getValueFromFieldDescription')->invoke(
2040
                $this->twigExtension,
2041
                $object,
2042
                $fieldDescription
2043
            )
2044
        );
2045
    }
2046
2047
    public function testRenderRelationElementNoObject(): void
2048
    {
2049
        $this->assertSame('foo', $this->twigExtension->renderRelationElement('foo', $this->fieldDescription));
2050
    }
2051
2052
    public function testRenderRelationElementToString(): void
2053
    {
2054
        $this->fieldDescription->expects($this->exactly(2))
2055
            ->method('getOption')
2056
            ->willReturnCallback(static function ($value, $default = null) {
2057
                if ('associated_property' === $value) {
2058
                    return $default;
2059
                }
2060
            });
2061
2062
        $element = new FooToString();
2063
        $this->assertSame('salut', $this->twigExtension->renderRelationElement($element, $this->fieldDescription));
2064
    }
2065
2066
    /**
2067
     * @group legacy
2068
     */
2069
    public function testDeprecatedRelationElementToString(): void
2070
    {
2071
        $this->fieldDescription->expects($this->exactly(2))
2072
            ->method('getOption')
2073
            ->willReturnCallback(static function ($value, $default = null) {
2074
                if ('associated_tostring' === $value) {
2075
                    return '__toString';
2076
                }
2077
            });
2078
2079
        $element = new FooToString();
2080
        $this->assertSame(
2081
            'salut',
2082
            $this->twigExtension->renderRelationElement($element, $this->fieldDescription)
2083
        );
2084
    }
2085
2086
    /**
2087
     * @group legacy
2088
     */
2089
    public function testRenderRelationElementCustomToString(): void
2090
    {
2091
        $this->fieldDescription->expects($this->exactly(2))
2092
            ->method('getOption')
2093
            ->willReturnCallback(static function ($value, $default = null) {
2094
                if ('associated_property' === $value) {
2095
                    return $default;
2096
                }
2097
2098
                if ('associated_tostring' === $value) {
2099
                    return 'customToString';
2100
                }
2101
            });
2102
2103
        $element = $this->getMockBuilder(\stdClass::class)
2104
            ->setMethods(['customToString'])
2105
            ->getMock();
2106
        $element
2107
            ->method('customToString')
2108
            ->willReturn('fooBar');
2109
2110
        $this->assertSame('fooBar', $this->twigExtension->renderRelationElement($element, $this->fieldDescription));
2111
    }
2112
2113
    /**
2114
     * @group legacy
2115
     */
2116
    public function testRenderRelationElementMethodNotExist(): void
2117
    {
2118
        $this->fieldDescription->expects($this->exactly(2))
2119
            ->method('getOption')
2120
2121
            ->willReturnCallback(static function ($value, $default = null) {
2122
                if ('associated_tostring' === $value) {
2123
                    return 'nonExistedMethod';
2124
                }
2125
            });
2126
2127
        $element = new \stdClass();
2128
        $this->expectException(\RuntimeException::class);
2129
        $this->expectExceptionMessage('You must define an `associated_property` option or create a `stdClass::__toString');
2130
2131
        $this->twigExtension->renderRelationElement($element, $this->fieldDescription);
2132
    }
2133
2134
    public function testRenderRelationElementWithPropertyPath(): void
2135
    {
2136
        $this->fieldDescription->expects($this->once())
2137
            ->method('getOption')
2138
2139
            ->willReturnCallback(static function ($value, $default = null) {
2140
                if ('associated_property' === $value) {
2141
                    return 'foo';
2142
                }
2143
            });
2144
2145
        $element = new \stdClass();
2146
        $element->foo = 'bar';
2147
2148
        $this->assertSame('bar', $this->twigExtension->renderRelationElement($element, $this->fieldDescription));
2149
    }
2150
2151
    public function testRenderRelationElementWithClosure(): void
2152
    {
2153
        $this->fieldDescription->expects($this->once())
2154
            ->method('getOption')
2155
2156
            ->willReturnCallback(static function ($value, $default = null) {
2157
                if ('associated_property' === $value) {
2158
                    return static function ($element): string {
2159
                        return sprintf('closure %s', $element->foo);
2160
                    };
2161
                }
2162
            });
2163
2164
        $element = new \stdClass();
2165
        $element->foo = 'bar';
2166
2167
        $this->assertSame(
2168
            'closure bar',
2169
            $this->twigExtension->renderRelationElement($element, $this->fieldDescription)
2170
        );
2171
    }
2172
2173
    public function testGetUrlsafeIdentifier(): void
2174
    {
2175
        $model = new \stdClass();
2176
2177
        // set admin to pool
2178
        $this->pool->setAdminServiceIds(['sonata_admin_foo_service']);
2179
        $this->pool->setAdminClasses([\stdClass::class => ['sonata_admin_foo_service']]);
2180
2181
        $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...
2182
            ->method('getUrlSafeIdentifier')
2183
            ->with($this->equalTo($model))
2184
            ->willReturn('1234567');
2185
2186
        $this->assertSame('1234567', $this->twigExtension->getUrlSafeIdentifier($model));
2187
    }
2188
2189
    public function testGetUrlsafeIdentifier_GivenAdmin_Foo(): void
2190
    {
2191
        $model = new \stdClass();
2192
2193
        // set admin to pool
2194
        $this->pool->setAdminServiceIds([
2195
            'sonata_admin_foo_service',
2196
            'sonata_admin_bar_service',
2197
        ]);
2198
        $this->pool->setAdminClasses([\stdClass::class => [
2199
            'sonata_admin_foo_service',
2200
            'sonata_admin_bar_service',
2201
        ]]);
2202
2203
        $this->admin->expects($this->once())
2204
            ->method('getUrlSafeIdentifier')
2205
            ->with($this->equalTo($model))
2206
            ->willReturn('1234567');
2207
2208
        $this->adminBar->expects($this->never())
2209
            ->method('getUrlSafeIdentifier');
2210
2211
        $this->assertSame('1234567', $this->twigExtension->getUrlSafeIdentifier($model, $this->admin));
2212
    }
2213
2214
    public function testGetUrlsafeIdentifier_GivenAdmin_Bar(): void
2215
    {
2216
        $model = new \stdClass();
2217
2218
        // set admin to pool
2219
        $this->pool->setAdminServiceIds(['sonata_admin_foo_service', 'sonata_admin_bar_service']);
2220
        $this->pool->setAdminClasses([\stdClass::class => [
2221
            'sonata_admin_foo_service',
2222
            'sonata_admin_bar_service',
2223
        ]]);
2224
2225
        $this->admin->expects($this->never())
2226
            ->method('getUrlSafeIdentifier');
2227
2228
        $this->adminBar->expects($this->once())
2229
            ->method('getUrlSafeIdentifier')
2230
            ->with($this->equalTo($model))
2231
            ->willReturn('1234567');
2232
2233
        $this->assertSame('1234567', $this->twigExtension->getUrlSafeIdentifier($model, $this->adminBar));
2234
    }
2235
2236
    public function xEditableChoicesProvider()
2237
    {
2238
        return [
2239
            'needs processing' => [
2240
                ['choices' => ['Status1' => 'Alias1', 'Status2' => 'Alias2']],
2241
                [
2242
                    ['value' => 'Status1', 'text' => 'Alias1'],
2243
                    ['value' => 'Status2', 'text' => 'Alias2'],
2244
                ],
2245
            ],
2246
            'already processed' => [
2247
                ['choices' => [
2248
                    ['value' => 'Status1', 'text' => 'Alias1'],
2249
                    ['value' => 'Status2', 'text' => 'Alias2'],
2250
                ]],
2251
                [
2252
                    ['value' => 'Status1', 'text' => 'Alias1'],
2253
                    ['value' => 'Status2', 'text' => 'Alias2'],
2254
                ],
2255
            ],
2256
            'not required' => [
2257
                [
2258
                    'required' => false,
2259
                    'choices' => ['' => '', 'Status1' => 'Alias1', 'Status2' => 'Alias2'],
2260
                ],
2261
                [
2262
                    ['value' => '', 'text' => ''],
2263
                    ['value' => 'Status1', 'text' => 'Alias1'],
2264
                    ['value' => 'Status2', 'text' => 'Alias2'],
2265
                ],
2266
            ],
2267
            'not required multiple' => [
2268
                [
2269
                    'required' => false,
2270
                    'multiple' => true,
2271
                    'choices' => ['Status1' => 'Alias1', 'Status2' => 'Alias2'],
2272
                ],
2273
                [
2274
                    ['value' => 'Status1', 'text' => 'Alias1'],
2275
                    ['value' => 'Status2', 'text' => 'Alias2'],
2276
                ],
2277
            ],
2278
        ];
2279
    }
2280
2281
    /**
2282
     * @dataProvider xEditablechoicesProvider
2283
     */
2284
    public function testGetXEditableChoicesIsIdempotent(array $options, array $expectedChoices): void
2285
    {
2286
        $fieldDescription = $this->getMockForAbstractClass(FieldDescriptionInterface::class);
2287
        $fieldDescription
2288
            ->method('getOption')
2289
            ->withConsecutive(
2290
                ['choices', []],
2291
                ['catalogue'],
2292
                ['required'],
2293
                ['multiple']
2294
            )
2295
            ->will($this->onConsecutiveCalls(
2296
                $options['choices'],
2297
                'MyCatalogue',
2298
                $options['multiple'] ?? null
2299
            ));
2300
2301
        $this->assertSame($expectedChoices, $this->twigExtension->getXEditableChoices($fieldDescription));
2302
    }
2303
2304
    public function select2LocalesProvider()
2305
    {
2306
        return [
2307
            ['ar', 'ar'],
2308
            ['az', 'az'],
2309
            ['bg', 'bg'],
2310
            ['ca', 'ca'],
2311
            ['cs', 'cs'],
2312
            ['da', 'da'],
2313
            ['de', 'de'],
2314
            ['el', 'el'],
2315
            [null, 'en'],
2316
            ['es', 'es'],
2317
            ['et', 'et'],
2318
            ['eu', 'eu'],
2319
            ['fa', 'fa'],
2320
            ['fi', 'fi'],
2321
            ['fr', 'fr'],
2322
            ['gl', 'gl'],
2323
            ['he', 'he'],
2324
            ['hr', 'hr'],
2325
            ['hu', 'hu'],
2326
            ['id', 'id'],
2327
            ['is', 'is'],
2328
            ['it', 'it'],
2329
            ['ja', 'ja'],
2330
            ['ka', 'ka'],
2331
            ['ko', 'ko'],
2332
            ['lt', 'lt'],
2333
            ['lv', 'lv'],
2334
            ['mk', 'mk'],
2335
            ['ms', 'ms'],
2336
            ['nb', 'nb'],
2337
            ['nl', 'nl'],
2338
            ['pl', 'pl'],
2339
            ['pt-PT', 'pt'],
2340
            ['pt-BR', 'pt-BR'],
2341
            ['pt-PT', 'pt-PT'],
2342
            ['ro', 'ro'],
2343
            ['rs', 'rs'],
2344
            ['ru', 'ru'],
2345
            ['sk', 'sk'],
2346
            ['sv', 'sv'],
2347
            ['th', 'th'],
2348
            ['tr', 'tr'],
2349
            ['ug-CN', 'ug'],
2350
            ['ug-CN', 'ug-CN'],
2351
            ['uk', 'uk'],
2352
            ['vi', 'vi'],
2353
            ['zh-CN', 'zh'],
2354
            ['zh-CN', 'zh-CN'],
2355
            ['zh-TW', 'zh-TW'],
2356
        ];
2357
    }
2358
2359
    /**
2360
     * @dataProvider select2LocalesProvider
2361
     */
2362
    public function testCanonicalizedLocaleForSelect2(?string $expected, string $original): void
2363
    {
2364
        $this->assertSame($expected, $this->twigExtension->getCanonicalizedLocaleForSelect2($this->mockExtensionContext($original)));
2365
    }
2366
2367
    public function momentLocalesProvider(): array
2368
    {
2369
        return [
2370
            ['af', 'af'],
2371
            ['ar-dz', 'ar-dz'],
2372
            ['ar', 'ar'],
2373
            ['ar-ly', 'ar-ly'],
2374
            ['ar-ma', 'ar-ma'],
2375
            ['ar-sa', 'ar-sa'],
2376
            ['ar-tn', 'ar-tn'],
2377
            ['az', 'az'],
2378
            ['be', 'be'],
2379
            ['bg', 'bg'],
2380
            ['bn', 'bn'],
2381
            ['bo', 'bo'],
2382
            ['br', 'br'],
2383
            ['bs', 'bs'],
2384
            ['ca', 'ca'],
2385
            ['cs', 'cs'],
2386
            ['cv', 'cv'],
2387
            ['cy', 'cy'],
2388
            ['da', 'da'],
2389
            ['de-at', 'de-at'],
2390
            ['de', 'de'],
2391
            ['de', 'de-de'],
2392
            ['dv', 'dv'],
2393
            ['el', 'el'],
2394
            [null, 'en'],
2395
            [null, 'en-us'],
2396
            ['en-au', 'en-au'],
2397
            ['en-ca', 'en-ca'],
2398
            ['en-gb', 'en-gb'],
2399
            ['en-ie', 'en-ie'],
2400
            ['en-nz', 'en-nz'],
2401
            ['eo', 'eo'],
2402
            ['es-do', 'es-do'],
2403
            ['es', 'es-ar'],
2404
            ['es', 'es-mx'],
2405
            ['es', 'es'],
2406
            ['et', 'et'],
2407
            ['eu', 'eu'],
2408
            ['fa', 'fa'],
2409
            ['fi', 'fi'],
2410
            ['fo', 'fo'],
2411
            ['fr-ca', 'fr-ca'],
2412
            ['fr-ch', 'fr-ch'],
2413
            ['fr', 'fr-fr'],
2414
            ['fr', 'fr'],
2415
            ['fy', 'fy'],
2416
            ['gd', 'gd'],
2417
            ['gl', 'gl'],
2418
            ['he', 'he'],
2419
            ['hi', 'hi'],
2420
            ['hr', 'hr'],
2421
            ['hu', 'hu'],
2422
            ['hy-am', 'hy-am'],
2423
            ['id', 'id'],
2424
            ['is', 'is'],
2425
            ['it', 'it'],
2426
            ['ja', 'ja'],
2427
            ['jv', 'jv'],
2428
            ['ka', 'ka'],
2429
            ['kk', 'kk'],
2430
            ['km', 'km'],
2431
            ['ko', 'ko'],
2432
            ['ky', 'ky'],
2433
            ['lb', 'lb'],
2434
            ['lo', 'lo'],
2435
            ['lt', 'lt'],
2436
            ['lv', 'lv'],
2437
            ['me', 'me'],
2438
            ['mi', 'mi'],
2439
            ['mk', 'mk'],
2440
            ['ml', 'ml'],
2441
            ['mr', 'mr'],
2442
            ['ms', 'ms'],
2443
            ['ms-my', 'ms-my'],
2444
            ['my', 'my'],
2445
            ['nb', 'nb'],
2446
            ['ne', 'ne'],
2447
            ['nl-be', 'nl-be'],
2448
            ['nl', 'nl'],
2449
            ['nl', 'nl-nl'],
2450
            ['nn', 'nn'],
2451
            ['pa-in', 'pa-in'],
2452
            ['pl', 'pl'],
2453
            ['pt-br', 'pt-br'],
2454
            ['pt', 'pt'],
2455
            ['ro', 'ro'],
2456
            ['ru', 'ru'],
2457
            ['se', 'se'],
2458
            ['si', 'si'],
2459
            ['sk', 'sk'],
2460
            ['sl', 'sl'],
2461
            ['sq', 'sq'],
2462
            ['sr-cyrl', 'sr-cyrl'],
2463
            ['sr', 'sr'],
2464
            ['ss', 'ss'],
2465
            ['sv', 'sv'],
2466
            ['sw', 'sw'],
2467
            ['ta', 'ta'],
2468
            ['te', 'te'],
2469
            ['tet', 'tet'],
2470
            ['th', 'th'],
2471
            ['tlh', 'tlh'],
2472
            ['tl-ph', 'tl-ph'],
2473
            ['tr', 'tr'],
2474
            ['tzl', 'tzl'],
2475
            ['tzm', 'tzm'],
2476
            ['tzm-latn', 'tzm-latn'],
2477
            ['uk', 'uk'],
2478
            ['uz', 'uz'],
2479
            ['vi', 'vi'],
2480
            ['x-pseudo', 'x-pseudo'],
2481
            ['yo', 'yo'],
2482
            ['zh-cn', 'zh-cn'],
2483
            ['zh-hk', 'zh-hk'],
2484
            ['zh-tw', 'zh-tw'],
2485
        ];
2486
    }
2487
2488
    /**
2489
     * @dataProvider momentLocalesProvider
2490
     */
2491
    public function testCanonicalizedLocaleForMoment(?string $expected, string $original): void
2492
    {
2493
        $this->assertSame($expected, $this->twigExtension->getCanonicalizedLocaleForMoment($this->mockExtensionContext($original)));
2494
    }
2495
2496
    public function testIsGrantedAffirmative(): void
2497
    {
2498
        $this->assertTrue(
2499
            $this->twigExtension->isGrantedAffirmative(['foo', 'bar'])
2500
        );
2501
        $this->assertTrue($this->twigExtension->isGrantedAffirmative('foo'));
2502
        $this->assertTrue($this->twigExtension->isGrantedAffirmative('bar'));
2503
    }
2504
2505
    /**
2506
     * @dataProvider getRenderViewElementCompareTests
2507
     */
2508
    public function testRenderViewElementCompare(string $expected, string $type, $value, array $options, ?string $objectName = null): void
2509
    {
2510
        $this->fieldDescription
2511
            ->method('getValue')
2512
            ->willReturn($value);
2513
2514
        $this->fieldDescription
2515
            ->method('getType')
2516
            ->willReturn($type);
2517
2518
        $this->fieldDescription
2519
            ->method('getOptions')
2520
            ->willReturn($options);
2521
2522
        $this->fieldDescription
2523
            ->method('getTemplate')
2524
            ->willReturnCallback(static function () use ($type, $options): ?string {
2525
                if (isset($options['template'])) {
2526
                    return $options['template'];
2527
                }
2528
2529
                switch ($type) {
2530
                    case 'boolean':
2531
                        return '@SonataAdmin/CRUD/show_boolean.html.twig';
2532
                    case 'datetime':
2533
                        return '@SonataAdmin/CRUD/show_datetime.html.twig';
2534
                    case 'date':
2535
                        return '@SonataAdmin/CRUD/show_date.html.twig';
2536
                    case 'time':
2537
                        return '@SonataAdmin/CRUD/show_time.html.twig';
2538
                    case 'currency':
2539
                        return '@SonataAdmin/CRUD/show_currency.html.twig';
2540
                    case 'percent':
2541
                        return '@SonataAdmin/CRUD/show_percent.html.twig';
2542
                    case 'email':
2543
                        return '@SonataAdmin/CRUD/show_email.html.twig';
2544
                    case 'choice':
2545
                        return '@SonataAdmin/CRUD/show_choice.html.twig';
2546
                    case 'array':
2547
                        return '@SonataAdmin/CRUD/show_array.html.twig';
2548
                    case 'trans':
2549
                        return '@SonataAdmin/CRUD/show_trans.html.twig';
2550
                    case 'url':
2551
                        return '@SonataAdmin/CRUD/show_url.html.twig';
2552
                    case 'html':
2553
                        return '@SonataAdmin/CRUD/show_html.html.twig';
2554
                    default:
2555
                        return null;
2556
                }
2557
            });
2558
2559
        $this->object->name = 'SonataAdmin';
2560
2561
        $comparedObject = clone $this->object;
2562
2563
        if (null !== $objectName) {
2564
            $comparedObject->name = $objectName;
2565
        }
2566
2567
        $this->assertSame(
2568
            $this->removeExtraWhitespace($expected),
2569
            $this->removeExtraWhitespace(
2570
                $this->twigExtension->renderViewElementCompare(
2571
                    $this->environment,
2572
                    $this->fieldDescription,
2573
                    $this->object,
2574
                    $comparedObject
2575
                )
2576
            )
2577
        );
2578
    }
2579
2580
    public function getRenderViewElementCompareTests(): iterable
2581
    {
2582
        return [
2583
            ['<th>Data</th> <td>Example</td><td>Example</td>', 'string', 'Example', ['safe' => false]],
2584
            ['<th>Data</th> <td>Example</td><td>Example</td>', 'text', 'Example', ['safe' => false]],
2585
            ['<th>Data</th> <td>Example</td><td>Example</td>', 'textarea', 'Example', ['safe' => false]],
2586
            ['<th>Data</th> <td>SonataAdmin<br/>Example</td><td>SonataAdmin<br/>Example</td>', 'virtual_field', 'Example', ['template' => 'custom_show_field.html.twig', 'safe' => false, 'SonataAdmin']],
2587
            ['<th class="diff">Data</th> <td>SonataAdmin<br/>Example</td><td>SonataAdmin<br/>Example</td>', 'virtual_field', 'Example', ['template' => 'custom_show_field.html.twig', 'safe' => false], 'sonata-project/admin-bundle'],
2588
            [
2589
                '<th>Data</th> <td><time datetime="2020-05-27T09:11:12+00:00" title="2020-05-27T09:11:12+00:00"> May 27, 2020 10:11 </time></td>'
2590
                .'<td><time datetime="2020-05-27T09:11:12+00:00" title="2020-05-27T09:11:12+00:00"> May 27, 2020 10:11 </time></td>',
2591
                'datetime',
2592
                new \DateTime('2020-05-27 10:11:12', new \DateTimeZone('Europe/London')), [],
2593
            ],
2594
            [
2595
                '<th>Data</th> <td><time datetime="2020-05-27T09:11:12+00:00" title="2020-05-27T09:11:12+00:00"> 27.05.2020 10:11:12 </time></td>'
2596
                .'<td><time datetime="2020-05-27T09:11:12+00:00" title="2020-05-27T09:11:12+00:00"> 27.05.2020 10:11:12 </time></td>',
2597
                'datetime',
2598
                new \DateTime('2020-05-27 10:11:12', new \DateTimeZone('Europe/London')),
2599
                ['format' => 'd.m.Y H:i:s'],
2600
            ],
2601
            [
2602
                '<th>Data</th> <td><time datetime="2020-05-27T10:11:12+00:00" title="2020-05-27T10:11:12+00:00"> May 27, 2020 18:11 </time></td>'
2603
                .'<td><time datetime="2020-05-27T10:11:12+00:00" title="2020-05-27T10:11:12+00:00"> May 27, 2020 18:11 </time></td>',
2604
                'datetime',
2605
                new \DateTime('2020-05-27 10:11:12', new \DateTimeZone('UTC')),
2606
                ['timezone' => 'Asia/Hong_Kong'],
2607
            ],
2608
            [
2609
                '<th>Data</th> <td><time datetime="2020-05-27" title="2020-05-27"> May 27, 2020 </time></td>'
2610
                .'<td><time datetime="2020-05-27" title="2020-05-27"> May 27, 2020 </time></td>',
2611
                'date',
2612
                new \DateTime('2020-05-27 10:11:12', new \DateTimeZone('Europe/London')),
2613
                [],
2614
            ],
2615
        ];
2616
    }
2617
2618
    /**
2619
     * This method generates url part for Twig layout.
2620
     */
2621
    private function buildTwigLikeUrl(array $url): string
2622
    {
2623
        return htmlspecialchars(http_build_query($url, '', '&', PHP_QUERY_RFC3986));
2624
    }
2625
2626
    private function getMethodAsPublic($privateMethod): \ReflectionMethod
2627
    {
2628
        $reflection = new \ReflectionMethod('Sonata\AdminBundle\Twig\Extension\SonataAdminExtension', $privateMethod);
2629
        $reflection->setAccessible(true);
2630
2631
        return $reflection;
2632
    }
2633
2634
    private function removeExtraWhitespace(string $string): string
2635
    {
2636
        return trim(preg_replace(
2637
            '/\s+/',
2638
            ' ',
2639
            $string
2640
        ));
2641
    }
2642
2643
    private function mockExtensionContext(string $locale): array
2644
    {
2645
        $request = $this->createMock(Request::class);
2646
        $request->method('getLocale')->willReturn($locale);
2647
        $appVariable = $this->createMock(AppVariable::class);
2648
        $appVariable->method('getRequest')->willReturn($request);
2649
2650
        return ['app' => $appVariable];
2651
    }
2652
}
2653