Completed
Push — 3.x ( a302a7...034439 )
by Grégoire
04:21
created

SonataAdminExtensionTest::testRenderListElement()   D

Complexity

Conditions 16
Paths 1

Size

Total Lines 83
Code Lines 65

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 83
rs 4.8945
c 0
b 0
f 0
cc 16
eloc 65
nc 1
nop 4

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/*
4
 * This file is part of the Sonata Project package.
5
 *
6
 * (c) Thomas Rabaix <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Sonata\AdminBundle\Tests\Twig\Extension;
13
14
use PHPUnit\Framework\TestCase;
15
use Psr\Log\LoggerInterface;
16
use Sonata\AdminBundle\Admin\AbstractAdmin;
17
use Sonata\AdminBundle\Admin\AdminInterface;
18
use Sonata\AdminBundle\Admin\FieldDescriptionInterface;
19
use Sonata\AdminBundle\Admin\Pool;
20
use Sonata\AdminBundle\Exception\NoValueException;
21
use Sonata\AdminBundle\Templating\TemplateRegistryInterface;
22
use Sonata\AdminBundle\Tests\Fixtures\Entity\FooToString;
23
use Sonata\AdminBundle\Twig\Extension\SonataAdminExtension;
24
use Symfony\Bridge\Twig\AppVariable;
25
use Symfony\Bridge\Twig\Extension\RoutingExtension;
26
use Symfony\Bridge\Twig\Extension\TranslationExtension;
27
use Symfony\Bridge\Twig\Tests\Extension\Fixtures\StubFilesystemLoader;
28
use Symfony\Component\Config\FileLocator;
29
use Symfony\Component\DependencyInjection\ContainerInterface;
30
use Symfony\Component\HttpFoundation\Request;
31
use Symfony\Component\Routing\Generator\UrlGenerator;
32
use Symfony\Component\Routing\Loader\XmlFileLoader;
33
use Symfony\Component\Routing\RequestContext;
34
use Symfony\Component\Translation\DependencyInjection\TranslationDumperPass;
35
use Symfony\Component\Translation\Loader\XliffFileLoader;
36
use Symfony\Component\Translation\MessageSelector;
37
use Symfony\Component\Translation\Translator;
38
use Symfony\Component\Translation\TranslatorInterface;
39
40
/**
41
 * Test for SonataAdminExtension.
42
 *
43
 * @author Andrej Hudec <[email protected]>
44
 */
45
class SonataAdminExtensionTest extends TestCase
46
{
47
    /**
48
     * @var SonataAdminExtension
49
     */
50
    private $twigExtension;
51
52
    /**
53
     * @var \Twig_Environment
54
     */
55
    private $environment;
56
57
    /**
58
     * @var AdminInterface
59
     */
60
    private $admin;
61
62
    /**
63
     * @var AdminInterface
64
     */
65
    private $adminBar;
66
67
    /**
68
     * @var FieldDescriptionInterface
69
     */
70
    private $fieldDescription;
71
72
    /**
73
     * @var \stdClass
74
     */
75
    private $object;
76
77
    /**
78
     * @var Pool
79
     */
80
    private $pool;
81
82
    /**
83
     * @var LoggerInterface
84
     */
85
    private $logger;
86
87
    /**
88
     * @var string[]
89
     */
90
    private $xEditableTypeMapping;
91
92
    /**
93
     * @var TranslatorInterface
94
     */
95
    private $translator;
96
97
    /**
98
     * @var ContainerInterface
99
     */
100
    private $container;
101
102
    /**
103
     * @var TemplateRegistryInterface
104
     */
105
    private $templateRegistry;
106
107
    public function setUp()
108
    {
109
        date_default_timezone_set('Europe/London');
110
111
        $container = $this->getMockForAbstractClass(ContainerInterface::class);
112
113
        $this->pool = new Pool($container, '', '');
114
        $this->pool->setAdminServiceIds(['sonata_admin_foo_service']);
115
        $this->pool->setAdminClasses(['fooClass' => ['sonata_admin_foo_service']]);
116
117
        $this->logger = $this->getMockForAbstractClass(LoggerInterface::class);
118
        $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...
119
            'choice' => 'select',
120
            'boolean' => 'select',
121
            'text' => 'text',
122
            'textarea' => 'textarea',
123
            'html' => 'textarea',
124
            'email' => 'email',
125
            'string' => 'text',
126
            'smallint' => 'text',
127
            'bigint' => 'text',
128
            'integer' => 'number',
129
            'decimal' => 'number',
130
            'currency' => 'number',
131
            'percent' => 'number',
132
            'url' => 'url',
133
        ];
134
135
        // translation extension
136
        $translator = new Translator(
137
            'en',
138
            // NEXT_MAJOR: simplify this when dropping symfony < 3.4
139
            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...
140
        );
141
        $translator->addLoader('xlf', new XliffFileLoader());
142
        $translator->addResource(
143
            'xlf',
144
            __DIR__.'/../../../src/Resources/translations/SonataAdminBundle.en.xliff',
145
            'en',
146
            'SonataAdminBundle'
147
        );
148
149
        $this->translator = $translator;
150
151
        $this->templateRegistry = $this->prophesize(TemplateRegistryInterface::class);
152
        $this->container = $this->prophesize(ContainerInterface::class);
153
        $this->container->get('sonata_admin_foo_service.template_registry')->willReturn($this->templateRegistry->reveal());
154
155
        $this->twigExtension = new SonataAdminExtension($this->pool, $this->logger, $this->translator, $this->container->reveal());
156
        $this->twigExtension->setXEditableTypeMapping($this->xEditableTypeMapping);
157
158
        $request = $this->createMock(Request::class);
159
        $request->expects($this->any())->method('get')->with('_sonata_admin')->willReturn('sonata_admin_foo_service');
160
161
        $loader = new StubFilesystemLoader([
162
            __DIR__.'/../../../src/Resources/views/CRUD',
163
        ]);
164
        $loader->addPath(__DIR__.'/../../../src/Resources/views/', 'SonataAdmin');
165
166
        $this->environment = new \Twig_Environment($loader, [
167
            'strict_variables' => true,
168
            'cache' => false,
169
            'autoescape' => 'html',
170
            'optimizations' => 0,
171
        ]);
172
        $this->environment->addExtension($this->twigExtension);
173
        $this->environment->addExtension(new TranslationExtension($translator));
174
        $this->environment->addExtension(new FakeTemplateRegistryExtension());
175
176
        // routing extension
177
        $xmlFileLoader = new XmlFileLoader(new FileLocator([__DIR__.'/../../../src/Resources/config/routing']));
178
        $routeCollection = $xmlFileLoader->load('sonata_admin.xml');
179
180
        $xmlFileLoader = new XmlFileLoader(new FileLocator([__DIR__.'/../../Fixtures/Resources/config/routing']));
181
        $testRouteCollection = $xmlFileLoader->load('routing.xml');
182
183
        $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...
184
        $requestContext = new RequestContext();
185
        $urlGenerator = new UrlGenerator($routeCollection, $requestContext);
186
        $this->environment->addExtension(new RoutingExtension($urlGenerator));
187
        $this->environment->addExtension(new \Twig_Extensions_Extension_Text());
188
189
        // initialize object
190
        $this->object = new \stdClass();
191
192
        // initialize admin
193
        $this->admin = $this->createMock(AbstractAdmin::class);
194
195
        $this->admin->expects($this->any())
196
            ->method('getCode')
197
            ->will($this->returnValue('sonata_admin_foo_service'));
198
199
        $this->admin->expects($this->any())
200
            ->method('id')
201
            ->with($this->equalTo($this->object))
202
            ->will($this->returnValue(12345));
203
204
        $this->admin->expects($this->any())
205
            ->method('getNormalizedIdentifier')
206
            ->with($this->equalTo($this->object))
207
            ->will($this->returnValue(12345));
208
209
        $this->admin->expects($this->any())
210
            ->method('trans')
211
            ->will($this->returnCallback(function ($id, $parameters = [], $domain = null) use ($translator) {
212
                return $translator->trans($id, $parameters, $domain);
213
            }));
214
215
        $this->adminBar = $this->createMock(AbstractAdmin::class);
216
        $this->adminBar->expects($this->any())
217
            ->method('hasAccess')
218
            ->will($this->returnValue(true));
219
        $this->adminBar->expects($this->any())
220
            ->method('getNormalizedIdentifier')
221
            ->with($this->equalTo($this->object))
222
            ->will($this->returnValue(12345));
223
224
        $container->expects($this->any())
225
            ->method('get')
226
            ->will($this->returnCallback(function ($id) {
227
                if ('sonata_admin_foo_service' == $id) {
228
                    return $this->admin;
229
                } elseif ('sonata_admin_bar_service' == $id) {
230
                    return $this->adminBar;
231
                }
232
            }));
233
234
        // initialize field description
235
        $this->fieldDescription = $this->getMockForAbstractClass(FieldDescriptionInterface::class);
236
237
        $this->fieldDescription->expects($this->any())
238
            ->method('getName')
239
            ->will($this->returnValue('fd_name'));
240
241
        $this->fieldDescription->expects($this->any())
242
            ->method('getAdmin')
243
            ->will($this->returnValue($this->admin));
244
245
        $this->fieldDescription->expects($this->any())
246
            ->method('getLabel')
247
            ->will($this->returnValue('Data'));
248
    }
249
250
    /**
251
     * @dataProvider getRenderListElementTests
252
     */
253
    public function testRenderListElement($expected, $type, $value, array $options)
254
    {
255
        $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...
256
            ->method('getPersistentParameters')
257
            ->will($this->returnValue(['context' => 'foo']));
258
259
        $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...
260
            ->method('hasAccess')
261
            ->will($this->returnValue(true));
262
263
        // NEXT_MAJOR: Remove this line
264
        $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...
265
            ->method('getTemplate')
266
            ->with('base_list_field')
267
            ->willReturn('@SonataAdmin/CRUD/base_list_field.html.twig');
268
269
        $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...
270
271
        $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...
272
            ->method('getValue')
273
            ->will($this->returnValue($value));
274
275
        $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...
276
            ->method('getType')
277
            ->will($this->returnValue($type));
278
279
        $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...
280
            ->method('getOptions')
281
            ->will($this->returnValue($options));
282
283
        $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...
284
            ->method('getOption')
285
            ->will($this->returnCallback(function ($name, $default = null) use ($options) {
286
                return isset($options[$name]) ? $options[$name] : $default;
287
            }));
288
289
        $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...
290
            ->method('getTemplate')
291
            ->will($this->returnCallback(function () use ($type) {
292
                switch ($type) {
293
                    case 'string':
294
                        return '@SonataAdmin/CRUD/list_string.html.twig';
295
                    case 'boolean':
296
                        return '@SonataAdmin/CRUD/list_boolean.html.twig';
297
                    case 'datetime':
298
                        return '@SonataAdmin/CRUD/list_datetime.html.twig';
299
                    case 'date':
300
                        return '@SonataAdmin/CRUD/list_date.html.twig';
301
                    case 'time':
302
                        return '@SonataAdmin/CRUD/list_time.html.twig';
303
                    case 'currency':
304
                        return '@SonataAdmin/CRUD/list_currency.html.twig';
305
                    case 'percent':
306
                        return '@SonataAdmin/CRUD/list_percent.html.twig';
307
                    case 'email':
308
                        return '@SonataAdmin/CRUD/list_email.html.twig';
309
                    case 'choice':
310
                        return '@SonataAdmin/CRUD/list_choice.html.twig';
311
                    case 'array':
312
                        return '@SonataAdmin/CRUD/list_array.html.twig';
313
                    case 'trans':
314
                        return '@SonataAdmin/CRUD/list_trans.html.twig';
315
                    case 'url':
316
                        return '@SonataAdmin/CRUD/list_url.html.twig';
317
                    case 'html':
318
                        return '@SonataAdmin/CRUD/list_html.html.twig';
319
                    case 'nonexistent':
320
                        // template doesn`t exist
321
                        return '@SonataAdmin/CRUD/list_nonexistent_template.html.twig';
322
                    default:
323
                        return false;
324
                }
325
            }));
326
327
        $this->assertSame(
328
            $this->removeExtraWhitespace($expected),
329
            $this->removeExtraWhitespace($this->twigExtension->renderListElement(
330
                $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...
331
                $this->object,
332
                $this->fieldDescription
333
            ))
334
        );
335
    }
336
337
    /**
338
     * @dataProvider getDeprecatedRenderListElementTests
339
     * @group legacy
340
     */
341
    public function testDeprecatedRenderListElement($expected, $value, array $options)
342
    {
343
        $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...
344
            ->method('hasAccess')
345
            ->will($this->returnValue(true));
346
347
        // NEXT_MAJOR: Remove this line
348
        $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...
349
            ->method('getTemplate')
350
            ->with('base_list_field')
351
            ->willReturn('@SonataAdmin/CRUD/base_list_field.html.twig');
352
353
        $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...
354
355
        $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...
356
            ->method('getValue')
357
            ->will($this->returnValue($value));
358
359
        $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...
360
            ->method('getType')
361
            ->will($this->returnValue('nonexistent'));
362
363
        $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...
364
            ->method('getOptions')
365
            ->will($this->returnValue($options));
366
367
        $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...
368
            ->method('getOption')
369
            ->will($this->returnCallback(function ($name, $default = null) use ($options) {
370
                return isset($options[$name]) ? $options[$name] : $default;
371
            }));
372
373
        $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...
374
            ->method('getTemplate')
375
            ->will($this->returnValue('@SonataAdmin/CRUD/list_nonexistent_template.html.twig'));
376
377
        $this->assertSame(
378
            $this->removeExtraWhitespace($expected),
379
            $this->removeExtraWhitespace($this->twigExtension->renderListElement(
380
                $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...
381
                $this->object,
382
                $this->fieldDescription
383
            ))
384
        );
385
    }
386
387
    public function getDeprecatedRenderListElementTests()
388
    {
389
        return [
390
            [
391
                '<td class="sonata-ba-list-field sonata-ba-list-field-nonexistent" objectId="12345"> Example </td>',
392
                'Example',
393
                [],
394
            ],
395
            [
396
                '<td class="sonata-ba-list-field sonata-ba-list-field-nonexistent" objectId="12345"> </td>',
397
                null,
398
                [],
399
            ],
400
        ];
401
    }
402
403
    public function getRenderListElementTests()
404
    {
405
        return [
406
            [
407
                '<td class="sonata-ba-list-field sonata-ba-list-field-string" objectId="12345"> Example </td>',
408
                'string',
409
                'Example',
410
                [],
411
            ],
412
            [
413
                '<td class="sonata-ba-list-field sonata-ba-list-field-string" objectId="12345"> </td>',
414
                'string',
415
                null,
416
                [],
417
            ],
418
            [
419
                '<td class="sonata-ba-list-field sonata-ba-list-field-text" objectId="12345"> Example </td>',
420
                'text',
421
                'Example',
422
                [],
423
            ],
424
            [
425
                '<td class="sonata-ba-list-field sonata-ba-list-field-text" objectId="12345"> </td>',
426
                'text',
427
                null,
428
                [],
429
            ],
430
            [
431
                '<td class="sonata-ba-list-field sonata-ba-list-field-textarea" objectId="12345"> Example </td>',
432
                'textarea',
433
                'Example',
434
                [],
435
            ],
436
            [
437
                '<td class="sonata-ba-list-field sonata-ba-list-field-textarea" objectId="12345"> </td>',
438
                'textarea',
439
                null,
440
                [],
441
            ],
442
            'datetime field' => [
443
                '<td class="sonata-ba-list-field sonata-ba-list-field-datetime" objectId="12345">
444
                    December 24, 2013 10:11
445
                </td>',
446
                'datetime',
447
                new \DateTime('2013-12-24 10:11:12', new \DateTimeZone('Europe/London')),
448
                [],
449
            ],
450
            [
451
                '<td class="sonata-ba-list-field sonata-ba-list-field-datetime" objectId="12345">
452
                    December 24, 2013 18:11
453
                </td>',
454
                'datetime',
455
                new \DateTime('2013-12-24 10:11:12', new \DateTimeZone('UTC')),
456
                ['timezone' => 'Asia/Hong_Kong'],
457
            ],
458
            [
459
                '<td class="sonata-ba-list-field sonata-ba-list-field-datetime" objectId="12345"> &nbsp; </td>',
460
                'datetime',
461
                null,
462
                [],
463
            ],
464
            [
465
                '<td class="sonata-ba-list-field sonata-ba-list-field-datetime" objectId="12345">
466
                    24.12.2013 10:11:12
467
                </td>',
468
                'datetime',
469
                new \DateTime('2013-12-24 10:11:12', new \DateTimeZone('Europe/London')),
470
                ['format' => 'd.m.Y H:i:s'],
471
            ],
472
            [
473
                '<td class="sonata-ba-list-field sonata-ba-list-field-datetime" objectId="12345"> &nbsp; </td>',
474
                'datetime',
475
                null,
476
                ['format' => 'd.m.Y H:i:s'],
477
            ],
478
            [
479
                '<td class="sonata-ba-list-field sonata-ba-list-field-datetime" objectId="12345">
480
                    24.12.2013 18:11:12
481
                </td>',
482
                'datetime',
483
                new \DateTime('2013-12-24 10:11:12', new \DateTimeZone('UTC')),
484
                ['format' => 'd.m.Y H:i:s', 'timezone' => 'Asia/Hong_Kong'],
485
            ],
486
            [
487
                '<td class="sonata-ba-list-field sonata-ba-list-field-datetime" objectId="12345"> &nbsp; </td>',
488
                'datetime',
489
                null,
490
                ['format' => 'd.m.Y H:i:s', 'timezone' => 'Asia/Hong_Kong'],
491
            ],
492
            [
493
                '<td class="sonata-ba-list-field sonata-ba-list-field-date" objectId="12345"> December 24, 2013 </td>',
494
                'date',
495
                new \DateTime('2013-12-24 10:11:12', new \DateTimeZone('Europe/London')),
496
                [],
497
            ],
498
            [
499
                '<td class="sonata-ba-list-field sonata-ba-list-field-date" objectId="12345"> &nbsp; </td>',
500
                'date',
501
                null,
502
                [],
503
            ],
504
            [
505
                '<td class="sonata-ba-list-field sonata-ba-list-field-date" objectId="12345"> 24.12.2013 </td>',
506
                'date',
507
                new \DateTime('2013-12-24 10:11:12', new \DateTimeZone('Europe/London')),
508
                ['format' => 'd.m.Y'],
509
            ],
510
            [
511
                '<td class="sonata-ba-list-field sonata-ba-list-field-date" objectId="12345"> &nbsp; </td>',
512
                'date',
513
                null,
514
                ['format' => 'd.m.Y'],
515
            ],
516
            [
517
                '<td class="sonata-ba-list-field sonata-ba-list-field-time" objectId="12345"> 10:11:12 </td>',
518
                'time',
519
                new \DateTime('2013-12-24 10:11:12', new \DateTimeZone('Europe/London')),
520
                [],
521
            ],
522
            [
523
                '<td class="sonata-ba-list-field sonata-ba-list-field-time" objectId="12345"> &nbsp; </td>',
524
                'time',
525
                null,
526
                [],
527
            ],
528
            [
529
                '<td class="sonata-ba-list-field sonata-ba-list-field-number" objectId="12345"> 10.746135 </td>',
530
                'number', 10.746135,
531
                [],
532
            ],
533
            [
534
                '<td class="sonata-ba-list-field sonata-ba-list-field-number" objectId="12345"> </td>',
535
                'number',
536
                null,
537
                [],
538
            ],
539
            [
540
                '<td class="sonata-ba-list-field sonata-ba-list-field-integer" objectId="12345"> 5678 </td>',
541
                'integer',
542
                5678,
543
                [],
544
            ],
545
            [
546
                '<td class="sonata-ba-list-field sonata-ba-list-field-integer" objectId="12345"> </td>',
547
                'integer',
548
                null,
549
                [],
550
            ],
551
            [
552
                '<td class="sonata-ba-list-field sonata-ba-list-field-percent" objectId="12345"> 1074.6135 % </td>',
553
                'percent',
554
                10.746135,
555
                [],
556
            ],
557
            [
558
                '<td class="sonata-ba-list-field sonata-ba-list-field-percent" objectId="12345"> 0 % </td>',
559
                'percent',
560
                null,
561
                [],
562
            ],
563
            [
564
                '<td class="sonata-ba-list-field sonata-ba-list-field-currency" objectId="12345"> EUR 10.746135 </td>',
565
                'currency',
566
                10.746135,
567
                ['currency' => 'EUR'],
568
            ],
569
            [
570
                '<td class="sonata-ba-list-field sonata-ba-list-field-currency" objectId="12345"> </td>',
571
                'currency',
572
                null,
573
                ['currency' => 'EUR'],
574
            ],
575
            [
576
                '<td class="sonata-ba-list-field sonata-ba-list-field-currency" objectId="12345"> GBP 51.23456 </td>',
577
                'currency',
578
                51.23456,
579
                ['currency' => 'GBP'],
580
            ],
581
            [
582
                '<td class="sonata-ba-list-field sonata-ba-list-field-currency" objectId="12345"> </td>',
583
                'currency',
584
                null,
585
                ['currency' => 'GBP'],
586
            ],
587
            [
588
                '<td class="sonata-ba-list-field sonata-ba-list-field-email" objectId="12345"> &nbsp; </td>',
589
                'email',
590
                null,
591
                [],
592
            ],
593
            [
594
                '<td class="sonata-ba-list-field sonata-ba-list-field-email" objectId="12345"> <a href="mailto:[email protected]">[email protected]</a> </td>',
595
                'email',
596
                '[email protected]',
597
                [],
598
            ],
599
            [
600
                '<td class="sonata-ba-list-field sonata-ba-list-field-email" objectId="12345">
601
                    <a href="mailto:[email protected]">[email protected]</a> </td>',
602
                'email',
603
                '[email protected]',
604
                ['as_string' => false],
605
            ],
606
            [
607
                '<td class="sonata-ba-list-field sonata-ba-list-field-email" objectId="12345"> [email protected] </td>',
608
                'email',
609
                '[email protected]',
610
                ['as_string' => true],
611
            ],
612
            [
613
                '<td class="sonata-ba-list-field sonata-ba-list-field-email" objectId="12345">
614
                    <a href="mailto:[email protected]?'.$this->buildTwigLikeUrl(['subject' => 'Main Theme', 'body' => 'Message Body']).'">[email protected]</a>  </td>',
615
                'email',
616
                '[email protected]',
617
                ['subject' => 'Main Theme', 'body' => 'Message Body'],
618
            ],
619
            [
620
                '<td class="sonata-ba-list-field sonata-ba-list-field-email" objectId="12345">
621
                    <a href="mailto:[email protected]?'.$this->buildTwigLikeUrl(['subject' => 'Main Theme']).'">[email protected]</a>  </td>',
622
                'email',
623
                '[email protected]',
624
                ['subject' => 'Main Theme'],
625
            ],
626
            [
627
                '<td class="sonata-ba-list-field sonata-ba-list-field-email" objectId="12345">
628
                    <a href="mailto:[email protected]?'.$this->buildTwigLikeUrl(['body' => 'Message Body']).'">[email protected]</a>  </td>',
629
                'email',
630
                '[email protected]',
631
                ['body' => 'Message Body'],
632
            ],
633
            [
634
                '<td class="sonata-ba-list-field sonata-ba-list-field-email" objectId="12345"> [email protected] </td>',
635
                'email',
636
                '[email protected]',
637
                ['as_string' => true, 'subject' => 'Main Theme', 'body' => 'Message Body'],
638
            ],
639
            [
640
                '<td class="sonata-ba-list-field sonata-ba-list-field-email" objectId="12345"> [email protected] </td>',
641
                'email',
642
                '[email protected]',
643
                ['as_string' => true, 'body' => 'Message Body'],
644
            ],
645
            [
646
                '<td class="sonata-ba-list-field sonata-ba-list-field-email" objectId="12345"> [email protected] </td>',
647
                'email',
648
                '[email protected]',
649
                ['as_string' => true, 'subject' => 'Main Theme'],
650
            ],
651
            [
652
                '<td class="sonata-ba-list-field sonata-ba-list-field-array" objectId="12345">
653
                    [1 => First] [2 => Second]
654
                </td>',
655
                'array',
656
                [1 => 'First', 2 => 'Second'],
657
                [],
658
            ],
659
            [
660
                '<td class="sonata-ba-list-field sonata-ba-list-field-array" objectId="12345"> </td>',
661
                'array',
662
                null,
663
                [],
664
            ],
665
            [
666
                '<td class="sonata-ba-list-field sonata-ba-list-field-boolean" objectId="12345">
667
                    <span class="label label-success">yes</span>
668
                </td>',
669
                'boolean',
670
                true,
671
                ['editable' => false],
672
            ],
673
            [
674
                '<td class="sonata-ba-list-field sonata-ba-list-field-boolean" objectId="12345">
675
                    <span class="label label-danger">no</span>
676
                </td>',
677
                'boolean',
678
                false,
679
                ['editable' => false],
680
            ],
681
            [
682
                '<td class="sonata-ba-list-field sonata-ba-list-field-boolean" objectId="12345">
683
                    <span class="label label-danger">no</span>
684
                </td>',
685
                'boolean',
686
                null,
687
                ['editable' => false],
688
            ],
689
            [
690
                <<<'EOT'
691
<td class="sonata-ba-list-field sonata-ba-list-field-boolean" objectId="12345">
692
    <span
693
        class="x-editable"
694
        data-type="select"
695
        data-value="1"
696
        data-title="Data"
697
        data-pk="12345"
698
        data-url="/core/set-object-field-value?context=list&amp;field=fd_name&amp;objectId=12345&amp;code=sonata_admin_foo_service"
699
        data-source="[{value: 0, text: 'no'},{value: 1, text: 'yes'}]"
700
    >
701
        <span class="label label-success">yes</span>
702
    </span>
703
</td>
704
EOT
705
            ,
706
                'boolean',
707
                true,
708
                ['editable' => true],
709
            ],
710
            [
711
                <<<'EOT'
712
<td class="sonata-ba-list-field sonata-ba-list-field-boolean" objectId="12345">
713
    <span
714
        class="x-editable"
715
        data-type="select"
716
        data-value="0"
717
        data-title="Data"
718
        data-pk="12345"
719
        data-url="/core/set-object-field-value?context=list&amp;field=fd_name&amp;objectId=12345&amp;code=sonata_admin_foo_service"
720
        data-source="[{value: 0, text: 'no'},{value: 1, text: 'yes'}]"
721
    >
722
    <span class="label label-danger">no</span> </span>
723
</td>
724
EOT
725
                ,
726
                'boolean',
727
                false,
728
                ['editable' => true],
729
            ],
730
            [
731
                <<<'EOT'
732
<td class="sonata-ba-list-field sonata-ba-list-field-boolean" objectId="12345">
733
    <span
734
        class="x-editable"
735
        data-type="select"
736
        data-value="0"
737
        data-title="Data"
738
        data-pk="12345"
739
        data-url="/core/set-object-field-value?context=list&amp;field=fd_name&amp;objectId=12345&amp;code=sonata_admin_foo_service"
740
        data-source="[{value: 0, text: 'no'},{value: 1, text: 'yes'}]" >
741
        <span class="label label-danger">no</span> </span>
742
</td>
743
EOT
744
                ,
745
                'boolean',
746
                null,
747
                ['editable' => true],
748
            ],
749
            [
750
                '<td class="sonata-ba-list-field sonata-ba-list-field-trans" objectId="12345"> Delete </td>',
751
                'trans',
752
                'action_delete',
753
                ['catalogue' => 'SonataAdminBundle'],
754
            ],
755
            [
756
                '<td class="sonata-ba-list-field sonata-ba-list-field-trans" objectId="12345"> </td>',
757
                'trans',
758
                null,
759
                ['catalogue' => 'SonataAdminBundle'],
760
            ],
761
            [
762
                '<td class="sonata-ba-list-field sonata-ba-list-field-trans" objectId="12345"> Delete </td>',
763
                'trans',
764
                'action_delete',
765
                ['format' => '%s', 'catalogue' => 'SonataAdminBundle'],
766
            ],
767
            [
768
                '<td class="sonata-ba-list-field sonata-ba-list-field-trans" objectId="12345">
769
                action.action_delete
770
                </td>',
771
                'trans',
772
                'action_delete',
773
                ['format' => 'action.%s'],
774
            ],
775
            [
776
                '<td class="sonata-ba-list-field sonata-ba-list-field-trans" objectId="12345">
777
                action.action_delete
778
                </td>',
779
                'trans',
780
                'action_delete',
781
                ['format' => 'action.%s', 'catalogue' => 'SonataAdminBundle'],
782
            ],
783
            [
784
                '<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345"> Status1 </td>',
785
                'choice',
786
                'Status1',
787
                [],
788
            ],
789
            [
790
                '<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345"> Status1 </td>',
791
                'choice',
792
                ['Status1'],
793
                ['choices' => [], 'multiple' => true],
794
            ],
795
            [
796
                '<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345"> Alias1 </td>',
797
                'choice',
798
                'Status1',
799
                ['choices' => ['Status1' => 'Alias1', 'Status2' => 'Alias2', 'Status3' => 'Alias3']],
800
            ],
801
            [
802
                '<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345"> </td>',
803
                'choice',
804
                null,
805
                ['choices' => ['Status1' => 'Alias1', 'Status2' => 'Alias2', 'Status3' => 'Alias3']],
806
            ],
807
            [
808
                '<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345">
809
                NoValidKeyInChoices
810
                </td>',
811
                'choice',
812
                'NoValidKeyInChoices',
813
                ['choices' => ['Status1' => 'Alias1', 'Status2' => 'Alias2', 'Status3' => 'Alias3']],
814
            ],
815
            [
816
                '<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345"> Delete </td>',
817
                'choice',
818
                'Foo',
819
                ['catalogue' => 'SonataAdminBundle', 'choices' => [
820
                    'Foo' => 'action_delete',
821
                    'Status2' => 'Alias2',
822
                    'Status3' => 'Alias3',
823
                ]],
824
            ],
825
            [
826
                '<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345"> Alias1, Alias3 </td>',
827
                'choice',
828
                ['Status1', 'Status3'],
829
                ['choices' => [
830
                    'Status1' => 'Alias1',
831
                    'Status2' => 'Alias2',
832
                    'Status3' => 'Alias3',
833
                ], 'multiple' => true], ],
834
            [
835
                '<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345"> Alias1 | Alias3 </td>',
836
                'choice',
837
                ['Status1', 'Status3'],
838
                ['choices' => [
839
                    'Status1' => 'Alias1',
840
                    'Status2' => 'Alias2',
841
                    'Status3' => 'Alias3',
842
                ], 'multiple' => true, 'delimiter' => ' | '], ],
843
            [
844
                '<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345"> </td>',
845
                'choice',
846
                null,
847
                ['choices' => [
848
                    'Status1' => 'Alias1',
849
                    'Status2' => 'Alias2',
850
                    'Status3' => 'Alias3',
851
                ], 'multiple' => true],
852
            ],
853
            [
854
                '<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345">
855
                NoValidKeyInChoices
856
                </td>',
857
                'choice',
858
                ['NoValidKeyInChoices'],
859
                ['choices' => [
860
                    'Status1' => 'Alias1',
861
                    'Status2' => 'Alias2',
862
                    'Status3' => 'Alias3',
863
                ], 'multiple' => true],
864
            ],
865
            [
866
                '<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345">
867
                NoValidKeyInChoices, Alias2
868
                </td>',
869
                'choice',
870
                ['NoValidKeyInChoices', 'Status2'],
871
                ['choices' => [
872
                    'Status1' => 'Alias1',
873
                    'Status2' => 'Alias2',
874
                    'Status3' => 'Alias3',
875
                ], 'multiple' => true],
876
            ],
877
            [
878
                '<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345"> Delete, Alias3 </td>',
879
                'choice',
880
                ['Foo', 'Status3'],
881
                ['catalogue' => 'SonataAdminBundle', 'choices' => [
882
                    'Foo' => 'action_delete',
883
                    'Status2' => 'Alias2',
884
                    'Status3' => 'Alias3',
885
                ], 'multiple' => true],
886
            ],
887
            [
888
                '<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345">
889
                &lt;b&gt;Alias1&lt;/b&gt;, &lt;b&gt;Alias3&lt;/b&gt;
890
            </td>',
891
                'choice',
892
                ['Status1', 'Status3'],
893
                ['choices' => [
894
                    'Status1' => '<b>Alias1</b>',
895
                    'Status2' => '<b>Alias2</b>',
896
                    'Status3' => '<b>Alias3</b>',
897
                ], 'multiple' => true], ],
898
            [
899
                <<<'EOT'
900
<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345">
901
    <span
902
        class="x-editable"
903
        data-type="select"
904
        data-value="Status1"
905
        data-title="Data"
906
        data-pk="12345"
907
        data-url="/core/set-object-field-value?context=list&amp;field=fd_name&amp;objectId=12345&amp;code=sonata_admin_foo_service"
908
        data-source="[]"
909
    >
910
        Status1
911
    </span>
912
</td>
913
EOT
914
                ,
915
                'choice',
916
                'Status1',
917
                ['editable' => true],
918
            ],
919
            [
920
                <<<'EOT'
921
<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345">
922
    <span
923
        class="x-editable"
924
        data-type="select"
925
        data-value="Status1"
926
        data-title="Data"
927
        data-pk="12345"
928
        data-url="/core/set-object-field-value?context=list&amp;field=fd_name&amp;objectId=12345&amp;code=sonata_admin_foo_service"
929
        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;}]" >
930
        Alias1 </span>
931
</td>
932
EOT
933
                ,
934
                'choice',
935
                'Status1',
936
                [
937
                    'editable' => true,
938
                    'choices' => [
939
                        'Status1' => 'Alias1',
940
                        'Status2' => 'Alias2',
941
                        'Status3' => 'Alias3',
942
                    ],
943
                ],
944
            ],
945
            [
946
                <<<'EOT'
947
<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345">
948
    <span
949
        class="x-editable"
950
        data-type="select"
951
        data-value=""
952
        data-title="Data"
953
        data-pk="12345"
954
        data-url="/core/set-object-field-value?context=list&amp;field=fd_name&amp;objectId=12345&amp;code=sonata_admin_foo_service"
955
        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;}]" >
956
957
    </span>
958
</td>
959
EOT
960
                ,
961
                'choice',
962
                null,
963
                [
964
                    'editable' => true,
965
                    'choices' => [
966
                        'Status1' => 'Alias1',
967
                        'Status2' => 'Alias2',
968
                        'Status3' => 'Alias3',
969
                    ],
970
                ],
971
            ],
972
            [
973
                <<<'EOT'
974
<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345">
975
    <span
976
        class="x-editable"
977
        data-type="select"
978
        data-value="NoValidKeyInChoices"
979
        data-title="Data" data-pk="12345"
980
        data-url="/core/set-object-field-value?context=list&amp;field=fd_name&amp;objectId=12345&amp;code=sonata_admin_foo_service"
981
        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;}]" >
982
        NoValidKeyInChoices
983
    </span>
984
</td>
985
EOT
986
                ,
987
                'choice',
988
                'NoValidKeyInChoices',
989
                [
990
                    'editable' => true,
991
                    'choices' => [
992
                        'Status1' => 'Alias1',
993
                        'Status2' => 'Alias2',
994
                        'Status3' => 'Alias3',
995
                    ],
996
                ],
997
            ],
998
            [
999
                <<<'EOT'
1000
<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345">
1001
    <span
1002
        class="x-editable"
1003
        data-type="select"
1004
        data-value="Foo"
1005
        data-title="Data"
1006
        data-pk="12345"
1007
        data-url="/core/set-object-field-value?context=list&amp;field=fd_name&amp;objectId=12345&amp;code=sonata_admin_foo_service"
1008
        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;}]" >
1009
         Delete
1010
    </span>
1011
</td>
1012
EOT
1013
                ,
1014
                'choice',
1015
                'Foo',
1016
                [
1017
                    'editable' => true,
1018
                    'catalogue' => 'SonataAdminBundle',
1019
                    'choices' => [
1020
                        'Foo' => 'action_delete',
1021
                        'Status2' => 'Alias2',
1022
                        'Status3' => 'Alias3',
1023
                    ],
1024
                ],
1025
            ],
1026
            [
1027
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345"> &nbsp; </td>',
1028
                'url',
1029
                null,
1030
                [],
1031
            ],
1032
            [
1033
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345"> &nbsp; </td>',
1034
                'url',
1035
                null,
1036
                ['url' => 'http://example.com'],
1037
            ],
1038
            [
1039
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345"> &nbsp; </td>',
1040
                'url',
1041
                null,
1042
                ['route' => ['name' => 'sonata_admin_foo']],
1043
            ],
1044
            [
1045
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
1046
                <a href="http://example.com">http://example.com</a>
1047
                </td>',
1048
                'url',
1049
                'http://example.com',
1050
                [],
1051
            ],
1052
            [
1053
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
1054
                <a href="https://example.com">https://example.com</a>
1055
                </td>',
1056
                'url',
1057
                'https://example.com',
1058
                [],
1059
            ],
1060
            [
1061
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
1062
                <a href="https://example.com" target="_blank">https://example.com</a>
1063
                </td>',
1064
                'url',
1065
                'https://example.com',
1066
                ['attributes' => ['target' => '_blank']],
1067
            ],
1068
            [
1069
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
1070
                <a href="https://example.com" target="_blank" class="fooLink">https://example.com</a>
1071
                </td>',
1072
                'url',
1073
                'https://example.com',
1074
                ['attributes' => ['target' => '_blank', 'class' => 'fooLink']],
1075
            ],
1076
            [
1077
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
1078
                <a href="http://example.com">example.com</a>
1079
                </td>',
1080
                'url',
1081
                'http://example.com',
1082
                ['hide_protocol' => true],
1083
            ],
1084
            [
1085
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
1086
                <a href="https://example.com">example.com</a>
1087
                </td>',
1088
                'url',
1089
                'https://example.com',
1090
                ['hide_protocol' => true],
1091
            ],
1092
            [
1093
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
1094
                <a href="http://example.com">http://example.com</a>
1095
                </td>',
1096
                'url',
1097
                'http://example.com',
1098
                ['hide_protocol' => false],
1099
            ],
1100
            [
1101
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
1102
                <a href="https://example.com">https://example.com</a>
1103
                </td>',
1104
                'url',
1105
                'https://example.com',
1106
                ['hide_protocol' => false],
1107
            ],
1108
            [
1109
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
1110
                <a href="http://example.com">Foo</a>
1111
                </td>',
1112
                'url',
1113
                'Foo',
1114
                ['url' => 'http://example.com'],
1115
            ],
1116
            [
1117
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
1118
                <a href="http://example.com">&lt;b&gt;Foo&lt;/b&gt;</a>
1119
                </td>',
1120
                'url',
1121
                '<b>Foo</b>',
1122
                ['url' => 'http://example.com'],
1123
            ],
1124
            [
1125
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
1126
                <a href="/foo">Foo</a>
1127
                </td>',
1128
                'url',
1129
                'Foo',
1130
                ['route' => ['name' => 'sonata_admin_foo']],
1131
            ],
1132
            [
1133
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
1134
                <a href="http://localhost/foo">Foo</a>
1135
                </td>',
1136
                'url',
1137
                'Foo',
1138
                ['route' => ['name' => 'sonata_admin_foo', 'absolute' => true]],
1139
            ],
1140
            [
1141
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
1142
                <a href="/foo">foo/bar?a=b&amp;c=123456789</a>
1143
                </td>',
1144
                'url',
1145
                'http://foo/bar?a=b&c=123456789',
1146
                ['route' => ['name' => 'sonata_admin_foo'],
1147
                'hide_protocol' => true, ],
1148
            ],
1149
            [
1150
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
1151
                <a href="http://localhost/foo">foo/bar?a=b&amp;c=123456789</a>
1152
                </td>',
1153
                'url',
1154
                'http://foo/bar?a=b&c=123456789',
1155
                [
1156
                    'route' => ['name' => 'sonata_admin_foo', 'absolute' => true],
1157
                    'hide_protocol' => true,
1158
                ],
1159
            ],
1160
            [
1161
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
1162
                <a href="/foo/abcd/efgh?param3=ijkl">Foo</a>
1163
                </td>',
1164
                'url',
1165
                'Foo',
1166
                [
1167
                    'route' => ['name' => 'sonata_admin_foo_param',
1168
                    'parameters' => ['param1' => 'abcd', 'param2' => 'efgh', 'param3' => 'ijkl'], ],
1169
                ],
1170
            ],
1171
            [
1172
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
1173
                <a href="http://localhost/foo/abcd/efgh?param3=ijkl">Foo</a>
1174
                </td>',
1175
                'url',
1176
                'Foo',
1177
                [
1178
                    'route' => ['name' => 'sonata_admin_foo_param',
1179
                    'absolute' => true,
1180
                    'parameters' => ['param1' => 'abcd', 'param2' => 'efgh', 'param3' => 'ijkl'], ],
1181
                ],
1182
            ],
1183
            [
1184
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
1185
                <a href="/foo/obj/abcd/12345/efgh?param3=ijkl">Foo</a>
1186
                </td>',
1187
                'url',
1188
                'Foo',
1189
                [
1190
                    'route' => ['name' => 'sonata_admin_foo_object',
1191
                    'parameters' => ['param1' => 'abcd', 'param2' => 'efgh', 'param3' => 'ijkl'],
1192
                    'identifier_parameter_name' => 'barId', ],
1193
                ],
1194
            ],
1195
            [
1196
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
1197
                <a href="http://localhost/foo/obj/abcd/12345/efgh?param3=ijkl">Foo</a>
1198
                </td>',
1199
                'url',
1200
                'Foo',
1201
                [
1202
                    'route' => ['name' => 'sonata_admin_foo_object',
1203
                    'absolute' => true,
1204
                    'parameters' => ['param1' => 'abcd', 'param2' => 'efgh', 'param3' => 'ijkl'],
1205
                    'identifier_parameter_name' => 'barId', ],
1206
                ],
1207
            ],
1208
            [
1209
                '<td class="sonata-ba-list-field sonata-ba-list-field-html" objectId="12345">
1210
                <p><strong>Creating a Template for the Field</strong> and form</p>
1211
                </td>',
1212
                'html',
1213
                '<p><strong>Creating a Template for the Field</strong> and form</p>',
1214
                [],
1215
            ],
1216
            [
1217
                '<td class="sonata-ba-list-field sonata-ba-list-field-html" objectId="12345">
1218
                Creating a Template for the Field and form
1219
                </td>',
1220
                'html',
1221
                '<p><strong>Creating a Template for the Field</strong> and form</p>',
1222
                ['strip' => true],
1223
            ],
1224
            [
1225
                '<td class="sonata-ba-list-field sonata-ba-list-field-html" objectId="12345">
1226
                Creating a Template for the Fi...
1227
                </td>',
1228
                'html',
1229
                '<p><strong>Creating a Template for the Field</strong> and form</p>',
1230
                ['truncate' => true],
1231
            ],
1232
            [
1233
                '<td class="sonata-ba-list-field sonata-ba-list-field-html" objectId="12345"> Creating a... </td>',
1234
                'html',
1235
                '<p><strong>Creating a Template for the Field</strong> and form</p>',
1236
                ['truncate' => ['length' => 10]],
1237
            ],
1238
            [
1239
                '<td class="sonata-ba-list-field sonata-ba-list-field-html" objectId="12345">
1240
                Creating a Template for the Field...
1241
                </td>',
1242
                'html',
1243
                '<p><strong>Creating a Template for the Field</strong> and form</p>',
1244
                ['truncate' => ['preserve' => true]],
1245
            ],
1246
            [
1247
                '<td class="sonata-ba-list-field sonata-ba-list-field-html" objectId="12345">
1248
                Creating a Template for the Fi etc.
1249
                </td>',
1250
                'html',
1251
                '<p><strong>Creating a Template for the Field</strong> and form</p>',
1252
                ['truncate' => ['separator' => ' etc.']],
1253
            ],
1254
            [
1255
                '<td class="sonata-ba-list-field sonata-ba-list-field-html" objectId="12345">
1256
                Creating a Template for[...]
1257
                </td>',
1258
                'html',
1259
                '<p><strong>Creating a Template for the Field</strong> and form</p>',
1260
                [
1261
                    'truncate' => [
1262
                        'length' => 20,
1263
                        'preserve' => true,
1264
                        'separator' => '[...]',
1265
                    ],
1266
                ],
1267
            ],
1268
1269
            [
1270
                <<<'EOT'
1271
<td class="sonata-ba-list-field sonata-ba-list-field-text" objectId="12345">
1272
<div
1273
    class="sonata-readmore"
1274
    data-readmore-height="40"
1275
    data-readmore-more="Read more"
1276
    data-readmore-less="Close">A very long string</div>
1277
</td>
1278
EOT
1279
                ,
1280
                'text',
1281
                'A very long string',
1282
                [
1283
                    'collapse' => true,
1284
                ],
1285
            ],
1286
            [
1287
                <<<'EOT'
1288
<td class="sonata-ba-list-field sonata-ba-list-field-text" objectId="12345">
1289
<div
1290
    class="sonata-readmore"
1291
    data-readmore-height="10"
1292
    data-readmore-more="More"
1293
    data-readmore-less="Less">A very long string</div>
1294
</td>
1295
EOT
1296
                ,
1297
                'text',
1298
                'A very long string',
1299
                [
1300
                    'collapse' => [
1301
                        'height' => 10,
1302
                        'more' => 'More',
1303
                        'less' => 'Less',
1304
                    ],
1305
                ],
1306
            ],
1307
        ];
1308
    }
1309
1310
    /**
1311
     * @group legacy
1312
     */
1313
    public function testRenderListElementNonExistentTemplate()
1314
    {
1315
        // NEXT_MAJOR: Remove this line
1316
        $this->admin->method('getTemplate')
0 ignored issues
show
Bug introduced by
The method method() 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...
1317
            ->with('base_list_field')
1318
            ->willReturn('@SonataAdmin/CRUD/base_list_field.html.twig');
1319
1320
        $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...
1321
1322
        $this->fieldDescription->expects($this->once())
0 ignored issues
show
Bug introduced by
The method expects() does not seem to exist on object<Sonata\AdminBundl...ldDescriptionInterface>.

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

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

Loading history...
1323
            ->method('getValue')
1324
            ->will($this->returnValue('Foo'));
1325
1326
        $this->fieldDescription->expects($this->once())
0 ignored issues
show
Bug introduced by
The method expects() does not seem to exist on object<Sonata\AdminBundl...ldDescriptionInterface>.

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

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

Loading history...
1327
            ->method('getFieldName')
1328
            ->will($this->returnValue('Foo_name'));
1329
1330
        $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...
1331
            ->method('getType')
1332
            ->will($this->returnValue('nonexistent'));
1333
1334
        $this->fieldDescription->expects($this->once())
0 ignored issues
show
Bug introduced by
The method expects() does not seem to exist on object<Sonata\AdminBundl...ldDescriptionInterface>.

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

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

Loading history...
1335
            ->method('getTemplate')
1336
            ->will($this->returnValue('@SonataAdmin/CRUD/list_nonexistent_template.html.twig'));
1337
1338
        $this->logger->expects($this->once())
0 ignored issues
show
Bug introduced by
The method expects() does not seem to exist on object<Psr\Log\LoggerInterface>.

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...
1339
            ->method('warning')
1340
            ->with(($this->stringStartsWith($this->removeExtraWhitespace(
1341
                'An error occured trying to load the template
1342
                "@SonataAdmin/CRUD/list_nonexistent_template.html.twig"
1343
                for the field "Foo_name", the default template
1344
                    "@SonataAdmin/CRUD/base_list_field.html.twig" was used
1345
                    instead.'
1346
            ))));
1347
1348
        $this->twigExtension->renderListElement($this->environment, $this->object, $this->fieldDescription);
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...
1349
    }
1350
1351
    /**
1352
     * @group                    legacy
1353
     */
1354
    public function testRenderListElementErrorLoadingTemplate()
1355
    {
1356
        $this->expectException(\Twig_Error_Loader::class);
1357
        $this->expectExceptionMessage('Unable to find template "@SonataAdmin/CRUD/base_list_nonexistent_field.html.twig"');
1358
1359
        // NEXT_MAJOR: Remove this line
1360
        $this->admin->method('getTemplate')
0 ignored issues
show
Bug introduced by
The method method() 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...
1361
            ->with('base_list_field')
1362
            ->willReturn('@SonataAdmin/CRUD/base_list_nonexistent_field.html.twig');
1363
1364
        $this->templateRegistry->getTemplate('base_list_field')->willReturn('@SonataAdmin/CRUD/base_list_nonexistent_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...
1365
1366
        $this->fieldDescription->expects($this->once())
0 ignored issues
show
Bug introduced by
The method expects() does not seem to exist on object<Sonata\AdminBundl...ldDescriptionInterface>.

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

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

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

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
2079
                $this->fieldDescription,
2080
                $template,
0 ignored issues
show
Compatibility introduced by
$template of type object<Twig_Template> is not a sub-type of object<Twig\Template>. It seems like you assume a child class of the class Twig_Template 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...
2081
                $parameters,
2082
                $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...
2083
            ))
2084
        );
2085
2086
        $this->environment->enableDebug();
2087
        $this->assertSame(
2088
            $this->removeExtraWhitespace(<<<'EOT'
2089
<!-- START
2090
    fieldName: fd_name
2091
    template: @SonataAdmin/CRUD/base_list_field.html.twig
2092
    compiled template: @SonataAdmin/CRUD/base_list_field.html.twig
2093
-->
2094
    <td class="sonata-ba-list-field sonata-ba-list-field-" objectId="12345"> foo </td>
2095
<!-- END - fieldName: fd_name -->
2096
EOT
2097
            ),
2098
            $this->removeExtraWhitespace(
2099
                $this->twigExtension->output($this->fieldDescription, $template, $parameters, $this->environment)
0 ignored issues
show
Compatibility introduced by
$template of type object<Twig_Template> is not a sub-type of object<Twig\Template>. It seems like you assume a child class of the class Twig_Template 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...
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...
Deprecated Code introduced by
The method Sonata\AdminBundle\Twig\...dminExtension::output() has been deprecated with message: since 3.33, to be removed in 4.0. Use render instead

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
2100
            )
2101
        );
2102
    }
2103
2104
    public function testRenderWithDebug()
2105
    {
2106
        $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...
2107
            ->method('getTemplate')
2108
            ->will($this->returnValue('@SonataAdmin/CRUD/base_list_field.html.twig'));
2109
2110
        $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...
2111
            ->method('getFieldName')
2112
            ->will($this->returnValue('fd_name'));
2113
2114
        $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...
2115
            ->method('getValue')
2116
            ->will($this->returnValue('foo'));
2117
2118
        $parameters = [
2119
            'admin' => $this->admin,
2120
            'value' => 'foo',
2121
            'field_description' => $this->fieldDescription,
2122
            'object' => $this->object,
2123
        ];
2124
2125
        $this->environment->enableDebug();
2126
2127
        $this->assertSame(
2128
            $this->removeExtraWhitespace(<<<'EOT'
2129
<!-- START
2130
    fieldName: fd_name
2131
    template: @SonataAdmin/CRUD/base_list_field.html.twig
2132
    compiled template: @SonataAdmin/CRUD/base_list_field.html.twig
2133
-->
2134
    <td class="sonata-ba-list-field sonata-ba-list-field-" objectId="12345"> foo </td>
2135
<!-- END - fieldName: fd_name -->
2136
EOT
2137
            ),
2138
            $this->removeExtraWhitespace(
2139
                $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...
2140
            )
2141
        );
2142
    }
2143
2144
    public function testRenderRelationElementNoObject()
2145
    {
2146
        $this->assertSame('foo', $this->twigExtension->renderRelationElement('foo', $this->fieldDescription));
2147
    }
2148
2149
    public function testRenderRelationElementToString()
2150
    {
2151
        $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...
2152
            ->method('getOption')
2153
            ->will($this->returnCallback(function ($value, $default = null) {
2154
                if ('associated_property' == $value) {
2155
                    return $default;
2156
                }
2157
            }));
2158
2159
        $element = new FooToString();
2160
        $this->assertSame('salut', $this->twigExtension->renderRelationElement($element, $this->fieldDescription));
2161
    }
2162
2163
    /**
2164
     * @group legacy
2165
     */
2166
    public function testDeprecatedRelationElementToString()
2167
    {
2168
        $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...
2169
            ->method('getOption')
2170
            ->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...
2171
                if ('associated_tostring' == $value) {
2172
                    return '__toString';
2173
                }
2174
            }));
2175
2176
        $element = new FooToString();
2177
        $this->assertSame(
2178
            'salut',
2179
            $this->twigExtension->renderRelationElement($element, $this->fieldDescription)
2180
        );
2181
    }
2182
2183
    /**
2184
     * @group legacy
2185
     */
2186
    public function testRenderRelationElementCustomToString()
2187
    {
2188
        $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...
2189
            ->method('getOption')
2190
            ->will($this->returnCallback(function ($value, $default = null) {
2191
                if ('associated_property' == $value) {
2192
                    return $default;
2193
                }
2194
2195
                if ('associated_tostring' == $value) {
2196
                    return 'customToString';
2197
                }
2198
            }));
2199
2200
        $element = $this->getMockBuilder('stdClass')
2201
            ->setMethods(['customToString'])
2202
            ->getMock();
2203
        $element->expects($this->any())
2204
            ->method('customToString')
2205
            ->will($this->returnValue('fooBar'));
2206
2207
        $this->assertSame('fooBar', $this->twigExtension->renderRelationElement($element, $this->fieldDescription));
2208
    }
2209
2210
    /**
2211
     * @group legacy
2212
     */
2213
    public function testRenderRelationElementMethodNotExist()
2214
    {
2215
        $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...
2216
            ->method('getOption')
2217
2218
            ->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...
2219
                if ('associated_tostring' == $value) {
2220
                    return 'nonExistedMethod';
2221
                }
2222
            }));
2223
2224
        $element = new \stdClass();
2225
        $this->expectException(\RuntimeException::class, 'You must define an `associated_property` option or create a `stdClass::__toString');
2226
2227
        $this->twigExtension->renderRelationElement($element, $this->fieldDescription);
2228
    }
2229
2230
    public function testRenderRelationElementWithPropertyPath()
2231
    {
2232
        $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...
2233
            ->method('getOption')
2234
2235
            ->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...
2236
                if ('associated_property' == $value) {
2237
                    return 'foo';
2238
                }
2239
            }));
2240
2241
        $element = new \stdClass();
2242
        $element->foo = 'bar';
2243
2244
        $this->assertSame('bar', $this->twigExtension->renderRelationElement($element, $this->fieldDescription));
2245
    }
2246
2247
    public function testRenderRelationElementWithClosure()
2248
    {
2249
        $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...
2250
            ->method('getOption')
2251
2252
            ->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...
2253
                if ('associated_property' == $value) {
2254
                    return function ($element) {
2255
                        return 'closure '.$element->foo;
2256
                    };
2257
                }
2258
            }));
2259
2260
        $element = new \stdClass();
2261
        $element->foo = 'bar';
2262
2263
        $this->assertSame(
2264
            'closure bar',
2265
            $this->twigExtension->renderRelationElement($element, $this->fieldDescription)
2266
        );
2267
    }
2268
2269
    public function testGetUrlsafeIdentifier()
2270
    {
2271
        $entity = new \stdClass();
2272
2273
        // set admin to pool
2274
        $this->pool->setAdminServiceIds(['sonata_admin_foo_service']);
2275
        $this->pool->setAdminClasses(['stdClass' => ['sonata_admin_foo_service']]);
2276
2277
        $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...
2278
            ->method('getUrlsafeIdentifier')
2279
            ->with($this->equalTo($entity))
2280
            ->will($this->returnValue(1234567));
2281
2282
        $this->assertSame(1234567, $this->twigExtension->getUrlsafeIdentifier($entity));
2283
    }
2284
2285
    public function testGetUrlsafeIdentifier_GivenAdmin_Foo()
0 ignored issues
show
Coding Style introduced by
Method name "SonataAdminExtensionTest::testGetUrlsafeIdentifier_GivenAdmin_Foo" is not in camel caps format
Loading history...
2286
    {
2287
        $entity = new \stdClass();
2288
2289
        // set admin to pool
2290
        $this->pool->setAdminServiceIds([
2291
            'sonata_admin_foo_service',
2292
            'sonata_admin_bar_service',
2293
        ]);
2294
        $this->pool->setAdminClasses(['stdClass' => [
2295
            'sonata_admin_foo_service',
2296
            'sonata_admin_bar_service',
2297
        ]]);
2298
2299
        $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...
2300
            ->method('getUrlsafeIdentifier')
2301
            ->with($this->equalTo($entity))
2302
            ->will($this->returnValue(1234567));
2303
2304
        $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...
2305
            ->method('getUrlsafeIdentifier');
2306
2307
        $this->assertSame(1234567, $this->twigExtension->getUrlsafeIdentifier($entity, $this->admin));
2308
    }
2309
2310
    public function testGetUrlsafeIdentifier_GivenAdmin_Bar()
0 ignored issues
show
Coding Style introduced by
Method name "SonataAdminExtensionTest::testGetUrlsafeIdentifier_GivenAdmin_Bar" is not in camel caps format
Loading history...
2311
    {
2312
        $entity = new \stdClass();
2313
2314
        // set admin to pool
2315
        $this->pool->setAdminServiceIds(['sonata_admin_foo_service', 'sonata_admin_bar_service']);
2316
        $this->pool->setAdminClasses(['stdClass' => [
2317
            'sonata_admin_foo_service',
2318
            'sonata_admin_bar_service',
2319
        ]]);
2320
2321
        $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...
2322
            ->method('getUrlsafeIdentifier');
2323
2324
        $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...
2325
            ->method('getUrlsafeIdentifier')
2326
            ->with($this->equalTo($entity))
2327
            ->will($this->returnValue(1234567));
2328
2329
        $this->assertSame(1234567, $this->twigExtension->getUrlsafeIdentifier($entity, $this->adminBar));
2330
    }
2331
2332
    public function xEditableChoicesProvider()
2333
    {
2334
        return [
2335
            'needs processing' => [
2336
                ['choices' => ['Status1' => 'Alias1', 'Status2' => 'Alias2']],
2337
                [
2338
                    ['value' => 'Status1', 'text' => 'Alias1'],
2339
                    ['value' => 'Status2', 'text' => 'Alias2'],
2340
                ],
2341
            ],
2342
            'already processed' => [
2343
                ['choices' => [
2344
                    ['value' => 'Status1', 'text' => 'Alias1'],
2345
                    ['value' => 'Status2', 'text' => 'Alias2'],
2346
                ]],
2347
                [
2348
                    ['value' => 'Status1', 'text' => 'Alias1'],
2349
                    ['value' => 'Status2', 'text' => 'Alias2'],
2350
                ],
2351
            ],
2352
            'not required' => [
2353
                [
2354
                    'required' => false,
2355
                    'choices' => ['' => '', 'Status1' => 'Alias1', 'Status2' => 'Alias2'],
2356
                ],
2357
                [
2358
                    ['value' => '', 'text' => ''],
2359
                    ['value' => 'Status1', 'text' => 'Alias1'],
2360
                    ['value' => 'Status2', 'text' => 'Alias2'],
2361
                ],
2362
            ],
2363
            'not required multiple' => [
2364
                [
2365
                    'required' => false,
2366
                    'multiple' => true,
2367
                    'choices' => ['Status1' => 'Alias1', 'Status2' => 'Alias2'],
2368
                ],
2369
                [
2370
                    ['value' => 'Status1', 'text' => 'Alias1'],
2371
                    ['value' => 'Status2', 'text' => 'Alias2'],
2372
                ],
2373
            ],
2374
        ];
2375
    }
2376
2377
    /**
2378
     * @dataProvider xEditablechoicesProvider
2379
     */
2380
    public function testGetXEditableChoicesIsIdempotent(array $options, $expectedChoices)
2381
    {
2382
        $fieldDescription = $this->getMockForAbstractClass(FieldDescriptionInterface::class);
2383
        $fieldDescription->expects($this->any())
2384
            ->method('getOption')
2385
            ->withConsecutive(
2386
                ['choices', []],
2387
                ['catalogue'],
2388
                ['required'],
2389
                ['multiple']
2390
            )
2391
            ->will($this->onConsecutiveCalls(
2392
                $options['choices'],
2393
                'MyCatalogue',
2394
                isset($options['multiple']) ? $options['multiple'] : null
2395
            ));
2396
2397
        $this->assertSame($expectedChoices, $this->twigExtension->getXEditableChoices($fieldDescription));
2398
    }
2399
2400
    public function select2LocalesProvider()
2401
    {
2402
        return [
2403
            ['ar', 'ar'],
2404
            ['az', 'az'],
2405
            ['bg', 'bg'],
2406
            ['ca', 'ca'],
2407
            ['cs', 'cs'],
2408
            ['da', 'da'],
2409
            ['de', 'de'],
2410
            ['el', 'el'],
2411
            [null, 'en'],
2412
            ['es', 'es'],
2413
            ['et', 'et'],
2414
            ['eu', 'eu'],
2415
            ['fa', 'fa'],
2416
            ['fi', 'fi'],
2417
            ['fr', 'fr'],
2418
            ['gl', 'gl'],
2419
            ['he', 'he'],
2420
            ['hr', 'hr'],
2421
            ['hu', 'hu'],
2422
            ['id', 'id'],
2423
            ['is', 'is'],
2424
            ['it', 'it'],
2425
            ['ja', 'ja'],
2426
            ['ka', 'ka'],
2427
            ['ko', 'ko'],
2428
            ['lt', 'lt'],
2429
            ['lv', 'lv'],
2430
            ['mk', 'mk'],
2431
            ['ms', 'ms'],
2432
            ['nb', 'nb'],
2433
            ['nl', 'nl'],
2434
            ['pl', 'pl'],
2435
            ['pt-PT', 'pt'],
2436
            ['pt-BR', 'pt-BR'],
2437
            ['pt-PT', 'pt-PT'],
2438
            ['ro', 'ro'],
2439
            ['rs', 'rs'],
2440
            ['ru', 'ru'],
2441
            ['sk', 'sk'],
2442
            ['sv', 'sv'],
2443
            ['th', 'th'],
2444
            ['tr', 'tr'],
2445
            ['ug-CN', 'ug'],
2446
            ['ug-CN', 'ug-CN'],
2447
            ['uk', 'uk'],
2448
            ['vi', 'vi'],
2449
            ['zh-CN', 'zh'],
2450
            ['zh-CN', 'zh-CN'],
2451
            ['zh-TW', 'zh-TW'],
2452
        ];
2453
    }
2454
2455
    /**
2456
     * @dataProvider select2LocalesProvider
2457
     */
2458
    public function testCanonicalizedLocaleForSelect2($expected, $original)
2459
    {
2460
        $this->assertSame($expected, $this->twigExtension->getCanonicalizedLocaleForSelect2($this->mockExtensionContext($original)));
2461
    }
2462
2463
    public function momentLocalesProvider()
2464
    {
2465
        return [
2466
            ['af', 'af'],
2467
            ['ar-dz', 'ar-dz'],
2468
            ['ar', 'ar'],
2469
            ['ar-ly', 'ar-ly'],
2470
            ['ar-ma', 'ar-ma'],
2471
            ['ar-sa', 'ar-sa'],
2472
            ['ar-tn', 'ar-tn'],
2473
            ['az', 'az'],
2474
            ['be', 'be'],
2475
            ['bg', 'bg'],
2476
            ['bn', 'bn'],
2477
            ['bo', 'bo'],
2478
            ['br', 'br'],
2479
            ['bs', 'bs'],
2480
            ['ca', 'ca'],
2481
            ['cs', 'cs'],
2482
            ['cv', 'cv'],
2483
            ['cy', 'cy'],
2484
            ['da', 'da'],
2485
            ['de-at', 'de-at'],
2486
            ['de', 'de'],
2487
            ['dv', 'dv'],
2488
            ['el', 'el'],
2489
            [null, 'en'],
2490
            [null, 'en-us'],
2491
            ['en-au', 'en-au'],
2492
            ['en-ca', 'en-ca'],
2493
            ['en-gb', 'en-gb'],
2494
            ['en-ie', 'en-ie'],
2495
            ['en-nz', 'en-nz'],
2496
            ['eo', 'eo'],
2497
            ['es-do', 'es-do'],
2498
            ['es', 'es-ar'],
2499
            ['es', 'es-mx'],
2500
            ['es', 'es'],
2501
            ['et', 'et'],
2502
            ['eu', 'eu'],
2503
            ['fa', 'fa'],
2504
            ['fi', 'fi'],
2505
            ['fo', 'fo'],
2506
            ['fr-ca', 'fr-ca'],
2507
            ['fr-ch', 'fr-ch'],
2508
            ['fr', 'fr'],
2509
            ['fy', 'fy'],
2510
            ['gd', 'gd'],
2511
            ['gl', 'gl'],
2512
            ['he', 'he'],
2513
            ['hi', 'hi'],
2514
            ['hr', 'hr'],
2515
            ['hu', 'hu'],
2516
            ['hy-am', 'hy-am'],
2517
            ['id', 'id'],
2518
            ['is', 'is'],
2519
            ['it', 'it'],
2520
            ['ja', 'ja'],
2521
            ['jv', 'jv'],
2522
            ['ka', 'ka'],
2523
            ['kk', 'kk'],
2524
            ['km', 'km'],
2525
            ['ko', 'ko'],
2526
            ['ky', 'ky'],
2527
            ['lb', 'lb'],
2528
            ['lo', 'lo'],
2529
            ['lt', 'lt'],
2530
            ['lv', 'lv'],
2531
            ['me', 'me'],
2532
            ['mi', 'mi'],
2533
            ['mk', 'mk'],
2534
            ['ml', 'ml'],
2535
            ['mr', 'mr'],
2536
            ['ms', 'ms'],
2537
            ['ms-my', 'ms-my'],
2538
            ['my', 'my'],
2539
            ['nb', 'nb'],
2540
            ['ne', 'ne'],
2541
            ['nl-be', 'nl-be'],
2542
            ['nl', 'nl'],
2543
            ['nl', 'nl-nl'],
2544
            ['nn', 'nn'],
2545
            ['pa-in', 'pa-in'],
2546
            ['pl', 'pl'],
2547
            ['pt-br', 'pt-br'],
2548
            ['pt', 'pt'],
2549
            ['ro', 'ro'],
2550
            ['ru', 'ru'],
2551
            ['se', 'se'],
2552
            ['si', 'si'],
2553
            ['sk', 'sk'],
2554
            ['sl', 'sl'],
2555
            ['sq', 'sq'],
2556
            ['sr-cyrl', 'sr-cyrl'],
2557
            ['sr', 'sr'],
2558
            ['ss', 'ss'],
2559
            ['sv', 'sv'],
2560
            ['sw', 'sw'],
2561
            ['ta', 'ta'],
2562
            ['te', 'te'],
2563
            ['tet', 'tet'],
2564
            ['th', 'th'],
2565
            ['tlh', 'tlh'],
2566
            ['tl-ph', 'tl-ph'],
2567
            ['tr', 'tr'],
2568
            ['tzl', 'tzl'],
2569
            ['tzm', 'tzm'],
2570
            ['tzm-latn', 'tzm-latn'],
2571
            ['uk', 'uk'],
2572
            ['uz', 'uz'],
2573
            ['vi', 'vi'],
2574
            ['x-pseudo', 'x-pseudo'],
2575
            ['yo', 'yo'],
2576
            ['zh-cn', 'zh-cn'],
2577
            ['zh-hk', 'zh-hk'],
2578
            ['zh-tw', 'zh-tw'],
2579
        ];
2580
    }
2581
2582
    /**
2583
     * @dataProvider momentLocalesProvider
2584
     */
2585
    public function testCanonicalizedLocaleForMoment($expected, $original)
2586
    {
2587
        $this->assertSame($expected, $this->twigExtension->getCanonicalizedLocaleForMoment($this->mockExtensionContext($original)));
2588
    }
2589
2590
    /**
2591
     * This method generates url part for Twig layout.
2592
     *
2593
     * @param array $url
2594
     *
2595
     * @return string
2596
     */
2597
    private function buildTwigLikeUrl($url)
2598
    {
2599
        return htmlspecialchars(http_build_query($url, '', '&', PHP_QUERY_RFC3986));
2600
    }
2601
2602
    private function removeExtraWhitespace($string)
2603
    {
2604
        return trim(preg_replace(
2605
            '/\s+/',
2606
            ' ',
2607
            $string
2608
        ));
2609
    }
2610
2611
    private function mockExtensionContext($locale)
2612
    {
2613
        $request = $this->createMock(Request::class);
2614
        $request->method('getLocale')->willReturn($locale);
2615
        $appVariable = $this->createMock(AppVariable::class);
2616
        $appVariable->method('getRequest')->willReturn($request);
2617
2618
        return ['app' => $appVariable];
2619
    }
2620
}
2621