Completed
Push — 3.x ( ecae9a...388af4 )
by Jordi Sala
03:54
created

SonataAdminExtensionTest::testRenderWithDebug()   B

Complexity

Conditions 1
Paths 1

Size

Total Lines 39
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Importance

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