Completed
Pull Request — master (#6210)
by Jordi Sala
02:51 queued 10s
created

  A

Complexity

Conditions 1
Paths 1

Size

Total Lines 22

Duplication

Lines 0
Ratio 0 %

Importance

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