Completed
Pull Request — master (#5229)
by Grégoire
30:41
created

testIsGrantedAffirmative()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 8
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 0
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of the Sonata Project package.
7
 *
8
 * (c) Thomas Rabaix <[email protected]>
9
 *
10
 * For the full copyright and license information, please view the LICENSE
11
 * file that was distributed with this source code.
12
 */
13
14
namespace Sonata\AdminBundle\Tests\Twig\Extension;
15
16
use PHPUnit\Framework\TestCase;
17
use Prophecy\Argument;
18
use Psr\Log\LoggerInterface;
19
use Sonata\AdminBundle\Admin\AbstractAdmin;
20
use Sonata\AdminBundle\Admin\AdminInterface;
21
use Sonata\AdminBundle\Admin\FieldDescriptionInterface;
22
use Sonata\AdminBundle\Admin\Pool;
23
use Sonata\AdminBundle\Exception\NoValueException;
24
use Sonata\AdminBundle\Templating\TemplateRegistryInterface;
25
use Sonata\AdminBundle\Tests\Fixtures\Entity\FooToString;
26
use Sonata\AdminBundle\Twig\Extension\SonataAdminExtension;
27
use Symfony\Bridge\Twig\AppVariable;
28
use Symfony\Bridge\Twig\Extension\RoutingExtension;
29
use Symfony\Bridge\Twig\Extension\TranslationExtension;
30
use Symfony\Bridge\Twig\Tests\Extension\Fixtures\StubFilesystemLoader;
31
use Symfony\Component\Config\FileLocator;
32
use Symfony\Component\DependencyInjection\ContainerInterface;
33
use Symfony\Component\HttpFoundation\Request;
34
use Symfony\Component\Routing\Generator\UrlGenerator;
35
use Symfony\Component\Routing\Loader\XmlFileLoader;
36
use Symfony\Component\Routing\RequestContext;
37
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
38
use Symfony\Component\Translation\DependencyInjection\TranslationDumperPass;
39
use Symfony\Component\Translation\Loader\XliffFileLoader;
40
use Symfony\Component\Translation\MessageSelector;
41
use Symfony\Component\Translation\Translator;
42
use Symfony\Component\Translation\TranslatorInterface;
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 \Twig_Environment
58
     */
59
    private $environment;
60
61
    /**
62
     * @var AdminInterface
63
     */
64
    private $admin;
65
66
    /**
67
     * @var AdminInterface
68
     */
69
    private $adminBar;
70
71
    /**
72
     * @var FieldDescriptionInterface
73
     */
74
    private $fieldDescription;
75
76
    /**
77
     * @var \stdClass
78
     */
79
    private $object;
80
81
    /**
82
     * @var Pool
83
     */
84
    private $pool;
85
86
    /**
87
     * @var LoggerInterface
88
     */
89
    private $logger;
90
91
    /**
92
     * @var string[]
93
     */
94
    private $xEditableTypeMapping;
95
96
    /**
97
     * @var TranslatorInterface
98
     */
99
    private $translator;
100
101
    /**
102
     * @var ContainerInterface
103
     */
104
    private $container;
105
106
    /**
107
     * @var TemplateRegistryInterface
108
     */
109
    private $templateRegistry;
110
111
    /**
112
     * @var AuthorizationCheckerInterface
113
     */
114
    private $securityChecker;
115
116
    public function setUp(): void
117
    {
118
        date_default_timezone_set('Europe/London');
119
120
        $container = $this->getMockForAbstractClass(ContainerInterface::class);
121
122
        $this->pool = new Pool($container, '', '');
123
        $this->pool->setAdminServiceIds(['sonata_admin_foo_service']);
124
        $this->pool->setAdminClasses(['fooClass' => ['sonata_admin_foo_service']]);
125
126
        $this->logger = $this->getMockForAbstractClass(LoggerInterface::class);
127
        $this->xEditableTypeMapping = [
0 ignored issues
show
Documentation Bug introduced by
It seems like array('choice' => 'selec...umber', 'url' => 'url') of type array<string,string,{"ch...tring","url":"string"}> is incompatible with the declared type array<integer,string> of property $xEditableTypeMapping.

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

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

Loading history...
128
            'choice' => 'select',
129
            'boolean' => 'select',
130
            'text' => 'text',
131
            'textarea' => 'textarea',
132
            'html' => 'textarea',
133
            'email' => 'email',
134
            'string' => 'text',
135
            'smallint' => 'text',
136
            'bigint' => 'text',
137
            'integer' => 'number',
138
            'decimal' => 'number',
139
            'currency' => 'number',
140
            'percent' => 'number',
141
            'url' => 'url',
142
        ];
143
144
        // translation extension
145
        $translator = new Translator(
146
            'en',
147
            // NEXT_MAJOR: simplify this when dropping symfony < 3.4
148
            class_exists(TranslationDumperPass::class) ? null : new MessageSelector()
0 ignored issues
show
Documentation introduced by
class_exists(\Symfony\Co...ation\MessageSelector() is of type object<Symfony\Component...lation\MessageSelector>, but the function expects a null|object<Symfony\Comp...sageFormatterInterface>.

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...
149
        );
150
        $translator->addLoader('xlf', new XliffFileLoader());
151
        $translator->addResource(
152
            'xlf',
153
            __DIR__.'/../../../src/Resources/translations/SonataAdminBundle.en.xliff',
154
            'en',
155
            'SonataAdminBundle'
156
        );
157
158
        $this->translator = $translator;
159
160
        $this->templateRegistry = $this->prophesize(TemplateRegistryInterface::class);
161
        $this->container = $this->prophesize(ContainerInterface::class);
162
        $this->container->get('sonata_admin_foo_service.template_registry')->willReturn($this->templateRegistry->reveal());
163
164
        $this->securityChecker = $this->prophesize(AuthorizationCheckerInterface::class);
165
        $this->securityChecker->isGranted(['foo', 'bar'], null)->willReturn(false);
166
        $this->securityChecker->isGranted(Argument::type('string'), null)->willReturn(true);
167
168
        $this->twigExtension = new SonataAdminExtension(
169
            $this->pool, $this->logger, $this->translator, $this->container->reveal(), $this->securityChecker->reveal()
170
        );
171
        $this->twigExtension->setXEditableTypeMapping($this->xEditableTypeMapping);
172
173
        $request = $this->createMock(Request::class);
174
        $request->expects($this->any())->method('get')->with('_sonata_admin')->willReturn('sonata_admin_foo_service');
175
176
        $loader = new StubFilesystemLoader([
177
            __DIR__.'/../../../src/Resources/views/CRUD',
178
        ]);
179
        $loader->addPath(__DIR__.'/../../../src/Resources/views/', 'SonataAdmin');
180
181
        $this->environment = new \Twig_Environment($loader, [
182
            'strict_variables' => true,
183
            'cache' => false,
184
            'autoescape' => 'html',
185
            'optimizations' => 0,
186
        ]);
187
        $this->environment->addExtension($this->twigExtension);
188
        $this->environment->addExtension(new TranslationExtension($translator));
189
        $this->environment->addExtension(new FakeTemplateRegistryExtension());
190
191
        // routing extension
192
        $xmlFileLoader = new XmlFileLoader(new FileLocator([__DIR__.'/../../../src/Resources/config/routing']));
193
        $routeCollection = $xmlFileLoader->load('sonata_admin.xml');
194
195
        $xmlFileLoader = new XmlFileLoader(new FileLocator([__DIR__.'/../../Fixtures/Resources/config/routing']));
196
        $testRouteCollection = $xmlFileLoader->load('routing.xml');
197
198
        $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...
199
        $requestContext = new RequestContext();
200
        $urlGenerator = new UrlGenerator($routeCollection, $requestContext);
201
        $this->environment->addExtension(new RoutingExtension($urlGenerator));
202
        $this->environment->addExtension(new \Twig_Extensions_Extension_Text());
203
204
        // initialize object
205
        $this->object = new \stdClass();
206
207
        // initialize admin
208
        $this->admin = $this->createMock(AbstractAdmin::class);
209
210
        $this->admin->expects($this->any())
211
            ->method('getCode')
212
            ->will($this->returnValue('sonata_admin_foo_service'));
213
214
        $this->admin->expects($this->any())
215
            ->method('id')
216
            ->with($this->equalTo($this->object))
217
            ->will($this->returnValue(12345));
218
219
        $this->admin->expects($this->any())
220
            ->method('getNormalizedIdentifier')
221
            ->with($this->equalTo($this->object))
222
            ->will($this->returnValue(12345));
223
224
        $this->admin->expects($this->any())
225
            ->method('trans')
226
            ->will($this->returnCallback(function ($id, $parameters = [], $domain = null) use ($translator) {
227
                return $translator->trans($id, $parameters, $domain);
228
            }));
229
230
        $this->adminBar = $this->createMock(AbstractAdmin::class);
231
        $this->adminBar->expects($this->any())
232
            ->method('hasAccess')
233
            ->will($this->returnValue(true));
234
        $this->adminBar->expects($this->any())
235
            ->method('getNormalizedIdentifier')
236
            ->with($this->equalTo($this->object))
237
            ->will($this->returnValue(12345));
238
239
        $container->expects($this->any())
240
            ->method('get')
241
            ->will($this->returnCallback(function ($id) {
242
                if ('sonata_admin_foo_service' == $id) {
243
                    return $this->admin;
244
                } elseif ('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->expects($this->any())
253
            ->method('getName')
254
            ->will($this->returnValue('fd_name'));
255
256
        $this->fieldDescription->expects($this->any())
257
            ->method('getAdmin')
258
            ->will($this->returnValue($this->admin));
259
260
        $this->fieldDescription->expects($this->any())
261
            ->method('getLabel')
262
            ->will($this->returnValue('Data'));
263
    }
264
265
    /**
266
     * @group legacy
267
     * @expectedDeprecation The Sonata\AdminBundle\Admin\AbstractAdmin::getTemplate method is deprecated (since 3.34, will be dropped in 4.0. Use TemplateRegistry services instead).
268
     * @dataProvider getRenderListElementTests
269
     */
270
    public function testRenderListElement($expected, $type, $value, array $options): void
271
    {
272
        $this->admin->expects($this->any())
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...
273
            ->method('getPersistentParameters')
274
            ->will($this->returnValue(['context' => 'foo']));
275
276
        $this->admin->expects($this->any())
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...
277
            ->method('hasAccess')
278
            ->will($this->returnValue(true));
279
280
        // NEXT_MAJOR: Remove this line
281
        $this->admin->expects($this->any())
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...
282
            ->method('getTemplate')
283
            ->with('base_list_field')
284
            ->willReturn('@SonataAdmin/CRUD/base_list_field.html.twig');
285
286
        $this->templateRegistry->getTemplate('base_list_field')->willReturn('@SonataAdmin/CRUD/base_list_field.html.twig');
0 ignored issues
show
Bug introduced by
The method willReturn cannot be called on $this->templateRegistry-...late('base_list_field') (of type string).

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

Loading history...
287
288
        $this->fieldDescription->expects($this->any())
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...
289
            ->method('getValue')
290
            ->will($this->returnValue($value));
291
292
        $this->fieldDescription->expects($this->any())
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...
293
            ->method('getType')
294
            ->will($this->returnValue($type));
295
296
        $this->fieldDescription->expects($this->any())
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...
297
            ->method('getOptions')
298
            ->will($this->returnValue($options));
299
300
        $this->fieldDescription->expects($this->any())
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...
301
            ->method('getOption')
302
            ->will($this->returnCallback(function ($name, $default = null) use ($options) {
303
                return $options[$name] ?? $default;
304
            }));
305
306
        $this->fieldDescription->expects($this->any())
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...
307
            ->method('getTemplate')
308
            ->will($this->returnCallback(function () use ($type) {
309
                switch ($type) {
310
                    case 'string':
311
                        return '@SonataAdmin/CRUD/list_string.html.twig';
312
                    case 'boolean':
313
                        return '@SonataAdmin/CRUD/list_boolean.html.twig';
314
                    case 'datetime':
315
                        return '@SonataAdmin/CRUD/list_datetime.html.twig';
316
                    case 'date':
317
                        return '@SonataAdmin/CRUD/list_date.html.twig';
318
                    case 'time':
319
                        return '@SonataAdmin/CRUD/list_time.html.twig';
320
                    case 'currency':
321
                        return '@SonataAdmin/CRUD/list_currency.html.twig';
322
                    case 'percent':
323
                        return '@SonataAdmin/CRUD/list_percent.html.twig';
324
                    case 'email':
325
                        return '@SonataAdmin/CRUD/list_email.html.twig';
326
                    case 'choice':
327
                        return '@SonataAdmin/CRUD/list_choice.html.twig';
328
                    case 'array':
329
                        return '@SonataAdmin/CRUD/list_array.html.twig';
330
                    case 'trans':
331
                        return '@SonataAdmin/CRUD/list_trans.html.twig';
332
                    case 'url':
333
                        return '@SonataAdmin/CRUD/list_url.html.twig';
334
                    case 'html':
335
                        return '@SonataAdmin/CRUD/list_html.html.twig';
336
                    case 'nonexistent':
337
                        // template doesn't exist
338
                        return '@SonataAdmin/CRUD/list_nonexistent_template.html.twig';
339
                    default:
340
                        return false;
341
                }
342
            }));
343
344
        $this->assertSame(
345
            $this->removeExtraWhitespace($expected),
346
            $this->removeExtraWhitespace($this->twigExtension->renderListElement(
347
                $this->environment,
0 ignored issues
show
Compatibility introduced by
$this->environment of type object<Twig_Environment> is not a sub-type of object<Twig\Environment>. It seems like you assume a child class of the class Twig_Environment to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
348
                $this->object,
349
                $this->fieldDescription
350
            ))
351
        );
352
    }
353
354
    public function getRenderListElementTests()
355
    {
356
        return [
357
            [
358
                '<td class="sonata-ba-list-field sonata-ba-list-field-string" objectId="12345"> Example </td>',
359
                'string',
360
                'Example',
361
                [],
362
            ],
363
            [
364
                '<td class="sonata-ba-list-field sonata-ba-list-field-string" objectId="12345"> </td>',
365
                'string',
366
                null,
367
                [],
368
            ],
369
            [
370
                '<td class="sonata-ba-list-field sonata-ba-list-field-text" objectId="12345"> Example </td>',
371
                'text',
372
                'Example',
373
                [],
374
            ],
375
            [
376
                '<td class="sonata-ba-list-field sonata-ba-list-field-text" objectId="12345"> </td>',
377
                'text',
378
                null,
379
                [],
380
            ],
381
            [
382
                '<td class="sonata-ba-list-field sonata-ba-list-field-textarea" objectId="12345"> Example </td>',
383
                'textarea',
384
                'Example',
385
                [],
386
            ],
387
            [
388
                '<td class="sonata-ba-list-field sonata-ba-list-field-textarea" objectId="12345"> </td>',
389
                'textarea',
390
                null,
391
                [],
392
            ],
393
            'datetime field' => [
394
                '<td class="sonata-ba-list-field sonata-ba-list-field-datetime" objectId="12345">
395
                    December 24, 2013 10:11
396
                </td>',
397
                'datetime',
398
                new \DateTime('2013-12-24 10:11:12', new \DateTimeZone('Europe/London')),
399
                [],
400
            ],
401
            [
402
                '<td class="sonata-ba-list-field sonata-ba-list-field-datetime" objectId="12345">
403
                    December 24, 2013 18:11
404
                </td>',
405
                'datetime',
406
                new \DateTime('2013-12-24 10:11:12', new \DateTimeZone('UTC')),
407
                ['timezone' => 'Asia/Hong_Kong'],
408
            ],
409
            [
410
                '<td class="sonata-ba-list-field sonata-ba-list-field-datetime" objectId="12345"> &nbsp; </td>',
411
                'datetime',
412
                null,
413
                [],
414
            ],
415
            [
416
                '<td class="sonata-ba-list-field sonata-ba-list-field-datetime" objectId="12345">
417
                    24.12.2013 10:11:12
418
                </td>',
419
                'datetime',
420
                new \DateTime('2013-12-24 10:11:12', new \DateTimeZone('Europe/London')),
421
                ['format' => 'd.m.Y H:i:s'],
422
            ],
423
            [
424
                '<td class="sonata-ba-list-field sonata-ba-list-field-datetime" objectId="12345"> &nbsp; </td>',
425
                'datetime',
426
                null,
427
                ['format' => 'd.m.Y H:i:s'],
428
            ],
429
            [
430
                '<td class="sonata-ba-list-field sonata-ba-list-field-datetime" objectId="12345">
431
                    24.12.2013 18:11:12
432
                </td>',
433
                'datetime',
434
                new \DateTime('2013-12-24 10:11:12', new \DateTimeZone('UTC')),
435
                ['format' => 'd.m.Y H:i:s', 'timezone' => 'Asia/Hong_Kong'],
436
            ],
437
            [
438
                '<td class="sonata-ba-list-field sonata-ba-list-field-datetime" objectId="12345"> &nbsp; </td>',
439
                'datetime',
440
                null,
441
                ['format' => 'd.m.Y H:i:s', 'timezone' => 'Asia/Hong_Kong'],
442
            ],
443
            [
444
                '<td class="sonata-ba-list-field sonata-ba-list-field-date" objectId="12345"> December 24, 2013 </td>',
445
                'date',
446
                new \DateTime('2013-12-24 10:11:12', new \DateTimeZone('Europe/London')),
447
                [],
448
            ],
449
            [
450
                '<td class="sonata-ba-list-field sonata-ba-list-field-date" objectId="12345"> &nbsp; </td>',
451
                'date',
452
                null,
453
                [],
454
            ],
455
            [
456
                '<td class="sonata-ba-list-field sonata-ba-list-field-date" objectId="12345"> 24.12.2013 </td>',
457
                'date',
458
                new \DateTime('2013-12-24 10:11:12', new \DateTimeZone('Europe/London')),
459
                ['format' => 'd.m.Y'],
460
            ],
461
            [
462
                '<td class="sonata-ba-list-field sonata-ba-list-field-date" objectId="12345"> &nbsp; </td>',
463
                'date',
464
                null,
465
                ['format' => 'd.m.Y'],
466
            ],
467
            [
468
                '<td class="sonata-ba-list-field sonata-ba-list-field-time" objectId="12345"> 10:11:12 </td>',
469
                'time',
470
                new \DateTime('2013-12-24 10:11:12', new \DateTimeZone('Europe/London')),
471
                [],
472
            ],
473
            [
474
                '<td class="sonata-ba-list-field sonata-ba-list-field-time" objectId="12345"> 18:11:12 </td>',
475
                'time',
476
                new \DateTime('2013-12-24 10:11:12', new \DateTimeZone('UTC')),
477
                ['timezone' => 'Asia/Hong_Kong'],
478
            ],
479
            [
480
                '<td class="sonata-ba-list-field sonata-ba-list-field-time" objectId="12345"> &nbsp; </td>',
481
                'time',
482
                null,
483
                [],
484
            ],
485
            [
486
                '<td class="sonata-ba-list-field sonata-ba-list-field-number" objectId="12345"> 10.746135 </td>',
487
                'number', 10.746135,
488
                [],
489
            ],
490
            [
491
                '<td class="sonata-ba-list-field sonata-ba-list-field-number" objectId="12345"> </td>',
492
                'number',
493
                null,
494
                [],
495
            ],
496
            [
497
                '<td class="sonata-ba-list-field sonata-ba-list-field-integer" objectId="12345"> 5678 </td>',
498
                'integer',
499
                5678,
500
                [],
501
            ],
502
            [
503
                '<td class="sonata-ba-list-field sonata-ba-list-field-integer" objectId="12345"> </td>',
504
                'integer',
505
                null,
506
                [],
507
            ],
508
            [
509
                '<td class="sonata-ba-list-field sonata-ba-list-field-percent" objectId="12345"> 1074.6135 % </td>',
510
                'percent',
511
                10.746135,
512
                [],
513
            ],
514
            [
515
                '<td class="sonata-ba-list-field sonata-ba-list-field-percent" objectId="12345"> 0 % </td>',
516
                'percent',
517
                null,
518
                [],
519
            ],
520
            [
521
                '<td class="sonata-ba-list-field sonata-ba-list-field-currency" objectId="12345"> EUR 10.746135 </td>',
522
                'currency',
523
                10.746135,
524
                ['currency' => 'EUR'],
525
            ],
526
            [
527
                '<td class="sonata-ba-list-field sonata-ba-list-field-currency" objectId="12345"> </td>',
528
                'currency',
529
                null,
530
                ['currency' => 'EUR'],
531
            ],
532
            [
533
                '<td class="sonata-ba-list-field sonata-ba-list-field-currency" objectId="12345"> GBP 51.23456 </td>',
534
                'currency',
535
                51.23456,
536
                ['currency' => 'GBP'],
537
            ],
538
            [
539
                '<td class="sonata-ba-list-field sonata-ba-list-field-currency" objectId="12345"> </td>',
540
                'currency',
541
                null,
542
                ['currency' => 'GBP'],
543
            ],
544
            [
545
                '<td class="sonata-ba-list-field sonata-ba-list-field-email" objectId="12345"> &nbsp; </td>',
546
                'email',
547
                null,
548
                [],
549
            ],
550
            [
551
                '<td class="sonata-ba-list-field sonata-ba-list-field-email" objectId="12345"> <a href="mailto:[email protected]">[email protected]</a> </td>',
552
                'email',
553
                '[email protected]',
554
                [],
555
            ],
556
            [
557
                '<td class="sonata-ba-list-field sonata-ba-list-field-email" objectId="12345">
558
                    <a href="mailto:[email protected]">[email protected]</a> </td>',
559
                'email',
560
                '[email protected]',
561
                ['as_string' => false],
562
            ],
563
            [
564
                '<td class="sonata-ba-list-field sonata-ba-list-field-email" objectId="12345"> [email protected] </td>',
565
                'email',
566
                '[email protected]',
567
                ['as_string' => true],
568
            ],
569
            [
570
                '<td class="sonata-ba-list-field sonata-ba-list-field-email" objectId="12345">
571
                    <a href="mailto:[email protected]?'.$this->buildTwigLikeUrl(['subject' => 'Main Theme', 'body' => 'Message Body']).'">[email protected]</a>  </td>',
572
                'email',
573
                '[email protected]',
574
                ['subject' => 'Main Theme', 'body' => 'Message Body'],
575
            ],
576
            [
577
                '<td class="sonata-ba-list-field sonata-ba-list-field-email" objectId="12345">
578
                    <a href="mailto:[email protected]?'.$this->buildTwigLikeUrl(['subject' => 'Main Theme']).'">[email protected]</a>  </td>',
579
                'email',
580
                '[email protected]',
581
                ['subject' => 'Main Theme'],
582
            ],
583
            [
584
                '<td class="sonata-ba-list-field sonata-ba-list-field-email" objectId="12345">
585
                    <a href="mailto:[email protected]?'.$this->buildTwigLikeUrl(['body' => 'Message Body']).'">[email protected]</a>  </td>',
586
                'email',
587
                '[email protected]',
588
                ['body' => 'Message Body'],
589
            ],
590
            [
591
                '<td class="sonata-ba-list-field sonata-ba-list-field-email" objectId="12345"> [email protected] </td>',
592
                'email',
593
                '[email protected]',
594
                ['as_string' => true, 'subject' => 'Main Theme', 'body' => 'Message Body'],
595
            ],
596
            [
597
                '<td class="sonata-ba-list-field sonata-ba-list-field-email" objectId="12345"> [email protected] </td>',
598
                'email',
599
                '[email protected]',
600
                ['as_string' => true, 'body' => 'Message Body'],
601
            ],
602
            [
603
                '<td class="sonata-ba-list-field sonata-ba-list-field-email" objectId="12345"> [email protected] </td>',
604
                'email',
605
                '[email protected]',
606
                ['as_string' => true, 'subject' => 'Main Theme'],
607
            ],
608
            [
609
                '<td class="sonata-ba-list-field sonata-ba-list-field-array" objectId="12345">
610
                    [1 => First] [2 => Second]
611
                </td>',
612
                'array',
613
                [1 => 'First', 2 => 'Second'],
614
                [],
615
            ],
616
            [
617
                '<td class="sonata-ba-list-field sonata-ba-list-field-array" objectId="12345"> </td>',
618
                'array',
619
                null,
620
                [],
621
            ],
622
            [
623
                '<td class="sonata-ba-list-field sonata-ba-list-field-boolean" objectId="12345">
624
                    <span class="label label-success">yes</span>
625
                </td>',
626
                'boolean',
627
                true,
628
                ['editable' => false],
629
            ],
630
            [
631
                '<td class="sonata-ba-list-field sonata-ba-list-field-boolean" objectId="12345">
632
                    <span class="label label-danger">no</span>
633
                </td>',
634
                'boolean',
635
                false,
636
                ['editable' => false],
637
            ],
638
            [
639
                '<td class="sonata-ba-list-field sonata-ba-list-field-boolean" objectId="12345">
640
                    <span class="label label-danger">no</span>
641
                </td>',
642
                'boolean',
643
                null,
644
                ['editable' => false],
645
            ],
646
            [
647
                <<<'EOT'
648
<td class="sonata-ba-list-field sonata-ba-list-field-boolean" objectId="12345">
649
    <span
650
        class="x-editable"
651
        data-type="select"
652
        data-value="1"
653
        data-title="Data"
654
        data-pk="12345"
655
        data-url="/core/set-object-field-value?context=list&amp;field=fd_name&amp;objectId=12345&amp;code=sonata_admin_foo_service"
656
        data-source="[{value: 0, text: 'no'},{value: 1, text: 'yes'}]"
657
    >
658
        <span class="label label-success">yes</span>
659
    </span>
660
</td>
661
EOT
662
            ,
663
                'boolean',
664
                true,
665
                ['editable' => true],
666
            ],
667
            [
668
                <<<'EOT'
669
<td class="sonata-ba-list-field sonata-ba-list-field-boolean" objectId="12345">
670
    <span
671
        class="x-editable"
672
        data-type="select"
673
        data-value="0"
674
        data-title="Data"
675
        data-pk="12345"
676
        data-url="/core/set-object-field-value?context=list&amp;field=fd_name&amp;objectId=12345&amp;code=sonata_admin_foo_service"
677
        data-source="[{value: 0, text: 'no'},{value: 1, text: 'yes'}]"
678
    >
679
    <span class="label label-danger">no</span> </span>
680
</td>
681
EOT
682
                ,
683
                'boolean',
684
                false,
685
                ['editable' => true],
686
            ],
687
            [
688
                <<<'EOT'
689
<td class="sonata-ba-list-field sonata-ba-list-field-boolean" objectId="12345">
690
    <span
691
        class="x-editable"
692
        data-type="select"
693
        data-value="0"
694
        data-title="Data"
695
        data-pk="12345"
696
        data-url="/core/set-object-field-value?context=list&amp;field=fd_name&amp;objectId=12345&amp;code=sonata_admin_foo_service"
697
        data-source="[{value: 0, text: 'no'},{value: 1, text: 'yes'}]" >
698
        <span class="label label-danger">no</span> </span>
699
</td>
700
EOT
701
                ,
702
                'boolean',
703
                null,
704
                ['editable' => true],
705
            ],
706
            [
707
                '<td class="sonata-ba-list-field sonata-ba-list-field-trans" objectId="12345"> Delete </td>',
708
                'trans',
709
                'action_delete',
710
                ['catalogue' => 'SonataAdminBundle'],
711
            ],
712
            [
713
                '<td class="sonata-ba-list-field sonata-ba-list-field-trans" objectId="12345"> </td>',
714
                'trans',
715
                null,
716
                ['catalogue' => 'SonataAdminBundle'],
717
            ],
718
            [
719
                '<td class="sonata-ba-list-field sonata-ba-list-field-trans" objectId="12345"> Delete </td>',
720
                'trans',
721
                'action_delete',
722
                ['format' => '%s', 'catalogue' => 'SonataAdminBundle'],
723
            ],
724
            [
725
                '<td class="sonata-ba-list-field sonata-ba-list-field-trans" objectId="12345">
726
                action.action_delete
727
                </td>',
728
                'trans',
729
                'action_delete',
730
                ['format' => 'action.%s'],
731
            ],
732
            [
733
                '<td class="sonata-ba-list-field sonata-ba-list-field-trans" objectId="12345">
734
                action.action_delete
735
                </td>',
736
                'trans',
737
                'action_delete',
738
                ['format' => 'action.%s', 'catalogue' => 'SonataAdminBundle'],
739
            ],
740
            [
741
                '<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345"> Status1 </td>',
742
                'choice',
743
                'Status1',
744
                [],
745
            ],
746
            [
747
                '<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345"> Status1 </td>',
748
                'choice',
749
                ['Status1'],
750
                ['choices' => [], 'multiple' => true],
751
            ],
752
            [
753
                '<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345"> Alias1 </td>',
754
                'choice',
755
                'Status1',
756
                ['choices' => ['Status1' => 'Alias1', 'Status2' => 'Alias2', 'Status3' => 'Alias3']],
757
            ],
758
            [
759
                '<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345"> </td>',
760
                'choice',
761
                null,
762
                ['choices' => ['Status1' => 'Alias1', 'Status2' => 'Alias2', 'Status3' => 'Alias3']],
763
            ],
764
            [
765
                '<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345">
766
                NoValidKeyInChoices
767
                </td>',
768
                'choice',
769
                'NoValidKeyInChoices',
770
                ['choices' => ['Status1' => 'Alias1', 'Status2' => 'Alias2', 'Status3' => 'Alias3']],
771
            ],
772
            [
773
                '<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345"> Delete </td>',
774
                'choice',
775
                'Foo',
776
                ['catalogue' => 'SonataAdminBundle', 'choices' => [
777
                    'Foo' => 'action_delete',
778
                    'Status2' => 'Alias2',
779
                    'Status3' => 'Alias3',
780
                ]],
781
            ],
782
            [
783
                '<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345"> Alias1, Alias3 </td>',
784
                'choice',
785
                ['Status1', 'Status3'],
786
                ['choices' => [
787
                    'Status1' => 'Alias1',
788
                    'Status2' => 'Alias2',
789
                    'Status3' => 'Alias3',
790
                ], 'multiple' => true], ],
791
            [
792
                '<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345"> Alias1 | Alias3 </td>',
793
                'choice',
794
                ['Status1', 'Status3'],
795
                ['choices' => [
796
                    'Status1' => 'Alias1',
797
                    'Status2' => 'Alias2',
798
                    'Status3' => 'Alias3',
799
                ], 'multiple' => true, 'delimiter' => ' | '], ],
800
            [
801
                '<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345"> </td>',
802
                'choice',
803
                null,
804
                ['choices' => [
805
                    'Status1' => 'Alias1',
806
                    'Status2' => 'Alias2',
807
                    'Status3' => 'Alias3',
808
                ], 'multiple' => true],
809
            ],
810
            [
811
                '<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345">
812
                NoValidKeyInChoices
813
                </td>',
814
                'choice',
815
                ['NoValidKeyInChoices'],
816
                ['choices' => [
817
                    'Status1' => 'Alias1',
818
                    'Status2' => 'Alias2',
819
                    'Status3' => 'Alias3',
820
                ], 'multiple' => true],
821
            ],
822
            [
823
                '<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345">
824
                NoValidKeyInChoices, Alias2
825
                </td>',
826
                'choice',
827
                ['NoValidKeyInChoices', 'Status2'],
828
                ['choices' => [
829
                    'Status1' => 'Alias1',
830
                    'Status2' => 'Alias2',
831
                    'Status3' => 'Alias3',
832
                ], 'multiple' => true],
833
            ],
834
            [
835
                '<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345"> Delete, Alias3 </td>',
836
                'choice',
837
                ['Foo', 'Status3'],
838
                ['catalogue' => 'SonataAdminBundle', 'choices' => [
839
                    'Foo' => 'action_delete',
840
                    'Status2' => 'Alias2',
841
                    'Status3' => 'Alias3',
842
                ], 'multiple' => true],
843
            ],
844
            [
845
                '<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345">
846
                &lt;b&gt;Alias1&lt;/b&gt;, &lt;b&gt;Alias3&lt;/b&gt;
847
            </td>',
848
                'choice',
849
                ['Status1', 'Status3'],
850
                ['choices' => [
851
                    'Status1' => '<b>Alias1</b>',
852
                    'Status2' => '<b>Alias2</b>',
853
                    'Status3' => '<b>Alias3</b>',
854
                ], 'multiple' => true], ],
855
            [
856
                <<<'EOT'
857
<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345">
858
    <span
859
        class="x-editable"
860
        data-type="select"
861
        data-value="Status1"
862
        data-title="Data"
863
        data-pk="12345"
864
        data-url="/core/set-object-field-value?context=list&amp;field=fd_name&amp;objectId=12345&amp;code=sonata_admin_foo_service"
865
        data-source="[]"
866
    >
867
        Status1
868
    </span>
869
</td>
870
EOT
871
                ,
872
                'choice',
873
                'Status1',
874
                ['editable' => true],
875
            ],
876
            [
877
                <<<'EOT'
878
<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345">
879
    <span
880
        class="x-editable"
881
        data-type="select"
882
        data-value="Status1"
883
        data-title="Data"
884
        data-pk="12345"
885
        data-url="/core/set-object-field-value?context=list&amp;field=fd_name&amp;objectId=12345&amp;code=sonata_admin_foo_service"
886
        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;}]" >
887
        Alias1 </span>
888
</td>
889
EOT
890
                ,
891
                'choice',
892
                'Status1',
893
                [
894
                    'editable' => true,
895
                    'choices' => [
896
                        'Status1' => 'Alias1',
897
                        'Status2' => 'Alias2',
898
                        'Status3' => 'Alias3',
899
                    ],
900
                ],
901
            ],
902
            [
903
                <<<'EOT'
904
<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345">
905
    <span
906
        class="x-editable"
907
        data-type="select"
908
        data-value=""
909
        data-title="Data"
910
        data-pk="12345"
911
        data-url="/core/set-object-field-value?context=list&amp;field=fd_name&amp;objectId=12345&amp;code=sonata_admin_foo_service"
912
        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;}]" >
913
914
    </span>
915
</td>
916
EOT
917
                ,
918
                'choice',
919
                null,
920
                [
921
                    'editable' => true,
922
                    'choices' => [
923
                        'Status1' => 'Alias1',
924
                        'Status2' => 'Alias2',
925
                        'Status3' => 'Alias3',
926
                    ],
927
                ],
928
            ],
929
            [
930
                <<<'EOT'
931
<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345">
932
    <span
933
        class="x-editable"
934
        data-type="select"
935
        data-value="NoValidKeyInChoices"
936
        data-title="Data" data-pk="12345"
937
        data-url="/core/set-object-field-value?context=list&amp;field=fd_name&amp;objectId=12345&amp;code=sonata_admin_foo_service"
938
        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;}]" >
939
        NoValidKeyInChoices
940
    </span>
941
</td>
942
EOT
943
                ,
944
                'choice',
945
                'NoValidKeyInChoices',
946
                [
947
                    'editable' => true,
948
                    'choices' => [
949
                        'Status1' => 'Alias1',
950
                        'Status2' => 'Alias2',
951
                        'Status3' => 'Alias3',
952
                    ],
953
                ],
954
            ],
955
            [
956
                <<<'EOT'
957
<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345">
958
    <span
959
        class="x-editable"
960
        data-type="select"
961
        data-value="Foo"
962
        data-title="Data"
963
        data-pk="12345"
964
        data-url="/core/set-object-field-value?context=list&amp;field=fd_name&amp;objectId=12345&amp;code=sonata_admin_foo_service"
965
        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;}]" >
966
         Delete
967
    </span>
968
</td>
969
EOT
970
                ,
971
                'choice',
972
                'Foo',
973
                [
974
                    'editable' => true,
975
                    'catalogue' => 'SonataAdminBundle',
976
                    'choices' => [
977
                        'Foo' => 'action_delete',
978
                        'Status2' => 'Alias2',
979
                        'Status3' => 'Alias3',
980
                    ],
981
                ],
982
            ],
983
            [
984
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345"> &nbsp; </td>',
985
                'url',
986
                null,
987
                [],
988
            ],
989
            [
990
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345"> &nbsp; </td>',
991
                'url',
992
                null,
993
                ['url' => 'http://example.com'],
994
            ],
995
            [
996
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345"> &nbsp; </td>',
997
                'url',
998
                null,
999
                ['route' => ['name' => 'sonata_admin_foo']],
1000
            ],
1001
            [
1002
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
1003
                <a href="http://example.com">http://example.com</a>
1004
                </td>',
1005
                'url',
1006
                'http://example.com',
1007
                [],
1008
            ],
1009
            [
1010
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
1011
                <a href="https://example.com">https://example.com</a>
1012
                </td>',
1013
                'url',
1014
                'https://example.com',
1015
                [],
1016
            ],
1017
            [
1018
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
1019
                <a href="https://example.com" target="_blank">https://example.com</a>
1020
                </td>',
1021
                'url',
1022
                'https://example.com',
1023
                ['attributes' => ['target' => '_blank']],
1024
            ],
1025
            [
1026
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
1027
                <a href="https://example.com" target="_blank" class="fooLink">https://example.com</a>
1028
                </td>',
1029
                'url',
1030
                'https://example.com',
1031
                ['attributes' => ['target' => '_blank', 'class' => 'fooLink']],
1032
            ],
1033
            [
1034
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
1035
                <a href="http://example.com">example.com</a>
1036
                </td>',
1037
                'url',
1038
                'http://example.com',
1039
                ['hide_protocol' => true],
1040
            ],
1041
            [
1042
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
1043
                <a href="https://example.com">example.com</a>
1044
                </td>',
1045
                'url',
1046
                'https://example.com',
1047
                ['hide_protocol' => true],
1048
            ],
1049
            [
1050
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
1051
                <a href="http://example.com">http://example.com</a>
1052
                </td>',
1053
                'url',
1054
                'http://example.com',
1055
                ['hide_protocol' => false],
1056
            ],
1057
            [
1058
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
1059
                <a href="https://example.com">https://example.com</a>
1060
                </td>',
1061
                'url',
1062
                'https://example.com',
1063
                ['hide_protocol' => false],
1064
            ],
1065
            [
1066
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
1067
                <a href="http://example.com">Foo</a>
1068
                </td>',
1069
                'url',
1070
                'Foo',
1071
                ['url' => 'http://example.com'],
1072
            ],
1073
            [
1074
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
1075
                <a href="http://example.com">&lt;b&gt;Foo&lt;/b&gt;</a>
1076
                </td>',
1077
                'url',
1078
                '<b>Foo</b>',
1079
                ['url' => 'http://example.com'],
1080
            ],
1081
            [
1082
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
1083
                <a href="/foo">Foo</a>
1084
                </td>',
1085
                'url',
1086
                'Foo',
1087
                ['route' => ['name' => 'sonata_admin_foo']],
1088
            ],
1089
            [
1090
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
1091
                <a href="http://localhost/foo">Foo</a>
1092
                </td>',
1093
                'url',
1094
                'Foo',
1095
                ['route' => ['name' => 'sonata_admin_foo', 'absolute' => true]],
1096
            ],
1097
            [
1098
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
1099
                <a href="/foo">foo/bar?a=b&amp;c=123456789</a>
1100
                </td>',
1101
                'url',
1102
                'http://foo/bar?a=b&c=123456789',
1103
                ['route' => ['name' => 'sonata_admin_foo'],
1104
                'hide_protocol' => true, ],
1105
            ],
1106
            [
1107
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
1108
                <a href="http://localhost/foo">foo/bar?a=b&amp;c=123456789</a>
1109
                </td>',
1110
                'url',
1111
                'http://foo/bar?a=b&c=123456789',
1112
                [
1113
                    'route' => ['name' => 'sonata_admin_foo', 'absolute' => true],
1114
                    'hide_protocol' => true,
1115
                ],
1116
            ],
1117
            [
1118
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
1119
                <a href="/foo/abcd/efgh?param3=ijkl">Foo</a>
1120
                </td>',
1121
                'url',
1122
                'Foo',
1123
                [
1124
                    'route' => ['name' => 'sonata_admin_foo_param',
1125
                    'parameters' => ['param1' => 'abcd', 'param2' => 'efgh', 'param3' => 'ijkl'], ],
1126
                ],
1127
            ],
1128
            [
1129
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
1130
                <a href="http://localhost/foo/abcd/efgh?param3=ijkl">Foo</a>
1131
                </td>',
1132
                'url',
1133
                'Foo',
1134
                [
1135
                    'route' => ['name' => 'sonata_admin_foo_param',
1136
                    'absolute' => true,
1137
                    'parameters' => ['param1' => 'abcd', 'param2' => 'efgh', 'param3' => 'ijkl'], ],
1138
                ],
1139
            ],
1140
            [
1141
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
1142
                <a href="/foo/obj/abcd/12345/efgh?param3=ijkl">Foo</a>
1143
                </td>',
1144
                'url',
1145
                'Foo',
1146
                [
1147
                    'route' => ['name' => 'sonata_admin_foo_object',
1148
                    'parameters' => ['param1' => 'abcd', 'param2' => 'efgh', 'param3' => 'ijkl'],
1149
                    'identifier_parameter_name' => 'barId', ],
1150
                ],
1151
            ],
1152
            [
1153
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
1154
                <a href="http://localhost/foo/obj/abcd/12345/efgh?param3=ijkl">Foo</a>
1155
                </td>',
1156
                'url',
1157
                'Foo',
1158
                [
1159
                    'route' => ['name' => 'sonata_admin_foo_object',
1160
                    'absolute' => true,
1161
                    'parameters' => ['param1' => 'abcd', 'param2' => 'efgh', 'param3' => 'ijkl'],
1162
                    'identifier_parameter_name' => 'barId', ],
1163
                ],
1164
            ],
1165
            [
1166
                '<td class="sonata-ba-list-field sonata-ba-list-field-html" objectId="12345">
1167
                <p><strong>Creating a Template for the Field</strong> and form</p>
1168
                </td>',
1169
                'html',
1170
                '<p><strong>Creating a Template for the Field</strong> and form</p>',
1171
                [],
1172
            ],
1173
            [
1174
                '<td class="sonata-ba-list-field sonata-ba-list-field-html" objectId="12345">
1175
                Creating a Template for the Field and form
1176
                </td>',
1177
                'html',
1178
                '<p><strong>Creating a Template for the Field</strong> and form</p>',
1179
                ['strip' => true],
1180
            ],
1181
            [
1182
                '<td class="sonata-ba-list-field sonata-ba-list-field-html" objectId="12345">
1183
                Creating a Template for the Fi...
1184
                </td>',
1185
                'html',
1186
                '<p><strong>Creating a Template for the Field</strong> and form</p>',
1187
                ['truncate' => true],
1188
            ],
1189
            [
1190
                '<td class="sonata-ba-list-field sonata-ba-list-field-html" objectId="12345"> Creating a... </td>',
1191
                'html',
1192
                '<p><strong>Creating a Template for the Field</strong> and form</p>',
1193
                ['truncate' => ['length' => 10]],
1194
            ],
1195
            [
1196
                '<td class="sonata-ba-list-field sonata-ba-list-field-html" objectId="12345">
1197
                Creating a Template for the Field...
1198
                </td>',
1199
                'html',
1200
                '<p><strong>Creating a Template for the Field</strong> and form</p>',
1201
                ['truncate' => ['preserve' => true]],
1202
            ],
1203
            [
1204
                '<td class="sonata-ba-list-field sonata-ba-list-field-html" objectId="12345">
1205
                Creating a Template for the Fi etc.
1206
                </td>',
1207
                'html',
1208
                '<p><strong>Creating a Template for the Field</strong> and form</p>',
1209
                ['truncate' => ['separator' => ' etc.']],
1210
            ],
1211
            [
1212
                '<td class="sonata-ba-list-field sonata-ba-list-field-html" objectId="12345">
1213
                Creating a Template for[...]
1214
                </td>',
1215
                'html',
1216
                '<p><strong>Creating a Template for the Field</strong> and form</p>',
1217
                [
1218
                    'truncate' => [
1219
                        'length' => 20,
1220
                        'preserve' => true,
1221
                        'separator' => '[...]',
1222
                    ],
1223
                ],
1224
            ],
1225
1226
            [
1227
                <<<'EOT'
1228
<td class="sonata-ba-list-field sonata-ba-list-field-text" objectId="12345">
1229
<div
1230
    class="sonata-readmore"
1231
    data-readmore-height="40"
1232
    data-readmore-more="Read more"
1233
    data-readmore-less="Close">A very long string</div>
1234
</td>
1235
EOT
1236
                ,
1237
                'text',
1238
                'A very long string',
1239
                [
1240
                    'collapse' => true,
1241
                ],
1242
            ],
1243
            [
1244
                <<<'EOT'
1245
<td class="sonata-ba-list-field sonata-ba-list-field-text" objectId="12345">
1246
<div
1247
    class="sonata-readmore"
1248
    data-readmore-height="10"
1249
    data-readmore-more="More"
1250
    data-readmore-less="Less">A very long string</div>
1251
</td>
1252
EOT
1253
                ,
1254
                'text',
1255
                'A very long string',
1256
                [
1257
                    'collapse' => [
1258
                        'height' => 10,
1259
                        'more' => 'More',
1260
                        'less' => 'Less',
1261
                    ],
1262
                ],
1263
            ],
1264
        ];
1265
    }
1266
1267
    /**
1268
     * @dataProvider getRenderViewElementTests
1269
     */
1270
    public function testRenderViewElement($expected, $type, $value, array $options): void
1271
    {
1272
        $this->admin->expects($this->any())
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...
1273
            ->method('getTemplate')
1274
            ->will($this->returnValue('@SonataAdmin/CRUD/base_show_field.html.twig'));
1275
1276
        $this->fieldDescription->expects($this->any())
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...
1277
            ->method('getValue')
1278
            ->will($this->returnCallback(function () use ($value) {
1279
                if ($value instanceof NoValueException) {
1280
                    throw  $value;
1281
                }
1282
1283
                return $value;
1284
            }));
1285
1286
        $this->fieldDescription->expects($this->any())
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...
1287
            ->method('getType')
1288
            ->will($this->returnValue($type));
1289
1290
        $this->fieldDescription->expects($this->any())
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...
1291
            ->method('getOptions')
1292
            ->will($this->returnValue($options));
1293
1294
        $this->fieldDescription->expects($this->any())
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...
1295
            ->method('getTemplate')
1296
            ->will($this->returnCallback(function () use ($type) {
1297
                switch ($type) {
1298
                    case 'boolean':
1299
                        return '@SonataAdmin/CRUD/show_boolean.html.twig';
1300
                    case 'datetime':
1301
                        return '@SonataAdmin/CRUD/show_datetime.html.twig';
1302
                    case 'date':
1303
                        return '@SonataAdmin/CRUD/show_date.html.twig';
1304
                    case 'time':
1305
                        return '@SonataAdmin/CRUD/show_time.html.twig';
1306
                    case 'currency':
1307
                        return '@SonataAdmin/CRUD/show_currency.html.twig';
1308
                    case 'percent':
1309
                        return '@SonataAdmin/CRUD/show_percent.html.twig';
1310
                    case 'email':
1311
                        return '@SonataAdmin/CRUD/show_email.html.twig';
1312
                    case 'choice':
1313
                        return '@SonataAdmin/CRUD/show_choice.html.twig';
1314
                    case 'array':
1315
                        return '@SonataAdmin/CRUD/show_array.html.twig';
1316
                    case 'trans':
1317
                        return '@SonataAdmin/CRUD/show_trans.html.twig';
1318
                    case 'url':
1319
                        return '@SonataAdmin/CRUD/show_url.html.twig';
1320
                    case 'html':
1321
                        return '@SonataAdmin/CRUD/show_html.html.twig';
1322
                    default:
1323
                        return false;
1324
                }
1325
            }));
1326
1327
        $this->assertSame(
1328
                $this->removeExtraWhitespace($expected),
1329
                $this->removeExtraWhitespace(
1330
                    $this->twigExtension->renderViewElement(
1331
                        $this->environment,
0 ignored issues
show
Compatibility introduced by
$this->environment of type object<Twig_Environment> is not a sub-type of object<Twig\Environment>. It seems like you assume a child class of the class Twig_Environment to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
1332
                        $this->fieldDescription,
1333
                        $this->object
1334
                    )
1335
                )
1336
            );
1337
    }
1338
1339
    public function getRenderViewElementTests()
1340
    {
1341
        return [
1342
            ['<th>Data</th> <td>Example</td>', 'string', 'Example', ['safe' => false]],
1343
            ['<th>Data</th> <td>Example</td>', 'text', 'Example', ['safe' => false]],
1344
            ['<th>Data</th> <td>Example</td>', 'textarea', 'Example', ['safe' => false]],
1345
            [
1346
                '<th>Data</th> <td>December 24, 2013 10:11</td>',
1347
                'datetime',
1348
                new \DateTime('2013-12-24 10:11:12', new \DateTimeZone('Europe/London')), [],
1349
            ],
1350
            [
1351
                '<th>Data</th> <td>24.12.2013 10:11:12</td>',
1352
                'datetime',
1353
                new \DateTime('2013-12-24 10:11:12', new \DateTimeZone('Europe/London')),
1354
                ['format' => 'd.m.Y H:i:s'],
1355
            ],
1356
            [
1357
                '<th>Data</th> <td>December 24, 2013 18:11</td>',
1358
                'datetime',
1359
                new \DateTime('2013-12-24 10:11:12', new \DateTimeZone('UTC')),
1360
                ['timezone' => 'Asia/Hong_Kong'],
1361
            ],
1362
            [
1363
                '<th>Data</th> <td>December 24, 2013</td>',
1364
                'date',
1365
                new \DateTime('2013-12-24 10:11:12', new \DateTimeZone('Europe/London')),
1366
                [],
1367
            ],
1368
            [
1369
                '<th>Data</th> <td>24.12.2013</td>',
1370
                'date',
1371
                new \DateTime('2013-12-24 10:11:12', new \DateTimeZone('Europe/London')),
1372
                ['format' => 'd.m.Y'],
1373
            ],
1374
            [
1375
                '<th>Data</th> <td>10:11:12</td>',
1376
                'time',
1377
                new \DateTime('2013-12-24 10:11:12', new \DateTimeZone('Europe/London')),
1378
                [],
1379
            ],
1380
            [
1381
                '<th>Data</th> <td>18:11:12</td>',
1382
                'time',
1383
                new \DateTime('2013-12-24 10:11:12', new \DateTimeZone('UTC')),
1384
                ['timezone' => 'Asia/Hong_Kong'],
1385
            ],
1386
            ['<th>Data</th> <td>10.746135</td>', 'number', 10.746135, ['safe' => false]],
1387
            ['<th>Data</th> <td>5678</td>', 'integer', 5678, ['safe' => false]],
1388
            ['<th>Data</th> <td> 1074.6135 % </td>', 'percent', 10.746135, []],
1389
            ['<th>Data</th> <td> EUR 10.746135 </td>', 'currency', 10.746135, ['currency' => 'EUR']],
1390
            ['<th>Data</th> <td> GBP 51.23456 </td>', 'currency', 51.23456, ['currency' => 'GBP']],
1391
            [
1392
                '<th>Data</th> <td> [1 => First] <br> [2 => Second] </td>',
1393
                'array',
1394
                [1 => 'First', 2 => 'Second'],
1395
                ['safe' => false],
1396
            ],
1397
            [
1398
                '<th>Data</th> <td> [1 => First] [2 => Second] </td>',
1399
                'array',
1400
                [1 => 'First', 2 => 'Second'],
1401
                ['safe' => false, 'inline' => true],
1402
            ],
1403
            [
1404
                '<th>Data</th> <td><span class="label label-success">yes</span></td>',
1405
                'boolean',
1406
                true,
1407
                [],
1408
            ],
1409
            [
1410
                '<th>Data</th> <td><span class="label label-danger">yes</span></td>',
1411
                'boolean',
1412
                true,
1413
                ['inverse' => true],
1414
            ],
1415
            ['<th>Data</th> <td><span class="label label-danger">no</span></td>', 'boolean', false, []],
1416
            [
1417
                '<th>Data</th> <td><span class="label label-success">no</span></td>',
1418
                'boolean',
1419
                false,
1420
                ['inverse' => true],
1421
            ],
1422
            [
1423
                '<th>Data</th> <td> Delete </td>',
1424
                'trans',
1425
                'action_delete',
1426
                ['safe' => false, 'catalogue' => 'SonataAdminBundle'],
1427
            ],
1428
            ['<th>Data</th> <td>Status1</td>', 'choice', 'Status1', ['safe' => false]],
1429
            [
1430
                '<th>Data</th> <td>Alias1</td>',
1431
                'choice',
1432
                'Status1',
1433
                ['safe' => false, 'choices' => [
1434
                    'Status1' => 'Alias1',
1435
                    'Status2' => 'Alias2',
1436
                    'Status3' => 'Alias3',
1437
                ]],
1438
            ],
1439
            [
1440
                '<th>Data</th> <td>NoValidKeyInChoices</td>',
1441
                'choice',
1442
                'NoValidKeyInChoices',
1443
                ['safe' => false, 'choices' => [
1444
                    'Status1' => 'Alias1',
1445
                    'Status2' => 'Alias2',
1446
                    'Status3' => 'Alias3',
1447
                ]],
1448
            ],
1449
            [
1450
                '<th>Data</th> <td>Delete</td>',
1451
                'choice',
1452
                'Foo',
1453
                ['safe' => false, 'catalogue' => 'SonataAdminBundle', 'choices' => [
1454
                    'Foo' => 'action_delete',
1455
                    'Status2' => 'Alias2',
1456
                    'Status3' => 'Alias3',
1457
                ]],
1458
            ],
1459
            [
1460
                '<th>Data</th> <td>NoValidKeyInChoices</td>',
1461
                'choice',
1462
                ['NoValidKeyInChoices'],
1463
                ['safe' => false, 'choices' => [
1464
                    'Status1' => 'Alias1',
1465
                    'Status2' => 'Alias2',
1466
                    'Status3' => 'Alias3',
1467
                ], 'multiple' => true],
1468
            ],
1469
            [
1470
                '<th>Data</th> <td>NoValidKeyInChoices, Alias2</td>',
1471
                'choice',
1472
                ['NoValidKeyInChoices', 'Status2'],
1473
                ['safe' => false, 'choices' => [
1474
                    'Status1' => 'Alias1',
1475
                    'Status2' => 'Alias2',
1476
                    'Status3' => 'Alias3',
1477
                ], 'multiple' => true],
1478
            ],
1479
            [
1480
                '<th>Data</th> <td>Alias1, Alias3</td>',
1481
                'choice',
1482
                ['Status1', 'Status3'],
1483
                ['safe' => false, 'choices' => [
1484
                    'Status1' => 'Alias1',
1485
                    'Status2' => 'Alias2',
1486
                    'Status3' => 'Alias3',
1487
                ], 'multiple' => true],
1488
            ],
1489
            [
1490
                '<th>Data</th> <td>Alias1 | Alias3</td>',
1491
                'choice',
1492
                ['Status1', 'Status3'], ['safe' => false, 'choices' => [
1493
                    'Status1' => 'Alias1',
1494
                    'Status2' => 'Alias2',
1495
                    'Status3' => 'Alias3',
1496
                ], 'multiple' => true, 'delimiter' => ' | '],
1497
            ],
1498
            [
1499
                '<th>Data</th> <td>Delete, Alias3</td>',
1500
                'choice',
1501
                ['Foo', 'Status3'],
1502
                ['safe' => false, 'catalogue' => 'SonataAdminBundle', 'choices' => [
1503
                    'Foo' => 'action_delete',
1504
                    'Status2' => 'Alias2',
1505
                    'Status3' => 'Alias3',
1506
                ], 'multiple' => true],
1507
            ],
1508
            [
1509
                '<th>Data</th> <td><b>Alias1</b>, <b>Alias3</b></td>',
1510
                'choice',
1511
                ['Status1', 'Status3'],
1512
                ['safe' => true, 'choices' => [
1513
                    'Status1' => '<b>Alias1</b>',
1514
                    'Status2' => '<b>Alias2</b>',
1515
                    'Status3' => '<b>Alias3</b>',
1516
                ], 'multiple' => true],
1517
            ],
1518
            [
1519
                '<th>Data</th> <td>&lt;b&gt;Alias1&lt;/b&gt;, &lt;b&gt;Alias3&lt;/b&gt;</td>',
1520
                'choice',
1521
                ['Status1', 'Status3'],
1522
                ['safe' => false, 'choices' => [
1523
                    'Status1' => '<b>Alias1</b>',
1524
                    'Status2' => '<b>Alias2</b>',
1525
                    'Status3' => '<b>Alias3</b>',
1526
                ], 'multiple' => true],
1527
            ],
1528
            [
1529
                '<th>Data</th> <td><a href="http://example.com">http://example.com</a></td>',
1530
                'url',
1531
                'http://example.com',
1532
                ['safe' => false],
1533
            ],
1534
            [
1535
                '<th>Data</th> <td><a href="http://example.com" target="_blank">http://example.com</a></td>',
1536
                'url',
1537
                'http://example.com',
1538
                ['safe' => false, 'attributes' => ['target' => '_blank']],
1539
            ],
1540
            [
1541
                '<th>Data</th> <td><a href="http://example.com" target="_blank" class="fooLink">http://example.com</a></td>',
1542
                'url',
1543
                'http://example.com',
1544
                ['safe' => false, 'attributes' => ['target' => '_blank', 'class' => 'fooLink']],
1545
            ],
1546
            [
1547
                '<th>Data</th> <td><a href="https://example.com">https://example.com</a></td>',
1548
                'url',
1549
                'https://example.com',
1550
                ['safe' => false],
1551
            ],
1552
            [
1553
                '<th>Data</th> <td><a href="http://example.com">example.com</a></td>',
1554
                'url',
1555
                'http://example.com',
1556
                ['safe' => false, 'hide_protocol' => true],
1557
            ],
1558
            [
1559
                '<th>Data</th> <td><a href="https://example.com">example.com</a></td>',
1560
                'url',
1561
                'https://example.com',
1562
                ['safe' => false, 'hide_protocol' => true],
1563
            ],
1564
            [
1565
                '<th>Data</th> <td><a href="http://example.com">http://example.com</a></td>',
1566
                'url',
1567
                'http://example.com',
1568
                ['safe' => false, 'hide_protocol' => false],
1569
            ],
1570
            [
1571
                '<th>Data</th> <td><a href="https://example.com">https://example.com</a></td>',
1572
                'url',
1573
                'https://example.com',
1574
                ['safe' => false,
1575
                'hide_protocol' => false, ],
1576
            ],
1577
            [
1578
                '<th>Data</th> <td><a href="http://example.com">Foo</a></td>',
1579
                'url',
1580
                'Foo',
1581
                ['safe' => false, 'url' => 'http://example.com'],
1582
            ],
1583
            [
1584
                '<th>Data</th> <td><a href="http://example.com">&lt;b&gt;Foo&lt;/b&gt;</a></td>',
1585
                'url',
1586
                '<b>Foo</b>',
1587
                ['safe' => false, 'url' => 'http://example.com'],
1588
            ],
1589
            [
1590
                '<th>Data</th> <td><a href="http://example.com"><b>Foo</b></a></td>',
1591
                'url',
1592
                '<b>Foo</b>',
1593
                ['safe' => true, 'url' => 'http://example.com'],
1594
            ],
1595
            [
1596
                '<th>Data</th> <td><a href="/foo">Foo</a></td>',
1597
                'url',
1598
                'Foo',
1599
                ['safe' => false, 'route' => ['name' => 'sonata_admin_foo']],
1600
            ],
1601
            [
1602
                '<th>Data</th> <td><a href="http://localhost/foo">Foo</a></td>',
1603
                'url',
1604
                'Foo',
1605
                ['safe' => false, 'route' => [
1606
                    'name' => 'sonata_admin_foo',
1607
                    'absolute' => true,
1608
                ]],
1609
            ],
1610
            [
1611
                '<th>Data</th> <td><a href="/foo">foo/bar?a=b&amp;c=123456789</a></td>',
1612
                'url',
1613
                'http://foo/bar?a=b&c=123456789',
1614
                [
1615
                    'safe' => false,
1616
                    'route' => ['name' => 'sonata_admin_foo'],
1617
                    'hide_protocol' => true,
1618
                ],
1619
            ],
1620
            [
1621
                '<th>Data</th> <td><a href="http://localhost/foo">foo/bar?a=b&amp;c=123456789</a></td>',
1622
                'url',
1623
                'http://foo/bar?a=b&c=123456789',
1624
                ['safe' => false, 'route' => [
1625
                    'name' => 'sonata_admin_foo',
1626
                    'absolute' => true,
1627
                ], 'hide_protocol' => true],
1628
            ],
1629
            [
1630
                '<th>Data</th> <td><a href="/foo/abcd/efgh?param3=ijkl">Foo</a></td>',
1631
                'url',
1632
                'Foo',
1633
                ['safe' => false, 'route' => [
1634
                    'name' => 'sonata_admin_foo_param',
1635
                    'parameters' => ['param1' => 'abcd', 'param2' => 'efgh', 'param3' => 'ijkl'],
1636
                ]],
1637
            ],
1638
            [
1639
                '<th>Data</th> <td><a href="http://localhost/foo/abcd/efgh?param3=ijkl">Foo</a></td>',
1640
                'url',
1641
                'Foo',
1642
                ['safe' => false, 'route' => [
1643
                    'name' => 'sonata_admin_foo_param',
1644
                    'absolute' => true,
1645
                    'parameters' => [
1646
                        'param1' => 'abcd',
1647
                        'param2' => 'efgh',
1648
                        'param3' => 'ijkl',
1649
                    ],
1650
                ]],
1651
            ],
1652
            [
1653
                '<th>Data</th> <td><a href="/foo/obj/abcd/12345/efgh?param3=ijkl">Foo</a></td>',
1654
                'url',
1655
                'Foo',
1656
                ['safe' => false, 'route' => [
1657
                    'name' => 'sonata_admin_foo_object',
1658
                    'parameters' => [
1659
                        'param1' => 'abcd',
1660
                        'param2' => 'efgh',
1661
                        'param3' => 'ijkl',
1662
                    ],
1663
                    'identifier_parameter_name' => 'barId',
1664
                ]],
1665
            ],
1666
            [
1667
                '<th>Data</th> <td><a href="http://localhost/foo/obj/abcd/12345/efgh?param3=ijkl">Foo</a></td>',
1668
                'url',
1669
                'Foo',
1670
                ['safe' => false, 'route' => [
1671
                    'name' => 'sonata_admin_foo_object',
1672
                    'absolute' => true,
1673
                    'parameters' => [
1674
                        'param1' => 'abcd',
1675
                        'param2' => 'efgh',
1676
                        'param3' => 'ijkl',
1677
                    ],
1678
                    'identifier_parameter_name' => 'barId',
1679
                ]],
1680
            ],
1681
            [
1682
                '<th>Data</th> <td> &nbsp;</td>',
1683
                'email',
1684
                null,
1685
                [],
1686
            ],
1687
            [
1688
                '<th>Data</th> <td> <a href="mailto:[email protected]">[email protected]</a></td>',
1689
                'email',
1690
                '[email protected]',
1691
                [],
1692
            ],
1693
            [
1694
                '<th>Data</th> <td> <a href="mailto:[email protected]?'.$this->buildTwigLikeUrl(['subject' => 'Main Theme', 'body' => 'Message Body']).'">[email protected]</a></td>',
1695
                'email',
1696
                '[email protected]',
1697
                ['subject' => 'Main Theme', 'body' => 'Message Body'],
1698
            ],
1699
            [
1700
                '<th>Data</th> <td> <a href="mailto:[email protected]?'.$this->buildTwigLikeUrl(['subject' => 'Main Theme']).'">[email protected]</a></td>',
1701
                'email',
1702
                '[email protected]',
1703
                ['subject' => 'Main Theme'],
1704
            ],
1705
            [
1706
                '<th>Data</th> <td> <a href="mailto:[email protected]?'.$this->buildTwigLikeUrl(['body' => 'Message Body']).'">[email protected]</a></td>',
1707
                'email',
1708
                '[email protected]',
1709
                ['body' => 'Message Body'],
1710
            ],
1711
            [
1712
                '<th>Data</th> <td> [email protected]</td>',
1713
                'email',
1714
                '[email protected]',
1715
                ['as_string' => true, 'subject' => 'Main Theme', 'body' => 'Message Body'],
1716
            ],
1717
            [
1718
                '<th>Data</th> <td> [email protected]</td>',
1719
                'email',
1720
                '[email protected]',
1721
                ['as_string' => true, 'subject' => 'Main Theme'],
1722
            ],
1723
            [
1724
                '<th>Data</th> <td> [email protected]</td>',
1725
                'email',
1726
                '[email protected]',
1727
                ['as_string' => true, 'body' => 'Message Body'],
1728
            ],
1729
            [
1730
                '<th>Data</th> <td> <a href="mailto:[email protected]">[email protected]</a></td>',
1731
                'email',
1732
                '[email protected]',
1733
                ['as_string' => false],
1734
            ],
1735
            [
1736
                '<th>Data</th> <td> [email protected]</td>',
1737
                'email',
1738
                '[email protected]',
1739
                ['as_string' => true],
1740
            ],
1741
            [
1742
                '<th>Data</th> <td><p><strong>Creating a Template for the Field</strong> and form</p> </td>',
1743
                'html',
1744
                '<p><strong>Creating a Template for the Field</strong> and form</p>',
1745
                [],
1746
            ],
1747
            [
1748
                '<th>Data</th> <td>Creating a Template for the Field and form </td>',
1749
                'html',
1750
                '<p><strong>Creating a Template for the Field</strong> and form</p>',
1751
                ['strip' => true],
1752
            ],
1753
            [
1754
                '<th>Data</th> <td> Creating a Template for the Fi... </td>',
1755
                'html',
1756
                '<p><strong>Creating a Template for the Field</strong> and form</p>',
1757
                ['truncate' => true],
1758
            ],
1759
            [
1760
                '<th>Data</th> <td> Creating a... </td>',
1761
                'html',
1762
                '<p><strong>Creating a Template for the Field</strong> and form</p>',
1763
                ['truncate' => ['length' => 10]],
1764
            ],
1765
            [
1766
                '<th>Data</th> <td> Creating a Template for the Field... </td>',
1767
                'html',
1768
                '<p><strong>Creating a Template for the Field</strong> and form</p>',
1769
                ['truncate' => ['preserve' => true]],
1770
            ],
1771
            [
1772
                '<th>Data</th> <td> Creating a Template for the Fi etc. </td>',
1773
                'html',
1774
                '<p><strong>Creating a Template for the Field</strong> and form</p>',
1775
                ['truncate' => ['separator' => ' etc.']],
1776
            ],
1777
            [
1778
                '<th>Data</th> <td> Creating a Template for[...] </td>',
1779
                'html',
1780
                '<p><strong>Creating a Template for the Field</strong> and form</p>',
1781
                [
1782
                    'truncate' => [
1783
                        'length' => 20,
1784
                        'preserve' => true,
1785
                        'separator' => '[...]',
1786
                    ],
1787
                ],
1788
            ],
1789
1790
            // NoValueException
1791
            ['<th>Data</th> <td></td>', 'string', new NoValueException(), ['safe' => false]],
1792
            ['<th>Data</th> <td></td>', 'text', new NoValueException(), ['safe' => false]],
1793
            ['<th>Data</th> <td></td>', 'textarea', new NoValueException(), ['safe' => false]],
1794
            ['<th>Data</th> <td>&nbsp;</td>', 'datetime', new NoValueException(), []],
1795
            [
1796
                '<th>Data</th> <td>&nbsp;</td>',
1797
                'datetime',
1798
                new NoValueException(),
1799
                ['format' => 'd.m.Y H:i:s'],
1800
            ],
1801
            ['<th>Data</th> <td>&nbsp;</td>', 'date', new NoValueException(), []],
1802
            ['<th>Data</th> <td>&nbsp;</td>', 'date', new NoValueException(), ['format' => 'd.m.Y']],
1803
            ['<th>Data</th> <td>&nbsp;</td>', 'time', new NoValueException(), []],
1804
            ['<th>Data</th> <td></td>', 'number', new NoValueException(), ['safe' => false]],
1805
            ['<th>Data</th> <td></td>', 'integer', new NoValueException(), ['safe' => false]],
1806
            ['<th>Data</th> <td> 0 % </td>', 'percent', new NoValueException(), []],
1807
            ['<th>Data</th> <td> </td>', 'currency', new NoValueException(), ['currency' => 'EUR']],
1808
            ['<th>Data</th> <td> </td>', 'currency', new NoValueException(), ['currency' => 'GBP']],
1809
            ['<th>Data</th> <td> </td>', 'array', new NoValueException(), ['safe' => false]],
1810
            [
1811
                '<th>Data</th> <td><span class="label label-danger">no</span></td>',
1812
                'boolean',
1813
                new NoValueException(),
1814
                [],
1815
            ],
1816
            [
1817
                '<th>Data</th> <td> </td>',
1818
                'trans',
1819
                new NoValueException(),
1820
                ['safe' => false, 'catalogue' => 'SonataAdminBundle'],
1821
            ],
1822
            [
1823
                '<th>Data</th> <td></td>',
1824
                'choice',
1825
                new NoValueException(),
1826
                ['safe' => false, 'choices' => []],
1827
            ],
1828
            [
1829
                '<th>Data</th> <td></td>',
1830
                'choice',
1831
                new NoValueException(),
1832
                ['safe' => false, 'choices' => [], 'multiple' => true],
1833
            ],
1834
            ['<th>Data</th> <td>&nbsp;</td>', 'url', new NoValueException(), []],
1835
            [
1836
                '<th>Data</th> <td>&nbsp;</td>',
1837
                'url',
1838
                new NoValueException(),
1839
                ['url' => 'http://example.com'],
1840
            ],
1841
            [
1842
                '<th>Data</th> <td>&nbsp;</td>',
1843
                'url',
1844
                new NoValueException(),
1845
                ['route' => ['name' => 'sonata_admin_foo']],
1846
            ],
1847
1848
            [
1849
                <<<'EOT'
1850
<th>Data</th> <td><div
1851
        class="sonata-readmore"
1852
        data-readmore-height="40"
1853
        data-readmore-more="Read more"
1854
        data-readmore-less="Close">
1855
            A very long string
1856
</div></td>
1857
EOT
1858
                ,
1859
                'text',
1860
                ' A very long string ',
1861
                [
1862
                    'collapse' => true,
1863
                    'safe' => false,
1864
                ],
1865
            ],
1866
            [
1867
                <<<'EOT'
1868
<th>Data</th> <td><div
1869
        class="sonata-readmore"
1870
        data-readmore-height="10"
1871
        data-readmore-more="More"
1872
        data-readmore-less="Less">
1873
            A very long string
1874
</div></td>
1875
EOT
1876
                ,
1877
                'text',
1878
                ' A very long string ',
1879
                [
1880
                    'collapse' => [
1881
                        'height' => 10,
1882
                        'more' => 'More',
1883
                        'less' => 'Less',
1884
                    ],
1885
                    'safe' => false,
1886
                ],
1887
            ],
1888
        ];
1889
    }
1890
1891
    public function testGetValueFromFieldDescription(): void
1892
    {
1893
        $object = new \stdClass();
1894
        $fieldDescription = $this->getMockForAbstractClass(FieldDescriptionInterface::class);
1895
1896
        $fieldDescription->expects($this->any())
1897
            ->method('getValue')
1898
            ->will($this->returnValue('test123'));
1899
1900
        $this->assertSame(
1901
            'test123',
1902
            $this->getMethodAsPublic('getValueFromFieldDescription')->invoke(
1903
                $this->twigExtension,
1904
                $object,
1905
                $fieldDescription
1906
            )
1907
        );
1908
    }
1909
1910
    public function testGetValueFromFieldDescriptionWithRemoveLoopException(): void
1911
    {
1912
        $object = $this->createMock(\ArrayAccess::class);
1913
        $fieldDescription = $this->getMockForAbstractClass(FieldDescriptionInterface::class);
1914
1915
        $this->expectException(\RuntimeException::class, 'remove the loop requirement');
1916
1917
        $this->assertSame(
1918
            'anything',
1919
            $this->getMethodAsPublic('getValueFromFieldDescription')->invoke(
1920
                $this->twigExtension,
1921
                $object,
1922
                $fieldDescription,
1923
                ['loop' => true]
1924
            )
1925
        );
1926
    }
1927
1928
    public function testGetValueFromFieldDescriptionWithNoValueException(): void
1929
    {
1930
        $object = new \stdClass();
1931
        $fieldDescription = $this->getMockForAbstractClass(FieldDescriptionInterface::class);
1932
1933
        $fieldDescription->expects($this->any())
1934
            ->method('getValue')
1935
            ->will($this->returnCallback(function (): void {
1936
                throw new NoValueException();
1937
            }));
1938
1939
        $fieldDescription->expects($this->any())
1940
            ->method('getAssociationAdmin')
1941
            ->will($this->returnValue(null));
1942
1943
        $this->assertNull(
1944
            $this->getMethodAsPublic('getValueFromFieldDescription')->invoke(
1945
                $this->twigExtension,
1946
                $object,
1947
                $fieldDescription
1948
            )
1949
        );
1950
    }
1951
1952
    public function testGetValueFromFieldDescriptionWithNoValueExceptionNewAdminInstance(): void
1953
    {
1954
        $object = new \stdClass();
1955
        $fieldDescription = $this->getMockForAbstractClass(FieldDescriptionInterface::class);
1956
1957
        $fieldDescription->expects($this->any())
1958
            ->method('getValue')
1959
            ->will($this->returnCallback(function (): void {
1960
                throw new NoValueException();
1961
            }));
1962
1963
        $fieldDescription->expects($this->any())
1964
            ->method('getAssociationAdmin')
1965
            ->will($this->returnValue($this->admin));
1966
1967
        $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...
1968
            ->method('getNewInstance')
1969
            ->will($this->returnValue('foo'));
1970
1971
        $this->assertSame(
1972
            'foo',
1973
            $this->getMethodAsPublic('getValueFromFieldDescription')->invoke(
1974
                $this->twigExtension,
1975
                $object,
1976
                $fieldDescription
1977
            )
1978
        );
1979
    }
1980
1981
    /**
1982
     * @group legacy
1983
     * @expectedDeprecation The Sonata\AdminBundle\Admin\AbstractAdmin::getTemplate method is deprecated (since 3.34, will be dropped in 4.0. Use TemplateRegistry services instead).
1984
     */
1985
    public function testRenderWithDebug(): void
1986
    {
1987
        $this->fieldDescription->expects($this->any())
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...
1988
            ->method('getTemplate')
1989
            ->will($this->returnValue('@SonataAdmin/CRUD/base_list_field.html.twig'));
1990
1991
        $this->fieldDescription->expects($this->any())
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...
1992
            ->method('getFieldName')
1993
            ->will($this->returnValue('fd_name'));
1994
1995
        $this->fieldDescription->expects($this->any())
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...
1996
            ->method('getValue')
1997
            ->will($this->returnValue('foo'));
1998
1999
        $parameters = [
2000
            'admin' => $this->admin,
2001
            'value' => 'foo',
2002
            'field_description' => $this->fieldDescription,
2003
            'object' => $this->object,
2004
        ];
2005
2006
        $this->environment->enableDebug();
2007
2008
        $this->assertSame(
2009
            $this->removeExtraWhitespace(<<<'EOT'
2010
<!-- START
2011
    fieldName: fd_name
2012
    template: @SonataAdmin/CRUD/base_list_field.html.twig
2013
    compiled template: @SonataAdmin/CRUD/base_list_field.html.twig
2014
-->
2015
    <td class="sonata-ba-list-field sonata-ba-list-field-" objectId="12345"> foo </td>
2016
<!-- END - fieldName: fd_name -->
2017
EOT
2018
            ),
2019
            $this->removeExtraWhitespace(
2020
                $this->twigExtension->renderListElement($this->environment, $this->object, $this->fieldDescription, $parameters)
0 ignored issues
show
Compatibility introduced by
$this->environment of type object<Twig_Environment> is not a sub-type of object<Twig\Environment>. It seems like you assume a child class of the class Twig_Environment to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
2021
            )
2022
        );
2023
    }
2024
2025
    public function testRenderRelationElementNoObject(): void
2026
    {
2027
        $this->assertSame('foo', $this->twigExtension->renderRelationElement('foo', $this->fieldDescription));
2028
    }
2029
2030
    public function testRenderRelationElementToString(): void
2031
    {
2032
        $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...
2033
            ->method('getOption')
2034
            ->will($this->returnCallback(function ($value, $default = null) {
2035
                if ('associated_property' == $value) {
2036
                    return $default;
2037
                }
2038
            }));
2039
2040
        $element = new FooToString();
2041
        $this->assertSame('salut', $this->twigExtension->renderRelationElement($element, $this->fieldDescription));
2042
    }
2043
2044
    /**
2045
     * @group legacy
2046
     */
2047
    public function testDeprecatedRelationElementToString(): void
2048
    {
2049
        $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...
2050
            ->method('getOption')
2051
            ->will($this->returnCallback(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...
2052
                if ('associated_tostring' == $value) {
2053
                    return '__toString';
2054
                }
2055
            }));
2056
2057
        $element = new FooToString();
2058
        $this->assertSame(
2059
            'salut',
2060
            $this->twigExtension->renderRelationElement($element, $this->fieldDescription)
2061
        );
2062
    }
2063
2064
    /**
2065
     * @group legacy
2066
     */
2067
    public function testRenderRelationElementCustomToString(): void
2068
    {
2069
        $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...
2070
            ->method('getOption')
2071
            ->will($this->returnCallback(function ($value, $default = null) {
2072
                if ('associated_property' == $value) {
2073
                    return $default;
2074
                }
2075
2076
                if ('associated_tostring' == $value) {
2077
                    return 'customToString';
2078
                }
2079
            }));
2080
2081
        $element = $this->getMockBuilder('stdClass')
2082
            ->setMethods(['customToString'])
2083
            ->getMock();
2084
        $element->expects($this->any())
2085
            ->method('customToString')
2086
            ->will($this->returnValue('fooBar'));
2087
2088
        $this->assertSame('fooBar', $this->twigExtension->renderRelationElement($element, $this->fieldDescription));
2089
    }
2090
2091
    /**
2092
     * @group legacy
2093
     */
2094
    public function testRenderRelationElementMethodNotExist(): void
2095
    {
2096
        $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...
2097
            ->method('getOption')
2098
2099
            ->will($this->returnCallback(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...
2100
                if ('associated_tostring' == $value) {
2101
                    return 'nonExistedMethod';
2102
                }
2103
            }));
2104
2105
        $element = new \stdClass();
2106
        $this->expectException(\RuntimeException::class, 'You must define an `associated_property` option or create a `stdClass::__toString');
2107
2108
        $this->twigExtension->renderRelationElement($element, $this->fieldDescription);
2109
    }
2110
2111
    public function testRenderRelationElementWithPropertyPath(): void
2112
    {
2113
        $this->fieldDescription->expects($this->exactly(1))
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...
2114
            ->method('getOption')
2115
2116
            ->will($this->returnCallback(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...
2117
                if ('associated_property' == $value) {
2118
                    return 'foo';
2119
                }
2120
            }));
2121
2122
        $element = new \stdClass();
2123
        $element->foo = 'bar';
2124
2125
        $this->assertSame('bar', $this->twigExtension->renderRelationElement($element, $this->fieldDescription));
2126
    }
2127
2128
    public function testRenderRelationElementWithClosure(): void
2129
    {
2130
        $this->fieldDescription->expects($this->exactly(1))
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...
2131
            ->method('getOption')
2132
2133
            ->will($this->returnCallback(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...
2134
                if ('associated_property' == $value) {
2135
                    return function ($element) {
2136
                        return 'closure '.$element->foo;
2137
                    };
2138
                }
2139
            }));
2140
2141
        $element = new \stdClass();
2142
        $element->foo = 'bar';
2143
2144
        $this->assertSame(
2145
            'closure bar',
2146
            $this->twigExtension->renderRelationElement($element, $this->fieldDescription)
2147
        );
2148
    }
2149
2150
    public function testGetUrlsafeIdentifier(): void
2151
    {
2152
        $entity = new \stdClass();
2153
2154
        // set admin to pool
2155
        $this->pool->setAdminServiceIds(['sonata_admin_foo_service']);
2156
        $this->pool->setAdminClasses(['stdClass' => ['sonata_admin_foo_service']]);
2157
2158
        $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...
2159
            ->method('getUrlsafeIdentifier')
2160
            ->with($this->equalTo($entity))
2161
            ->will($this->returnValue(1234567));
2162
2163
        $this->assertSame(1234567, $this->twigExtension->getUrlsafeIdentifier($entity));
2164
    }
2165
2166
    public function testGetUrlsafeIdentifier_GivenAdmin_Foo(): void
0 ignored issues
show
Coding Style introduced by
Method name "SonataAdminExtensionTest::testGetUrlsafeIdentifier_GivenAdmin_Foo" is not in camel caps format
Loading history...
2167
    {
2168
        $entity = new \stdClass();
2169
2170
        // set admin to pool
2171
        $this->pool->setAdminServiceIds([
2172
            'sonata_admin_foo_service',
2173
            'sonata_admin_bar_service',
2174
        ]);
2175
        $this->pool->setAdminClasses(['stdClass' => [
2176
            'sonata_admin_foo_service',
2177
            'sonata_admin_bar_service',
2178
        ]]);
2179
2180
        $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...
2181
            ->method('getUrlsafeIdentifier')
2182
            ->with($this->equalTo($entity))
2183
            ->will($this->returnValue(1234567));
2184
2185
        $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...
2186
            ->method('getUrlsafeIdentifier');
2187
2188
        $this->assertSame(1234567, $this->twigExtension->getUrlsafeIdentifier($entity, $this->admin));
2189
    }
2190
2191
    public function testGetUrlsafeIdentifier_GivenAdmin_Bar(): void
0 ignored issues
show
Coding Style introduced by
Method name "SonataAdminExtensionTest::testGetUrlsafeIdentifier_GivenAdmin_Bar" is not in camel caps format
Loading history...
2192
    {
2193
        $entity = new \stdClass();
2194
2195
        // set admin to pool
2196
        $this->pool->setAdminServiceIds(['sonata_admin_foo_service', 'sonata_admin_bar_service']);
2197
        $this->pool->setAdminClasses(['stdClass' => [
2198
            'sonata_admin_foo_service',
2199
            'sonata_admin_bar_service',
2200
        ]]);
2201
2202
        $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...
2203
            ->method('getUrlsafeIdentifier');
2204
2205
        $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...
2206
            ->method('getUrlsafeIdentifier')
2207
            ->with($this->equalTo($entity))
2208
            ->will($this->returnValue(1234567));
2209
2210
        $this->assertSame(1234567, $this->twigExtension->getUrlsafeIdentifier($entity, $this->adminBar));
2211
    }
2212
2213
    public function xEditableChoicesProvider()
2214
    {
2215
        return [
2216
            'needs processing' => [
2217
                ['choices' => ['Status1' => 'Alias1', 'Status2' => 'Alias2']],
2218
                [
2219
                    ['value' => 'Status1', 'text' => 'Alias1'],
2220
                    ['value' => 'Status2', 'text' => 'Alias2'],
2221
                ],
2222
            ],
2223
            'already processed' => [
2224
                ['choices' => [
2225
                    ['value' => 'Status1', 'text' => 'Alias1'],
2226
                    ['value' => 'Status2', 'text' => 'Alias2'],
2227
                ]],
2228
                [
2229
                    ['value' => 'Status1', 'text' => 'Alias1'],
2230
                    ['value' => 'Status2', 'text' => 'Alias2'],
2231
                ],
2232
            ],
2233
            'not required' => [
2234
                [
2235
                    'required' => false,
2236
                    'choices' => ['' => '', 'Status1' => 'Alias1', 'Status2' => 'Alias2'],
2237
                ],
2238
                [
2239
                    ['value' => '', 'text' => ''],
2240
                    ['value' => 'Status1', 'text' => 'Alias1'],
2241
                    ['value' => 'Status2', 'text' => 'Alias2'],
2242
                ],
2243
            ],
2244
            'not required multiple' => [
2245
                [
2246
                    'required' => false,
2247
                    'multiple' => true,
2248
                    'choices' => ['Status1' => 'Alias1', 'Status2' => 'Alias2'],
2249
                ],
2250
                [
2251
                    ['value' => 'Status1', 'text' => 'Alias1'],
2252
                    ['value' => 'Status2', 'text' => 'Alias2'],
2253
                ],
2254
            ],
2255
        ];
2256
    }
2257
2258
    /**
2259
     * @dataProvider xEditablechoicesProvider
2260
     */
2261
    public function testGetXEditableChoicesIsIdempotent(array $options, $expectedChoices): void
2262
    {
2263
        $fieldDescription = $this->getMockForAbstractClass(FieldDescriptionInterface::class);
2264
        $fieldDescription->expects($this->any())
2265
            ->method('getOption')
2266
            ->withConsecutive(
2267
                ['choices', []],
2268
                ['catalogue'],
2269
                ['required'],
2270
                ['multiple']
2271
            )
2272
            ->will($this->onConsecutiveCalls(
2273
                $options['choices'],
2274
                'MyCatalogue',
2275
                $options['multiple'] ?? null
2276
            ));
2277
2278
        $this->assertSame($expectedChoices, $this->twigExtension->getXEditableChoices($fieldDescription));
2279
    }
2280
2281
    public function select2LocalesProvider()
2282
    {
2283
        return [
2284
            ['ar', 'ar'],
2285
            ['az', 'az'],
2286
            ['bg', 'bg'],
2287
            ['ca', 'ca'],
2288
            ['cs', 'cs'],
2289
            ['da', 'da'],
2290
            ['de', 'de'],
2291
            ['el', 'el'],
2292
            [null, 'en'],
2293
            ['es', 'es'],
2294
            ['et', 'et'],
2295
            ['eu', 'eu'],
2296
            ['fa', 'fa'],
2297
            ['fi', 'fi'],
2298
            ['fr', 'fr'],
2299
            ['gl', 'gl'],
2300
            ['he', 'he'],
2301
            ['hr', 'hr'],
2302
            ['hu', 'hu'],
2303
            ['id', 'id'],
2304
            ['is', 'is'],
2305
            ['it', 'it'],
2306
            ['ja', 'ja'],
2307
            ['ka', 'ka'],
2308
            ['ko', 'ko'],
2309
            ['lt', 'lt'],
2310
            ['lv', 'lv'],
2311
            ['mk', 'mk'],
2312
            ['ms', 'ms'],
2313
            ['nb', 'nb'],
2314
            ['nl', 'nl'],
2315
            ['pl', 'pl'],
2316
            ['pt-PT', 'pt'],
2317
            ['pt-BR', 'pt-BR'],
2318
            ['pt-PT', 'pt-PT'],
2319
            ['ro', 'ro'],
2320
            ['rs', 'rs'],
2321
            ['ru', 'ru'],
2322
            ['sk', 'sk'],
2323
            ['sv', 'sv'],
2324
            ['th', 'th'],
2325
            ['tr', 'tr'],
2326
            ['ug-CN', 'ug'],
2327
            ['ug-CN', 'ug-CN'],
2328
            ['uk', 'uk'],
2329
            ['vi', 'vi'],
2330
            ['zh-CN', 'zh'],
2331
            ['zh-CN', 'zh-CN'],
2332
            ['zh-TW', 'zh-TW'],
2333
        ];
2334
    }
2335
2336
    /**
2337
     * @dataProvider select2LocalesProvider
2338
     */
2339
    public function testCanonicalizedLocaleForSelect2($expected, $original): void
2340
    {
2341
        $this->assertSame($expected, $this->twigExtension->getCanonicalizedLocaleForSelect2($this->mockExtensionContext($original)));
2342
    }
2343
2344
    public function momentLocalesProvider()
2345
    {
2346
        return [
2347
            ['af', 'af'],
2348
            ['ar-dz', 'ar-dz'],
2349
            ['ar', 'ar'],
2350
            ['ar-ly', 'ar-ly'],
2351
            ['ar-ma', 'ar-ma'],
2352
            ['ar-sa', 'ar-sa'],
2353
            ['ar-tn', 'ar-tn'],
2354
            ['az', 'az'],
2355
            ['be', 'be'],
2356
            ['bg', 'bg'],
2357
            ['bn', 'bn'],
2358
            ['bo', 'bo'],
2359
            ['br', 'br'],
2360
            ['bs', 'bs'],
2361
            ['ca', 'ca'],
2362
            ['cs', 'cs'],
2363
            ['cv', 'cv'],
2364
            ['cy', 'cy'],
2365
            ['da', 'da'],
2366
            ['de-at', 'de-at'],
2367
            ['de', 'de'],
2368
            ['dv', 'dv'],
2369
            ['el', 'el'],
2370
            [null, 'en'],
2371
            [null, 'en-us'],
2372
            ['en-au', 'en-au'],
2373
            ['en-ca', 'en-ca'],
2374
            ['en-gb', 'en-gb'],
2375
            ['en-ie', 'en-ie'],
2376
            ['en-nz', 'en-nz'],
2377
            ['eo', 'eo'],
2378
            ['es-do', 'es-do'],
2379
            ['es', 'es-ar'],
2380
            ['es', 'es-mx'],
2381
            ['es', 'es'],
2382
            ['et', 'et'],
2383
            ['eu', 'eu'],
2384
            ['fa', 'fa'],
2385
            ['fi', 'fi'],
2386
            ['fo', 'fo'],
2387
            ['fr-ca', 'fr-ca'],
2388
            ['fr-ch', 'fr-ch'],
2389
            ['fr', 'fr'],
2390
            ['fy', 'fy'],
2391
            ['gd', 'gd'],
2392
            ['gl', 'gl'],
2393
            ['he', 'he'],
2394
            ['hi', 'hi'],
2395
            ['hr', 'hr'],
2396
            ['hu', 'hu'],
2397
            ['hy-am', 'hy-am'],
2398
            ['id', 'id'],
2399
            ['is', 'is'],
2400
            ['it', 'it'],
2401
            ['ja', 'ja'],
2402
            ['jv', 'jv'],
2403
            ['ka', 'ka'],
2404
            ['kk', 'kk'],
2405
            ['km', 'km'],
2406
            ['ko', 'ko'],
2407
            ['ky', 'ky'],
2408
            ['lb', 'lb'],
2409
            ['lo', 'lo'],
2410
            ['lt', 'lt'],
2411
            ['lv', 'lv'],
2412
            ['me', 'me'],
2413
            ['mi', 'mi'],
2414
            ['mk', 'mk'],
2415
            ['ml', 'ml'],
2416
            ['mr', 'mr'],
2417
            ['ms', 'ms'],
2418
            ['ms-my', 'ms-my'],
2419
            ['my', 'my'],
2420
            ['nb', 'nb'],
2421
            ['ne', 'ne'],
2422
            ['nl-be', 'nl-be'],
2423
            ['nl', 'nl'],
2424
            ['nl', 'nl-nl'],
2425
            ['nn', 'nn'],
2426
            ['pa-in', 'pa-in'],
2427
            ['pl', 'pl'],
2428
            ['pt-br', 'pt-br'],
2429
            ['pt', 'pt'],
2430
            ['ro', 'ro'],
2431
            ['ru', 'ru'],
2432
            ['se', 'se'],
2433
            ['si', 'si'],
2434
            ['sk', 'sk'],
2435
            ['sl', 'sl'],
2436
            ['sq', 'sq'],
2437
            ['sr-cyrl', 'sr-cyrl'],
2438
            ['sr', 'sr'],
2439
            ['ss', 'ss'],
2440
            ['sv', 'sv'],
2441
            ['sw', 'sw'],
2442
            ['ta', 'ta'],
2443
            ['te', 'te'],
2444
            ['tet', 'tet'],
2445
            ['th', 'th'],
2446
            ['tlh', 'tlh'],
2447
            ['tl-ph', 'tl-ph'],
2448
            ['tr', 'tr'],
2449
            ['tzl', 'tzl'],
2450
            ['tzm', 'tzm'],
2451
            ['tzm-latn', 'tzm-latn'],
2452
            ['uk', 'uk'],
2453
            ['uz', 'uz'],
2454
            ['vi', 'vi'],
2455
            ['x-pseudo', 'x-pseudo'],
2456
            ['yo', 'yo'],
2457
            ['zh-cn', 'zh-cn'],
2458
            ['zh-hk', 'zh-hk'],
2459
            ['zh-tw', 'zh-tw'],
2460
        ];
2461
    }
2462
2463
    /**
2464
     * @dataProvider momentLocalesProvider
2465
     */
2466
    public function testCanonicalizedLocaleForMoment($expected, $original): void
2467
    {
2468
        $this->assertSame($expected, $this->twigExtension->getCanonicalizedLocaleForMoment($this->mockExtensionContext($original)));
2469
    }
2470
2471
    public function testIsGrantedAffirmative(): void
2472
    {
2473
        $this->assertTrue(
2474
            $this->twigExtension->isGrantedAffirmative(['foo', 'bar'])
2475
        );
2476
        $this->assertTrue($this->twigExtension->isGrantedAffirmative('foo'));
2477
        $this->assertTrue($this->twigExtension->isGrantedAffirmative('bar'));
2478
    }
2479
2480
    /**
2481
     * This method generates url part for Twig layout.
2482
     *
2483
     * @param array $url
2484
     *
2485
     * @return string
2486
     */
2487
    private function buildTwigLikeUrl($url)
2488
    {
2489
        return htmlspecialchars(http_build_query($url, '', '&', PHP_QUERY_RFC3986));
2490
    }
2491
2492
    private function getMethodAsPublic($privateMethod)
2493
    {
2494
        $reflection = new \ReflectionMethod('Sonata\AdminBundle\Twig\Extension\SonataAdminExtension', $privateMethod);
2495
        $reflection->setAccessible(true);
2496
2497
        return $reflection;
2498
    }
2499
2500
    private function removeExtraWhitespace($string)
2501
    {
2502
        return trim(preg_replace(
2503
            '/\s+/',
2504
            ' ',
2505
            $string
2506
        ));
2507
    }
2508
2509
    private function mockExtensionContext($locale)
2510
    {
2511
        $request = $this->createMock(Request::class);
2512
        $request->method('getLocale')->willReturn($locale);
2513
        $appVariable = $this->createMock(AppVariable::class);
2514
        $appVariable->method('getRequest')->willReturn($request);
2515
2516
        return ['app' => $appVariable];
2517
    }
2518
}
2519