Completed
Pull Request — master (#4831)
by Jordi Sala
10:38 queued 05:56
created

testGetValueFromFieldDescriptionWithNoValueException()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 23
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 23
rs 9.0856
c 0
b 0
f 0
cc 1
eloc 15
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 Symfony\Bridge\Twig\Extension\RoutingExtension;
24
use Symfony\Bridge\Twig\Extension\TranslationExtension;
25
use Symfony\Bridge\Twig\Tests\Extension\Fixtures\StubFilesystemLoader;
26
use Symfony\Component\Config\FileLocator;
27
use Symfony\Component\DependencyInjection\ContainerInterface;
28
use Symfony\Component\Routing\Generator\UrlGenerator;
29
use Symfony\Component\Routing\Loader\XmlFileLoader;
30
use Symfony\Component\Routing\RequestContext;
31
use Symfony\Component\Translation\DependencyInjection\TranslationDumperPass;
32
use Symfony\Component\Translation\Loader\XliffFileLoader;
33
use Symfony\Component\Translation\MessageSelector;
34
use Symfony\Component\Translation\Translator;
35
use Symfony\Component\Translation\TranslatorInterface;
36
37
/**
38
 * Test for SonataAdminExtension.
39
 *
40
 * @author Andrej Hudec <[email protected]>
41
 */
42
class SonataAdminExtensionTest extends TestCase
43
{
44
    /**
45
     * @var SonataAdminExtension
46
     */
47
    private $twigExtension;
48
49
    /**
50
     * @var \Twig_Environment
51
     */
52
    private $environment;
53
54
    /**
55
     * @var AdminInterface
56
     */
57
    private $admin;
58
59
    /**
60
     * @var AdminInterface
61
     */
62
    private $adminBar;
63
64
    /**
65
     * @var FieldDescriptionInterface
66
     */
67
    private $fieldDescription;
68
69
    /**
70
     * @var \stdClass
71
     */
72
    private $object;
73
74
    /**
75
     * @var Pool
76
     */
77
    private $pool;
78
79
    /**
80
     * @var LoggerInterface
81
     */
82
    private $logger;
83
84
    /**
85
     * @var string[]
86
     */
87
    private $xEditableTypeMapping;
88
89
    /**
90
     * @var TranslatorInterface
91
     */
92
    private $translator;
93
94
    public function setUp()
95
    {
96
        date_default_timezone_set('Europe/London');
97
98
        $container = $this->getMockForAbstractClass(ContainerInterface::class);
99
100
        $this->pool = new Pool($container, '', '');
101
        $this->pool->setAdminServiceIds(['sonata_admin_foo_service']);
102
        $this->pool->setAdminClasses(['fooClass' => ['sonata_admin_foo_service']]);
103
104
        $this->logger = $this->getMockForAbstractClass(LoggerInterface::class);
105
        $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...
106
            'choice' => 'select',
107
            'boolean' => 'select',
108
            'text' => 'text',
109
            'textarea' => 'textarea',
110
            'html' => 'textarea',
111
            'email' => 'email',
112
            'string' => 'text',
113
            'smallint' => 'text',
114
            'bigint' => 'text',
115
            'integer' => 'number',
116
            'decimal' => 'number',
117
            'currency' => 'number',
118
            'percent' => 'number',
119
            'url' => 'url',
120
        ];
121
122
        // translation extension
123
        $translator = new Translator(
124
            'en',
125
            // NEXT_MAJOR: simplify this when dropping symfony < 3.4
126
            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...
127
        );
128
        $translator->addLoader('xlf', new XliffFileLoader());
129
        $translator->addResource(
130
            'xlf',
131
            __DIR__.'/../../../src/Resources/translations/SonataAdminBundle.en.xliff',
132
            'en',
133
            'SonataAdminBundle'
134
        );
135
136
        $this->translator = $translator;
137
138
        $this->twigExtension = new SonataAdminExtension($this->pool, $this->logger, $this->translator);
139
        $this->twigExtension->setXEditableTypeMapping($this->xEditableTypeMapping);
140
141
        $loader = new StubFilesystemLoader([
142
            __DIR__.'/../../../src/Resources/views/CRUD',
143
        ]);
144
145
        $this->environment = new \Twig_Environment($loader, [
146
            'strict_variables' => true,
147
            'cache' => false,
148
            'autoescape' => 'html',
149
            'optimizations' => 0,
150
        ]);
151
        $this->environment->addExtension($this->twigExtension);
152
        $this->environment->addExtension(new TranslationExtension($translator));
153
154
        // routing extension
155
        $xmlFileLoader = new XmlFileLoader(new FileLocator([__DIR__.'/../../../src/Resources/config/routing']));
156
        $routeCollection = $xmlFileLoader->load('sonata_admin.xml');
157
158
        $xmlFileLoader = new XmlFileLoader(new FileLocator([__DIR__.'/../../Fixtures/Resources/config/routing']));
159
        $testRouteCollection = $xmlFileLoader->load('routing.xml');
160
161
        $routeCollection->addCollection($testRouteCollection);
162
        $requestContext = new RequestContext();
163
        $urlGenerator = new UrlGenerator($routeCollection, $requestContext);
164
        $this->environment->addExtension(new RoutingExtension($urlGenerator));
165
        $this->environment->addExtension(new \Twig_Extensions_Extension_Text());
166
167
        // initialize object
168
        $this->object = new \stdClass();
169
170
        // initialize admin
171
        $this->admin = $this->createMock(AbstractAdmin::class);
172
173
        $this->admin->expects($this->any())
174
            ->method('getCode')
175
            ->will($this->returnValue('xyz'));
176
177
        $this->admin->expects($this->any())
178
            ->method('id')
179
            ->with($this->equalTo($this->object))
180
            ->will($this->returnValue(12345));
181
182
        $this->admin->expects($this->any())
183
            ->method('getNormalizedIdentifier')
184
            ->with($this->equalTo($this->object))
185
            ->will($this->returnValue(12345));
186
187
        $this->admin->expects($this->any())
188
            ->method('trans')
189
            ->will($this->returnCallback(function ($id, $parameters = [], $domain = null) use ($translator) {
190
                return $translator->trans($id, $parameters, $domain);
191
            }));
192
193
        $this->adminBar = $this->createMock(AbstractAdmin::class);
194
        $this->adminBar->expects($this->any())
195
            ->method('hasAccess')
196
            ->will($this->returnValue(true));
197
        $this->adminBar->expects($this->any())
198
            ->method('getNormalizedIdentifier')
199
            ->with($this->equalTo($this->object))
200
            ->will($this->returnValue(12345));
201
202
        $container->expects($this->any())
203
            ->method('get')
204
            ->will($this->returnCallback(function ($id) {
205
                if ('sonata_admin_foo_service' == $id) {
206
                    return $this->admin;
207
                } elseif ('sonata_admin_bar_service' == $id) {
208
                    return $this->adminBar;
209
                }
210
            }));
211
212
        // initialize field description
213
        $this->fieldDescription = $this->getMockForAbstractClass(FieldDescriptionInterface::class);
214
215
        $this->fieldDescription->expects($this->any())
216
            ->method('getName')
217
            ->will($this->returnValue('fd_name'));
218
219
        $this->fieldDescription->expects($this->any())
220
            ->method('getAdmin')
221
            ->will($this->returnValue($this->admin));
222
223
        $this->fieldDescription->expects($this->any())
224
            ->method('getLabel')
225
            ->will($this->returnValue('Data'));
226
    }
227
228
    /**
229
     * @dataProvider getRenderListElementTests
230
     */
231
    public function testRenderListElement($expected, $type, $value, array $options)
232
    {
233
        $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...
234
            ->method('getPersistentParameters')
235
            ->will($this->returnValue(['context' => 'foo']));
236
237
        $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...
238
            ->method('hasAccess')
239
            ->will($this->returnValue(true));
240
241
        $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...
242
            ->method('getTemplate')
243
            ->with($this->equalTo('base_list_field'))
244
            ->will($this->returnValue('SonataAdminBundle:CRUD:base_list_field.html.twig'));
245
246
        $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...
247
            ->method('getValue')
248
            ->will($this->returnValue($value));
249
250
        $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...
251
            ->method('getType')
252
            ->will($this->returnValue($type));
253
254
        $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...
255
            ->method('getOptions')
256
            ->will($this->returnValue($options));
257
258
        $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...
259
            ->method('getOption')
260
            ->will($this->returnCallback(function ($name, $default = null) use ($options) {
261
                return isset($options[$name]) ? $options[$name] : $default;
262
            }));
263
264
        $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...
265
            ->method('getTemplate')
266
            ->will($this->returnCallback(function () use ($type) {
267
                switch ($type) {
268
                    case 'string':
269
                        return 'SonataAdminBundle:CRUD:list_string.html.twig';
270
                    case 'boolean':
271
                        return 'SonataAdminBundle:CRUD:list_boolean.html.twig';
272
                    case 'datetime':
273
                        return 'SonataAdminBundle:CRUD:list_datetime.html.twig';
274
                    case 'date':
275
                        return 'SonataAdminBundle:CRUD:list_date.html.twig';
276
                    case 'time':
277
                        return 'SonataAdminBundle:CRUD:list_time.html.twig';
278
                    case 'currency':
279
                        return 'SonataAdminBundle:CRUD:list_currency.html.twig';
280
                    case 'percent':
281
                        return 'SonataAdminBundle:CRUD:list_percent.html.twig';
282
                    case 'email':
283
                        return 'SonataAdminBundle:CRUD:list_email.html.twig';
284
                    case 'choice':
285
                        return 'SonataAdminBundle:CRUD:list_choice.html.twig';
286
                    case 'array':
287
                        return 'SonataAdminBundle:CRUD:list_array.html.twig';
288
                    case 'trans':
289
                        return 'SonataAdminBundle:CRUD:list_trans.html.twig';
290
                    case 'url':
291
                        return 'SonataAdminBundle:CRUD:list_url.html.twig';
292
                    case 'html':
293
                        return 'SonataAdminBundle:CRUD:list_html.html.twig';
294
                    default:
295
                        return false;
296
                }
297
            }));
298
299
        $this->assertSame(
300
            $this->removeExtraWhitespace($expected),
301
            $this->removeExtraWhitespace($this->twigExtension->renderListElement(
302
                $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...
303
                $this->object,
304
                $this->fieldDescription
305
            ))
306
        );
307
    }
308
309
    public function getRenderListElementTests()
310
    {
311
        return [
312
            [
313
                '<td class="sonata-ba-list-field sonata-ba-list-field-string" objectId="12345"> Example </td>',
314
                'string',
315
                'Example',
316
                [],
317
            ],
318
            [
319
                '<td class="sonata-ba-list-field sonata-ba-list-field-string" objectId="12345"> </td>',
320
                'string',
321
                null,
322
                [],
323
            ],
324
            [
325
                '<td class="sonata-ba-list-field sonata-ba-list-field-text" objectId="12345"> Example </td>',
326
                'text',
327
                'Example',
328
                [],
329
            ],
330
            [
331
                '<td class="sonata-ba-list-field sonata-ba-list-field-text" objectId="12345"> </td>',
332
                'text',
333
                null,
334
                [],
335
            ],
336
            [
337
                '<td class="sonata-ba-list-field sonata-ba-list-field-textarea" objectId="12345"> Example </td>',
338
                'textarea',
339
                'Example',
340
                [],
341
            ],
342
            [
343
                '<td class="sonata-ba-list-field sonata-ba-list-field-textarea" objectId="12345"> </td>',
344
                'textarea',
345
                null,
346
                [],
347
            ],
348
            'datetime field' => [
349
                '<td class="sonata-ba-list-field sonata-ba-list-field-datetime" objectId="12345">
350
                    December 24, 2013 10:11
351
                </td>',
352
                'datetime',
353
                new \DateTime('2013-12-24 10:11:12', new \DateTimeZone('Europe/London')),
354
                [],
355
            ],
356
            [
357
                '<td class="sonata-ba-list-field sonata-ba-list-field-datetime" objectId="12345">
358
                    December 24, 2013 18:11
359
                </td>',
360
                'datetime',
361
                new \DateTime('2013-12-24 10:11:12', new \DateTimeZone('UTC')),
362
                ['timezone' => 'Asia/Hong_Kong'],
363
            ],
364
            [
365
                '<td class="sonata-ba-list-field sonata-ba-list-field-datetime" objectId="12345"> &nbsp; </td>',
366
                'datetime',
367
                null,
368
                [],
369
            ],
370
            [
371
                '<td class="sonata-ba-list-field sonata-ba-list-field-datetime" objectId="12345">
372
                    24.12.2013 10:11:12
373
                </td>',
374
                'datetime',
375
                new \DateTime('2013-12-24 10:11:12', new \DateTimeZone('Europe/London')),
376
                ['format' => 'd.m.Y H:i:s'],
377
            ],
378
            [
379
                '<td class="sonata-ba-list-field sonata-ba-list-field-datetime" objectId="12345"> &nbsp; </td>',
380
                'datetime',
381
                null,
382
                ['format' => 'd.m.Y H:i:s'],
383
            ],
384
            [
385
                '<td class="sonata-ba-list-field sonata-ba-list-field-datetime" objectId="12345">
386
                    24.12.2013 18:11:12
387
                </td>',
388
                'datetime',
389
                new \DateTime('2013-12-24 10:11:12', new \DateTimeZone('UTC')),
390
                ['format' => 'd.m.Y H:i:s', 'timezone' => 'Asia/Hong_Kong'],
391
            ],
392
            [
393
                '<td class="sonata-ba-list-field sonata-ba-list-field-datetime" objectId="12345"> &nbsp; </td>',
394
                'datetime',
395
                null,
396
                ['format' => 'd.m.Y H:i:s', 'timezone' => 'Asia/Hong_Kong'],
397
            ],
398
            [
399
                '<td class="sonata-ba-list-field sonata-ba-list-field-date" objectId="12345"> December 24, 2013 </td>',
400
                'date',
401
                new \DateTime('2013-12-24 10:11:12', new \DateTimeZone('Europe/London')),
402
                [],
403
            ],
404
            [
405
                '<td class="sonata-ba-list-field sonata-ba-list-field-date" objectId="12345"> &nbsp; </td>',
406
                'date',
407
                null,
408
                [],
409
            ],
410
            [
411
                '<td class="sonata-ba-list-field sonata-ba-list-field-date" objectId="12345"> 24.12.2013 </td>',
412
                'date',
413
                new \DateTime('2013-12-24 10:11:12', new \DateTimeZone('Europe/London')),
414
                ['format' => 'd.m.Y'],
415
            ],
416
            [
417
                '<td class="sonata-ba-list-field sonata-ba-list-field-date" objectId="12345"> &nbsp; </td>',
418
                'date',
419
                null,
420
                ['format' => 'd.m.Y'],
421
            ],
422
            [
423
                '<td class="sonata-ba-list-field sonata-ba-list-field-time" objectId="12345"> 10:11:12 </td>',
424
                'time',
425
                new \DateTime('2013-12-24 10:11:12', new \DateTimeZone('Europe/London')),
426
                [],
427
            ],
428
            [
429
                '<td class="sonata-ba-list-field sonata-ba-list-field-time" objectId="12345"> &nbsp; </td>',
430
                'time',
431
                null,
432
                [],
433
            ],
434
            [
435
                '<td class="sonata-ba-list-field sonata-ba-list-field-number" objectId="12345"> 10.746135 </td>',
436
                'number', 10.746135,
437
                [],
438
            ],
439
            [
440
                '<td class="sonata-ba-list-field sonata-ba-list-field-number" objectId="12345"> </td>',
441
                'number',
442
                null,
443
                [],
444
            ],
445
            [
446
                '<td class="sonata-ba-list-field sonata-ba-list-field-integer" objectId="12345"> 5678 </td>',
447
                'integer',
448
                5678,
449
                [],
450
            ],
451
            [
452
                '<td class="sonata-ba-list-field sonata-ba-list-field-integer" objectId="12345"> </td>',
453
                'integer',
454
                null,
455
                [],
456
            ],
457
            [
458
                '<td class="sonata-ba-list-field sonata-ba-list-field-percent" objectId="12345"> 1074.6135 % </td>',
459
                'percent',
460
                10.746135,
461
                [],
462
            ],
463
            [
464
                '<td class="sonata-ba-list-field sonata-ba-list-field-percent" objectId="12345"> 0 % </td>',
465
                'percent',
466
                null,
467
                [],
468
            ],
469
            [
470
                '<td class="sonata-ba-list-field sonata-ba-list-field-currency" objectId="12345"> EUR 10.746135 </td>',
471
                'currency',
472
                10.746135,
473
                ['currency' => 'EUR'],
474
            ],
475
            [
476
                '<td class="sonata-ba-list-field sonata-ba-list-field-currency" objectId="12345"> </td>',
477
                'currency',
478
                null,
479
                ['currency' => 'EUR'],
480
            ],
481
            [
482
                '<td class="sonata-ba-list-field sonata-ba-list-field-currency" objectId="12345"> GBP 51.23456 </td>',
483
                'currency',
484
                51.23456,
485
                ['currency' => 'GBP'],
486
            ],
487
            [
488
                '<td class="sonata-ba-list-field sonata-ba-list-field-currency" objectId="12345"> </td>',
489
                'currency',
490
                null,
491
                ['currency' => 'GBP'],
492
            ],
493
            [
494
                '<td class="sonata-ba-list-field sonata-ba-list-field-email" objectId="12345"> &nbsp; </td>',
495
                'email',
496
                null,
497
                [],
498
            ],
499
            [
500
                '<td class="sonata-ba-list-field sonata-ba-list-field-email" objectId="12345"> <a href="mailto:[email protected]">[email protected]</a> </td>',
501
                'email',
502
                '[email protected]',
503
                [],
504
            ],
505
            [
506
                '<td class="sonata-ba-list-field sonata-ba-list-field-email" objectId="12345">
507
                    <a href="mailto:[email protected]">[email protected]</a> </td>',
508
                'email',
509
                '[email protected]',
510
                ['as_string' => false],
511
            ],
512
            [
513
                '<td class="sonata-ba-list-field sonata-ba-list-field-email" objectId="12345"> [email protected] </td>',
514
                'email',
515
                '[email protected]',
516
                ['as_string' => true],
517
            ],
518
            [
519
                '<td class="sonata-ba-list-field sonata-ba-list-field-email" objectId="12345">
520
                    <a href="mailto:[email protected]?'.$this->buildTwigLikeUrl(['subject' => 'Main Theme', 'body' => 'Message Body']).'">[email protected]</a>  </td>',
521
                'email',
522
                '[email protected]',
523
                ['subject' => 'Main Theme', 'body' => 'Message Body'],
524
            ],
525
            [
526
                '<td class="sonata-ba-list-field sonata-ba-list-field-email" objectId="12345">
527
                    <a href="mailto:[email protected]?'.$this->buildTwigLikeUrl(['subject' => 'Main Theme']).'">[email protected]</a>  </td>',
528
                'email',
529
                '[email protected]',
530
                ['subject' => 'Main Theme'],
531
            ],
532
            [
533
                '<td class="sonata-ba-list-field sonata-ba-list-field-email" objectId="12345">
534
                    <a href="mailto:[email protected]?'.$this->buildTwigLikeUrl(['body' => 'Message Body']).'">[email protected]</a>  </td>',
535
                'email',
536
                '[email protected]',
537
                ['body' => 'Message Body'],
538
            ],
539
            [
540
                '<td class="sonata-ba-list-field sonata-ba-list-field-email" objectId="12345"> [email protected] </td>',
541
                'email',
542
                '[email protected]',
543
                ['as_string' => true, 'subject' => 'Main Theme', 'body' => 'Message Body'],
544
            ],
545
            [
546
                '<td class="sonata-ba-list-field sonata-ba-list-field-email" objectId="12345"> [email protected] </td>',
547
                'email',
548
                '[email protected]',
549
                ['as_string' => true, 'body' => 'Message Body'],
550
            ],
551
            [
552
                '<td class="sonata-ba-list-field sonata-ba-list-field-email" objectId="12345"> [email protected] </td>',
553
                'email',
554
                '[email protected]',
555
                ['as_string' => true, 'subject' => 'Main Theme'],
556
            ],
557
            [
558
                '<td class="sonata-ba-list-field sonata-ba-list-field-array" objectId="12345">
559
                    [1 => First] [2 => Second]
560
                </td>',
561
                'array',
562
                [1 => 'First', 2 => 'Second'],
563
                [],
564
            ],
565
            [
566
                '<td class="sonata-ba-list-field sonata-ba-list-field-array" objectId="12345"> </td>',
567
                'array',
568
                null,
569
                [],
570
            ],
571
            [
572
                '<td class="sonata-ba-list-field sonata-ba-list-field-boolean" objectId="12345">
573
                    <span class="label label-success">yes</span>
574
                </td>',
575
                'boolean',
576
                true,
577
                ['editable' => false],
578
            ],
579
            [
580
                '<td class="sonata-ba-list-field sonata-ba-list-field-boolean" objectId="12345">
581
                    <span class="label label-danger">no</span>
582
                </td>',
583
                'boolean',
584
                false,
585
                ['editable' => false],
586
            ],
587
            [
588
                '<td class="sonata-ba-list-field sonata-ba-list-field-boolean" objectId="12345">
589
                    <span class="label label-danger">no</span>
590
                </td>',
591
                'boolean',
592
                null,
593
                ['editable' => false],
594
            ],
595
            [
596
                <<<'EOT'
597
<td class="sonata-ba-list-field sonata-ba-list-field-boolean" objectId="12345">
598
    <span
599
        class="x-editable"
600
        data-type="select"
601
        data-value="1"
602
        data-title="Data"
603
        data-pk="12345"
604
        data-url="/core/set-object-field-value?context=list&amp;field=fd_name&amp;objectId=12345&amp;code=xyz"
605
        data-source="[{value: 0, text: 'no'},{value: 1, text: 'yes'}]"
606
    >
607
        <span class="label label-success">yes</span>
608
    </span>
609
</td>
610
EOT
611
            ,
612
                'boolean',
613
                true,
614
                ['editable' => true],
615
            ],
616
            [
617
                <<<'EOT'
618
<td class="sonata-ba-list-field sonata-ba-list-field-boolean" objectId="12345">
619
    <span
620
        class="x-editable"
621
        data-type="select"
622
        data-value="0"
623
        data-title="Data"
624
        data-pk="12345"
625
        data-url="/core/set-object-field-value?context=list&amp;field=fd_name&amp;objectId=12345&amp;code=xyz"
626
        data-source="[{value: 0, text: 'no'},{value: 1, text: 'yes'}]"
627
    >
628
    <span class="label label-danger">no</span> </span>
629
</td>
630
EOT
631
                ,
632
                'boolean',
633
                false,
634
                ['editable' => true],
635
            ],
636
            [
637
                <<<'EOT'
638
<td class="sonata-ba-list-field sonata-ba-list-field-boolean" objectId="12345">
639
    <span
640
        class="x-editable"
641
        data-type="select"
642
        data-value="0"
643
        data-title="Data"
644
        data-pk="12345"
645
        data-url="/core/set-object-field-value?context=list&amp;field=fd_name&amp;objectId=12345&amp;code=xyz"
646
        data-source="[{value: 0, text: 'no'},{value: 1, text: 'yes'}]" >
647
        <span class="label label-danger">no</span> </span>
648
</td>
649
EOT
650
                ,
651
                'boolean',
652
                null,
653
                ['editable' => true],
654
            ],
655
            [
656
                '<td class="sonata-ba-list-field sonata-ba-list-field-trans" objectId="12345"> Delete </td>',
657
                'trans',
658
                'action_delete',
659
                ['catalogue' => 'SonataAdminBundle'],
660
            ],
661
            [
662
                '<td class="sonata-ba-list-field sonata-ba-list-field-trans" objectId="12345"> </td>',
663
                'trans',
664
                null,
665
                ['catalogue' => 'SonataAdminBundle'],
666
            ],
667
            [
668
                '<td class="sonata-ba-list-field sonata-ba-list-field-trans" objectId="12345"> Delete </td>',
669
                'trans',
670
                'action_delete',
671
                ['format' => '%s', 'catalogue' => 'SonataAdminBundle'],
672
            ],
673
            [
674
                '<td class="sonata-ba-list-field sonata-ba-list-field-trans" objectId="12345">
675
                action.action_delete
676
                </td>',
677
                'trans',
678
                'action_delete',
679
                ['format' => 'action.%s'],
680
            ],
681
            [
682
                '<td class="sonata-ba-list-field sonata-ba-list-field-trans" objectId="12345">
683
                action.action_delete
684
                </td>',
685
                'trans',
686
                'action_delete',
687
                ['format' => 'action.%s', 'catalogue' => 'SonataAdminBundle'],
688
            ],
689
            [
690
                '<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345"> Status1 </td>',
691
                'choice',
692
                'Status1',
693
                [],
694
            ],
695
            [
696
                '<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345"> Status1 </td>',
697
                'choice',
698
                ['Status1'],
699
                ['choices' => [], 'multiple' => true],
700
            ],
701
            [
702
                '<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345"> Alias1 </td>',
703
                'choice',
704
                'Status1',
705
                ['choices' => ['Status1' => 'Alias1', 'Status2' => 'Alias2', 'Status3' => 'Alias3']],
706
            ],
707
            [
708
                '<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345"> </td>',
709
                'choice',
710
                null,
711
                ['choices' => ['Status1' => 'Alias1', 'Status2' => 'Alias2', 'Status3' => 'Alias3']],
712
            ],
713
            [
714
                '<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345">
715
                NoValidKeyInChoices
716
                </td>',
717
                'choice',
718
                'NoValidKeyInChoices',
719
                ['choices' => ['Status1' => 'Alias1', 'Status2' => 'Alias2', 'Status3' => 'Alias3']],
720
            ],
721
            [
722
                '<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345"> Delete </td>',
723
                'choice',
724
                'Foo',
725
                ['catalogue' => 'SonataAdminBundle', 'choices' => [
726
                    'Foo' => 'action_delete',
727
                    'Status2' => 'Alias2',
728
                    'Status3' => 'Alias3',
729
                ]],
730
            ],
731
            [
732
                '<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345"> Alias1, Alias3 </td>',
733
                'choice',
734
                ['Status1', 'Status3'],
735
                ['choices' => [
736
                    'Status1' => 'Alias1',
737
                    'Status2' => 'Alias2',
738
                    'Status3' => 'Alias3',
739
                ], 'multiple' => true], ],
740
            [
741
                '<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345"> Alias1 | Alias3 </td>',
742
                'choice',
743
                ['Status1', 'Status3'],
744
                ['choices' => [
745
                    'Status1' => 'Alias1',
746
                    'Status2' => 'Alias2',
747
                    'Status3' => 'Alias3',
748
                ], 'multiple' => true, 'delimiter' => ' | '], ],
749
            [
750
                '<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345"> </td>',
751
                'choice',
752
                null,
753
                ['choices' => [
754
                    'Status1' => 'Alias1',
755
                    'Status2' => 'Alias2',
756
                    'Status3' => 'Alias3',
757
                ], 'multiple' => true],
758
            ],
759
            [
760
                '<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345">
761
                NoValidKeyInChoices
762
                </td>',
763
                'choice',
764
                ['NoValidKeyInChoices'],
765
                ['choices' => [
766
                    'Status1' => 'Alias1',
767
                    'Status2' => 'Alias2',
768
                    'Status3' => 'Alias3',
769
                ], 'multiple' => true],
770
            ],
771
            [
772
                '<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345">
773
                NoValidKeyInChoices, Alias2
774
                </td>',
775
                'choice',
776
                ['NoValidKeyInChoices', 'Status2'],
777
                ['choices' => [
778
                    'Status1' => 'Alias1',
779
                    'Status2' => 'Alias2',
780
                    'Status3' => 'Alias3',
781
                ], 'multiple' => true],
782
            ],
783
            [
784
                '<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345"> Delete, Alias3 </td>',
785
                'choice',
786
                ['Foo', 'Status3'],
787
                ['catalogue' => 'SonataAdminBundle', 'choices' => [
788
                    'Foo' => 'action_delete',
789
                    'Status2' => 'Alias2',
790
                    'Status3' => 'Alias3',
791
                ], 'multiple' => true],
792
            ],
793
            [
794
                '<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345">
795
                &lt;b&gt;Alias1&lt;/b&gt;, &lt;b&gt;Alias3&lt;/b&gt;
796
            </td>',
797
                'choice',
798
                ['Status1', 'Status3'],
799
                ['choices' => [
800
                    'Status1' => '<b>Alias1</b>',
801
                    'Status2' => '<b>Alias2</b>',
802
                    'Status3' => '<b>Alias3</b>',
803
                ], 'multiple' => true], ],
804
            [
805
                <<<'EOT'
806
<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345">
807
    <span
808
        class="x-editable"
809
        data-type="select"
810
        data-value="Status1"
811
        data-title="Data"
812
        data-pk="12345"
813
        data-url="/core/set-object-field-value?context=list&amp;field=fd_name&amp;objectId=12345&amp;code=xyz"
814
        data-source="[]"
815
    >
816
        Status1
817
    </span>
818
</td>
819
EOT
820
                ,
821
                'choice',
822
                'Status1',
823
                ['editable' => true],
824
            ],
825
            [
826
                <<<'EOT'
827
<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345">
828
    <span
829
        class="x-editable"
830
        data-type="select"
831
        data-value="Status1"
832
        data-title="Data"
833
        data-pk="12345"
834
        data-url="/core/set-object-field-value?context=list&amp;field=fd_name&amp;objectId=12345&amp;code=xyz"
835
        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;}]" >
836
        Alias1 </span>
837
</td>
838
EOT
839
                ,
840
                'choice',
841
                'Status1',
842
                [
843
                    'editable' => true,
844
                    'choices' => [
845
                        'Status1' => 'Alias1',
846
                        'Status2' => 'Alias2',
847
                        'Status3' => 'Alias3',
848
                    ],
849
                ],
850
            ],
851
            [
852
                <<<'EOT'
853
<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345">
854
    <span
855
        class="x-editable"
856
        data-type="select"
857
        data-value=""
858
        data-title="Data"
859
        data-pk="12345"
860
        data-url="/core/set-object-field-value?context=list&amp;field=fd_name&amp;objectId=12345&amp;code=xyz"
861
        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;}]" >
862
863
    </span>
864
</td>
865
EOT
866
                ,
867
                'choice',
868
                null,
869
                [
870
                    'editable' => true,
871
                    'choices' => [
872
                        'Status1' => 'Alias1',
873
                        'Status2' => 'Alias2',
874
                        'Status3' => 'Alias3',
875
                    ],
876
                ],
877
            ],
878
            [
879
                <<<'EOT'
880
<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345">
881
    <span
882
        class="x-editable"
883
        data-type="select"
884
        data-value="NoValidKeyInChoices"
885
        data-title="Data" data-pk="12345"
886
        data-url="/core/set-object-field-value?context=list&amp;field=fd_name&amp;objectId=12345&amp;code=xyz"
887
        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;}]" >
888
        NoValidKeyInChoices
889
    </span>
890
</td>
891
EOT
892
                ,
893
                'choice',
894
                'NoValidKeyInChoices',
895
                [
896
                    'editable' => true,
897
                    'choices' => [
898
                        'Status1' => 'Alias1',
899
                        'Status2' => 'Alias2',
900
                        'Status3' => 'Alias3',
901
                    ],
902
                ],
903
            ],
904
            [
905
                <<<'EOT'
906
<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345">
907
    <span
908
        class="x-editable"
909
        data-type="select"
910
        data-value="Foo"
911
        data-title="Data"
912
        data-pk="12345"
913
        data-url="/core/set-object-field-value?context=list&amp;field=fd_name&amp;objectId=12345&amp;code=xyz"
914
        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;}]" >
915
         Delete
916
    </span>
917
</td>
918
EOT
919
                ,
920
                'choice',
921
                'Foo',
922
                [
923
                    'editable' => true,
924
                    'catalogue' => 'SonataAdminBundle',
925
                    'choices' => [
926
                        'Foo' => 'action_delete',
927
                        'Status2' => 'Alias2',
928
                        'Status3' => 'Alias3',
929
                    ],
930
                ],
931
            ],
932
            [
933
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345"> &nbsp; </td>',
934
                'url',
935
                null,
936
                [],
937
            ],
938
            [
939
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345"> &nbsp; </td>',
940
                'url',
941
                null,
942
                ['url' => 'http://example.com'],
943
            ],
944
            [
945
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345"> &nbsp; </td>',
946
                'url',
947
                null,
948
                ['route' => ['name' => 'sonata_admin_foo']],
949
            ],
950
            [
951
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
952
                <a href="http://example.com">http://example.com</a>
953
                </td>',
954
                'url',
955
                'http://example.com',
956
                [],
957
            ],
958
            [
959
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
960
                <a href="https://example.com">https://example.com</a>
961
                </td>',
962
                'url',
963
                'https://example.com',
964
                [],
965
            ],
966
            [
967
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
968
                <a href="https://example.com" target="_blank">https://example.com</a>
969
                </td>',
970
                'url',
971
                'https://example.com',
972
                ['attributes' => ['target' => '_blank']],
973
            ],
974
            [
975
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
976
                <a href="https://example.com" target="_blank" class="fooLink">https://example.com</a>
977
                </td>',
978
                'url',
979
                'https://example.com',
980
                ['attributes' => ['target' => '_blank', 'class' => 'fooLink']],
981
            ],
982
            [
983
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
984
                <a href="http://example.com">example.com</a>
985
                </td>',
986
                'url',
987
                'http://example.com',
988
                ['hide_protocol' => true],
989
            ],
990
            [
991
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
992
                <a href="https://example.com">example.com</a>
993
                </td>',
994
                'url',
995
                'https://example.com',
996
                ['hide_protocol' => true],
997
            ],
998
            [
999
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
1000
                <a href="http://example.com">http://example.com</a>
1001
                </td>',
1002
                'url',
1003
                'http://example.com',
1004
                ['hide_protocol' => false],
1005
            ],
1006
            [
1007
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
1008
                <a href="https://example.com">https://example.com</a>
1009
                </td>',
1010
                'url',
1011
                'https://example.com',
1012
                ['hide_protocol' => false],
1013
            ],
1014
            [
1015
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
1016
                <a href="http://example.com">Foo</a>
1017
                </td>',
1018
                'url',
1019
                'Foo',
1020
                ['url' => 'http://example.com'],
1021
            ],
1022
            [
1023
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
1024
                <a href="http://example.com">&lt;b&gt;Foo&lt;/b&gt;</a>
1025
                </td>',
1026
                'url',
1027
                '<b>Foo</b>',
1028
                ['url' => 'http://example.com'],
1029
            ],
1030
            [
1031
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
1032
                <a href="/foo">Foo</a>
1033
                </td>',
1034
                'url',
1035
                'Foo',
1036
                ['route' => ['name' => 'sonata_admin_foo']],
1037
            ],
1038
            [
1039
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
1040
                <a href="http://localhost/foo">Foo</a>
1041
                </td>',
1042
                'url',
1043
                'Foo',
1044
                ['route' => ['name' => 'sonata_admin_foo', 'absolute' => true]],
1045
            ],
1046
            [
1047
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
1048
                <a href="/foo">foo/bar?a=b&amp;c=123456789</a>
1049
                </td>',
1050
                'url',
1051
                'http://foo/bar?a=b&c=123456789',
1052
                ['route' => ['name' => 'sonata_admin_foo'],
1053
                'hide_protocol' => true, ],
1054
            ],
1055
            [
1056
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
1057
                <a href="http://localhost/foo">foo/bar?a=b&amp;c=123456789</a>
1058
                </td>',
1059
                'url',
1060
                'http://foo/bar?a=b&c=123456789',
1061
                [
1062
                    'route' => ['name' => 'sonata_admin_foo', 'absolute' => true],
1063
                    'hide_protocol' => true,
1064
                ],
1065
            ],
1066
            [
1067
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
1068
                <a href="/foo/abcd/efgh?param3=ijkl">Foo</a>
1069
                </td>',
1070
                'url',
1071
                'Foo',
1072
                [
1073
                    'route' => ['name' => 'sonata_admin_foo_param',
1074
                    'parameters' => ['param1' => 'abcd', 'param2' => 'efgh', 'param3' => 'ijkl'], ],
1075
                ],
1076
            ],
1077
            [
1078
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
1079
                <a href="http://localhost/foo/abcd/efgh?param3=ijkl">Foo</a>
1080
                </td>',
1081
                'url',
1082
                'Foo',
1083
                [
1084
                    'route' => ['name' => 'sonata_admin_foo_param',
1085
                    'absolute' => true,
1086
                    'parameters' => ['param1' => 'abcd', 'param2' => 'efgh', 'param3' => 'ijkl'], ],
1087
                ],
1088
            ],
1089
            [
1090
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
1091
                <a href="/foo/obj/abcd/12345/efgh?param3=ijkl">Foo</a>
1092
                </td>',
1093
                'url',
1094
                'Foo',
1095
                [
1096
                    'route' => ['name' => 'sonata_admin_foo_object',
1097
                    'parameters' => ['param1' => 'abcd', 'param2' => 'efgh', 'param3' => 'ijkl'],
1098
                    'identifier_parameter_name' => 'barId', ],
1099
                ],
1100
            ],
1101
            [
1102
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
1103
                <a href="http://localhost/foo/obj/abcd/12345/efgh?param3=ijkl">Foo</a>
1104
                </td>',
1105
                'url',
1106
                'Foo',
1107
                [
1108
                    'route' => ['name' => 'sonata_admin_foo_object',
1109
                    'absolute' => true,
1110
                    'parameters' => ['param1' => 'abcd', 'param2' => 'efgh', 'param3' => 'ijkl'],
1111
                    'identifier_parameter_name' => 'barId', ],
1112
                ],
1113
            ],
1114
            [
1115
                '<td class="sonata-ba-list-field sonata-ba-list-field-html" objectId="12345">
1116
                <p><strong>Creating a Template for the Field</strong> and form</p>
1117
                </td>',
1118
                'html',
1119
                '<p><strong>Creating a Template for the Field</strong> and form</p>',
1120
                [],
1121
            ],
1122
            [
1123
                '<td class="sonata-ba-list-field sonata-ba-list-field-html" objectId="12345">
1124
                Creating a Template for the Field and form
1125
                </td>',
1126
                'html',
1127
                '<p><strong>Creating a Template for the Field</strong> and form</p>',
1128
                ['strip' => true],
1129
            ],
1130
            [
1131
                '<td class="sonata-ba-list-field sonata-ba-list-field-html" objectId="12345">
1132
                Creating a Template for the Fi...
1133
                </td>',
1134
                'html',
1135
                '<p><strong>Creating a Template for the Field</strong> and form</p>',
1136
                ['truncate' => true],
1137
            ],
1138
            [
1139
                '<td class="sonata-ba-list-field sonata-ba-list-field-html" objectId="12345"> Creating a... </td>',
1140
                'html',
1141
                '<p><strong>Creating a Template for the Field</strong> and form</p>',
1142
                ['truncate' => ['length' => 10]],
1143
            ],
1144
            [
1145
                '<td class="sonata-ba-list-field sonata-ba-list-field-html" objectId="12345">
1146
                Creating a Template for the Field...
1147
                </td>',
1148
                'html',
1149
                '<p><strong>Creating a Template for the Field</strong> and form</p>',
1150
                ['truncate' => ['preserve' => true]],
1151
            ],
1152
            [
1153
                '<td class="sonata-ba-list-field sonata-ba-list-field-html" objectId="12345">
1154
                Creating a Template for the Fi etc.
1155
                </td>',
1156
                'html',
1157
                '<p><strong>Creating a Template for the Field</strong> and form</p>',
1158
                ['truncate' => ['separator' => ' etc.']],
1159
            ],
1160
            [
1161
                '<td class="sonata-ba-list-field sonata-ba-list-field-html" objectId="12345">
1162
                Creating a Template for[...]
1163
                </td>',
1164
                'html',
1165
                '<p><strong>Creating a Template for the Field</strong> and form</p>',
1166
                [
1167
                    'truncate' => [
1168
                        'length' => 20,
1169
                        'preserve' => true,
1170
                        'separator' => '[...]',
1171
                    ],
1172
                ],
1173
            ],
1174
1175
            [
1176
                <<<'EOT'
1177
<td class="sonata-ba-list-field sonata-ba-list-field-text" objectId="12345">
1178
<div
1179
    class="sonata-readmore"
1180
    data-readmore-height="40"
1181
    data-readmore-more="Read more"
1182
    data-readmore-less="Close">A very long string</div>
1183
</td>
1184
EOT
1185
                ,
1186
                'text',
1187
                'A very long string',
1188
                [
1189
                    'collapse' => true,
1190
                ],
1191
            ],
1192
            [
1193
                <<<'EOT'
1194
<td class="sonata-ba-list-field sonata-ba-list-field-text" objectId="12345">
1195
<div
1196
    class="sonata-readmore"
1197
    data-readmore-height="10"
1198
    data-readmore-more="More"
1199
    data-readmore-less="Less">A very long string</div>
1200
</td>
1201
EOT
1202
                ,
1203
                'text',
1204
                'A very long string',
1205
                [
1206
                    'collapse' => [
1207
                        'height' => 10,
1208
                        'more' => 'More',
1209
                        'less' => 'Less',
1210
                    ],
1211
                ],
1212
            ],
1213
        ];
1214
    }
1215
1216
    /**
1217
     * @dataProvider getRenderViewElementTests
1218
     */
1219
    public function testRenderViewElement($expected, $type, $value, array $options)
1220
    {
1221
        $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...
1222
            ->method('getTemplate')
1223
            ->will($this->returnValue('SonataAdminBundle:CRUD:base_show_field.html.twig'));
1224
1225
        $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...
1226
            ->method('getValue')
1227
            ->will($this->returnCallback(function () use ($value) {
1228
                if ($value instanceof NoValueException) {
1229
                    throw  $value;
1230
                }
1231
1232
                return $value;
1233
            }));
1234
1235
        $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...
1236
            ->method('getType')
1237
            ->will($this->returnValue($type));
1238
1239
        $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...
1240
            ->method('getOptions')
1241
            ->will($this->returnValue($options));
1242
1243
        $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...
1244
            ->method('getTemplate')
1245
            ->will($this->returnCallback(function () use ($type) {
1246
                switch ($type) {
1247
                    case 'boolean':
1248
                        return 'SonataAdminBundle:CRUD:show_boolean.html.twig';
1249
                    case 'datetime':
1250
                        return 'SonataAdminBundle:CRUD:show_datetime.html.twig';
1251
                    case 'date':
1252
                        return 'SonataAdminBundle:CRUD:show_date.html.twig';
1253
                    case 'time':
1254
                        return 'SonataAdminBundle:CRUD:show_time.html.twig';
1255
                    case 'currency':
1256
                        return 'SonataAdminBundle:CRUD:show_currency.html.twig';
1257
                    case 'percent':
1258
                        return 'SonataAdminBundle:CRUD:show_percent.html.twig';
1259
                    case 'email':
1260
                        return 'SonataAdminBundle:CRUD:show_email.html.twig';
1261
                    case 'choice':
1262
                        return 'SonataAdminBundle:CRUD:show_choice.html.twig';
1263
                    case 'array':
1264
                        return 'SonataAdminBundle:CRUD:show_array.html.twig';
1265
                    case 'trans':
1266
                        return 'SonataAdminBundle:CRUD:show_trans.html.twig';
1267
                    case 'url':
1268
                        return 'SonataAdminBundle:CRUD:show_url.html.twig';
1269
                    case 'html':
1270
                        return 'SonataAdminBundle:CRUD:show_html.html.twig';
1271
                    default:
1272
                        return false;
1273
                }
1274
            }));
1275
1276
        $this->assertSame(
1277
                $this->removeExtraWhitespace($expected),
1278
                $this->removeExtraWhitespace(
1279
                    $this->twigExtension->renderViewElement(
1280
                        $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...
1281
                        $this->fieldDescription,
1282
                        $this->object
1283
                    )
1284
                )
1285
            );
1286
    }
1287
1288
    public function getRenderViewElementTests()
1289
    {
1290
        return [
1291
            ['<th>Data</th> <td>Example</td>', 'string', 'Example', ['safe' => false]],
1292
            ['<th>Data</th> <td>Example</td>', 'text', 'Example', ['safe' => false]],
1293
            ['<th>Data</th> <td>Example</td>', 'textarea', 'Example', ['safe' => false]],
1294
            [
1295
                '<th>Data</th> <td>December 24, 2013 10:11</td>',
1296
                'datetime',
1297
                new \DateTime('2013-12-24 10:11:12', new \DateTimeZone('Europe/London')), [],
1298
            ],
1299
            [
1300
                '<th>Data</th> <td>24.12.2013 10:11:12</td>',
1301
                'datetime',
1302
                new \DateTime('2013-12-24 10:11:12', new \DateTimeZone('Europe/London')),
1303
                ['format' => 'd.m.Y H:i:s'],
1304
            ],
1305
            [
1306
                '<th>Data</th> <td>December 24, 2013</td>',
1307
                'date',
1308
                new \DateTime('2013-12-24 10:11:12', new \DateTimeZone('Europe/London')),
1309
                [],
1310
            ],
1311
            [
1312
                '<th>Data</th> <td>24.12.2013</td>',
1313
                'date',
1314
                new \DateTime('2013-12-24 10:11:12', new \DateTimeZone('Europe/London')),
1315
                ['format' => 'd.m.Y'],
1316
            ],
1317
            [
1318
                '<th>Data</th> <td>10:11:12</td>',
1319
                'time',
1320
                new \DateTime('2013-12-24 10:11:12', new \DateTimeZone('Europe/London')),
1321
                [],
1322
            ],
1323
            ['<th>Data</th> <td>10.746135</td>', 'number', 10.746135, ['safe' => false]],
1324
            ['<th>Data</th> <td>5678</td>', 'integer', 5678, ['safe' => false]],
1325
            ['<th>Data</th> <td> 1074.6135 % </td>', 'percent', 10.746135, []],
1326
            ['<th>Data</th> <td> EUR 10.746135 </td>', 'currency', 10.746135, ['currency' => 'EUR']],
1327
            ['<th>Data</th> <td> GBP 51.23456 </td>', 'currency', 51.23456, ['currency' => 'GBP']],
1328
            [
1329
                '<th>Data</th> <td> [1 => First] <br> [2 => Second] </td>',
1330
                'array',
1331
                [1 => 'First', 2 => 'Second'],
1332
                ['safe' => false],
1333
            ],
1334
            [
1335
                '<th>Data</th> <td> [1 => First] [2 => Second] </td>',
1336
                'array',
1337
                [1 => 'First', 2 => 'Second'],
1338
                ['safe' => false, 'inline' => true],
1339
            ],
1340
            [
1341
                '<th>Data</th> <td><span class="label label-success">yes</span></td>',
1342
                'boolean',
1343
                true,
1344
                [],
1345
            ],
1346
            [
1347
                '<th>Data</th> <td><span class="label label-danger">yes</span></td>',
1348
                'boolean',
1349
                true,
1350
                ['inverse' => true],
1351
            ],
1352
            ['<th>Data</th> <td><span class="label label-danger">no</span></td>', 'boolean', false, []],
1353
            [
1354
                '<th>Data</th> <td><span class="label label-success">no</span></td>',
1355
                'boolean',
1356
                false,
1357
                ['inverse' => true],
1358
            ],
1359
            [
1360
                '<th>Data</th> <td> Delete </td>',
1361
                'trans',
1362
                'action_delete',
1363
                ['safe' => false, 'catalogue' => 'SonataAdminBundle'],
1364
            ],
1365
            ['<th>Data</th> <td>Status1</td>', 'choice', 'Status1', ['safe' => false]],
1366
            [
1367
                '<th>Data</th> <td>Alias1</td>',
1368
                'choice',
1369
                'Status1',
1370
                ['safe' => false, 'choices' => [
1371
                    'Status1' => 'Alias1',
1372
                    'Status2' => 'Alias2',
1373
                    'Status3' => 'Alias3',
1374
                ]],
1375
            ],
1376
            [
1377
                '<th>Data</th> <td>NoValidKeyInChoices</td>',
1378
                'choice',
1379
                'NoValidKeyInChoices',
1380
                ['safe' => false, 'choices' => [
1381
                    'Status1' => 'Alias1',
1382
                    'Status2' => 'Alias2',
1383
                    'Status3' => 'Alias3',
1384
                ]],
1385
            ],
1386
            [
1387
                '<th>Data</th> <td>Delete</td>',
1388
                'choice',
1389
                'Foo',
1390
                ['safe' => false, 'catalogue' => 'SonataAdminBundle', 'choices' => [
1391
                    'Foo' => 'action_delete',
1392
                    'Status2' => 'Alias2',
1393
                    'Status3' => 'Alias3',
1394
                ]],
1395
            ],
1396
            [
1397
                '<th>Data</th> <td>NoValidKeyInChoices</td>',
1398
                'choice',
1399
                ['NoValidKeyInChoices'],
1400
                ['safe' => false, 'choices' => [
1401
                    'Status1' => 'Alias1',
1402
                    'Status2' => 'Alias2',
1403
                    'Status3' => 'Alias3',
1404
                ], 'multiple' => true],
1405
            ],
1406
            [
1407
                '<th>Data</th> <td>NoValidKeyInChoices, Alias2</td>',
1408
                'choice',
1409
                ['NoValidKeyInChoices', 'Status2'],
1410
                ['safe' => false, 'choices' => [
1411
                    'Status1' => 'Alias1',
1412
                    'Status2' => 'Alias2',
1413
                    'Status3' => 'Alias3',
1414
                ], 'multiple' => true],
1415
            ],
1416
            [
1417
                '<th>Data</th> <td>Alias1, Alias3</td>',
1418
                'choice',
1419
                ['Status1', 'Status3'],
1420
                ['safe' => false, 'choices' => [
1421
                    'Status1' => 'Alias1',
1422
                    'Status2' => 'Alias2',
1423
                    'Status3' => 'Alias3',
1424
                ], 'multiple' => true],
1425
            ],
1426
            [
1427
                '<th>Data</th> <td>Alias1 | Alias3</td>',
1428
                'choice',
1429
                ['Status1', 'Status3'], ['safe' => false, 'choices' => [
1430
                    'Status1' => 'Alias1',
1431
                    'Status2' => 'Alias2',
1432
                    'Status3' => 'Alias3',
1433
                ], 'multiple' => true, 'delimiter' => ' | '],
1434
            ],
1435
            [
1436
                '<th>Data</th> <td>Delete, Alias3</td>',
1437
                'choice',
1438
                ['Foo', 'Status3'],
1439
                ['safe' => false, 'catalogue' => 'SonataAdminBundle', 'choices' => [
1440
                    'Foo' => 'action_delete',
1441
                    'Status2' => 'Alias2',
1442
                    'Status3' => 'Alias3',
1443
                ], 'multiple' => true],
1444
            ],
1445
            [
1446
                '<th>Data</th> <td><b>Alias1</b>, <b>Alias3</b></td>',
1447
                'choice',
1448
                ['Status1', 'Status3'],
1449
                ['safe' => true, 'choices' => [
1450
                    'Status1' => '<b>Alias1</b>',
1451
                    'Status2' => '<b>Alias2</b>',
1452
                    'Status3' => '<b>Alias3</b>',
1453
                ], 'multiple' => true],
1454
            ],
1455
            [
1456
                '<th>Data</th> <td>&lt;b&gt;Alias1&lt;/b&gt;, &lt;b&gt;Alias3&lt;/b&gt;</td>',
1457
                'choice',
1458
                ['Status1', 'Status3'],
1459
                ['safe' => false, 'choices' => [
1460
                    'Status1' => '<b>Alias1</b>',
1461
                    'Status2' => '<b>Alias2</b>',
1462
                    'Status3' => '<b>Alias3</b>',
1463
                ], 'multiple' => true],
1464
            ],
1465
            [
1466
                '<th>Data</th> <td><a href="http://example.com">http://example.com</a></td>',
1467
                'url',
1468
                'http://example.com',
1469
                ['safe' => false],
1470
            ],
1471
            [
1472
                '<th>Data</th> <td><a href="http://example.com" target="_blank">http://example.com</a></td>',
1473
                'url',
1474
                'http://example.com',
1475
                ['safe' => false, 'attributes' => ['target' => '_blank']],
1476
            ],
1477
            [
1478
                '<th>Data</th> <td><a href="http://example.com" target="_blank" class="fooLink">http://example.com</a></td>',
1479
                'url',
1480
                'http://example.com',
1481
                ['safe' => false, 'attributes' => ['target' => '_blank', 'class' => 'fooLink']],
1482
            ],
1483
            [
1484
                '<th>Data</th> <td><a href="https://example.com">https://example.com</a></td>',
1485
                'url',
1486
                'https://example.com',
1487
                ['safe' => false],
1488
            ],
1489
            [
1490
                '<th>Data</th> <td><a href="http://example.com">example.com</a></td>',
1491
                'url',
1492
                'http://example.com',
1493
                ['safe' => false, 'hide_protocol' => true],
1494
            ],
1495
            [
1496
                '<th>Data</th> <td><a href="https://example.com">example.com</a></td>',
1497
                'url',
1498
                'https://example.com',
1499
                ['safe' => false, 'hide_protocol' => true],
1500
            ],
1501
            [
1502
                '<th>Data</th> <td><a href="http://example.com">http://example.com</a></td>',
1503
                'url',
1504
                'http://example.com',
1505
                ['safe' => false, 'hide_protocol' => false],
1506
            ],
1507
            [
1508
                '<th>Data</th> <td><a href="https://example.com">https://example.com</a></td>',
1509
                'url',
1510
                'https://example.com',
1511
                ['safe' => false,
1512
                'hide_protocol' => false, ],
1513
            ],
1514
            [
1515
                '<th>Data</th> <td><a href="http://example.com">Foo</a></td>',
1516
                'url',
1517
                'Foo',
1518
                ['safe' => false, 'url' => 'http://example.com'],
1519
            ],
1520
            [
1521
                '<th>Data</th> <td><a href="http://example.com">&lt;b&gt;Foo&lt;/b&gt;</a></td>',
1522
                'url',
1523
                '<b>Foo</b>',
1524
                ['safe' => false, 'url' => 'http://example.com'],
1525
            ],
1526
            [
1527
                '<th>Data</th> <td><a href="http://example.com"><b>Foo</b></a></td>',
1528
                'url',
1529
                '<b>Foo</b>',
1530
                ['safe' => true, 'url' => 'http://example.com'],
1531
            ],
1532
            [
1533
                '<th>Data</th> <td><a href="/foo">Foo</a></td>',
1534
                'url',
1535
                'Foo',
1536
                ['safe' => false, 'route' => ['name' => 'sonata_admin_foo']],
1537
            ],
1538
            [
1539
                '<th>Data</th> <td><a href="http://localhost/foo">Foo</a></td>',
1540
                'url',
1541
                'Foo',
1542
                ['safe' => false, 'route' => [
1543
                    'name' => 'sonata_admin_foo',
1544
                    'absolute' => true,
1545
                ]],
1546
            ],
1547
            [
1548
                '<th>Data</th> <td><a href="/foo">foo/bar?a=b&amp;c=123456789</a></td>',
1549
                'url',
1550
                'http://foo/bar?a=b&c=123456789',
1551
                [
1552
                    'safe' => false,
1553
                    'route' => ['name' => 'sonata_admin_foo'],
1554
                    'hide_protocol' => true,
1555
                ],
1556
            ],
1557
            [
1558
                '<th>Data</th> <td><a href="http://localhost/foo">foo/bar?a=b&amp;c=123456789</a></td>',
1559
                'url',
1560
                'http://foo/bar?a=b&c=123456789',
1561
                ['safe' => false, 'route' => [
1562
                    'name' => 'sonata_admin_foo',
1563
                    'absolute' => true,
1564
                ], 'hide_protocol' => true],
1565
            ],
1566
            [
1567
                '<th>Data</th> <td><a href="/foo/abcd/efgh?param3=ijkl">Foo</a></td>',
1568
                'url',
1569
                'Foo',
1570
                ['safe' => false, 'route' => [
1571
                    'name' => 'sonata_admin_foo_param',
1572
                    'parameters' => ['param1' => 'abcd', 'param2' => 'efgh', 'param3' => 'ijkl'],
1573
                ]],
1574
            ],
1575
            [
1576
                '<th>Data</th> <td><a href="http://localhost/foo/abcd/efgh?param3=ijkl">Foo</a></td>',
1577
                'url',
1578
                'Foo',
1579
                ['safe' => false, 'route' => [
1580
                    'name' => 'sonata_admin_foo_param',
1581
                    'absolute' => true,
1582
                    'parameters' => [
1583
                        'param1' => 'abcd',
1584
                        'param2' => 'efgh',
1585
                        'param3' => 'ijkl',
1586
                    ],
1587
                ]],
1588
            ],
1589
            [
1590
                '<th>Data</th> <td><a href="/foo/obj/abcd/12345/efgh?param3=ijkl">Foo</a></td>',
1591
                'url',
1592
                'Foo',
1593
                ['safe' => false, 'route' => [
1594
                    'name' => 'sonata_admin_foo_object',
1595
                    'parameters' => [
1596
                        'param1' => 'abcd',
1597
                        'param2' => 'efgh',
1598
                        'param3' => 'ijkl',
1599
                    ],
1600
                    'identifier_parameter_name' => 'barId',
1601
                ]],
1602
            ],
1603
            [
1604
                '<th>Data</th> <td><a href="http://localhost/foo/obj/abcd/12345/efgh?param3=ijkl">Foo</a></td>',
1605
                'url',
1606
                'Foo',
1607
                ['safe' => false, 'route' => [
1608
                    'name' => 'sonata_admin_foo_object',
1609
                    'absolute' => true,
1610
                    'parameters' => [
1611
                        'param1' => 'abcd',
1612
                        'param2' => 'efgh',
1613
                        'param3' => 'ijkl',
1614
                    ],
1615
                    'identifier_parameter_name' => 'barId',
1616
                ]],
1617
            ],
1618
            [
1619
                '<th>Data</th> <td> &nbsp;</td>',
1620
                'email',
1621
                null,
1622
                [],
1623
            ],
1624
            [
1625
                '<th>Data</th> <td> <a href="mailto:[email protected]">[email protected]</a></td>',
1626
                'email',
1627
                '[email protected]',
1628
                [],
1629
            ],
1630
            [
1631
                '<th>Data</th> <td> <a href="mailto:[email protected]?'.$this->buildTwigLikeUrl(['subject' => 'Main Theme', 'body' => 'Message Body']).'">[email protected]</a></td>',
1632
                'email',
1633
                '[email protected]',
1634
                ['subject' => 'Main Theme', 'body' => 'Message Body'],
1635
            ],
1636
            [
1637
                '<th>Data</th> <td> <a href="mailto:[email protected]?'.$this->buildTwigLikeUrl(['subject' => 'Main Theme']).'">[email protected]</a></td>',
1638
                'email',
1639
                '[email protected]',
1640
                ['subject' => 'Main Theme'],
1641
            ],
1642
            [
1643
                '<th>Data</th> <td> <a href="mailto:[email protected]?'.$this->buildTwigLikeUrl(['body' => 'Message Body']).'">[email protected]</a></td>',
1644
                'email',
1645
                '[email protected]',
1646
                ['body' => 'Message Body'],
1647
            ],
1648
            [
1649
                '<th>Data</th> <td> [email protected]</td>',
1650
                'email',
1651
                '[email protected]',
1652
                ['as_string' => true, 'subject' => 'Main Theme', 'body' => 'Message Body'],
1653
            ],
1654
            [
1655
                '<th>Data</th> <td> [email protected]</td>',
1656
                'email',
1657
                '[email protected]',
1658
                ['as_string' => true, 'subject' => 'Main Theme'],
1659
            ],
1660
            [
1661
                '<th>Data</th> <td> [email protected]</td>',
1662
                'email',
1663
                '[email protected]',
1664
                ['as_string' => true, 'body' => 'Message Body'],
1665
            ],
1666
            [
1667
                '<th>Data</th> <td> <a href="mailto:[email protected]">[email protected]</a></td>',
1668
                'email',
1669
                '[email protected]',
1670
                ['as_string' => false],
1671
            ],
1672
            [
1673
                '<th>Data</th> <td> [email protected]</td>',
1674
                'email',
1675
                '[email protected]',
1676
                ['as_string' => true],
1677
            ],
1678
            [
1679
                '<th>Data</th> <td><p><strong>Creating a Template for the Field</strong> and form</p> </td>',
1680
                'html',
1681
                '<p><strong>Creating a Template for the Field</strong> and form</p>',
1682
                [],
1683
            ],
1684
            [
1685
                '<th>Data</th> <td>Creating a Template for the Field and form </td>',
1686
                'html',
1687
                '<p><strong>Creating a Template for the Field</strong> and form</p>',
1688
                ['strip' => true],
1689
            ],
1690
            [
1691
                '<th>Data</th> <td> Creating a Template for the Fi... </td>',
1692
                'html',
1693
                '<p><strong>Creating a Template for the Field</strong> and form</p>',
1694
                ['truncate' => true],
1695
            ],
1696
            [
1697
                '<th>Data</th> <td> Creating a... </td>',
1698
                'html',
1699
                '<p><strong>Creating a Template for the Field</strong> and form</p>',
1700
                ['truncate' => ['length' => 10]],
1701
            ],
1702
            [
1703
                '<th>Data</th> <td> Creating a Template for the Field... </td>',
1704
                'html',
1705
                '<p><strong>Creating a Template for the Field</strong> and form</p>',
1706
                ['truncate' => ['preserve' => true]],
1707
            ],
1708
            [
1709
                '<th>Data</th> <td> Creating a Template for the Fi etc. </td>',
1710
                'html',
1711
                '<p><strong>Creating a Template for the Field</strong> and form</p>',
1712
                ['truncate' => ['separator' => ' etc.']],
1713
            ],
1714
            [
1715
                '<th>Data</th> <td> Creating a Template for[...] </td>',
1716
                'html',
1717
                '<p><strong>Creating a Template for the Field</strong> and form</p>',
1718
                [
1719
                    'truncate' => [
1720
                        'length' => 20,
1721
                        'preserve' => true,
1722
                        'separator' => '[...]',
1723
                    ],
1724
                ],
1725
            ],
1726
1727
            // NoValueException
1728
            ['<th>Data</th> <td></td>', 'string', new NoValueException(), ['safe' => false]],
1729
            ['<th>Data</th> <td></td>', 'text', new NoValueException(), ['safe' => false]],
1730
            ['<th>Data</th> <td></td>', 'textarea', new NoValueException(), ['safe' => false]],
1731
            ['<th>Data</th> <td>&nbsp;</td>', 'datetime', new NoValueException(), []],
1732
            [
1733
                '<th>Data</th> <td>&nbsp;</td>',
1734
                'datetime',
1735
                new NoValueException(),
1736
                ['format' => 'd.m.Y H:i:s'],
1737
            ],
1738
            ['<th>Data</th> <td>&nbsp;</td>', 'date', new NoValueException(), []],
1739
            ['<th>Data</th> <td>&nbsp;</td>', 'date', new NoValueException(), ['format' => 'd.m.Y']],
1740
            ['<th>Data</th> <td>&nbsp;</td>', 'time', new NoValueException(), []],
1741
            ['<th>Data</th> <td></td>', 'number', new NoValueException(), ['safe' => false]],
1742
            ['<th>Data</th> <td></td>', 'integer', new NoValueException(), ['safe' => false]],
1743
            ['<th>Data</th> <td> 0 % </td>', 'percent', new NoValueException(), []],
1744
            ['<th>Data</th> <td> </td>', 'currency', new NoValueException(), ['currency' => 'EUR']],
1745
            ['<th>Data</th> <td> </td>', 'currency', new NoValueException(), ['currency' => 'GBP']],
1746
            ['<th>Data</th> <td> </td>', 'array', new NoValueException(), ['safe' => false]],
1747
            [
1748
                '<th>Data</th> <td><span class="label label-danger">no</span></td>',
1749
                'boolean',
1750
                new NoValueException(),
1751
                [],
1752
            ],
1753
            [
1754
                '<th>Data</th> <td> </td>',
1755
                'trans',
1756
                new NoValueException(),
1757
                ['safe' => false, 'catalogue' => 'SonataAdminBundle'],
1758
            ],
1759
            [
1760
                '<th>Data</th> <td></td>',
1761
                'choice',
1762
                new NoValueException(),
1763
                ['safe' => false, 'choices' => []],
1764
            ],
1765
            [
1766
                '<th>Data</th> <td></td>',
1767
                'choice',
1768
                new NoValueException(),
1769
                ['safe' => false, 'choices' => [], 'multiple' => true],
1770
            ],
1771
            ['<th>Data</th> <td>&nbsp;</td>', 'url', new NoValueException(), []],
1772
            [
1773
                '<th>Data</th> <td>&nbsp;</td>',
1774
                'url',
1775
                new NoValueException(),
1776
                ['url' => 'http://example.com'],
1777
            ],
1778
            [
1779
                '<th>Data</th> <td>&nbsp;</td>',
1780
                'url',
1781
                new NoValueException(),
1782
                ['route' => ['name' => 'sonata_admin_foo']],
1783
            ],
1784
1785
            [
1786
                <<<'EOT'
1787
<th>Data</th> <td><div
1788
        class="sonata-readmore"
1789
        data-readmore-height="40"
1790
        data-readmore-more="Read more"
1791
        data-readmore-less="Close">
1792
            A very long string
1793
</div></td>
1794
EOT
1795
                ,
1796
                'text',
1797
                ' A very long string ',
1798
                [
1799
                    'collapse' => true,
1800
                    'safe' => false,
1801
                ],
1802
            ],
1803
            [
1804
                <<<'EOT'
1805
<th>Data</th> <td><div
1806
        class="sonata-readmore"
1807
        data-readmore-height="10"
1808
        data-readmore-more="More"
1809
        data-readmore-less="Less">
1810
            A very long string
1811
</div></td>
1812
EOT
1813
                ,
1814
                'text',
1815
                ' A very long string ',
1816
                [
1817
                    'collapse' => [
1818
                        'height' => 10,
1819
                        'more' => 'More',
1820
                        'less' => 'Less',
1821
                    ],
1822
                    'safe' => false,
1823
                ],
1824
            ],
1825
        ];
1826
    }
1827
1828
    public function testGetValueFromFieldDescription()
1829
    {
1830
        $object = new \stdClass();
1831
        $fieldDescription = $this->getMockForAbstractClass(FieldDescriptionInterface::class);
1832
1833
        $fieldDescription->expects($this->any())
1834
            ->method('getValue')
1835
            ->will($this->returnValue('test123'));
1836
1837
        $this->assertSame(
1838
            'test123',
1839
            $this->getMethodAsPublic('getValueFromFieldDescription')->invoke(
1840
                $this->twigExtension,
1841
                $object,
1842
                $fieldDescription
1843
            )
1844
        );
1845
    }
1846
1847
    public function testGetValueFromFieldDescriptionWithRemoveLoopException()
1848
    {
1849
        $object = $this->createMock(\ArrayAccess::class);
1850
        $fieldDescription = $this->getMockForAbstractClass(FieldDescriptionInterface::class);
1851
1852
        $this->expectException(\RuntimeException::class, 'remove the loop requirement');
1853
1854
        $this->assertSame(
1855
            'anything',
1856
            $this->getMethodAsPublic('getValueFromFieldDescription')->invoke(
1857
                $this->twigExtension,
1858
                $object,
1859
                $fieldDescription,
1860
                ['loop' => true]
1861
            )
1862
        );
1863
    }
1864
1865
    public function testGetValueFromFieldDescriptionWithNoValueException()
1866
    {
1867
        $object = new \stdClass();
1868
        $fieldDescription = $this->getMockForAbstractClass(FieldDescriptionInterface::class);
1869
1870
        $fieldDescription->expects($this->any())
1871
            ->method('getValue')
1872
            ->will($this->returnCallback(function () {
1873
                throw new NoValueException();
1874
            }));
1875
1876
        $fieldDescription->expects($this->any())
1877
            ->method('getAssociationAdmin')
1878
            ->will($this->returnValue(null));
1879
1880
        $this->assertNull(
1881
            $this->getMethodAsPublic('getValueFromFieldDescription')->invoke(
1882
                $this->twigExtension,
1883
                $object,
1884
                $fieldDescription
1885
            )
1886
        );
1887
    }
1888
1889
    public function testGetValueFromFieldDescriptionWithNoValueExceptionNewAdminInstance()
1890
    {
1891
        $object = new \stdClass();
1892
        $fieldDescription = $this->getMockForAbstractClass(FieldDescriptionInterface::class);
1893
1894
        $fieldDescription->expects($this->any())
1895
            ->method('getValue')
1896
            ->will($this->returnCallback(function () {
1897
                throw new NoValueException();
1898
            }));
1899
1900
        $fieldDescription->expects($this->any())
1901
            ->method('getAssociationAdmin')
1902
            ->will($this->returnValue($this->admin));
1903
1904
        $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...
1905
            ->method('getNewInstance')
1906
            ->will($this->returnValue('foo'));
1907
1908
        $this->assertSame(
1909
            'foo',
1910
            $this->getMethodAsPublic('getValueFromFieldDescription')->invoke(
1911
                $this->twigExtension,
1912
                $object,
1913
                $fieldDescription
1914
            )
1915
        );
1916
    }
1917
1918
    public function testOutput()
1919
    {
1920
        $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...
1921
            ->method('getTemplate')
1922
            ->will($this->returnValue('SonataAdminBundle:CRUD:base_list_field.html.twig'));
1923
1924
        $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...
1925
            ->method('getFieldName')
1926
            ->will($this->returnValue('fd_name'));
1927
1928
        $this->environment->disableDebug();
1929
1930
        $parameters = [
1931
            'admin' => $this->admin,
1932
            'value' => 'foo',
1933
            'field_description' => $this->fieldDescription,
1934
            'object' => $this->object,
1935
        ];
1936
1937
        $template = $this->environment->loadTemplate('SonataAdminBundle:CRUD:base_list_field.html.twig');
1938
1939
        $reflection = $this->getMethodAsPublic('output');
1940
1941
        $this->assertSame(
1942
            '<td class="sonata-ba-list-field sonata-ba-list-field-" objectId="12345"> foo </td>',
1943
            $this->removeExtraWhitespace($reflection->invoke(
1944
                $this->twigExtension,
1945
                $this->fieldDescription,
1946
                $template,
1947
                $parameters,
1948
                $this->environment
1949
            ))
1950
        );
1951
1952
        $this->environment->enableDebug();
1953
        $this->assertSame(
1954
            $this->removeExtraWhitespace(<<<'EOT'
1955
<!-- START
1956
    fieldName: fd_name
1957
    template: SonataAdminBundle:CRUD:base_list_field.html.twig
1958
    compiled template: SonataAdminBundle:CRUD:base_list_field.html.twig
1959
-->
1960
    <td class="sonata-ba-list-field sonata-ba-list-field-" objectId="12345"> foo </td>
1961
<!-- END - fieldName: fd_name -->
1962
EOT
1963
            ),
1964
            $this->removeExtraWhitespace(
1965
                $reflection->invoke(
1966
                    $this->twigExtension,
1967
                    $this->fieldDescription,
1968
                    $template,
1969
                    $parameters,
1970
                    $this->environment
1971
                )
1972
            )
1973
        );
1974
    }
1975
1976
    public function testRenderRelationElementNoObject()
1977
    {
1978
        $this->assertSame('foo', $this->twigExtension->renderRelationElement('foo', $this->fieldDescription));
1979
    }
1980
1981
    public function testRenderRelationElementToString()
1982
    {
1983
        $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...
1984
            ->method('getOption')
1985
            ->will($this->returnCallback(function ($value, $default = null) {
1986
                if ('associated_property' == $value) {
1987
                    return $default;
1988
                }
1989
            }));
1990
1991
        $element = new FooToString();
1992
        $this->assertSame('salut', $this->twigExtension->renderRelationElement($element, $this->fieldDescription));
1993
    }
1994
1995
    /**
1996
     * @group legacy
1997
     */
1998
    public function testDeprecatedRelationElementToString()
1999
    {
2000
        $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...
2001
            ->method('getOption')
2002
            ->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...
2003
                if ('associated_tostring' == $value) {
2004
                    return '__toString';
2005
                }
2006
            }));
2007
2008
        $element = new FooToString();
2009
        $this->assertSame(
2010
            'salut',
2011
            $this->twigExtension->renderRelationElement($element, $this->fieldDescription)
2012
        );
2013
    }
2014
2015
    /**
2016
     * @group legacy
2017
     */
2018
    public function testRenderRelationElementCustomToString()
2019
    {
2020
        $this->fieldDescription->expects($this->exactly(2))
0 ignored issues
show
Bug introduced by
The method expects() does not seem to exist on object<Sonata\AdminBundl...ldDescriptionInterface>.

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

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

Loading history...
2021
            ->method('getOption')
2022
            ->will($this->returnCallback(function ($value, $default = null) {
2023
                if ('associated_property' == $value) {
2024
                    return $default;
2025
                }
2026
2027
                if ('associated_tostring' == $value) {
2028
                    return 'customToString';
2029
                }
2030
            }));
2031
2032
        $element = $this->getMockBuilder('stdClass')
2033
            ->setMethods(['customToString'])
2034
            ->getMock();
2035
        $element->expects($this->any())
2036
            ->method('customToString')
2037
            ->will($this->returnValue('fooBar'));
2038
2039
        $this->assertSame('fooBar', $this->twigExtension->renderRelationElement($element, $this->fieldDescription));
2040
    }
2041
2042
    /**
2043
     * @group legacy
2044
     */
2045
    public function testRenderRelationElementMethodNotExist()
2046
    {
2047
        $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...
2048
            ->method('getOption')
2049
2050
            ->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...
2051
                if ('associated_tostring' == $value) {
2052
                    return 'nonExistedMethod';
2053
                }
2054
            }));
2055
2056
        $element = new \stdClass();
2057
        $this->expectException(\RuntimeException::class, 'You must define an `associated_property` option or create a `stdClass::__toString');
2058
2059
        $this->twigExtension->renderRelationElement($element, $this->fieldDescription);
2060
    }
2061
2062
    public function testRenderRelationElementWithPropertyPath()
2063
    {
2064
        $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...
2065
            ->method('getOption')
2066
2067
            ->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...
2068
                if ('associated_property' == $value) {
2069
                    return 'foo';
2070
                }
2071
            }));
2072
2073
        $element = new \stdClass();
2074
        $element->foo = 'bar';
2075
2076
        $this->assertSame('bar', $this->twigExtension->renderRelationElement($element, $this->fieldDescription));
2077
    }
2078
2079
    public function testRenderRelationElementWithClosure()
2080
    {
2081
        $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...
2082
            ->method('getOption')
2083
2084
            ->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...
2085
                if ('associated_property' == $value) {
2086
                    return function ($element) {
2087
                        return 'closure '.$element->foo;
2088
                    };
2089
                }
2090
            }));
2091
2092
        $element = new \stdClass();
2093
        $element->foo = 'bar';
2094
2095
        $this->assertSame(
2096
            'closure bar',
2097
            $this->twigExtension->renderRelationElement($element, $this->fieldDescription)
2098
        );
2099
    }
2100
2101
    public function testGetUrlsafeIdentifier()
2102
    {
2103
        $entity = new \stdClass();
2104
2105
        // set admin to pool
2106
        $this->pool->setAdminServiceIds(['sonata_admin_foo_service']);
2107
        $this->pool->setAdminClasses(['stdClass' => ['sonata_admin_foo_service']]);
2108
2109
        $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...
2110
            ->method('getUrlsafeIdentifier')
2111
            ->with($this->equalTo($entity))
2112
            ->will($this->returnValue(1234567));
2113
2114
        $this->assertSame(1234567, $this->twigExtension->getUrlsafeIdentifier($entity));
2115
    }
2116
2117
    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...
2118
    {
2119
        $entity = new \stdClass();
2120
2121
        // set admin to pool
2122
        $this->pool->setAdminServiceIds([
2123
            'sonata_admin_foo_service',
2124
            'sonata_admin_bar_service',
2125
        ]);
2126
        $this->pool->setAdminClasses(['stdClass' => [
2127
            'sonata_admin_foo_service',
2128
            'sonata_admin_bar_service',
2129
        ]]);
2130
2131
        $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...
2132
            ->method('getUrlsafeIdentifier')
2133
            ->with($this->equalTo($entity))
2134
            ->will($this->returnValue(1234567));
2135
2136
        $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...
2137
            ->method('getUrlsafeIdentifier');
2138
2139
        $this->assertSame(1234567, $this->twigExtension->getUrlsafeIdentifier($entity, $this->admin));
2140
    }
2141
2142
    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...
2143
    {
2144
        $entity = new \stdClass();
2145
2146
        // set admin to pool
2147
        $this->pool->setAdminServiceIds(['sonata_admin_foo_service', 'sonata_admin_bar_service']);
2148
        $this->pool->setAdminClasses(['stdClass' => [
2149
            'sonata_admin_foo_service',
2150
            'sonata_admin_bar_service',
2151
        ]]);
2152
2153
        $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...
2154
            ->method('getUrlsafeIdentifier');
2155
2156
        $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...
2157
            ->method('getUrlsafeIdentifier')
2158
            ->with($this->equalTo($entity))
2159
            ->will($this->returnValue(1234567));
2160
2161
        $this->assertSame(1234567, $this->twigExtension->getUrlsafeIdentifier($entity, $this->adminBar));
2162
    }
2163
2164
    public function xEditableChoicesProvider()
2165
    {
2166
        return [
2167
            'needs processing' => [['Status1' => 'Alias1', 'Status2' => 'Alias2']],
2168
            'already processed' => [[
2169
                ['value' => 'Status1', 'text' => 'Alias1'],
2170
                ['value' => 'Status2', 'text' => 'Alias2'],
2171
            ]],
2172
        ];
2173
    }
2174
2175
    /**
2176
     * @dataProvider xEditablechoicesProvider
2177
     */
2178
    public function testGetXEditableChoicesIsIdempotent(array $input)
2179
    {
2180
        $fieldDescription = $this->getMockForAbstractClass(FieldDescriptionInterface::class);
2181
        $fieldDescription->expects($this->exactly(2))
2182
            ->method('getOption')
2183
            ->withConsecutive(
2184
                ['choices', []],
2185
                ['catalogue']
2186
            )
2187
            ->will($this->onConsecutiveCalls(
2188
                $input,
2189
                'MyCatalogue'
2190
            ));
2191
2192
        $this->assertSame(
2193
            [
2194
                ['value' => 'Status1', 'text' => 'Alias1'],
2195
                ['value' => 'Status2', 'text' => 'Alias2'],
2196
            ],
2197
            $this->twigExtension->getXEditableChoices($fieldDescription)
2198
        );
2199
    }
2200
2201
    /**
2202
     * This method generates url part for Twig layout.
2203
     *
2204
     * @param array $url
2205
     *
2206
     * @return string
2207
     */
2208
    private function buildTwigLikeUrl($url)
2209
    {
2210
        return htmlspecialchars(http_build_query($url, '', '&', PHP_QUERY_RFC3986));
2211
    }
2212
2213
    private function getMethodAsPublic($privateMethod)
2214
    {
2215
        $reflection = new \ReflectionMethod('Sonata\AdminBundle\Twig\Extension\SonataAdminExtension', $privateMethod);
2216
        $reflection->setAccessible(true);
2217
2218
        return $reflection;
2219
    }
2220
2221
    private function removeExtraWhitespace($string)
2222
    {
2223
        return trim(preg_replace(
2224
            '/\s+/',
2225
            ' ',
2226
            $string
2227
        ));
2228
    }
2229
}
2230