Completed
Push — master ( 4e1c5d...6050c4 )
by Grégoire
22:25 queued 19:06
created

xEditableChoicesProvider()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 44

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 44
rs 9.216
c 0
b 0
f 0
cc 1
nc 1
nop 0
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 Prophecy\Argument;
18
use Psr\Log\LoggerInterface;
19
use Sonata\AdminBundle\Admin\AbstractAdmin;
20
use Sonata\AdminBundle\Admin\AdminInterface;
21
use Sonata\AdminBundle\Admin\FieldDescriptionInterface;
22
use Sonata\AdminBundle\Admin\Pool;
23
use Sonata\AdminBundle\Exception\NoValueException;
24
use Sonata\AdminBundle\Templating\TemplateRegistryInterface;
25
use Sonata\AdminBundle\Tests\Fixtures\Entity\FooToString;
26
use Sonata\AdminBundle\Twig\Extension\SonataAdminExtension;
27
use Symfony\Bridge\Twig\AppVariable;
28
use Symfony\Bridge\Twig\Extension\RoutingExtension;
29
use Symfony\Bridge\Twig\Extension\TranslationExtension;
30
use Symfony\Component\Config\FileLocator;
31
use Symfony\Component\DependencyInjection\ContainerInterface;
32
use Symfony\Component\HttpFoundation\Request;
33
use Symfony\Component\Routing\Generator\UrlGenerator;
34
use Symfony\Component\Routing\Loader\XmlFileLoader;
35
use Symfony\Component\Routing\RequestContext;
36
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
37
use Symfony\Component\Translation\Loader\XliffFileLoader;
38
use Symfony\Component\Translation\Translator;
39
use Symfony\Component\Translation\TranslatorInterface;
40
use Twig\Environment;
41
use Twig\Extensions\TextExtension;
42
use Twig\Loader\FilesystemLoader;
43
44
/**
45
 * Test for SonataAdminExtension.
46
 *
47
 * @author Andrej Hudec <[email protected]>
48
 */
49
class SonataAdminExtensionTest extends TestCase
50
{
51
    /**
52
     * @var SonataAdminExtension
53
     */
54
    private $twigExtension;
55
56
    /**
57
     * @var Environment
58
     */
59
    private $environment;
60
61
    /**
62
     * @var AdminInterface
63
     */
64
    private $admin;
65
66
    /**
67
     * @var AdminInterface
68
     */
69
    private $adminBar;
70
71
    /**
72
     * @var FieldDescriptionInterface
73
     */
74
    private $fieldDescription;
75
76
    /**
77
     * @var \stdClass
78
     */
79
    private $object;
80
81
    /**
82
     * @var Pool
83
     */
84
    private $pool;
85
86
    /**
87
     * @var LoggerInterface
88
     */
89
    private $logger;
90
91
    /**
92
     * @var string[]
93
     */
94
    private $xEditableTypeMapping;
95
96
    /**
97
     * @var TranslatorInterface
98
     */
99
    private $translator;
100
101
    /**
102
     * @var ContainerInterface
103
     */
104
    private $container;
105
106
    /**
107
     * @var TemplateRegistryInterface
108
     */
109
    private $templateRegistry;
110
111
    /**
112
     * @var AuthorizationCheckerInterface
113
     */
114
    private $securityChecker;
115
116
    public function setUp(): void
117
    {
118
        date_default_timezone_set('Europe/London');
119
120
        $container = $this->getMockForAbstractClass(ContainerInterface::class);
121
122
        $this->pool = new Pool($container, '', '');
123
        $this->pool->setAdminServiceIds(['sonata_admin_foo_service']);
124
        $this->pool->setAdminClasses(['fooClass' => ['sonata_admin_foo_service']]);
125
126
        $this->logger = $this->getMockForAbstractClass(LoggerInterface::class);
127
        $this->xEditableTypeMapping = [
0 ignored issues
show
Documentation Bug introduced by
It seems like array('choice' => 'selec...umber', 'url' => 'url') of type array<string,string,{"ch...tring","url":"string"}> is incompatible with the declared type array<integer,string> of property $xEditableTypeMapping.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
128
            'choice' => 'select',
129
            'boolean' => 'select',
130
            'text' => 'text',
131
            'textarea' => 'textarea',
132
            'html' => 'textarea',
133
            'email' => 'email',
134
            'string' => 'text',
135
            'smallint' => 'text',
136
            'bigint' => 'text',
137
            'integer' => 'number',
138
            'decimal' => 'number',
139
            'currency' => 'number',
140
            'percent' => 'number',
141
            'url' => 'url',
142
        ];
143
144
        // translation extension
145
        $translator = new Translator('en');
146
        $translator->addLoader('xlf', new XliffFileLoader());
147
        $translator->addResource(
148
            'xlf',
149
            __DIR__.'/../../../src/Resources/translations/SonataAdminBundle.en.xliff',
150
            'en',
151
            'SonataAdminBundle'
152
        );
153
154
        $this->translator = $translator;
155
156
        $this->templateRegistry = $this->prophesize(TemplateRegistryInterface::class);
157
        $this->container = $this->prophesize(ContainerInterface::class);
158
        $this->container->get('sonata_admin_foo_service.template_registry')->willReturn($this->templateRegistry->reveal());
159
160
        $this->securityChecker = $this->prophesize(AuthorizationCheckerInterface::class);
161
        $this->securityChecker->isGranted(['foo', 'bar'], null)->willReturn(false);
162
        $this->securityChecker->isGranted(Argument::type('string'), null)->willReturn(true);
163
164
        $this->twigExtension = new SonataAdminExtension(
165
            $this->pool, $this->logger, $this->translator, $this->container->reveal(), $this->securityChecker->reveal()
166
        );
167
        $this->twigExtension->setXEditableTypeMapping($this->xEditableTypeMapping);
168
169
        $request = $this->createMock(Request::class);
170
        $request->method('get')->with('_sonata_admin')->willReturn('sonata_admin_foo_service');
171
172
        $loader = new FilesystemLoader([
173
            __DIR__.'/../../../src/Resources/views/CRUD',
174
        ]);
175
        $loader->addPath(__DIR__.'/../../../src/Resources/views/', 'SonataAdmin');
176
177
        $this->environment = new Environment($loader, [
178
            'strict_variables' => true,
179
            'cache' => false,
180
            'autoescape' => 'html',
181
            'optimizations' => 0,
182
        ]);
183
        $this->environment->addExtension($this->twigExtension);
184
        $this->environment->addExtension(new TranslationExtension($translator));
185
        $this->environment->addExtension(new FakeTemplateRegistryExtension());
186
187
        // routing extension
188
        $xmlFileLoader = new XmlFileLoader(new FileLocator([__DIR__.'/../../../src/Resources/config/routing']));
189
        $routeCollection = $xmlFileLoader->load('sonata_admin.xml');
190
191
        $xmlFileLoader = new XmlFileLoader(new FileLocator([__DIR__.'/../../Fixtures/Resources/config/routing']));
192
        $testRouteCollection = $xmlFileLoader->load('routing.xml');
193
194
        $routeCollection->addCollection($testRouteCollection);
0 ignored issues
show
Documentation introduced by
$testRouteCollection is of type object<Symfony\Component\Routing\RouteCollection>, but the function expects a object<self>.

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

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

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

function acceptsInteger($int) { }

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

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
195
        $requestContext = new RequestContext();
196
        $urlGenerator = new UrlGenerator($routeCollection, $requestContext);
197
        $this->environment->addExtension(new RoutingExtension($urlGenerator));
198
        $this->environment->addExtension(new TextExtension());
199
200
        // initialize object
201
        $this->object = new \stdClass();
202
203
        // initialize admin
204
        $this->admin = $this->createMock(AbstractAdmin::class);
205
206
        $this->admin
207
            ->method('getCode')
208
            ->willReturn('sonata_admin_foo_service');
209
210
        $this->admin
211
            ->method('id')
212
            ->with($this->equalTo($this->object))
213
            ->willReturn(12345);
214
215
        $this->admin
216
            ->method('getNormalizedIdentifier')
217
            ->with($this->equalTo($this->object))
218
            ->willReturn(12345);
219
220
        $this->admin
221
            ->method('trans')
222
            ->willReturnCallback(static function ($id, $parameters = [], $domain = null) use ($translator) {
223
                return $translator->trans($id, $parameters, $domain);
224
            });
225
226
        $this->adminBar = $this->createMock(AbstractAdmin::class);
227
        $this->adminBar
228
            ->method('hasAccess')
229
            ->willReturn(true);
230
        $this->adminBar
231
            ->method('getNormalizedIdentifier')
232
            ->with($this->equalTo($this->object))
233
            ->willReturn(12345);
234
235
        $container
236
            ->method('get')
237
            ->willReturnCallback(function (string $id) {
238
                if ('sonata_admin_foo_service' === $id) {
239
                    return $this->admin;
240
                }
241
242
                if ('sonata_admin_bar_service' === $id) {
243
                    return $this->adminBar;
244
                }
245
            });
246
247
        // initialize field description
248
        $this->fieldDescription = $this->getMockForAbstractClass(FieldDescriptionInterface::class);
249
250
        $this->fieldDescription
251
            ->method('getName')
252
            ->willReturn('fd_name');
253
254
        $this->fieldDescription
255
            ->method('getAdmin')
256
            ->willReturn($this->admin);
257
258
        $this->fieldDescription
259
            ->method('getLabel')
260
            ->willReturn('Data');
261
    }
262
263
    public function getRenderListElementTests()
264
    {
265
        return [
266
            [
267
                '<td class="sonata-ba-list-field sonata-ba-list-field-string" objectId="12345"> Example </td>',
268
                'string',
269
                'Example',
270
                [],
271
            ],
272
            [
273
                '<td class="sonata-ba-list-field sonata-ba-list-field-string" objectId="12345"> </td>',
274
                'string',
275
                null,
276
                [],
277
            ],
278
            [
279
                '<td class="sonata-ba-list-field sonata-ba-list-field-text" objectId="12345"> Example </td>',
280
                'text',
281
                'Example',
282
                [],
283
            ],
284
            [
285
                '<td class="sonata-ba-list-field sonata-ba-list-field-text" objectId="12345"> </td>',
286
                'text',
287
                null,
288
                [],
289
            ],
290
            [
291
                '<td class="sonata-ba-list-field sonata-ba-list-field-textarea" objectId="12345"> Example </td>',
292
                'textarea',
293
                'Example',
294
                [],
295
            ],
296
            [
297
                '<td class="sonata-ba-list-field sonata-ba-list-field-textarea" objectId="12345"> </td>',
298
                'textarea',
299
                null,
300
                [],
301
            ],
302
            'datetime field' => [
303
                '<td class="sonata-ba-list-field sonata-ba-list-field-datetime" objectId="12345">
304
                    <time datetime="2013-12-24T10:11:12+00:00" title="2013-12-24T10:11:12+00:00">
305
                        December 24, 2013 10:11
306
                    </time>
307
                </td>',
308
                'datetime',
309
                new \DateTime('2013-12-24 10:11:12', new \DateTimeZone('Europe/London')),
310
                [],
311
            ],
312
            [
313
                '<td class="sonata-ba-list-field sonata-ba-list-field-datetime" objectId="12345">
314
                    <time datetime="2013-12-24T10:11:12+00:00" title="2013-12-24T10:11:12+00:00">
315
                        December 24, 2013 18:11
316
                    </time>
317
                </td>',
318
                'datetime',
319
                new \DateTime('2013-12-24 10:11:12', new \DateTimeZone('UTC')),
320
                ['timezone' => 'Asia/Hong_Kong'],
321
            ],
322
            [
323
                '<td class="sonata-ba-list-field sonata-ba-list-field-datetime" objectId="12345"> &nbsp; </td>',
324
                'datetime',
325
                null,
326
                [],
327
            ],
328
            [
329
                '<td class="sonata-ba-list-field sonata-ba-list-field-datetime" objectId="12345">
330
                    <time datetime="2013-12-24T10:11:12+00:00" title="2013-12-24T10:11:12+00:00">
331
                        24.12.2013 10:11:12
332
                    </time>
333
                </td>',
334
                'datetime',
335
                new \DateTime('2013-12-24 10:11:12', new \DateTimeZone('Europe/London')),
336
                ['format' => 'd.m.Y H:i:s'],
337
            ],
338
            [
339
                '<td class="sonata-ba-list-field sonata-ba-list-field-datetime" objectId="12345"> &nbsp; </td>',
340
                'datetime',
341
                null,
342
                ['format' => 'd.m.Y H:i:s'],
343
            ],
344
            [
345
                '<td class="sonata-ba-list-field sonata-ba-list-field-datetime" objectId="12345">
346
                    <time datetime="2013-12-24T10:11:12+00:00" title="2013-12-24T10:11:12+00:00">
347
                        24.12.2013 18:11:12
348
                    </time>
349
                </td>',
350
                'datetime',
351
                new \DateTime('2013-12-24 10:11:12', new \DateTimeZone('UTC')),
352
                ['format' => 'd.m.Y H:i:s', 'timezone' => 'Asia/Hong_Kong'],
353
            ],
354
            [
355
                '<td class="sonata-ba-list-field sonata-ba-list-field-datetime" objectId="12345"> &nbsp; </td>',
356
                'datetime',
357
                null,
358
                ['format' => 'd.m.Y H:i:s', 'timezone' => 'Asia/Hong_Kong'],
359
            ],
360
            [
361
                '<td class="sonata-ba-list-field sonata-ba-list-field-date" objectId="12345">
362
                    <time datetime="2013-12-24" title="2013-12-24">
363
                        December 24, 2013
364
                    </time>
365
                </td>',
366
                'date',
367
                new \DateTime('2013-12-24 10:11:12', new \DateTimeZone('Europe/London')),
368
                [],
369
            ],
370
            [
371
                '<td class="sonata-ba-list-field sonata-ba-list-field-date" objectId="12345"> &nbsp; </td>',
372
                'date',
373
                null,
374
                [],
375
            ],
376
            [
377
                '<td class="sonata-ba-list-field sonata-ba-list-field-date" objectId="12345">
378
                    <time datetime="2013-12-24" title="2013-12-24">
379
                        24.12.2013
380
                    </time>
381
                </td>',
382
                'date',
383
                new \DateTime('2013-12-24 10:11:12', new \DateTimeZone('Europe/London')),
384
                ['format' => 'd.m.Y'],
385
            ],
386
            [
387
                '<td class="sonata-ba-list-field sonata-ba-list-field-date" objectId="12345"> &nbsp; </td>',
388
                'date',
389
                null,
390
                ['format' => 'd.m.Y'],
391
            ],
392
            [
393
                '<td class="sonata-ba-list-field sonata-ba-list-field-time" objectId="12345">
394
                    <time datetime="10:11:12+00:00" title="10:11:12+00:00">
395
                        10:11:12
396
                    </time>
397
                </td>',
398
                'time',
399
                new \DateTime('2013-12-24 10:11:12', new \DateTimeZone('Europe/London')),
400
                [],
401
            ],
402
            [
403
                '<td class="sonata-ba-list-field sonata-ba-list-field-time" objectId="12345">
404
                    <time datetime="10:11:12+00:00" title="10:11:12+00:00">
405
                        18:11:12
406
                    </time>
407
                </td>',
408
                'time',
409
                new \DateTime('2013-12-24 10:11:12', new \DateTimeZone('UTC')),
410
                ['timezone' => 'Asia/Hong_Kong'],
411
            ],
412
            [
413
                '<td class="sonata-ba-list-field sonata-ba-list-field-time" objectId="12345"> &nbsp; </td>',
414
                'time',
415
                null,
416
                [],
417
            ],
418
            [
419
                '<td class="sonata-ba-list-field sonata-ba-list-field-number" objectId="12345"> 10.746135 </td>',
420
                'number', 10.746135,
421
                [],
422
            ],
423
            [
424
                '<td class="sonata-ba-list-field sonata-ba-list-field-number" objectId="12345"> </td>',
425
                'number',
426
                null,
427
                [],
428
            ],
429
            [
430
                '<td class="sonata-ba-list-field sonata-ba-list-field-integer" objectId="12345"> 5678 </td>',
431
                'integer',
432
                5678,
433
                [],
434
            ],
435
            [
436
                '<td class="sonata-ba-list-field sonata-ba-list-field-integer" objectId="12345"> </td>',
437
                'integer',
438
                null,
439
                [],
440
            ],
441
            [
442
                '<td class="sonata-ba-list-field sonata-ba-list-field-percent" objectId="12345"> 1074.6135 % </td>',
443
                'percent',
444
                10.746135,
445
                [],
446
            ],
447
            [
448
                '<td class="sonata-ba-list-field sonata-ba-list-field-percent" objectId="12345"> 0 % </td>',
449
                'percent',
450
                null,
451
                [],
452
            ],
453
            [
454
                '<td class="sonata-ba-list-field sonata-ba-list-field-currency" objectId="12345"> EUR 10.746135 </td>',
455
                'currency',
456
                10.746135,
457
                ['currency' => 'EUR'],
458
            ],
459
            [
460
                '<td class="sonata-ba-list-field sonata-ba-list-field-currency" objectId="12345"> </td>',
461
                'currency',
462
                null,
463
                ['currency' => 'EUR'],
464
            ],
465
            [
466
                '<td class="sonata-ba-list-field sonata-ba-list-field-currency" objectId="12345"> GBP 51.23456 </td>',
467
                'currency',
468
                51.23456,
469
                ['currency' => 'GBP'],
470
            ],
471
            [
472
                '<td class="sonata-ba-list-field sonata-ba-list-field-currency" objectId="12345"> </td>',
473
                'currency',
474
                null,
475
                ['currency' => 'GBP'],
476
            ],
477
            [
478
                '<td class="sonata-ba-list-field sonata-ba-list-field-email" objectId="12345"> &nbsp; </td>',
479
                'email',
480
                null,
481
                [],
482
            ],
483
            [
484
                '<td class="sonata-ba-list-field sonata-ba-list-field-email" objectId="12345"> <a href="mailto:[email protected]">[email protected]</a> </td>',
485
                'email',
486
                '[email protected]',
487
                [],
488
            ],
489
            [
490
                '<td class="sonata-ba-list-field sonata-ba-list-field-email" objectId="12345">
491
                    <a href="mailto:[email protected]">[email protected]</a> </td>',
492
                'email',
493
                '[email protected]',
494
                ['as_string' => false],
495
            ],
496
            [
497
                '<td class="sonata-ba-list-field sonata-ba-list-field-email" objectId="12345"> [email protected] </td>',
498
                'email',
499
                '[email protected]',
500
                ['as_string' => true],
501
            ],
502
            [
503
                '<td class="sonata-ba-list-field sonata-ba-list-field-email" objectId="12345">
504
                    <a href="mailto:[email protected]?'.$this->buildTwigLikeUrl(['subject' => 'Main Theme', 'body' => 'Message Body']).'">[email protected]</a>  </td>',
505
                'email',
506
                '[email protected]',
507
                ['subject' => 'Main Theme', 'body' => 'Message Body'],
508
            ],
509
            [
510
                '<td class="sonata-ba-list-field sonata-ba-list-field-email" objectId="12345">
511
                    <a href="mailto:[email protected]?'.$this->buildTwigLikeUrl(['subject' => 'Main Theme']).'">[email protected]</a>  </td>',
512
                'email',
513
                '[email protected]',
514
                ['subject' => 'Main Theme'],
515
            ],
516
            [
517
                '<td class="sonata-ba-list-field sonata-ba-list-field-email" objectId="12345">
518
                    <a href="mailto:[email protected]?'.$this->buildTwigLikeUrl(['body' => 'Message Body']).'">[email protected]</a>  </td>',
519
                'email',
520
                '[email protected]',
521
                ['body' => 'Message Body'],
522
            ],
523
            [
524
                '<td class="sonata-ba-list-field sonata-ba-list-field-email" objectId="12345"> [email protected] </td>',
525
                'email',
526
                '[email protected]',
527
                ['as_string' => true, 'subject' => 'Main Theme', 'body' => 'Message Body'],
528
            ],
529
            [
530
                '<td class="sonata-ba-list-field sonata-ba-list-field-email" objectId="12345"> [email protected] </td>',
531
                'email',
532
                '[email protected]',
533
                ['as_string' => true, 'body' => 'Message Body'],
534
            ],
535
            [
536
                '<td class="sonata-ba-list-field sonata-ba-list-field-email" objectId="12345"> [email protected] </td>',
537
                'email',
538
                '[email protected]',
539
                ['as_string' => true, 'subject' => 'Main Theme'],
540
            ],
541
            [
542
                '<td class="sonata-ba-list-field sonata-ba-list-field-array" objectId="12345">
543
                    [1 => First] [2 => Second]
544
                </td>',
545
                'array',
546
                [1 => 'First', 2 => 'Second'],
547
                [],
548
            ],
549
            [
550
                '<td class="sonata-ba-list-field sonata-ba-list-field-array" objectId="12345"> </td>',
551
                'array',
552
                null,
553
                [],
554
            ],
555
            [
556
                '<td class="sonata-ba-list-field sonata-ba-list-field-boolean" objectId="12345">
557
                    <span class="label label-success">yes</span>
558
                </td>',
559
                'boolean',
560
                true,
561
                ['editable' => false],
562
            ],
563
            [
564
                '<td class="sonata-ba-list-field sonata-ba-list-field-boolean" objectId="12345">
565
                    <span class="label label-danger">no</span>
566
                </td>',
567
                'boolean',
568
                false,
569
                ['editable' => false],
570
            ],
571
            [
572
                '<td class="sonata-ba-list-field sonata-ba-list-field-boolean" objectId="12345">
573
                    <span class="label label-danger">no</span>
574
                </td>',
575
                'boolean',
576
                null,
577
                ['editable' => false],
578
            ],
579
            [
580
                <<<'EOT'
581
<td class="sonata-ba-list-field sonata-ba-list-field-boolean" objectId="12345">
582
    <span
583
        class="x-editable"
584
        data-type="select"
585
        data-value="1"
586
        data-title="Data"
587
        data-pk="12345"
588
        data-url="/core/set-object-field-value?context=list&amp;field=fd_name&amp;objectId=12345&amp;code=sonata_admin_foo_service"
589
        data-source="[{value: 0, text: 'no'},{value: 1, text: 'yes'}]"
590
    >
591
        <span class="label label-success">yes</span>
592
    </span>
593
</td>
594
EOT
595
            ,
596
                'boolean',
597
                true,
598
                ['editable' => true],
599
            ],
600
            [
601
                <<<'EOT'
602
<td class="sonata-ba-list-field sonata-ba-list-field-boolean" objectId="12345">
603
    <span
604
        class="x-editable"
605
        data-type="select"
606
        data-value="0"
607
        data-title="Data"
608
        data-pk="12345"
609
        data-url="/core/set-object-field-value?context=list&amp;field=fd_name&amp;objectId=12345&amp;code=sonata_admin_foo_service"
610
        data-source="[{value: 0, text: 'no'},{value: 1, text: 'yes'}]"
611
    >
612
    <span class="label label-danger">no</span> </span>
613
</td>
614
EOT
615
                ,
616
                'boolean',
617
                false,
618
                ['editable' => true],
619
            ],
620
            [
621
                <<<'EOT'
622
<td class="sonata-ba-list-field sonata-ba-list-field-boolean" objectId="12345">
623
    <span
624
        class="x-editable"
625
        data-type="select"
626
        data-value="0"
627
        data-title="Data"
628
        data-pk="12345"
629
        data-url="/core/set-object-field-value?context=list&amp;field=fd_name&amp;objectId=12345&amp;code=sonata_admin_foo_service"
630
        data-source="[{value: 0, text: 'no'},{value: 1, text: 'yes'}]" >
631
        <span class="label label-danger">no</span> </span>
632
</td>
633
EOT
634
                ,
635
                'boolean',
636
                null,
637
                ['editable' => true],
638
            ],
639
            [
640
                '<td class="sonata-ba-list-field sonata-ba-list-field-trans" objectId="12345"> Delete </td>',
641
                'trans',
642
                'action_delete',
643
                ['catalogue' => 'SonataAdminBundle'],
644
            ],
645
            [
646
                '<td class="sonata-ba-list-field sonata-ba-list-field-trans" objectId="12345"> </td>',
647
                'trans',
648
                null,
649
                ['catalogue' => 'SonataAdminBundle'],
650
            ],
651
            [
652
                '<td class="sonata-ba-list-field sonata-ba-list-field-trans" objectId="12345"> Delete </td>',
653
                'trans',
654
                'action_delete',
655
                ['format' => '%s', 'catalogue' => 'SonataAdminBundle'],
656
            ],
657
            [
658
                '<td class="sonata-ba-list-field sonata-ba-list-field-trans" objectId="12345">
659
                action.action_delete
660
                </td>',
661
                'trans',
662
                'action_delete',
663
                ['format' => 'action.%s'],
664
            ],
665
            [
666
                '<td class="sonata-ba-list-field sonata-ba-list-field-trans" objectId="12345">
667
                action.action_delete
668
                </td>',
669
                'trans',
670
                'action_delete',
671
                ['format' => 'action.%s', 'catalogue' => 'SonataAdminBundle'],
672
            ],
673
            [
674
                '<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345"> Status1 </td>',
675
                'choice',
676
                'Status1',
677
                [],
678
            ],
679
            [
680
                '<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345"> Status1 </td>',
681
                'choice',
682
                ['Status1'],
683
                ['choices' => [], 'multiple' => true],
684
            ],
685
            [
686
                '<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345"> Alias1 </td>',
687
                'choice',
688
                'Status1',
689
                ['choices' => ['Status1' => 'Alias1', 'Status2' => 'Alias2', 'Status3' => 'Alias3']],
690
            ],
691
            [
692
                '<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345"> </td>',
693
                'choice',
694
                null,
695
                ['choices' => ['Status1' => 'Alias1', 'Status2' => 'Alias2', 'Status3' => 'Alias3']],
696
            ],
697
            [
698
                '<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345">
699
                NoValidKeyInChoices
700
                </td>',
701
                'choice',
702
                'NoValidKeyInChoices',
703
                ['choices' => ['Status1' => 'Alias1', 'Status2' => 'Alias2', 'Status3' => 'Alias3']],
704
            ],
705
            [
706
                '<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345"> Delete </td>',
707
                'choice',
708
                'Foo',
709
                ['catalogue' => 'SonataAdminBundle', 'choices' => [
710
                    'Foo' => 'action_delete',
711
                    'Status2' => 'Alias2',
712
                    'Status3' => 'Alias3',
713
                ]],
714
            ],
715
            [
716
                '<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345"> Alias1, Alias3 </td>',
717
                'choice',
718
                ['Status1', 'Status3'],
719
                ['choices' => [
720
                    'Status1' => 'Alias1',
721
                    'Status2' => 'Alias2',
722
                    'Status3' => 'Alias3',
723
                ], 'multiple' => true], ],
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, 'delimiter' => ' | '], ],
733
            [
734
                '<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345"> </td>',
735
                'choice',
736
                null,
737
                ['choices' => [
738
                    'Status1' => 'Alias1',
739
                    'Status2' => 'Alias2',
740
                    'Status3' => 'Alias3',
741
                ], 'multiple' => true],
742
            ],
743
            [
744
                '<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345">
745
                NoValidKeyInChoices
746
                </td>',
747
                'choice',
748
                ['NoValidKeyInChoices'],
749
                ['choices' => [
750
                    'Status1' => 'Alias1',
751
                    'Status2' => 'Alias2',
752
                    'Status3' => 'Alias3',
753
                ], 'multiple' => true],
754
            ],
755
            [
756
                '<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345">
757
                NoValidKeyInChoices, Alias2
758
                </td>',
759
                'choice',
760
                ['NoValidKeyInChoices', 'Status2'],
761
                ['choices' => [
762
                    'Status1' => 'Alias1',
763
                    'Status2' => 'Alias2',
764
                    'Status3' => 'Alias3',
765
                ], 'multiple' => true],
766
            ],
767
            [
768
                '<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345"> Delete, Alias3 </td>',
769
                'choice',
770
                ['Foo', 'Status3'],
771
                ['catalogue' => 'SonataAdminBundle', 'choices' => [
772
                    'Foo' => 'action_delete',
773
                    'Status2' => 'Alias2',
774
                    'Status3' => 'Alias3',
775
                ], 'multiple' => true],
776
            ],
777
            [
778
                '<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345">
779
                &lt;b&gt;Alias1&lt;/b&gt;, &lt;b&gt;Alias3&lt;/b&gt;
780
            </td>',
781
                'choice',
782
                ['Status1', 'Status3'],
783
                ['choices' => [
784
                    'Status1' => '<b>Alias1</b>',
785
                    'Status2' => '<b>Alias2</b>',
786
                    'Status3' => '<b>Alias3</b>',
787
                ], 'multiple' => true], ],
788
            [
789
                <<<'EOT'
790
<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345">
791
    <span
792
        class="x-editable"
793
        data-type="select"
794
        data-value="Status1"
795
        data-title="Data"
796
        data-pk="12345"
797
        data-url="/core/set-object-field-value?context=list&amp;field=fd_name&amp;objectId=12345&amp;code=sonata_admin_foo_service"
798
        data-source="[]"
799
    >
800
        Status1
801
    </span>
802
</td>
803
EOT
804
                ,
805
                'choice',
806
                'Status1',
807
                ['editable' => true],
808
            ],
809
            [
810
                <<<'EOT'
811
<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345">
812
    <span
813
        class="x-editable"
814
        data-type="select"
815
        data-value="Status1"
816
        data-title="Data"
817
        data-pk="12345"
818
        data-url="/core/set-object-field-value?context=list&amp;field=fd_name&amp;objectId=12345&amp;code=sonata_admin_foo_service"
819
        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;}]" >
820
        Alias1 </span>
821
</td>
822
EOT
823
                ,
824
                'choice',
825
                'Status1',
826
                [
827
                    'editable' => true,
828
                    'choices' => [
829
                        'Status1' => 'Alias1',
830
                        'Status2' => 'Alias2',
831
                        'Status3' => 'Alias3',
832
                    ],
833
                ],
834
            ],
835
            [
836
                <<<'EOT'
837
<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345">
838
    <span
839
        class="x-editable"
840
        data-type="select"
841
        data-value=""
842
        data-title="Data"
843
        data-pk="12345"
844
        data-url="/core/set-object-field-value?context=list&amp;field=fd_name&amp;objectId=12345&amp;code=sonata_admin_foo_service"
845
        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;}]" >
846
847
    </span>
848
</td>
849
EOT
850
                ,
851
                'choice',
852
                null,
853
                [
854
                    'editable' => true,
855
                    'choices' => [
856
                        'Status1' => 'Alias1',
857
                        'Status2' => 'Alias2',
858
                        'Status3' => 'Alias3',
859
                    ],
860
                ],
861
            ],
862
            [
863
                <<<'EOT'
864
<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345">
865
    <span
866
        class="x-editable"
867
        data-type="select"
868
        data-value="NoValidKeyInChoices"
869
        data-title="Data" data-pk="12345"
870
        data-url="/core/set-object-field-value?context=list&amp;field=fd_name&amp;objectId=12345&amp;code=sonata_admin_foo_service"
871
        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;}]" >
872
        NoValidKeyInChoices
873
    </span>
874
</td>
875
EOT
876
                ,
877
                'choice',
878
                'NoValidKeyInChoices',
879
                [
880
                    'editable' => true,
881
                    'choices' => [
882
                        'Status1' => 'Alias1',
883
                        'Status2' => 'Alias2',
884
                        'Status3' => 'Alias3',
885
                    ],
886
                ],
887
            ],
888
            [
889
                <<<'EOT'
890
<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345">
891
    <span
892
        class="x-editable"
893
        data-type="select"
894
        data-value="Foo"
895
        data-title="Data"
896
        data-pk="12345"
897
        data-url="/core/set-object-field-value?context=list&amp;field=fd_name&amp;objectId=12345&amp;code=sonata_admin_foo_service"
898
        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;}]" >
899
         Delete
900
    </span>
901
</td>
902
EOT
903
                ,
904
                'choice',
905
                'Foo',
906
                [
907
                    'editable' => true,
908
                    'catalogue' => 'SonataAdminBundle',
909
                    'choices' => [
910
                        'Foo' => 'action_delete',
911
                        'Status2' => 'Alias2',
912
                        'Status3' => 'Alias3',
913
                    ],
914
                ],
915
            ],
916
            [
917
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345"> &nbsp; </td>',
918
                'url',
919
                null,
920
                [],
921
            ],
922
            [
923
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345"> &nbsp; </td>',
924
                'url',
925
                null,
926
                ['url' => 'http://example.com'],
927
            ],
928
            [
929
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345"> &nbsp; </td>',
930
                'url',
931
                null,
932
                ['route' => ['name' => 'sonata_admin_foo']],
933
            ],
934
            [
935
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
936
                <a href="http://example.com">http://example.com</a>
937
                </td>',
938
                'url',
939
                'http://example.com',
940
                [],
941
            ],
942
            [
943
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
944
                <a href="https://example.com">https://example.com</a>
945
                </td>',
946
                'url',
947
                'https://example.com',
948
                [],
949
            ],
950
            [
951
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
952
                <a href="https://example.com" target="_blank">https://example.com</a>
953
                </td>',
954
                'url',
955
                'https://example.com',
956
                ['attributes' => ['target' => '_blank']],
957
            ],
958
            [
959
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
960
                <a href="https://example.com" target="_blank" class="fooLink">https://example.com</a>
961
                </td>',
962
                'url',
963
                'https://example.com',
964
                ['attributes' => ['target' => '_blank', 'class' => 'fooLink']],
965
            ],
966
            [
967
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
968
                <a href="http://example.com">example.com</a>
969
                </td>',
970
                'url',
971
                'http://example.com',
972
                ['hide_protocol' => true],
973
            ],
974
            [
975
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
976
                <a href="https://example.com">example.com</a>
977
                </td>',
978
                'url',
979
                'https://example.com',
980
                ['hide_protocol' => true],
981
            ],
982
            [
983
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
984
                <a href="http://example.com">http://example.com</a>
985
                </td>',
986
                'url',
987
                'http://example.com',
988
                ['hide_protocol' => false],
989
            ],
990
            [
991
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
992
                <a href="https://example.com">https://example.com</a>
993
                </td>',
994
                'url',
995
                'https://example.com',
996
                ['hide_protocol' => false],
997
            ],
998
            [
999
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
1000
                <a href="http://example.com">Foo</a>
1001
                </td>',
1002
                'url',
1003
                'Foo',
1004
                ['url' => 'http://example.com'],
1005
            ],
1006
            [
1007
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
1008
                <a href="http://example.com">&lt;b&gt;Foo&lt;/b&gt;</a>
1009
                </td>',
1010
                'url',
1011
                '<b>Foo</b>',
1012
                ['url' => 'http://example.com'],
1013
            ],
1014
            [
1015
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
1016
                <a href="/foo">Foo</a>
1017
                </td>',
1018
                'url',
1019
                'Foo',
1020
                ['route' => ['name' => 'sonata_admin_foo']],
1021
            ],
1022
            [
1023
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
1024
                <a href="http://localhost/foo">Foo</a>
1025
                </td>',
1026
                'url',
1027
                'Foo',
1028
                ['route' => ['name' => 'sonata_admin_foo', 'absolute' => true]],
1029
            ],
1030
            [
1031
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
1032
                <a href="/foo">foo/bar?a=b&amp;c=123456789</a>
1033
                </td>',
1034
                'url',
1035
                'http://foo/bar?a=b&c=123456789',
1036
                ['route' => ['name' => 'sonata_admin_foo'],
1037
                'hide_protocol' => true, ],
1038
            ],
1039
            [
1040
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
1041
                <a href="http://localhost/foo">foo/bar?a=b&amp;c=123456789</a>
1042
                </td>',
1043
                'url',
1044
                'http://foo/bar?a=b&c=123456789',
1045
                [
1046
                    'route' => ['name' => 'sonata_admin_foo', 'absolute' => true],
1047
                    'hide_protocol' => true,
1048
                ],
1049
            ],
1050
            [
1051
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
1052
                <a href="/foo/abcd/efgh?param3=ijkl">Foo</a>
1053
                </td>',
1054
                'url',
1055
                'Foo',
1056
                [
1057
                    'route' => ['name' => 'sonata_admin_foo_param',
1058
                    'parameters' => ['param1' => 'abcd', 'param2' => 'efgh', 'param3' => 'ijkl'], ],
1059
                ],
1060
            ],
1061
            [
1062
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
1063
                <a href="http://localhost/foo/abcd/efgh?param3=ijkl">Foo</a>
1064
                </td>',
1065
                'url',
1066
                'Foo',
1067
                [
1068
                    'route' => ['name' => 'sonata_admin_foo_param',
1069
                    'absolute' => true,
1070
                    'parameters' => ['param1' => 'abcd', 'param2' => 'efgh', 'param3' => 'ijkl'], ],
1071
                ],
1072
            ],
1073
            [
1074
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
1075
                <a href="/foo/obj/abcd/12345/efgh?param3=ijkl">Foo</a>
1076
                </td>',
1077
                'url',
1078
                'Foo',
1079
                [
1080
                    'route' => ['name' => 'sonata_admin_foo_object',
1081
                    'parameters' => ['param1' => 'abcd', 'param2' => 'efgh', 'param3' => 'ijkl'],
1082
                    'identifier_parameter_name' => 'barId', ],
1083
                ],
1084
            ],
1085
            [
1086
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
1087
                <a href="http://localhost/foo/obj/abcd/12345/efgh?param3=ijkl">Foo</a>
1088
                </td>',
1089
                'url',
1090
                'Foo',
1091
                [
1092
                    'route' => ['name' => 'sonata_admin_foo_object',
1093
                    'absolute' => true,
1094
                    'parameters' => ['param1' => 'abcd', 'param2' => 'efgh', 'param3' => 'ijkl'],
1095
                    'identifier_parameter_name' => 'barId', ],
1096
                ],
1097
            ],
1098
            [
1099
                '<td class="sonata-ba-list-field sonata-ba-list-field-html" objectId="12345">
1100
                <p><strong>Creating a Template for the Field</strong> and form</p>
1101
                </td>',
1102
                'html',
1103
                '<p><strong>Creating a Template for the Field</strong> and form</p>',
1104
                [],
1105
            ],
1106
            [
1107
                '<td class="sonata-ba-list-field sonata-ba-list-field-html" objectId="12345">
1108
                Creating a Template for the Field and form
1109
                </td>',
1110
                'html',
1111
                '<p><strong>Creating a Template for the Field</strong> and form</p>',
1112
                ['strip' => true],
1113
            ],
1114
            [
1115
                '<td class="sonata-ba-list-field sonata-ba-list-field-html" objectId="12345">
1116
                Creating a Template for the Fi...
1117
                </td>',
1118
                'html',
1119
                '<p><strong>Creating a Template for the Field</strong> and form</p>',
1120
                ['truncate' => true],
1121
            ],
1122
            [
1123
                '<td class="sonata-ba-list-field sonata-ba-list-field-html" objectId="12345"> Creating a... </td>',
1124
                'html',
1125
                '<p><strong>Creating a Template for the Field</strong> and form</p>',
1126
                ['truncate' => ['length' => 10]],
1127
            ],
1128
            [
1129
                '<td class="sonata-ba-list-field sonata-ba-list-field-html" objectId="12345">
1130
                Creating a Template for the Field...
1131
                </td>',
1132
                'html',
1133
                '<p><strong>Creating a Template for the Field</strong> and form</p>',
1134
                ['truncate' => ['preserve' => true]],
1135
            ],
1136
            [
1137
                '<td class="sonata-ba-list-field sonata-ba-list-field-html" objectId="12345">
1138
                Creating a Template for the Fi etc.
1139
                </td>',
1140
                'html',
1141
                '<p><strong>Creating a Template for the Field</strong> and form</p>',
1142
                ['truncate' => ['separator' => ' etc.']],
1143
            ],
1144
            [
1145
                '<td class="sonata-ba-list-field sonata-ba-list-field-html" objectId="12345">
1146
                Creating a Template for[...]
1147
                </td>',
1148
                'html',
1149
                '<p><strong>Creating a Template for the Field</strong> and form</p>',
1150
                [
1151
                    'truncate' => [
1152
                        'length' => 20,
1153
                        'preserve' => true,
1154
                        'separator' => '[...]',
1155
                    ],
1156
                ],
1157
            ],
1158
1159
            [
1160
                <<<'EOT'
1161
<td class="sonata-ba-list-field sonata-ba-list-field-text" objectId="12345">
1162
<div
1163
    class="sonata-readmore"
1164
    data-readmore-height="40"
1165
    data-readmore-more="Read more"
1166
    data-readmore-less="Close">A very long string</div>
1167
</td>
1168
EOT
1169
                ,
1170
                'text',
1171
                'A very long string',
1172
                [
1173
                    'collapse' => true,
1174
                ],
1175
            ],
1176
            [
1177
                <<<'EOT'
1178
<td class="sonata-ba-list-field sonata-ba-list-field-text" objectId="12345">
1179
<div
1180
    class="sonata-readmore"
1181
    data-readmore-height="10"
1182
    data-readmore-more="More"
1183
    data-readmore-less="Less">A very long string</div>
1184
</td>
1185
EOT
1186
                ,
1187
                'text',
1188
                'A very long string',
1189
                [
1190
                    'collapse' => [
1191
                        'height' => 10,
1192
                        'more' => 'More',
1193
                        'less' => 'Less',
1194
                    ],
1195
                ],
1196
            ],
1197
            [
1198
                <<<'EOT'
1199
<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345">
1200
    <span
1201
        class="x-editable"
1202
        data-type="checklist"
1203
        data-value="[&quot;Status1&quot;,&quot;Status2&quot;]"
1204
        data-title="Data"
1205
        data-pk="12345"
1206
        data-url="/core/set-object-field-value?context=list&amp;field=fd_name&amp;objectId=12345&amp;code=sonata_admin_foo_service"
1207
        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;}]" >
1208
         Delete, Alias2
1209
    </span>
1210
</td>
1211
EOT
1212
                ,
1213
                'choice',
1214
                [
1215
                    'Status1',
1216
                    'Status2',
1217
                ],
1218
                [
1219
                    'editable' => true,
1220
                    'multiple' => true,
1221
                    'catalogue' => 'SonataAdminBundle',
1222
                    'choices' => [
1223
                        'Status1' => 'action_delete',
1224
                        'Status2' => 'Alias2',
1225
                        'Status3' => 'Alias3',
1226
                    ],
1227
                ],
1228
            ],
1229
        ];
1230
    }
1231
1232
    /**
1233
     * @dataProvider getRenderViewElementTests
1234
     */
1235
    public function testRenderViewElement(string $expected, string $type, $value, array $options): void
1236
    {
1237
        $this->fieldDescription
0 ignored issues
show
Bug introduced by
The method method() does not seem to exist on object<Sonata\AdminBundl...ldDescriptionInterface>.

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...
1238
            ->method('getValue')
1239
            ->willReturnCallback(static function () use ($value) {
1240
                if ($value instanceof NoValueException) {
1241
                    throw  $value;
1242
                }
1243
1244
                return $value;
1245
            });
1246
1247
        $this->fieldDescription
0 ignored issues
show
Bug introduced by
The method method() does not seem to exist on object<Sonata\AdminBundl...ldDescriptionInterface>.

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...
1248
            ->method('getType')
1249
            ->willReturn($type);
1250
1251
        $this->fieldDescription
0 ignored issues
show
Bug introduced by
The method method() does not seem to exist on object<Sonata\AdminBundl...ldDescriptionInterface>.

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...
1252
            ->method('getOptions')
1253
            ->willReturn($options);
1254
1255
        $this->fieldDescription
0 ignored issues
show
Bug introduced by
The method method() does not seem to exist on object<Sonata\AdminBundl...ldDescriptionInterface>.

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...
1256
            ->method('getTemplate')
1257
            ->willReturnCallback(static function () use ($type) {
1258
                switch ($type) {
1259
                    case 'boolean':
1260
                        return '@SonataAdmin/CRUD/show_boolean.html.twig';
1261
                    case 'datetime':
1262
                        return '@SonataAdmin/CRUD/show_datetime.html.twig';
1263
                    case 'date':
1264
                        return '@SonataAdmin/CRUD/show_date.html.twig';
1265
                    case 'time':
1266
                        return '@SonataAdmin/CRUD/show_time.html.twig';
1267
                    case 'currency':
1268
                        return '@SonataAdmin/CRUD/show_currency.html.twig';
1269
                    case 'percent':
1270
                        return '@SonataAdmin/CRUD/show_percent.html.twig';
1271
                    case 'email':
1272
                        return '@SonataAdmin/CRUD/show_email.html.twig';
1273
                    case 'choice':
1274
                        return '@SonataAdmin/CRUD/show_choice.html.twig';
1275
                    case 'array':
1276
                        return '@SonataAdmin/CRUD/show_array.html.twig';
1277
                    case 'trans':
1278
                        return '@SonataAdmin/CRUD/show_trans.html.twig';
1279
                    case 'url':
1280
                        return '@SonataAdmin/CRUD/show_url.html.twig';
1281
                    case 'html':
1282
                        return '@SonataAdmin/CRUD/show_html.html.twig';
1283
                    default:
1284
                        return false;
1285
                }
1286
            });
1287
1288
        $this->assertSame(
1289
                $this->removeExtraWhitespace($expected),
1290
                $this->removeExtraWhitespace(
1291
                    $this->twigExtension->renderViewElement(
1292
                        $this->environment,
1293
                        $this->fieldDescription,
1294
                        $this->object
1295
                    )
1296
                )
1297
            );
1298
    }
1299
1300
    public function getRenderViewElementTests()
1301
    {
1302
        return [
1303
            ['<th>Data</th> <td>Example</td>', 'string', 'Example', ['safe' => false]],
1304
            ['<th>Data</th> <td>Example</td>', 'text', 'Example', ['safe' => false]],
1305
            ['<th>Data</th> <td>Example</td>', 'textarea', 'Example', ['safe' => false]],
1306
            [
1307
                '<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>',
1308
                'datetime',
1309
                new \DateTime('2013-12-24 10:11:12', new \DateTimeZone('Europe/London')), [],
1310
            ],
1311
            [
1312
                '<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>',
1313
                'datetime',
1314
                new \DateTime('2013-12-24 10:11:12', new \DateTimeZone('Europe/London')),
1315
                ['format' => 'd.m.Y H:i:s'],
1316
            ],
1317
            [
1318
                '<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>',
1319
                'datetime',
1320
                new \DateTime('2013-12-24 10:11:12', new \DateTimeZone('UTC')),
1321
                ['timezone' => 'Asia/Hong_Kong'],
1322
            ],
1323
            [
1324
                '<th>Data</th> <td><time datetime="2013-12-24" title="2013-12-24"> December 24, 2013 </time></td>',
1325
                'date',
1326
                new \DateTime('2013-12-24 10:11:12', new \DateTimeZone('Europe/London')),
1327
                [],
1328
            ],
1329
            [
1330
                '<th>Data</th> <td><time datetime="2013-12-24" title="2013-12-24"> 24.12.2013 </time></td>',
1331
                'date',
1332
                new \DateTime('2013-12-24 10:11:12', new \DateTimeZone('Europe/London')),
1333
                ['format' => 'd.m.Y'],
1334
            ],
1335
            [
1336
                '<th>Data</th> <td><time datetime="10:11:12+00:00" title="10:11:12+00:00"> 10:11:12 </time></td>',
1337
                'time',
1338
                new \DateTime('2013-12-24 10:11:12', new \DateTimeZone('Europe/London')),
1339
                [],
1340
            ],
1341
            [
1342
                '<th>Data</th> <td><time datetime="10:11:12+00:00" title="10:11:12+00:00"> 18:11:12 </time></td>',
1343
                'time',
1344
                new \DateTime('2013-12-24 10:11:12', new \DateTimeZone('UTC')),
1345
                ['timezone' => 'Asia/Hong_Kong'],
1346
            ],
1347
            ['<th>Data</th> <td>10.746135</td>', 'number', 10.746135, ['safe' => false]],
1348
            ['<th>Data</th> <td>5678</td>', 'integer', 5678, ['safe' => false]],
1349
            ['<th>Data</th> <td> 1074.6135 % </td>', 'percent', 10.746135, []],
1350
            ['<th>Data</th> <td> EUR 10.746135 </td>', 'currency', 10.746135, ['currency' => 'EUR']],
1351
            ['<th>Data</th> <td> GBP 51.23456 </td>', 'currency', 51.23456, ['currency' => 'GBP']],
1352
            [
1353
                '<th>Data</th> <td> [1 => First] <br> [2 => Second] </td>',
1354
                'array',
1355
                [1 => 'First', 2 => 'Second'],
1356
                ['safe' => false],
1357
            ],
1358
            [
1359
                '<th>Data</th> <td> [1 => First] [2 => Second] </td>',
1360
                'array',
1361
                [1 => 'First', 2 => 'Second'],
1362
                ['safe' => false, 'inline' => true],
1363
            ],
1364
            [
1365
                '<th>Data</th> <td><span class="label label-success">yes</span></td>',
1366
                'boolean',
1367
                true,
1368
                [],
1369
            ],
1370
            [
1371
                '<th>Data</th> <td><span class="label label-danger">yes</span></td>',
1372
                'boolean',
1373
                true,
1374
                ['inverse' => true],
1375
            ],
1376
            ['<th>Data</th> <td><span class="label label-danger">no</span></td>', 'boolean', false, []],
1377
            [
1378
                '<th>Data</th> <td><span class="label label-success">no</span></td>',
1379
                'boolean',
1380
                false,
1381
                ['inverse' => true],
1382
            ],
1383
            [
1384
                '<th>Data</th> <td> Delete </td>',
1385
                'trans',
1386
                'action_delete',
1387
                ['safe' => false, 'catalogue' => 'SonataAdminBundle'],
1388
            ],
1389
            [
1390
                '<th>Data</th> <td> Delete </td>',
1391
                'trans',
1392
                'delete',
1393
                ['safe' => false, 'catalogue' => 'SonataAdminBundle', 'format' => 'action_%s'],
1394
            ],
1395
            ['<th>Data</th> <td>Status1</td>', 'choice', 'Status1', ['safe' => false]],
1396
            [
1397
                '<th>Data</th> <td>Alias1</td>',
1398
                'choice',
1399
                'Status1',
1400
                ['safe' => false, 'choices' => [
1401
                    'Status1' => 'Alias1',
1402
                    'Status2' => 'Alias2',
1403
                    'Status3' => 'Alias3',
1404
                ]],
1405
            ],
1406
            [
1407
                '<th>Data</th> <td>NoValidKeyInChoices</td>',
1408
                'choice',
1409
                'NoValidKeyInChoices',
1410
                ['safe' => false, 'choices' => [
1411
                    'Status1' => 'Alias1',
1412
                    'Status2' => 'Alias2',
1413
                    'Status3' => 'Alias3',
1414
                ]],
1415
            ],
1416
            [
1417
                '<th>Data</th> <td>Delete</td>',
1418
                'choice',
1419
                'Foo',
1420
                ['safe' => false, 'catalogue' => 'SonataAdminBundle', 'choices' => [
1421
                    'Foo' => 'action_delete',
1422
                    'Status2' => 'Alias2',
1423
                    'Status3' => 'Alias3',
1424
                ]],
1425
            ],
1426
            [
1427
                '<th>Data</th> <td>NoValidKeyInChoices</td>',
1428
                'choice',
1429
                ['NoValidKeyInChoices'],
1430
                ['safe' => false, 'choices' => [
1431
                    'Status1' => 'Alias1',
1432
                    'Status2' => 'Alias2',
1433
                    'Status3' => 'Alias3',
1434
                ], 'multiple' => true],
1435
            ],
1436
            [
1437
                '<th>Data</th> <td>NoValidKeyInChoices, Alias2</td>',
1438
                'choice',
1439
                ['NoValidKeyInChoices', 'Status2'],
1440
                ['safe' => false, 'choices' => [
1441
                    'Status1' => 'Alias1',
1442
                    'Status2' => 'Alias2',
1443
                    'Status3' => 'Alias3',
1444
                ], 'multiple' => true],
1445
            ],
1446
            [
1447
                '<th>Data</th> <td>Alias1, Alias3</td>',
1448
                'choice',
1449
                ['Status1', 'Status3'],
1450
                ['safe' => false, 'choices' => [
1451
                    'Status1' => 'Alias1',
1452
                    'Status2' => 'Alias2',
1453
                    'Status3' => 'Alias3',
1454
                ], 'multiple' => true],
1455
            ],
1456
            [
1457
                '<th>Data</th> <td>Alias1 | Alias3</td>',
1458
                'choice',
1459
                ['Status1', 'Status3'], ['safe' => false, 'choices' => [
1460
                    'Status1' => 'Alias1',
1461
                    'Status2' => 'Alias2',
1462
                    'Status3' => 'Alias3',
1463
                ], 'multiple' => true, 'delimiter' => ' | '],
1464
            ],
1465
            [
1466
                '<th>Data</th> <td>Delete, Alias3</td>',
1467
                'choice',
1468
                ['Foo', 'Status3'],
1469
                ['safe' => false, 'catalogue' => 'SonataAdminBundle', 'choices' => [
1470
                    'Foo' => 'action_delete',
1471
                    'Status2' => 'Alias2',
1472
                    'Status3' => 'Alias3',
1473
                ], 'multiple' => true],
1474
            ],
1475
            [
1476
                '<th>Data</th> <td><b>Alias1</b>, <b>Alias3</b></td>',
1477
                'choice',
1478
                ['Status1', 'Status3'],
1479
                ['safe' => true, 'choices' => [
1480
                    'Status1' => '<b>Alias1</b>',
1481
                    'Status2' => '<b>Alias2</b>',
1482
                    'Status3' => '<b>Alias3</b>',
1483
                ], 'multiple' => true],
1484
            ],
1485
            [
1486
                '<th>Data</th> <td>&lt;b&gt;Alias1&lt;/b&gt;, &lt;b&gt;Alias3&lt;/b&gt;</td>',
1487
                'choice',
1488
                ['Status1', 'Status3'],
1489
                ['safe' => false, 'choices' => [
1490
                    'Status1' => '<b>Alias1</b>',
1491
                    'Status2' => '<b>Alias2</b>',
1492
                    'Status3' => '<b>Alias3</b>',
1493
                ], 'multiple' => true],
1494
            ],
1495
            [
1496
                '<th>Data</th> <td><a href="http://example.com">http://example.com</a></td>',
1497
                'url',
1498
                'http://example.com',
1499
                ['safe' => false],
1500
            ],
1501
            [
1502
                '<th>Data</th> <td><a href="http://example.com" target="_blank">http://example.com</a></td>',
1503
                'url',
1504
                'http://example.com',
1505
                ['safe' => false, 'attributes' => ['target' => '_blank']],
1506
            ],
1507
            [
1508
                '<th>Data</th> <td><a href="http://example.com" target="_blank" class="fooLink">http://example.com</a></td>',
1509
                'url',
1510
                'http://example.com',
1511
                ['safe' => false, 'attributes' => ['target' => '_blank', 'class' => 'fooLink']],
1512
            ],
1513
            [
1514
                '<th>Data</th> <td><a href="https://example.com">https://example.com</a></td>',
1515
                'url',
1516
                'https://example.com',
1517
                ['safe' => false],
1518
            ],
1519
            [
1520
                '<th>Data</th> <td><a href="http://example.com">example.com</a></td>',
1521
                'url',
1522
                'http://example.com',
1523
                ['safe' => false, 'hide_protocol' => true],
1524
            ],
1525
            [
1526
                '<th>Data</th> <td><a href="https://example.com">example.com</a></td>',
1527
                'url',
1528
                'https://example.com',
1529
                ['safe' => false, 'hide_protocol' => true],
1530
            ],
1531
            [
1532
                '<th>Data</th> <td><a href="http://example.com">http://example.com</a></td>',
1533
                'url',
1534
                'http://example.com',
1535
                ['safe' => false, 'hide_protocol' => false],
1536
            ],
1537
            [
1538
                '<th>Data</th> <td><a href="https://example.com">https://example.com</a></td>',
1539
                'url',
1540
                'https://example.com',
1541
                ['safe' => false,
1542
                'hide_protocol' => false, ],
1543
            ],
1544
            [
1545
                '<th>Data</th> <td><a href="http://example.com">Foo</a></td>',
1546
                'url',
1547
                'Foo',
1548
                ['safe' => false, 'url' => 'http://example.com'],
1549
            ],
1550
            [
1551
                '<th>Data</th> <td><a href="http://example.com">&lt;b&gt;Foo&lt;/b&gt;</a></td>',
1552
                'url',
1553
                '<b>Foo</b>',
1554
                ['safe' => false, 'url' => 'http://example.com'],
1555
            ],
1556
            [
1557
                '<th>Data</th> <td><a href="http://example.com"><b>Foo</b></a></td>',
1558
                'url',
1559
                '<b>Foo</b>',
1560
                ['safe' => true, 'url' => 'http://example.com'],
1561
            ],
1562
            [
1563
                '<th>Data</th> <td><a href="/foo">Foo</a></td>',
1564
                'url',
1565
                'Foo',
1566
                ['safe' => false, 'route' => ['name' => 'sonata_admin_foo']],
1567
            ],
1568
            [
1569
                '<th>Data</th> <td><a href="http://localhost/foo">Foo</a></td>',
1570
                'url',
1571
                'Foo',
1572
                ['safe' => false, 'route' => [
1573
                    'name' => 'sonata_admin_foo',
1574
                    'absolute' => true,
1575
                ]],
1576
            ],
1577
            [
1578
                '<th>Data</th> <td><a href="/foo">foo/bar?a=b&amp;c=123456789</a></td>',
1579
                'url',
1580
                'http://foo/bar?a=b&c=123456789',
1581
                [
1582
                    'safe' => false,
1583
                    'route' => ['name' => 'sonata_admin_foo'],
1584
                    'hide_protocol' => true,
1585
                ],
1586
            ],
1587
            [
1588
                '<th>Data</th> <td><a href="http://localhost/foo">foo/bar?a=b&amp;c=123456789</a></td>',
1589
                'url',
1590
                'http://foo/bar?a=b&c=123456789',
1591
                ['safe' => false, 'route' => [
1592
                    'name' => 'sonata_admin_foo',
1593
                    'absolute' => true,
1594
                ], 'hide_protocol' => true],
1595
            ],
1596
            [
1597
                '<th>Data</th> <td><a href="/foo/abcd/efgh?param3=ijkl">Foo</a></td>',
1598
                'url',
1599
                'Foo',
1600
                ['safe' => false, 'route' => [
1601
                    'name' => 'sonata_admin_foo_param',
1602
                    'parameters' => ['param1' => 'abcd', 'param2' => 'efgh', 'param3' => 'ijkl'],
1603
                ]],
1604
            ],
1605
            [
1606
                '<th>Data</th> <td><a href="http://localhost/foo/abcd/efgh?param3=ijkl">Foo</a></td>',
1607
                'url',
1608
                'Foo',
1609
                ['safe' => false, 'route' => [
1610
                    'name' => 'sonata_admin_foo_param',
1611
                    'absolute' => true,
1612
                    'parameters' => [
1613
                        'param1' => 'abcd',
1614
                        'param2' => 'efgh',
1615
                        'param3' => 'ijkl',
1616
                    ],
1617
                ]],
1618
            ],
1619
            [
1620
                '<th>Data</th> <td><a href="/foo/obj/abcd/12345/efgh?param3=ijkl">Foo</a></td>',
1621
                'url',
1622
                'Foo',
1623
                ['safe' => false, 'route' => [
1624
                    'name' => 'sonata_admin_foo_object',
1625
                    'parameters' => [
1626
                        'param1' => 'abcd',
1627
                        'param2' => 'efgh',
1628
                        'param3' => 'ijkl',
1629
                    ],
1630
                    'identifier_parameter_name' => 'barId',
1631
                ]],
1632
            ],
1633
            [
1634
                '<th>Data</th> <td><a href="http://localhost/foo/obj/abcd/12345/efgh?param3=ijkl">Foo</a></td>',
1635
                'url',
1636
                'Foo',
1637
                ['safe' => false, 'route' => [
1638
                    'name' => 'sonata_admin_foo_object',
1639
                    'absolute' => true,
1640
                    'parameters' => [
1641
                        'param1' => 'abcd',
1642
                        'param2' => 'efgh',
1643
                        'param3' => 'ijkl',
1644
                    ],
1645
                    'identifier_parameter_name' => 'barId',
1646
                ]],
1647
            ],
1648
            [
1649
                '<th>Data</th> <td> &nbsp;</td>',
1650
                'email',
1651
                null,
1652
                [],
1653
            ],
1654
            [
1655
                '<th>Data</th> <td> <a href="mailto:[email protected]">[email protected]</a></td>',
1656
                'email',
1657
                '[email protected]',
1658
                [],
1659
            ],
1660
            [
1661
                '<th>Data</th> <td> <a href="mailto:[email protected]?'.$this->buildTwigLikeUrl(['subject' => 'Main Theme', 'body' => 'Message Body']).'">[email protected]</a></td>',
1662
                'email',
1663
                '[email protected]',
1664
                ['subject' => 'Main Theme', 'body' => 'Message Body'],
1665
            ],
1666
            [
1667
                '<th>Data</th> <td> <a href="mailto:[email protected]?'.$this->buildTwigLikeUrl(['subject' => 'Main Theme']).'">[email protected]</a></td>',
1668
                'email',
1669
                '[email protected]',
1670
                ['subject' => 'Main Theme'],
1671
            ],
1672
            [
1673
                '<th>Data</th> <td> <a href="mailto:[email protected]?'.$this->buildTwigLikeUrl(['body' => 'Message Body']).'">[email protected]</a></td>',
1674
                'email',
1675
                '[email protected]',
1676
                ['body' => 'Message Body'],
1677
            ],
1678
            [
1679
                '<th>Data</th> <td> [email protected]</td>',
1680
                'email',
1681
                '[email protected]',
1682
                ['as_string' => true, 'subject' => 'Main Theme', 'body' => 'Message Body'],
1683
            ],
1684
            [
1685
                '<th>Data</th> <td> [email protected]</td>',
1686
                'email',
1687
                '[email protected]',
1688
                ['as_string' => true, 'subject' => 'Main Theme'],
1689
            ],
1690
            [
1691
                '<th>Data</th> <td> [email protected]</td>',
1692
                'email',
1693
                '[email protected]',
1694
                ['as_string' => true, 'body' => 'Message Body'],
1695
            ],
1696
            [
1697
                '<th>Data</th> <td> <a href="mailto:[email protected]">[email protected]</a></td>',
1698
                'email',
1699
                '[email protected]',
1700
                ['as_string' => false],
1701
            ],
1702
            [
1703
                '<th>Data</th> <td> [email protected]</td>',
1704
                'email',
1705
                '[email protected]',
1706
                ['as_string' => true],
1707
            ],
1708
            [
1709
                '<th>Data</th> <td><p><strong>Creating a Template for the Field</strong> and form</p> </td>',
1710
                'html',
1711
                '<p><strong>Creating a Template for the Field</strong> and form</p>',
1712
                [],
1713
            ],
1714
            [
1715
                '<th>Data</th> <td>Creating a Template for the Field and form </td>',
1716
                'html',
1717
                '<p><strong>Creating a Template for the Field</strong> and form</p>',
1718
                ['strip' => true],
1719
            ],
1720
            [
1721
                '<th>Data</th> <td> Creating a Template for the Fi... </td>',
1722
                'html',
1723
                '<p><strong>Creating a Template for the Field</strong> and form</p>',
1724
                ['truncate' => true],
1725
            ],
1726
            [
1727
                '<th>Data</th> <td> Creating a... </td>',
1728
                'html',
1729
                '<p><strong>Creating a Template for the Field</strong> and form</p>',
1730
                ['truncate' => ['length' => 10]],
1731
            ],
1732
            [
1733
                '<th>Data</th> <td> Creating a Template for the Field... </td>',
1734
                'html',
1735
                '<p><strong>Creating a Template for the Field</strong> and form</p>',
1736
                ['truncate' => ['preserve' => true]],
1737
            ],
1738
            [
1739
                '<th>Data</th> <td> Creating a Template for the Fi etc. </td>',
1740
                'html',
1741
                '<p><strong>Creating a Template for the Field</strong> and form</p>',
1742
                ['truncate' => ['separator' => ' etc.']],
1743
            ],
1744
            [
1745
                '<th>Data</th> <td> Creating a Template for[...] </td>',
1746
                'html',
1747
                '<p><strong>Creating a Template for the Field</strong> and form</p>',
1748
                [
1749
                    'truncate' => [
1750
                        'length' => 20,
1751
                        'preserve' => true,
1752
                        'separator' => '[...]',
1753
                    ],
1754
                ],
1755
            ],
1756
1757
            // NoValueException
1758
            ['<th>Data</th> <td></td>', 'string', new NoValueException(), ['safe' => false]],
1759
            ['<th>Data</th> <td></td>', 'text', new NoValueException(), ['safe' => false]],
1760
            ['<th>Data</th> <td></td>', 'textarea', new NoValueException(), ['safe' => false]],
1761
            ['<th>Data</th> <td>&nbsp;</td>', 'datetime', new NoValueException(), []],
1762
            [
1763
                '<th>Data</th> <td>&nbsp;</td>',
1764
                'datetime',
1765
                new NoValueException(),
1766
                ['format' => 'd.m.Y H:i:s'],
1767
            ],
1768
            ['<th>Data</th> <td>&nbsp;</td>', 'date', new NoValueException(), []],
1769
            ['<th>Data</th> <td>&nbsp;</td>', 'date', new NoValueException(), ['format' => 'd.m.Y']],
1770
            ['<th>Data</th> <td>&nbsp;</td>', 'time', new NoValueException(), []],
1771
            ['<th>Data</th> <td></td>', 'number', new NoValueException(), ['safe' => false]],
1772
            ['<th>Data</th> <td></td>', 'integer', new NoValueException(), ['safe' => false]],
1773
            ['<th>Data</th> <td> 0 % </td>', 'percent', new NoValueException(), []],
1774
            ['<th>Data</th> <td> </td>', 'currency', new NoValueException(), ['currency' => 'EUR']],
1775
            ['<th>Data</th> <td> </td>', 'currency', new NoValueException(), ['currency' => 'GBP']],
1776
            ['<th>Data</th> <td> </td>', 'array', new NoValueException(), ['safe' => false]],
1777
            [
1778
                '<th>Data</th> <td><span class="label label-danger">no</span></td>',
1779
                'boolean',
1780
                new NoValueException(),
1781
                [],
1782
            ],
1783
            [
1784
                '<th>Data</th> <td> </td>',
1785
                'trans',
1786
                new NoValueException(),
1787
                ['safe' => false, 'catalogue' => 'SonataAdminBundle'],
1788
            ],
1789
            [
1790
                '<th>Data</th> <td></td>',
1791
                'choice',
1792
                new NoValueException(),
1793
                ['safe' => false, 'choices' => []],
1794
            ],
1795
            [
1796
                '<th>Data</th> <td></td>',
1797
                'choice',
1798
                new NoValueException(),
1799
                ['safe' => false, 'choices' => [], 'multiple' => true],
1800
            ],
1801
            ['<th>Data</th> <td>&nbsp;</td>', 'url', new NoValueException(), []],
1802
            [
1803
                '<th>Data</th> <td>&nbsp;</td>',
1804
                'url',
1805
                new NoValueException(),
1806
                ['url' => 'http://example.com'],
1807
            ],
1808
            [
1809
                '<th>Data</th> <td>&nbsp;</td>',
1810
                'url',
1811
                new NoValueException(),
1812
                ['route' => ['name' => 'sonata_admin_foo']],
1813
            ],
1814
1815
            [
1816
                <<<'EOT'
1817
<th>Data</th> <td><div
1818
        class="sonata-readmore"
1819
        data-readmore-height="40"
1820
        data-readmore-more="Read more"
1821
        data-readmore-less="Close">
1822
            A very long string
1823
</div></td>
1824
EOT
1825
                ,
1826
                'text',
1827
                ' A very long string ',
1828
                [
1829
                    'collapse' => true,
1830
                    'safe' => false,
1831
                ],
1832
            ],
1833
            [
1834
                <<<'EOT'
1835
<th>Data</th> <td><div
1836
        class="sonata-readmore"
1837
        data-readmore-height="10"
1838
        data-readmore-more="More"
1839
        data-readmore-less="Less">
1840
            A very long string
1841
</div></td>
1842
EOT
1843
                ,
1844
                'text',
1845
                ' A very long string ',
1846
                [
1847
                    'collapse' => [
1848
                        'height' => 10,
1849
                        'more' => 'More',
1850
                        'less' => 'Less',
1851
                    ],
1852
                    'safe' => false,
1853
                ],
1854
            ],
1855
        ];
1856
    }
1857
1858
    public function testGetValueFromFieldDescription(): void
1859
    {
1860
        $object = new \stdClass();
1861
        $fieldDescription = $this->getMockForAbstractClass(FieldDescriptionInterface::class);
1862
1863
        $fieldDescription
1864
            ->method('getValue')
1865
            ->willReturn('test123');
1866
1867
        $this->assertSame(
1868
            'test123',
1869
            $this->getMethodAsPublic('getValueFromFieldDescription')->invoke(
1870
                $this->twigExtension,
1871
                $object,
1872
                $fieldDescription
1873
            )
1874
        );
1875
    }
1876
1877
    public function testGetValueFromFieldDescriptionWithRemoveLoopException(): void
1878
    {
1879
        $object = $this->createMock(\ArrayAccess::class);
1880
        $fieldDescription = $this->getMockForAbstractClass(FieldDescriptionInterface::class);
1881
1882
        $this->expectException(\RuntimeException::class);
1883
        $this->expectExceptionMessage('remove the loop requirement');
1884
1885
        $this->assertSame(
1886
            'anything',
1887
            $this->getMethodAsPublic('getValueFromFieldDescription')->invoke(
1888
                $this->twigExtension,
1889
                $object,
1890
                $fieldDescription,
1891
                ['loop' => true]
1892
            )
1893
        );
1894
    }
1895
1896
    public function testGetValueFromFieldDescriptionWithNoValueException(): void
1897
    {
1898
        $object = new \stdClass();
1899
        $fieldDescription = $this->getMockForAbstractClass(FieldDescriptionInterface::class);
1900
1901
        $fieldDescription
1902
            ->method('getValue')
1903
            ->willReturnCallback(static function (): void {
1904
                throw new NoValueException();
1905
            });
1906
1907
        $fieldDescription
1908
            ->method('getAssociationAdmin')
1909
            ->willReturn(null);
1910
1911
        $this->assertNull(
1912
            $this->getMethodAsPublic('getValueFromFieldDescription')->invoke(
1913
                $this->twigExtension,
1914
                $object,
1915
                $fieldDescription
1916
            )
1917
        );
1918
    }
1919
1920
    public function testGetValueFromFieldDescriptionWithNoValueExceptionNewAdminInstance(): void
1921
    {
1922
        $object = new \stdClass();
1923
        $fieldDescription = $this->getMockForAbstractClass(FieldDescriptionInterface::class);
1924
1925
        $fieldDescription
1926
            ->method('getValue')
1927
            ->willReturnCallback(static function (): void {
1928
                throw new NoValueException();
1929
            });
1930
1931
        $fieldDescription
1932
            ->method('getAssociationAdmin')
1933
            ->willReturn($this->admin);
1934
1935
        $this->admin->expects($this->once())
0 ignored issues
show
Bug introduced by
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...
1936
            ->method('getNewInstance')
1937
            ->willReturn('foo');
1938
1939
        $this->assertSame(
1940
            'foo',
1941
            $this->getMethodAsPublic('getValueFromFieldDescription')->invoke(
1942
                $this->twigExtension,
1943
                $object,
1944
                $fieldDescription
1945
            )
1946
        );
1947
    }
1948
1949
    public function testRenderRelationElementNoObject(): void
1950
    {
1951
        $this->assertSame('foo', $this->twigExtension->renderRelationElement('foo', $this->fieldDescription));
1952
    }
1953
1954
    public function testRenderRelationElementToString(): void
1955
    {
1956
        $this->fieldDescription->expects($this->exactly(2))
0 ignored issues
show
Bug introduced by
The method expects() does not seem to exist on object<Sonata\AdminBundl...ldDescriptionInterface>.

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...
1957
            ->method('getOption')
1958
            ->willReturnCallback(static function ($value, $default = null) {
1959
                if ('associated_property' === $value) {
1960
                    return $default;
1961
                }
1962
            });
1963
1964
        $element = new FooToString();
1965
        $this->assertSame('salut', $this->twigExtension->renderRelationElement($element, $this->fieldDescription));
1966
    }
1967
1968
    /**
1969
     * @group legacy
1970
     */
1971
    public function testDeprecatedRelationElementToString(): void
1972
    {
1973
        $this->fieldDescription->expects($this->exactly(2))
0 ignored issues
show
Bug introduced by
The method expects() does not seem to exist on object<Sonata\AdminBundl...ldDescriptionInterface>.

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...
1974
            ->method('getOption')
1975
            ->willReturnCallback(static function ($value, $default = null) {
0 ignored issues
show
Unused Code introduced by
The parameter $default is not used and could be removed.

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

Loading history...
1976
                if ('associated_tostring' === $value) {
1977
                    return '__toString';
1978
                }
1979
            });
1980
1981
        $element = new FooToString();
1982
        $this->assertSame(
1983
            'salut',
1984
            $this->twigExtension->renderRelationElement($element, $this->fieldDescription)
1985
        );
1986
    }
1987
1988
    /**
1989
     * @group legacy
1990
     */
1991
    public function testRenderRelationElementCustomToString(): void
1992
    {
1993
        $this->fieldDescription->expects($this->exactly(2))
0 ignored issues
show
Bug introduced by
The method expects() does not seem to exist on object<Sonata\AdminBundl...ldDescriptionInterface>.

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...
1994
            ->method('getOption')
1995
            ->willReturnCallback(static function ($value, $default = null) {
1996
                if ('associated_property' === $value) {
1997
                    return $default;
1998
                }
1999
2000
                if ('associated_tostring' === $value) {
2001
                    return 'customToString';
2002
                }
2003
            });
2004
2005
        $element = $this->getMockBuilder('stdClass')
2006
            ->setMethods(['customToString'])
2007
            ->getMock();
2008
        $element
2009
            ->method('customToString')
2010
            ->willReturn('fooBar');
2011
2012
        $this->assertSame('fooBar', $this->twigExtension->renderRelationElement($element, $this->fieldDescription));
2013
    }
2014
2015
    /**
2016
     * @group legacy
2017
     */
2018
    public function testRenderRelationElementMethodNotExist(): void
2019
    {
2020
        $this->fieldDescription->expects($this->exactly(2))
0 ignored issues
show
Bug introduced by
The method expects() does not seem to exist on object<Sonata\AdminBundl...ldDescriptionInterface>.

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...
2021
            ->method('getOption')
2022
2023
            ->willReturnCallback(static function ($value, $default = null) {
0 ignored issues
show
Unused Code introduced by
The parameter $default is not used and could be removed.

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

Loading history...
2024
                if ('associated_tostring' === $value) {
2025
                    return 'nonExistedMethod';
2026
                }
2027
            });
2028
2029
        $element = new \stdClass();
2030
        $this->expectException(\RuntimeException::class);
2031
        $this->expectExceptionMessage('You must define an `associated_property` option or create a `stdClass::__toString');
2032
2033
        $this->twigExtension->renderRelationElement($element, $this->fieldDescription);
2034
    }
2035
2036
    public function testRenderRelationElementWithPropertyPath(): void
2037
    {
2038
        $this->fieldDescription->expects($this->once())
0 ignored issues
show
Bug introduced by
The method expects() does not seem to exist on object<Sonata\AdminBundl...ldDescriptionInterface>.

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...
2039
            ->method('getOption')
2040
2041
            ->willReturnCallback(static function ($value, $default = null) {
0 ignored issues
show
Unused Code introduced by
The parameter $default is not used and could be removed.

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

Loading history...
2042
                if ('associated_property' === $value) {
2043
                    return 'foo';
2044
                }
2045
            });
2046
2047
        $element = new \stdClass();
2048
        $element->foo = 'bar';
2049
2050
        $this->assertSame('bar', $this->twigExtension->renderRelationElement($element, $this->fieldDescription));
2051
    }
2052
2053
    public function testRenderRelationElementWithClosure(): void
2054
    {
2055
        $this->fieldDescription->expects($this->once())
0 ignored issues
show
Bug introduced by
The method expects() does not seem to exist on object<Sonata\AdminBundl...ldDescriptionInterface>.

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...
2056
            ->method('getOption')
2057
2058
            ->willReturnCallback(static function ($value, $default = null) {
0 ignored issues
show
Unused Code introduced by
The parameter $default is not used and could be removed.

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

Loading history...
2059
                if ('associated_property' === $value) {
2060
                    return static function ($element): string {
2061
                        return 'closure '.$element->foo;
2062
                    };
2063
                }
2064
            });
2065
2066
        $element = new \stdClass();
2067
        $element->foo = 'bar';
2068
2069
        $this->assertSame(
2070
            'closure bar',
2071
            $this->twigExtension->renderRelationElement($element, $this->fieldDescription)
2072
        );
2073
    }
2074
2075
    public function testGetUrlsafeIdentifier(): void
2076
    {
2077
        $entity = new \stdClass();
2078
2079
        // set admin to pool
2080
        $this->pool->setAdminServiceIds(['sonata_admin_foo_service']);
2081
        $this->pool->setAdminClasses(['stdClass' => ['sonata_admin_foo_service']]);
2082
2083
        $this->admin->expects($this->once())
0 ignored issues
show
Bug introduced by
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...
2084
            ->method('getUrlsafeIdentifier')
2085
            ->with($this->equalTo($entity))
2086
            ->willReturn(1234567);
2087
2088
        $this->assertSame(1234567, $this->twigExtension->getUrlsafeIdentifier($entity));
2089
    }
2090
2091
    public function testGetUrlsafeIdentifier_GivenAdmin_Foo(): void
2092
    {
2093
        $entity = new \stdClass();
2094
2095
        // set admin to pool
2096
        $this->pool->setAdminServiceIds([
2097
            'sonata_admin_foo_service',
2098
            'sonata_admin_bar_service',
2099
        ]);
2100
        $this->pool->setAdminClasses(['stdClass' => [
2101
            'sonata_admin_foo_service',
2102
            'sonata_admin_bar_service',
2103
        ]]);
2104
2105
        $this->admin->expects($this->once())
0 ignored issues
show
Bug introduced by
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...
2106
            ->method('getUrlsafeIdentifier')
2107
            ->with($this->equalTo($entity))
2108
            ->willReturn(1234567);
2109
2110
        $this->adminBar->expects($this->never())
0 ignored issues
show
Bug introduced by
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...
2111
            ->method('getUrlsafeIdentifier');
2112
2113
        $this->assertSame(1234567, $this->twigExtension->getUrlsafeIdentifier($entity, $this->admin));
2114
    }
2115
2116
    public function testGetUrlsafeIdentifier_GivenAdmin_Bar(): void
2117
    {
2118
        $entity = new \stdClass();
2119
2120
        // set admin to pool
2121
        $this->pool->setAdminServiceIds(['sonata_admin_foo_service', 'sonata_admin_bar_service']);
2122
        $this->pool->setAdminClasses(['stdClass' => [
2123
            'sonata_admin_foo_service',
2124
            'sonata_admin_bar_service',
2125
        ]]);
2126
2127
        $this->admin->expects($this->never())
0 ignored issues
show
Bug introduced by
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...
2128
            ->method('getUrlsafeIdentifier');
2129
2130
        $this->adminBar->expects($this->once())
0 ignored issues
show
Bug introduced by
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...
2131
            ->method('getUrlsafeIdentifier')
2132
            ->with($this->equalTo($entity))
2133
            ->willReturn(1234567);
2134
2135
        $this->assertSame(1234567, $this->twigExtension->getUrlsafeIdentifier($entity, $this->adminBar));
2136
    }
2137
2138
    public function xEditableChoicesProvider()
2139
    {
2140
        return [
2141
            'needs processing' => [
2142
                ['choices' => ['Status1' => 'Alias1', 'Status2' => 'Alias2']],
2143
                [
2144
                    ['value' => 'Status1', 'text' => 'Alias1'],
2145
                    ['value' => 'Status2', 'text' => 'Alias2'],
2146
                ],
2147
            ],
2148
            'already processed' => [
2149
                ['choices' => [
2150
                    ['value' => 'Status1', 'text' => 'Alias1'],
2151
                    ['value' => 'Status2', 'text' => 'Alias2'],
2152
                ]],
2153
                [
2154
                    ['value' => 'Status1', 'text' => 'Alias1'],
2155
                    ['value' => 'Status2', 'text' => 'Alias2'],
2156
                ],
2157
            ],
2158
            'not required' => [
2159
                [
2160
                    'required' => false,
2161
                    'choices' => ['' => '', 'Status1' => 'Alias1', 'Status2' => 'Alias2'],
2162
                ],
2163
                [
2164
                    ['value' => '', 'text' => ''],
2165
                    ['value' => 'Status1', 'text' => 'Alias1'],
2166
                    ['value' => 'Status2', 'text' => 'Alias2'],
2167
                ],
2168
            ],
2169
            'not required multiple' => [
2170
                [
2171
                    'required' => false,
2172
                    'multiple' => true,
2173
                    'choices' => ['Status1' => 'Alias1', 'Status2' => 'Alias2'],
2174
                ],
2175
                [
2176
                    ['value' => 'Status1', 'text' => 'Alias1'],
2177
                    ['value' => 'Status2', 'text' => 'Alias2'],
2178
                ],
2179
            ],
2180
        ];
2181
    }
2182
2183
    /**
2184
     * @dataProvider xEditablechoicesProvider
2185
     */
2186
    public function testGetXEditableChoicesIsIdempotent(array $options, array $expectedChoices): void
2187
    {
2188
        $fieldDescription = $this->getMockForAbstractClass(FieldDescriptionInterface::class);
2189
        $fieldDescription
2190
            ->method('getOption')
2191
            ->withConsecutive(
2192
                ['choices', []],
2193
                ['catalogue'],
2194
                ['required'],
2195
                ['multiple']
2196
            )
2197
            ->will($this->onConsecutiveCalls(
2198
                $options['choices'],
2199
                'MyCatalogue',
2200
                $options['multiple'] ?? null
2201
            ));
2202
2203
        $this->assertSame($expectedChoices, $this->twigExtension->getXEditableChoices($fieldDescription));
2204
    }
2205
2206
    public function select2LocalesProvider()
2207
    {
2208
        return [
2209
            ['ar', 'ar'],
2210
            ['az', 'az'],
2211
            ['bg', 'bg'],
2212
            ['ca', 'ca'],
2213
            ['cs', 'cs'],
2214
            ['da', 'da'],
2215
            ['de', 'de'],
2216
            ['el', 'el'],
2217
            [null, 'en'],
2218
            ['es', 'es'],
2219
            ['et', 'et'],
2220
            ['eu', 'eu'],
2221
            ['fa', 'fa'],
2222
            ['fi', 'fi'],
2223
            ['fr', 'fr'],
2224
            ['gl', 'gl'],
2225
            ['he', 'he'],
2226
            ['hr', 'hr'],
2227
            ['hu', 'hu'],
2228
            ['id', 'id'],
2229
            ['is', 'is'],
2230
            ['it', 'it'],
2231
            ['ja', 'ja'],
2232
            ['ka', 'ka'],
2233
            ['ko', 'ko'],
2234
            ['lt', 'lt'],
2235
            ['lv', 'lv'],
2236
            ['mk', 'mk'],
2237
            ['ms', 'ms'],
2238
            ['nb', 'nb'],
2239
            ['nl', 'nl'],
2240
            ['pl', 'pl'],
2241
            ['pt-PT', 'pt'],
2242
            ['pt-BR', 'pt-BR'],
2243
            ['pt-PT', 'pt-PT'],
2244
            ['ro', 'ro'],
2245
            ['rs', 'rs'],
2246
            ['ru', 'ru'],
2247
            ['sk', 'sk'],
2248
            ['sv', 'sv'],
2249
            ['th', 'th'],
2250
            ['tr', 'tr'],
2251
            ['ug-CN', 'ug'],
2252
            ['ug-CN', 'ug-CN'],
2253
            ['uk', 'uk'],
2254
            ['vi', 'vi'],
2255
            ['zh-CN', 'zh'],
2256
            ['zh-CN', 'zh-CN'],
2257
            ['zh-TW', 'zh-TW'],
2258
        ];
2259
    }
2260
2261
    /**
2262
     * @dataProvider select2LocalesProvider
2263
     */
2264
    public function testCanonicalizedLocaleForSelect2(?string $expected, string $original): void
2265
    {
2266
        $this->assertSame($expected, $this->twigExtension->getCanonicalizedLocaleForSelect2($this->mockExtensionContext($original)));
2267
    }
2268
2269
    public function momentLocalesProvider(): array
2270
    {
2271
        return [
2272
            ['af', 'af'],
2273
            ['ar-dz', 'ar-dz'],
2274
            ['ar', 'ar'],
2275
            ['ar-ly', 'ar-ly'],
2276
            ['ar-ma', 'ar-ma'],
2277
            ['ar-sa', 'ar-sa'],
2278
            ['ar-tn', 'ar-tn'],
2279
            ['az', 'az'],
2280
            ['be', 'be'],
2281
            ['bg', 'bg'],
2282
            ['bn', 'bn'],
2283
            ['bo', 'bo'],
2284
            ['br', 'br'],
2285
            ['bs', 'bs'],
2286
            ['ca', 'ca'],
2287
            ['cs', 'cs'],
2288
            ['cv', 'cv'],
2289
            ['cy', 'cy'],
2290
            ['da', 'da'],
2291
            ['de-at', 'de-at'],
2292
            ['de', 'de'],
2293
            ['de', 'de-de'],
2294
            ['dv', 'dv'],
2295
            ['el', 'el'],
2296
            [null, 'en'],
2297
            [null, 'en-us'],
2298
            ['en-au', 'en-au'],
2299
            ['en-ca', 'en-ca'],
2300
            ['en-gb', 'en-gb'],
2301
            ['en-ie', 'en-ie'],
2302
            ['en-nz', 'en-nz'],
2303
            ['eo', 'eo'],
2304
            ['es-do', 'es-do'],
2305
            ['es', 'es-ar'],
2306
            ['es', 'es-mx'],
2307
            ['es', 'es'],
2308
            ['et', 'et'],
2309
            ['eu', 'eu'],
2310
            ['fa', 'fa'],
2311
            ['fi', 'fi'],
2312
            ['fo', 'fo'],
2313
            ['fr-ca', 'fr-ca'],
2314
            ['fr-ch', 'fr-ch'],
2315
            ['fr', 'fr-fr'],
2316
            ['fr', 'fr'],
2317
            ['fy', 'fy'],
2318
            ['gd', 'gd'],
2319
            ['gl', 'gl'],
2320
            ['he', 'he'],
2321
            ['hi', 'hi'],
2322
            ['hr', 'hr'],
2323
            ['hu', 'hu'],
2324
            ['hy-am', 'hy-am'],
2325
            ['id', 'id'],
2326
            ['is', 'is'],
2327
            ['it', 'it'],
2328
            ['ja', 'ja'],
2329
            ['jv', 'jv'],
2330
            ['ka', 'ka'],
2331
            ['kk', 'kk'],
2332
            ['km', 'km'],
2333
            ['ko', 'ko'],
2334
            ['ky', 'ky'],
2335
            ['lb', 'lb'],
2336
            ['lo', 'lo'],
2337
            ['lt', 'lt'],
2338
            ['lv', 'lv'],
2339
            ['me', 'me'],
2340
            ['mi', 'mi'],
2341
            ['mk', 'mk'],
2342
            ['ml', 'ml'],
2343
            ['mr', 'mr'],
2344
            ['ms', 'ms'],
2345
            ['ms-my', 'ms-my'],
2346
            ['my', 'my'],
2347
            ['nb', 'nb'],
2348
            ['ne', 'ne'],
2349
            ['nl-be', 'nl-be'],
2350
            ['nl', 'nl'],
2351
            ['nl', 'nl-nl'],
2352
            ['nn', 'nn'],
2353
            ['pa-in', 'pa-in'],
2354
            ['pl', 'pl'],
2355
            ['pt-br', 'pt-br'],
2356
            ['pt', 'pt'],
2357
            ['ro', 'ro'],
2358
            ['ru', 'ru'],
2359
            ['se', 'se'],
2360
            ['si', 'si'],
2361
            ['sk', 'sk'],
2362
            ['sl', 'sl'],
2363
            ['sq', 'sq'],
2364
            ['sr-cyrl', 'sr-cyrl'],
2365
            ['sr', 'sr'],
2366
            ['ss', 'ss'],
2367
            ['sv', 'sv'],
2368
            ['sw', 'sw'],
2369
            ['ta', 'ta'],
2370
            ['te', 'te'],
2371
            ['tet', 'tet'],
2372
            ['th', 'th'],
2373
            ['tlh', 'tlh'],
2374
            ['tl-ph', 'tl-ph'],
2375
            ['tr', 'tr'],
2376
            ['tzl', 'tzl'],
2377
            ['tzm', 'tzm'],
2378
            ['tzm-latn', 'tzm-latn'],
2379
            ['uk', 'uk'],
2380
            ['uz', 'uz'],
2381
            ['vi', 'vi'],
2382
            ['x-pseudo', 'x-pseudo'],
2383
            ['yo', 'yo'],
2384
            ['zh-cn', 'zh-cn'],
2385
            ['zh-hk', 'zh-hk'],
2386
            ['zh-tw', 'zh-tw'],
2387
        ];
2388
    }
2389
2390
    /**
2391
     * @dataProvider momentLocalesProvider
2392
     */
2393
    public function testCanonicalizedLocaleForMoment(?string $expected, string $original): void
2394
    {
2395
        $this->assertSame($expected, $this->twigExtension->getCanonicalizedLocaleForMoment($this->mockExtensionContext($original)));
2396
    }
2397
2398
    public function testIsGrantedAffirmative(): void
2399
    {
2400
        $this->assertTrue(
2401
            $this->twigExtension->isGrantedAffirmative(['foo', 'bar'])
2402
        );
2403
        $this->assertTrue($this->twigExtension->isGrantedAffirmative('foo'));
2404
        $this->assertTrue($this->twigExtension->isGrantedAffirmative('bar'));
2405
    }
2406
2407
    /**
2408
     * This method generates url part for Twig layout.
2409
     */
2410
    private function buildTwigLikeUrl(array $url): string
2411
    {
2412
        return htmlspecialchars(http_build_query($url, '', '&', PHP_QUERY_RFC3986));
2413
    }
2414
2415
    private function getMethodAsPublic($privateMethod): \ReflectionMethod
2416
    {
2417
        $reflection = new \ReflectionMethod('Sonata\AdminBundle\Twig\Extension\SonataAdminExtension', $privateMethod);
2418
        $reflection->setAccessible(true);
2419
2420
        return $reflection;
2421
    }
2422
2423
    private function removeExtraWhitespace(string $string): string
2424
    {
2425
        return trim(preg_replace(
2426
            '/\s+/',
2427
            ' ',
2428
            $string
2429
        ));
2430
    }
2431
2432
    private function mockExtensionContext(string $locale): array
2433
    {
2434
        $request = $this->createMock(Request::class);
2435
        $request->method('getLocale')->willReturn($locale);
2436
        $appVariable = $this->createMock(AppVariable::class);
2437
        $appVariable->method('getRequest')->willReturn($request);
2438
2439
        return ['app' => $appVariable];
2440
    }
2441
}
2442