Completed
Pull Request — 3.x (#6200)
by
unknown
03:13
created

testRenderRelationElementCustomToString()   A

Complexity

Conditions 3
Paths 1

Size

Total Lines 23

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 23
rs 9.552
c 0
b 0
f 0
cc 3
nc 1
nop 0
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of the Sonata Project package.
7
 *
8
 * (c) Thomas Rabaix <[email protected]>
9
 *
10
 * For the full copyright and license information, please view the LICENSE
11
 * file that was distributed with this source code.
12
 */
13
14
namespace Sonata\AdminBundle\Tests\Twig\Extension;
15
16
use PHPUnit\Framework\TestCase;
17
use Prophecy\Argument;
18
use Psr\Log\LoggerInterface;
19
use Sonata\AdminBundle\Admin\AbstractAdmin;
20
use Sonata\AdminBundle\Admin\AdminInterface;
21
use Sonata\AdminBundle\Admin\FieldDescriptionInterface;
22
use Sonata\AdminBundle\Admin\Pool;
23
use Sonata\AdminBundle\Exception\NoValueException;
24
use Sonata\AdminBundle\Templating\TemplateRegistryInterface;
25
use Sonata\AdminBundle\Tests\Fixtures\Entity\FooToString;
26
use Sonata\AdminBundle\Tests\Fixtures\StubFilesystemLoader;
27
use Sonata\AdminBundle\Twig\Extension\SonataAdminExtension;
28
use Symfony\Bridge\Twig\AppVariable;
29
use Symfony\Bridge\Twig\Extension\RoutingExtension;
30
use Symfony\Bridge\Twig\Extension\TranslationExtension;
31
use Symfony\Component\Config\FileLocator;
32
use Symfony\Component\DependencyInjection\ContainerInterface;
33
use Symfony\Component\HttpFoundation\Request;
34
use Symfony\Component\Routing\Generator\UrlGenerator;
35
use Symfony\Component\Routing\Loader\XmlFileLoader;
36
use Symfony\Component\Routing\RequestContext;
37
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
38
use Symfony\Component\Translation\Loader\XliffFileLoader;
39
use Symfony\Component\Translation\Translator;
40
use Symfony\Component\Translation\TranslatorInterface as LegacyTranslatorInterface;
41
use Symfony\Contracts\Translation\TranslatorInterface;
42
use Twig\Environment;
43
use Twig\Error\LoaderError;
44
use Twig\Extra\String\StringExtension;
45
46
/**
47
 * Test for SonataAdminExtension.
48
 *
49
 * @author Andrej Hudec <[email protected]>
50
 */
51
class SonataAdminExtensionTest extends TestCase
52
{
53
    /**
54
     * @var SonataAdminExtension
55
     */
56
    private $twigExtension;
57
58
    /**
59
     * @var Environment
60
     */
61
    private $environment;
62
63
    /**
64
     * @var AdminInterface
65
     */
66
    private $admin;
67
68
    /**
69
     * @var AdminInterface
70
     */
71
    private $adminBar;
72
73
    /**
74
     * @var FieldDescriptionInterface
75
     */
76
    private $fieldDescription;
77
78
    /**
79
     * @var \stdClass
80
     */
81
    private $object;
82
83
    /**
84
     * @var Pool
85
     */
86
    private $pool;
87
88
    /**
89
     * @var LoggerInterface
90
     */
91
    private $logger;
92
93
    /**
94
     * @var string[]
95
     */
96
    private $xEditableTypeMapping;
97
98
    /**
99
     * @var TranslatorInterface
100
     */
101
    private $translator;
102
103
    /**
104
     * @var ContainerInterface
105
     */
106
    private $container;
107
108
    /**
109
     * @var TemplateRegistryInterface
110
     */
111
    private $templateRegistry;
112
113
    /**
114
     * @var AuthorizationCheckerInterface
115
     */
116
    private $securityChecker;
117
118
    protected function setUp(): void
119
    {
120
        date_default_timezone_set('Europe/London');
121
122
        $container = $this->createMock(ContainerInterface::class);
123
124
        $this->pool = new Pool($container, '', '');
125
        $this->pool->setAdminServiceIds(['sonata_admin_foo_service']);
126
        $this->pool->setAdminClasses(['fooClass' => ['sonata_admin_foo_service']]);
127
128
        $this->logger = $this->getMockForAbstractClass(LoggerInterface::class);
129
        $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...
130
            'choice' => 'select',
131
            'boolean' => 'select',
132
            'text' => 'text',
133
            'textarea' => 'textarea',
134
            'html' => 'textarea',
135
            'email' => 'email',
136
            'string' => 'text',
137
            'smallint' => 'text',
138
            'bigint' => 'text',
139
            'integer' => 'number',
140
            'decimal' => 'number',
141
            'currency' => 'number',
142
            'percent' => 'number',
143
            'url' => 'url',
144
        ];
145
146
        // translation extension
147
        $translator = new Translator('en');
148
        $translator->addLoader('xlf', new XliffFileLoader());
149
        $translator->addResource(
150
            'xlf',
151
            sprintf('%s/../../../src/Resources/translations/SonataAdminBundle.en.xliff', __DIR__),
152
            'en',
153
            'SonataAdminBundle'
154
        );
155
156
        $this->translator = $translator;
157
158
        $this->templateRegistry = $this->prophesize(TemplateRegistryInterface::class);
159
        $this->container = $this->prophesize(ContainerInterface::class);
160
        $this->container->get('sonata_admin_foo_service.template_registry')->willReturn($this->templateRegistry->reveal());
161
162
        $this->securityChecker = $this->prophesize(AuthorizationCheckerInterface::class);
163
        $this->securityChecker->isGranted(['foo', 'bar'], null)->willReturn(false);
164
        $this->securityChecker->isGranted(Argument::type('string'), null)->willReturn(true);
165
166
        $this->twigExtension = new SonataAdminExtension(
167
            $this->pool,
168
            $this->logger,
169
            $this->translator,
170
            $this->container->reveal(),
171
            $this->securityChecker->reveal()
172
        );
173
        $this->twigExtension->setXEditableTypeMapping($this->xEditableTypeMapping);
174
175
        $request = $this->createMock(Request::class);
176
        $request->method('get')->with('_sonata_admin')->willReturn('sonata_admin_foo_service');
177
178
        $loader = new StubFilesystemLoader([
179
            __DIR__.'/../../../src/Resources/views/CRUD',
180
            __DIR__.'/../../Fixtures/Resources/views/CRUD',
181
        ]);
182
        $loader->addPath(__DIR__.'/../../../src/Resources/views/', 'SonataAdmin');
183
        $loader->addPath(__DIR__.'/../../Fixtures/Resources/views/', 'App');
184
185
        $this->environment = new Environment($loader, [
186
            'strict_variables' => true,
187
            'cache' => false,
188
            'autoescape' => 'html',
189
            'optimizations' => 0,
190
        ]);
191
        $this->environment->addExtension($this->twigExtension);
192
        $this->environment->addExtension(new TranslationExtension($translator));
193
        $this->environment->addExtension(new FakeTemplateRegistryExtension());
194
195
        // routing extension
196
        $xmlFileLoader = new XmlFileLoader(new FileLocator([sprintf('%s/../../../src/Resources/config/routing', __DIR__)]));
197
        $routeCollection = $xmlFileLoader->load('sonata_admin.xml');
198
199
        $xmlFileLoader = new XmlFileLoader(new FileLocator([sprintf('%s/../../Fixtures/Resources/config/routing', __DIR__)]));
200
        $testRouteCollection = $xmlFileLoader->load('routing.xml');
201
202
        $routeCollection->addCollection($testRouteCollection);
0 ignored issues
show
Documentation introduced by
$testRouteCollection is of type object<Symfony\Component\Routing\RouteCollection>, but the function expects a object<self>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
203
        $requestContext = new RequestContext();
204
        $urlGenerator = new UrlGenerator($routeCollection, $requestContext);
205
        $this->environment->addExtension(new RoutingExtension($urlGenerator));
206
        $this->environment->addExtension(new StringExtension());
207
208
        // initialize object
209
        $this->object = new \stdClass();
210
211
        // initialize admin
212
        $this->admin = $this->createMock(AbstractAdmin::class);
213
214
        $this->admin
215
            ->method('getCode')
216
            ->willReturn('sonata_admin_foo_service');
217
218
        $this->admin
219
            ->method('id')
220
            ->with($this->equalTo($this->object))
221
            ->willReturn(12345);
222
223
        $this->admin
224
            ->method('getNormalizedIdentifier')
225
            ->with($this->equalTo($this->object))
226
            ->willReturn(12345);
227
228
        $this->admin
229
            ->method('trans')
230
            ->willReturnCallback(static function ($id, $parameters = [], $domain = null) use ($translator) {
231
                return $translator->trans($id, $parameters, $domain);
232
            });
233
234
        $this->adminBar = $this->createMock(AbstractAdmin::class);
235
        $this->adminBar
236
            ->method('hasAccess')
237
            ->willReturn(true);
238
        $this->adminBar
239
            ->method('getNormalizedIdentifier')
240
            ->with($this->equalTo($this->object))
241
            ->willReturn(12345);
242
243
        $container
244
            ->method('get')
245
            ->willReturnCallback(function (string $id) {
246
                if ('sonata_admin_foo_service' === $id) {
247
                    return $this->admin;
248
                }
249
250
                if ('sonata_admin_bar_service' === $id) {
251
                    return $this->adminBar;
252
                }
253
            });
254
255
        // initialize field description
256
        $this->fieldDescription = $this->getMockForAbstractClass(FieldDescriptionInterface::class);
257
258
        $this->fieldDescription
259
            ->method('getName')
260
            ->willReturn('fd_name');
261
262
        $this->fieldDescription
263
            ->method('getAdmin')
264
            ->willReturn($this->admin);
265
266
        $this->fieldDescription
267
            ->method('getLabel')
268
            ->willReturn('Data');
269
    }
270
271
    /**
272
     * NEXT_MAJOR: Remove this method.
273
     *
274
     * @group legacy
275
     */
276
    public function testConstructThrowsExceptionWithWrongTranslationArgument(): void
277
    {
278
        $this->expectException(\TypeError::class);
279
280
        new SonataAdminExtension(
281
            $this->pool,
282
            null,
283
            new \stdClass()
284
        );
285
    }
286
287
    /**
288
     * @doesNotPerformAssertions
289
     * @group legacy
290
     */
291
    public function testConstructWithLegacyTranslator(): void
292
    {
293
        new SonataAdminExtension(
294
            $this->pool,
295
            null,
296
            $this->createStub(LegacyTranslatorInterface::class)
297
        );
298
    }
299
300
    /**
301
     * @group legacy
302
     * @expectedDeprecation The Sonata\AdminBundle\Admin\AbstractAdmin::getTemplate method is deprecated (since sonata-project/admin-bundle 3.34, will be dropped in 4.0. Use TemplateRegistry services instead).
303
     * @dataProvider getRenderListElementTests
304
     */
305
    public function testRenderListElement(string $expected, string $type, $value, array $options): void
306
    {
307
        $this->admin
0 ignored issues
show
Bug introduced by
The method method() does not seem to exist on object<Sonata\AdminBundle\Admin\AdminInterface>.

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

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

Loading history...
308
            ->method('getPersistentParameters')
309
            ->willReturn(['context' => 'foo']);
310
311
        $this->admin
0 ignored issues
show
Bug introduced by
The method method() does not seem to exist on object<Sonata\AdminBundle\Admin\AdminInterface>.

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

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

Loading history...
312
            ->method('hasAccess')
313
            ->willReturn(true);
314
315
        // NEXT_MAJOR: Remove this line
316
        $this->admin
0 ignored issues
show
Bug introduced by
The method method() does not seem to exist on object<Sonata\AdminBundle\Admin\AdminInterface>.

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

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

Loading history...
317
            ->method('getTemplate')
318
            ->with('base_list_field')
319
            ->willReturn('@SonataAdmin/CRUD/base_list_field.html.twig');
320
321
        $this->templateRegistry->getTemplate('base_list_field')->willReturn('@SonataAdmin/CRUD/base_list_field.html.twig');
0 ignored issues
show
Bug introduced by
The method willReturn cannot be called on $this->templateRegistry-...late('base_list_field') (of type string).

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

Loading history...
322
323
        $this->fieldDescription
0 ignored issues
show
Bug introduced by
The method method() does not seem to exist on object<Sonata\AdminBundl...ldDescriptionInterface>.

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

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

Loading history...
324
            ->method('getValue')
325
            ->willReturn($value);
326
327
        $this->fieldDescription
0 ignored issues
show
Bug introduced by
The method method() does not seem to exist on object<Sonata\AdminBundl...ldDescriptionInterface>.

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

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

Loading history...
328
            ->method('getType')
329
            ->willReturn($type);
330
331
        $this->fieldDescription
0 ignored issues
show
Bug introduced by
The method method() does not seem to exist on object<Sonata\AdminBundl...ldDescriptionInterface>.

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

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

Loading history...
332
            ->method('getOptions')
333
            ->willReturn($options);
334
335
        $this->fieldDescription
0 ignored issues
show
Bug introduced by
The method method() does not seem to exist on object<Sonata\AdminBundl...ldDescriptionInterface>.

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

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

Loading history...
336
            ->method('getOption')
337
            ->willReturnCallback(static function ($name, $default = null) use ($options) {
338
                return $options[$name] ?? $default;
339
            });
340
341
        $this->fieldDescription
0 ignored issues
show
Bug introduced by
The method method() does not seem to exist on object<Sonata\AdminBundl...ldDescriptionInterface>.

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

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

Loading history...
342
            ->method('getTemplate')
343
            ->willReturnCallback(static function () use ($type): ?string {
344
                switch ($type) {
345
                    case 'string':
346
                        return '@SonataAdmin/CRUD/list_string.html.twig';
347
                    case 'boolean':
348
                        return '@SonataAdmin/CRUD/list_boolean.html.twig';
349
                    case 'datetime':
350
                        return '@SonataAdmin/CRUD/list_datetime.html.twig';
351
                    case 'date':
352
                        return '@SonataAdmin/CRUD/list_date.html.twig';
353
                    case 'time':
354
                        return '@SonataAdmin/CRUD/list_time.html.twig';
355
                    case 'currency':
356
                        return '@SonataAdmin/CRUD/list_currency.html.twig';
357
                    case 'percent':
358
                        return '@SonataAdmin/CRUD/list_percent.html.twig';
359
                    case 'email':
360
                        return '@SonataAdmin/CRUD/list_email.html.twig';
361
                    case 'choice':
362
                        return '@SonataAdmin/CRUD/list_choice.html.twig';
363
                    case 'array':
364
                        return '@SonataAdmin/CRUD/list_array.html.twig';
365
                    case 'trans':
366
                        return '@SonataAdmin/CRUD/list_trans.html.twig';
367
                    case 'url':
368
                        return '@SonataAdmin/CRUD/list_url.html.twig';
369
                    case 'html':
370
                        return '@SonataAdmin/CRUD/list_html.html.twig';
371
                    case 'nonexistent':
372
                        // template doesn`t exist
373
                        return '@SonataAdmin/CRUD/list_nonexistent_template.html.twig';
374
                    default:
375
                        return null;
376
                }
377
            });
378
379
        $this->assertSame(
380
            $this->removeExtraWhitespace($expected),
381
            $this->removeExtraWhitespace($this->twigExtension->renderListElement(
382
                $this->environment,
383
                $this->object,
384
                $this->fieldDescription
385
            ))
386
        );
387
    }
388
389
    /**
390
     * @group legacy
391
     * @expectedDeprecation The Sonata\AdminBundle\Admin\AbstractAdmin::getTemplate method is deprecated (since sonata-project/admin-bundle 3.34, will be dropped in 4.0. Use TemplateRegistry services instead).
392
     */
393
    public function testRenderListElementWithAdditionalValuesInArray(): void
394
    {
395
        // NEXT_MAJOR: Remove this line
396
        $this->admin
0 ignored issues
show
Bug introduced by
The method method() does not seem to exist on object<Sonata\AdminBundle\Admin\AdminInterface>.

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

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

Loading history...
397
            ->method('getTemplate')
398
            ->with('base_list_field')
399
            ->willReturn('@SonataAdmin/CRUD/base_list_field.html.twig');
400
401
        $this->templateRegistry->getTemplate('base_list_field')->willReturn('@SonataAdmin/CRUD/base_list_field.html.twig');
0 ignored issues
show
Bug introduced by
The method willReturn cannot be called on $this->templateRegistry-...late('base_list_field') (of type string).

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

Loading history...
402
403
        $this->fieldDescription
0 ignored issues
show
Bug introduced by
The method method() does not seem to exist on object<Sonata\AdminBundl...ldDescriptionInterface>.

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

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

Loading history...
404
            ->method('getTemplate')
405
            ->willReturn('@SonataAdmin/CRUD/list_string.html.twig');
406
407
        $this->assertSame(
408
            $this->removeExtraWhitespace('<td class="sonata-ba-list-field sonata-ba-list-field-" objectId="12345"> Extra value </td>'),
409
            $this->removeExtraWhitespace($this->twigExtension->renderListElement(
410
                $this->environment,
411
                [$this->object, 'fd_name' => 'Extra value'],
412
                $this->fieldDescription
413
            ))
414
        );
415
    }
416
417
    /**
418
     * @group legacy
419
     * @expectedDeprecation Accessing a non existing value is deprecated since sonata-project/admin-bundle 3.67 and will throw an exception in 4.0.
420
     */
421
    public function testRenderListElementWithNoValueException(): void
422
    {
423
        // NEXT_MAJOR: Remove this line
424
        $this->admin
0 ignored issues
show
Bug introduced by
The method method() does not seem to exist on object<Sonata\AdminBundle\Admin\AdminInterface>.

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

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

Loading history...
425
            ->method('getTemplate')
426
            ->with('base_list_field')
427
            ->willReturn('@SonataAdmin/CRUD/base_list_field.html.twig');
428
429
        $this->templateRegistry->getTemplate('base_list_field')->willReturn('@SonataAdmin/CRUD/base_list_field.html.twig');
0 ignored issues
show
Bug introduced by
The method willReturn cannot be called on $this->templateRegistry-...late('base_list_field') (of type string).

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

Loading history...
430
431
        $this->fieldDescription
0 ignored issues
show
Bug introduced by
The method method() does not seem to exist on object<Sonata\AdminBundl...ldDescriptionInterface>.

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

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

Loading history...
432
            ->method('getValue')
433
            ->willReturnCallback(static function (): void {
434
                throw new NoValueException();
435
            });
436
437
        $this->assertSame(
438
            $this->removeExtraWhitespace('<td class="sonata-ba-list-field sonata-ba-list-field-" objectId="12345"> </td>'),
439
            $this->removeExtraWhitespace($this->twigExtension->renderListElement(
440
                $this->environment,
441
                $this->object,
442
                $this->fieldDescription
443
            ))
444
        );
445
    }
446
447
    /**
448
     * @dataProvider getDeprecatedRenderListElementTests
449
     * @group legacy
450
     */
451
    public function testDeprecatedRenderListElement(string $expected, ?string $value, array $options): void
452
    {
453
        $this->admin
0 ignored issues
show
Bug introduced by
The method method() does not seem to exist on object<Sonata\AdminBundle\Admin\AdminInterface>.

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

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

Loading history...
454
            ->method('hasAccess')
455
            ->willReturn(true);
456
457
        // NEXT_MAJOR: Remove this line
458
        $this->admin
0 ignored issues
show
Bug introduced by
The method method() does not seem to exist on object<Sonata\AdminBundle\Admin\AdminInterface>.

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

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

Loading history...
459
            ->method('getTemplate')
460
            ->with('base_list_field')
461
            ->willReturn('@SonataAdmin/CRUD/base_list_field.html.twig');
462
463
        $this->templateRegistry->getTemplate('base_list_field')->willReturn('@SonataAdmin/CRUD/base_list_field.html.twig');
0 ignored issues
show
Bug introduced by
The method willReturn cannot be called on $this->templateRegistry-...late('base_list_field') (of type string).

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

Loading history...
464
465
        $this->fieldDescription
0 ignored issues
show
Bug introduced by
The method method() does not seem to exist on object<Sonata\AdminBundl...ldDescriptionInterface>.

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

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

Loading history...
466
            ->method('getValue')
467
            ->willReturn($value);
468
469
        $this->fieldDescription
0 ignored issues
show
Bug introduced by
The method method() does not seem to exist on object<Sonata\AdminBundl...ldDescriptionInterface>.

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

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

Loading history...
470
            ->method('getType')
471
            ->willReturn('nonexistent');
472
473
        $this->fieldDescription
0 ignored issues
show
Bug introduced by
The method method() does not seem to exist on object<Sonata\AdminBundl...ldDescriptionInterface>.

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

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

Loading history...
474
            ->method('getOptions')
475
            ->willReturn($options);
476
477
        $this->fieldDescription
0 ignored issues
show
Bug introduced by
The method method() does not seem to exist on object<Sonata\AdminBundl...ldDescriptionInterface>.

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

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

Loading history...
478
            ->method('getOption')
479
            ->willReturnCallback(static function ($name, $default = null) use ($options) {
480
                return $options[$name] ?? $default;
481
            });
482
483
        $this->fieldDescription
0 ignored issues
show
Bug introduced by
The method method() does not seem to exist on object<Sonata\AdminBundl...ldDescriptionInterface>.

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

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

Loading history...
484
            ->method('getTemplate')
485
            ->willReturn('@SonataAdmin/CRUD/list_nonexistent_template.html.twig');
486
487
        $this->assertSame(
488
            $this->removeExtraWhitespace($expected),
489
            $this->removeExtraWhitespace($this->twigExtension->renderListElement(
490
                $this->environment,
491
                $this->object,
492
                $this->fieldDescription
493
            ))
494
        );
495
    }
496
497
    public function getDeprecatedRenderListElementTests()
498
    {
499
        return [
500
            [
501
                '<td class="sonata-ba-list-field sonata-ba-list-field-nonexistent" objectId="12345"> Example </td>',
502
                'Example',
503
                [],
504
            ],
505
            [
506
                '<td class="sonata-ba-list-field sonata-ba-list-field-nonexistent" objectId="12345"> </td>',
507
                null,
508
                [],
509
            ],
510
        ];
511
    }
512
513
    public function getRenderListElementTests()
514
    {
515
        return [
516
            [
517
                '<td class="sonata-ba-list-field sonata-ba-list-field-string" objectId="12345"> Example </td>',
518
                'string',
519
                'Example',
520
                [],
521
            ],
522
            [
523
                '<td class="sonata-ba-list-field sonata-ba-list-field-string" objectId="12345"> </td>',
524
                'string',
525
                null,
526
                [],
527
            ],
528
            [
529
                '<td class="sonata-ba-list-field sonata-ba-list-field-text" objectId="12345"> Example </td>',
530
                'text',
531
                'Example',
532
                [],
533
            ],
534
            [
535
                '<td class="sonata-ba-list-field sonata-ba-list-field-text" objectId="12345"> </td>',
536
                'text',
537
                null,
538
                [],
539
            ],
540
            [
541
                '<td class="sonata-ba-list-field sonata-ba-list-field-textarea" objectId="12345"> Example </td>',
542
                'textarea',
543
                'Example',
544
                [],
545
            ],
546
            [
547
                '<td class="sonata-ba-list-field sonata-ba-list-field-textarea" objectId="12345"> </td>',
548
                'textarea',
549
                null,
550
                [],
551
            ],
552
            'datetime field' => [
553
                '<td class="sonata-ba-list-field sonata-ba-list-field-datetime" objectId="12345">
554
                    <time datetime="2013-12-24T10:11:12+00:00" title="2013-12-24T10:11:12+00:00">
555
                        December 24, 2013 10:11
556
                    </time>
557
                </td>',
558
                'datetime',
559
                new \DateTime('2013-12-24 10:11:12', new \DateTimeZone('Europe/London')),
560
                [],
561
            ],
562
            [
563
                '<td class="sonata-ba-list-field sonata-ba-list-field-datetime" objectId="12345">
564
                    <time datetime="2013-12-24T10:11:12+00:00" title="2013-12-24T10:11:12+00:00">
565
                        December 24, 2013 18:11
566
                    </time>
567
                </td>',
568
                'datetime',
569
                new \DateTime('2013-12-24 10:11:12', new \DateTimeZone('UTC')),
570
                ['timezone' => 'Asia/Hong_Kong'],
571
            ],
572
            [
573
                '<td class="sonata-ba-list-field sonata-ba-list-field-datetime" objectId="12345"> &nbsp; </td>',
574
                'datetime',
575
                null,
576
                [],
577
            ],
578
            [
579
                '<td class="sonata-ba-list-field sonata-ba-list-field-datetime" objectId="12345">
580
                    <time datetime="2013-12-24T10:11:12+00:00" title="2013-12-24T10:11:12+00:00">
581
                        24.12.2013 10:11:12
582
                    </time>
583
                </td>',
584
                'datetime',
585
                new \DateTime('2013-12-24 10:11:12', new \DateTimeZone('Europe/London')),
586
                ['format' => 'd.m.Y H:i:s'],
587
            ],
588
            [
589
                '<td class="sonata-ba-list-field sonata-ba-list-field-datetime" objectId="12345"> &nbsp; </td>',
590
                'datetime',
591
                null,
592
                ['format' => 'd.m.Y H:i:s'],
593
            ],
594
            [
595
                '<td class="sonata-ba-list-field sonata-ba-list-field-datetime" objectId="12345">
596
                    <time datetime="2013-12-24T10:11:12+00:00" title="2013-12-24T10:11:12+00:00">
597
                        24.12.2013 18:11:12
598
                    </time>
599
                </td>',
600
                'datetime',
601
                new \DateTime('2013-12-24 10:11:12', new \DateTimeZone('UTC')),
602
                ['format' => 'd.m.Y H:i:s', 'timezone' => 'Asia/Hong_Kong'],
603
            ],
604
            [
605
                '<td class="sonata-ba-list-field sonata-ba-list-field-datetime" objectId="12345"> &nbsp; </td>',
606
                'datetime',
607
                null,
608
                ['format' => 'd.m.Y H:i:s', 'timezone' => 'Asia/Hong_Kong'],
609
            ],
610
            [
611
                '<td class="sonata-ba-list-field sonata-ba-list-field-date" objectId="12345">
612
                    <time datetime="2013-12-24" title="2013-12-24">
613
                        December 24, 2013
614
                    </time>
615
                </td>',
616
                'date',
617
                new \DateTime('2013-12-24 10:11:12', new \DateTimeZone('Europe/London')),
618
                [],
619
            ],
620
            [
621
                '<td class="sonata-ba-list-field sonata-ba-list-field-date" objectId="12345"> &nbsp; </td>',
622
                'date',
623
                null,
624
                [],
625
            ],
626
            [
627
                '<td class="sonata-ba-list-field sonata-ba-list-field-date" objectId="12345">
628
                    <time datetime="2013-12-24" title="2013-12-24">
629
                        24.12.2013
630
                    </time>
631
                </td>',
632
                'date',
633
                new \DateTime('2013-12-24 10:11:12', new \DateTimeZone('Europe/London')),
634
                ['format' => 'd.m.Y'],
635
            ],
636
            [
637
                '<td class="sonata-ba-list-field sonata-ba-list-field-date" objectId="12345"> &nbsp; </td>',
638
                'date',
639
                null,
640
                ['format' => 'd.m.Y'],
641
            ],
642
            [
643
                '<td class="sonata-ba-list-field sonata-ba-list-field-time" objectId="12345">
644
                    <time datetime="10:11:12+00:00" title="10:11:12+00:00">
645
                        10:11:12
646
                    </time>
647
                </td>',
648
                'time',
649
                new \DateTime('2013-12-24 10:11:12', new \DateTimeZone('Europe/London')),
650
                [],
651
            ],
652
            [
653
                '<td class="sonata-ba-list-field sonata-ba-list-field-time" objectId="12345">
654
                    <time datetime="10:11:12+00:00" title="10:11:12+00:00">
655
                        18:11:12
656
                    </time>
657
                </td>',
658
                'time',
659
                new \DateTime('2013-12-24 10:11:12', new \DateTimeZone('UTC')),
660
                ['timezone' => 'Asia/Hong_Kong'],
661
            ],
662
            [
663
                '<td class="sonata-ba-list-field sonata-ba-list-field-time" objectId="12345"> &nbsp; </td>',
664
                'time',
665
                null,
666
                [],
667
            ],
668
            [
669
                '<td class="sonata-ba-list-field sonata-ba-list-field-number" objectId="12345"> 10.746135 </td>',
670
                'number', 10.746135,
671
                [],
672
            ],
673
            [
674
                '<td class="sonata-ba-list-field sonata-ba-list-field-number" objectId="12345"> </td>',
675
                'number',
676
                null,
677
                [],
678
            ],
679
            [
680
                '<td class="sonata-ba-list-field sonata-ba-list-field-integer" objectId="12345"> 5678 </td>',
681
                'integer',
682
                5678,
683
                [],
684
            ],
685
            [
686
                '<td class="sonata-ba-list-field sonata-ba-list-field-integer" objectId="12345"> </td>',
687
                'integer',
688
                null,
689
                [],
690
            ],
691
            [
692
                '<td class="sonata-ba-list-field sonata-ba-list-field-percent" objectId="12345"> 1074.6135 % </td>',
693
                'percent',
694
                10.746135,
695
                [],
696
            ],
697
            [
698
                '<td class="sonata-ba-list-field sonata-ba-list-field-percent" objectId="12345"> 0 % </td>',
699
                'percent',
700
                null,
701
                [],
702
            ],
703
            [
704
                '<td class="sonata-ba-list-field sonata-ba-list-field-currency" objectId="12345"> EUR 10.746135 </td>',
705
                'currency',
706
                10.746135,
707
                ['currency' => 'EUR'],
708
            ],
709
            [
710
                '<td class="sonata-ba-list-field sonata-ba-list-field-currency" objectId="12345"> </td>',
711
                'currency',
712
                null,
713
                ['currency' => 'EUR'],
714
            ],
715
            [
716
                '<td class="sonata-ba-list-field sonata-ba-list-field-currency" objectId="12345"> GBP 51.23456 </td>',
717
                'currency',
718
                51.23456,
719
                ['currency' => 'GBP'],
720
            ],
721
            [
722
                '<td class="sonata-ba-list-field sonata-ba-list-field-currency" objectId="12345"> </td>',
723
                'currency',
724
                null,
725
                ['currency' => 'GBP'],
726
            ],
727
            [
728
                '<td class="sonata-ba-list-field sonata-ba-list-field-email" objectId="12345"> &nbsp; </td>',
729
                'email',
730
                null,
731
                [],
732
            ],
733
            [
734
                '<td class="sonata-ba-list-field sonata-ba-list-field-email" objectId="12345"> <a href="mailto:[email protected]">[email protected]</a> </td>',
735
                'email',
736
                '[email protected]',
737
                [],
738
            ],
739
            [
740
                '<td class="sonata-ba-list-field sonata-ba-list-field-email" objectId="12345">
741
                    <a href="mailto:[email protected]">[email protected]</a> </td>',
742
                'email',
743
                '[email protected]',
744
                ['as_string' => false],
745
            ],
746
            [
747
                '<td class="sonata-ba-list-field sonata-ba-list-field-email" objectId="12345"> [email protected] </td>',
748
                'email',
749
                '[email protected]',
750
                ['as_string' => true],
751
            ],
752
            [
753
                '<td class="sonata-ba-list-field sonata-ba-list-field-email" objectId="12345">
754
                    <a href="mailto:[email protected]?'.$this->buildTwigLikeUrl(['subject' => 'Main Theme', 'body' => 'Message Body']).'">[email protected]</a>  </td>',
755
                'email',
756
                '[email protected]',
757
                ['subject' => 'Main Theme', 'body' => 'Message Body'],
758
            ],
759
            [
760
                '<td class="sonata-ba-list-field sonata-ba-list-field-email" objectId="12345">
761
                    <a href="mailto:[email protected]?'.$this->buildTwigLikeUrl(['subject' => 'Main Theme']).'">[email protected]</a>  </td>',
762
                'email',
763
                '[email protected]',
764
                ['subject' => 'Main Theme'],
765
            ],
766
            [
767
                '<td class="sonata-ba-list-field sonata-ba-list-field-email" objectId="12345">
768
                    <a href="mailto:[email protected]?'.$this->buildTwigLikeUrl(['body' => 'Message Body']).'">[email protected]</a>  </td>',
769
                'email',
770
                '[email protected]',
771
                ['body' => 'Message Body'],
772
            ],
773
            [
774
                '<td class="sonata-ba-list-field sonata-ba-list-field-email" objectId="12345"> [email protected] </td>',
775
                'email',
776
                '[email protected]',
777
                ['as_string' => true, 'subject' => 'Main Theme', 'body' => 'Message Body'],
778
            ],
779
            [
780
                '<td class="sonata-ba-list-field sonata-ba-list-field-email" objectId="12345"> [email protected] </td>',
781
                'email',
782
                '[email protected]',
783
                ['as_string' => true, 'body' => 'Message Body'],
784
            ],
785
            [
786
                '<td class="sonata-ba-list-field sonata-ba-list-field-email" objectId="12345"> [email protected] </td>',
787
                'email',
788
                '[email protected]',
789
                ['as_string' => true, 'subject' => 'Main Theme'],
790
            ],
791
            [
792
                '<td class="sonata-ba-list-field sonata-ba-list-field-array" objectId="12345">
793
                    [1&nbsp;=>&nbsp;First, 2&nbsp;=>&nbsp;Second]
794
                </td>',
795
                'array',
796
                [1 => 'First', 2 => 'Second'],
797
                [],
798
            ],
799
            [
800
                '<td class="sonata-ba-list-field sonata-ba-list-field-array" objectId="12345"> [] </td>',
801
                'array',
802
                null,
803
                [],
804
            ],
805
            [
806
                '<td class="sonata-ba-list-field sonata-ba-list-field-boolean" objectId="12345">
807
                    <span class="label label-success">yes</span>
808
                </td>',
809
                'boolean',
810
                true,
811
                ['editable' => false],
812
            ],
813
            [
814
                '<td class="sonata-ba-list-field sonata-ba-list-field-boolean" objectId="12345">
815
                    <span class="label label-danger">no</span>
816
                </td>',
817
                'boolean',
818
                false,
819
                ['editable' => false],
820
            ],
821
            [
822
                '<td class="sonata-ba-list-field sonata-ba-list-field-boolean" objectId="12345">
823
                    <span class="label label-danger">no</span>
824
                </td>',
825
                'boolean',
826
                null,
827
                ['editable' => false],
828
            ],
829
            [
830
                <<<'EOT'
831
<td class="sonata-ba-list-field sonata-ba-list-field-boolean" objectId="12345">
832
    <span
833
        class="x-editable"
834
        data-type="select"
835
        data-value="1"
836
        data-title="Data"
837
        data-pk="12345"
838
        data-url="/core/set-object-field-value?context=list&amp;field=fd_name&amp;objectId=12345&amp;code=sonata_admin_foo_service"
839
        data-source="[{value: 0, text: 'no'},{value: 1, text: 'yes'}]"
840
    >
841
        <span class="label label-success">yes</span>
842
    </span>
843
</td>
844
EOT
845
            ,
846
                'boolean',
847
                true,
848
                ['editable' => true],
849
            ],
850
            [
851
                <<<'EOT'
852
<td class="sonata-ba-list-field sonata-ba-list-field-boolean" objectId="12345">
853
    <span
854
        class="x-editable"
855
        data-type="select"
856
        data-value="0"
857
        data-title="Data"
858
        data-pk="12345"
859
        data-url="/core/set-object-field-value?context=list&amp;field=fd_name&amp;objectId=12345&amp;code=sonata_admin_foo_service"
860
        data-source="[{value: 0, text: 'no'},{value: 1, text: 'yes'}]"
861
    >
862
    <span class="label label-danger">no</span> </span>
863
</td>
864
EOT
865
                ,
866
                'boolean',
867
                false,
868
                ['editable' => true],
869
            ],
870
            [
871
                <<<'EOT'
872
<td class="sonata-ba-list-field sonata-ba-list-field-boolean" objectId="12345">
873
    <span
874
        class="x-editable"
875
        data-type="select"
876
        data-value="0"
877
        data-title="Data"
878
        data-pk="12345"
879
        data-url="/core/set-object-field-value?context=list&amp;field=fd_name&amp;objectId=12345&amp;code=sonata_admin_foo_service"
880
        data-source="[{value: 0, text: 'no'},{value: 1, text: 'yes'}]" >
881
        <span class="label label-danger">no</span> </span>
882
</td>
883
EOT
884
                ,
885
                'boolean',
886
                null,
887
                ['editable' => true],
888
            ],
889
            [
890
                '<td class="sonata-ba-list-field sonata-ba-list-field-trans" objectId="12345"> Delete </td>',
891
                'trans',
892
                'action_delete',
893
                ['catalogue' => 'SonataAdminBundle'],
894
            ],
895
            [
896
                '<td class="sonata-ba-list-field sonata-ba-list-field-trans" objectId="12345"> </td>',
897
                'trans',
898
                null,
899
                ['catalogue' => 'SonataAdminBundle'],
900
            ],
901
            [
902
                '<td class="sonata-ba-list-field sonata-ba-list-field-trans" objectId="12345"> Delete </td>',
903
                'trans',
904
                'action_delete',
905
                ['format' => '%s', 'catalogue' => 'SonataAdminBundle'],
906
            ],
907
            [
908
                '<td class="sonata-ba-list-field sonata-ba-list-field-trans" objectId="12345">
909
                action.action_delete
910
                </td>',
911
                'trans',
912
                'action_delete',
913
                ['format' => 'action.%s'],
914
            ],
915
            [
916
                '<td class="sonata-ba-list-field sonata-ba-list-field-trans" objectId="12345">
917
                action.action_delete
918
                </td>',
919
                'trans',
920
                'action_delete',
921
                ['format' => 'action.%s', 'catalogue' => 'SonataAdminBundle'],
922
            ],
923
            [
924
                '<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345"> Status1 </td>',
925
                'choice',
926
                'Status1',
927
                [],
928
            ],
929
            [
930
                '<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345"> Status1 </td>',
931
                'choice',
932
                ['Status1'],
933
                ['choices' => [], 'multiple' => true],
934
            ],
935
            [
936
                '<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345"> Alias1 </td>',
937
                'choice',
938
                'Status1',
939
                ['choices' => ['Status1' => 'Alias1', 'Status2' => 'Alias2', 'Status3' => 'Alias3']],
940
            ],
941
            [
942
                '<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345"> </td>',
943
                'choice',
944
                null,
945
                ['choices' => ['Status1' => 'Alias1', 'Status2' => 'Alias2', 'Status3' => 'Alias3']],
946
            ],
947
            [
948
                '<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345">
949
                NoValidKeyInChoices
950
                </td>',
951
                'choice',
952
                'NoValidKeyInChoices',
953
                ['choices' => ['Status1' => 'Alias1', 'Status2' => 'Alias2', 'Status3' => 'Alias3']],
954
            ],
955
            [
956
                '<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345"> Delete </td>',
957
                'choice',
958
                'Foo',
959
                ['catalogue' => 'SonataAdminBundle', 'choices' => [
960
                    'Foo' => 'action_delete',
961
                    'Status2' => 'Alias2',
962
                    'Status3' => 'Alias3',
963
                ]],
964
            ],
965
            [
966
                '<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345"> Alias1, Alias3 </td>',
967
                'choice',
968
                ['Status1', 'Status3'],
969
                ['choices' => [
970
                    'Status1' => 'Alias1',
971
                    'Status2' => 'Alias2',
972
                    'Status3' => 'Alias3',
973
                ], 'multiple' => true], ],
974
            [
975
                '<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345"> Alias1 | Alias3 </td>',
976
                'choice',
977
                ['Status1', 'Status3'],
978
                ['choices' => [
979
                    'Status1' => 'Alias1',
980
                    'Status2' => 'Alias2',
981
                    'Status3' => 'Alias3',
982
                ], 'multiple' => true, 'delimiter' => ' | '], ],
983
            [
984
                '<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345"> </td>',
985
                'choice',
986
                null,
987
                ['choices' => [
988
                    'Status1' => 'Alias1',
989
                    'Status2' => 'Alias2',
990
                    'Status3' => 'Alias3',
991
                ], 'multiple' => true],
992
            ],
993
            [
994
                '<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345">
995
                NoValidKeyInChoices
996
                </td>',
997
                'choice',
998
                ['NoValidKeyInChoices'],
999
                ['choices' => [
1000
                    'Status1' => 'Alias1',
1001
                    'Status2' => 'Alias2',
1002
                    'Status3' => 'Alias3',
1003
                ], 'multiple' => true],
1004
            ],
1005
            [
1006
                '<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345">
1007
                NoValidKeyInChoices, Alias2
1008
                </td>',
1009
                'choice',
1010
                ['NoValidKeyInChoices', 'Status2'],
1011
                ['choices' => [
1012
                    'Status1' => 'Alias1',
1013
                    'Status2' => 'Alias2',
1014
                    'Status3' => 'Alias3',
1015
                ], 'multiple' => true],
1016
            ],
1017
            [
1018
                '<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345"> Delete, Alias3 </td>',
1019
                'choice',
1020
                ['Foo', 'Status3'],
1021
                ['catalogue' => 'SonataAdminBundle', 'choices' => [
1022
                    'Foo' => 'action_delete',
1023
                    'Status2' => 'Alias2',
1024
                    'Status3' => 'Alias3',
1025
                ], 'multiple' => true],
1026
            ],
1027
            [
1028
                '<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345">
1029
                &lt;b&gt;Alias1&lt;/b&gt;, &lt;b&gt;Alias3&lt;/b&gt;
1030
            </td>',
1031
                'choice',
1032
                ['Status1', 'Status3'],
1033
                ['choices' => [
1034
                    'Status1' => '<b>Alias1</b>',
1035
                    'Status2' => '<b>Alias2</b>',
1036
                    'Status3' => '<b>Alias3</b>',
1037
                ], 'multiple' => true], ],
1038
            [
1039
                <<<'EOT'
1040
<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345">
1041
    <span
1042
        class="x-editable"
1043
        data-type="select"
1044
        data-value="Status1"
1045
        data-title="Data"
1046
        data-pk="12345"
1047
        data-url="/core/set-object-field-value?context=list&amp;field=fd_name&amp;objectId=12345&amp;code=sonata_admin_foo_service"
1048
        data-source="[]"
1049
    >
1050
        Status1
1051
    </span>
1052
</td>
1053
EOT
1054
                ,
1055
                'choice',
1056
                'Status1',
1057
                ['editable' => true],
1058
            ],
1059
            [
1060
                <<<'EOT'
1061
<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345">
1062
    <span
1063
        class="x-editable"
1064
        data-type="select"
1065
        data-value="Status1"
1066
        data-title="Data"
1067
        data-pk="12345"
1068
        data-url="/core/set-object-field-value?context=list&amp;field=fd_name&amp;objectId=12345&amp;code=sonata_admin_foo_service"
1069
        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;}]" >
1070
        Alias1 </span>
1071
</td>
1072
EOT
1073
                ,
1074
                'choice',
1075
                'Status1',
1076
                [
1077
                    'editable' => true,
1078
                    'choices' => [
1079
                        'Status1' => 'Alias1',
1080
                        'Status2' => 'Alias2',
1081
                        'Status3' => 'Alias3',
1082
                    ],
1083
                ],
1084
            ],
1085
            [
1086
                <<<'EOT'
1087
<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345">
1088
    <span
1089
        class="x-editable"
1090
        data-type="select"
1091
        data-value=""
1092
        data-title="Data"
1093
        data-pk="12345"
1094
        data-url="/core/set-object-field-value?context=list&amp;field=fd_name&amp;objectId=12345&amp;code=sonata_admin_foo_service"
1095
        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;}]" >
1096
1097
    </span>
1098
</td>
1099
EOT
1100
                ,
1101
                'choice',
1102
                null,
1103
                [
1104
                    'editable' => true,
1105
                    'choices' => [
1106
                        'Status1' => 'Alias1',
1107
                        'Status2' => 'Alias2',
1108
                        'Status3' => 'Alias3',
1109
                    ],
1110
                ],
1111
            ],
1112
            [
1113
                <<<'EOT'
1114
<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345">
1115
    <span
1116
        class="x-editable"
1117
        data-type="select"
1118
        data-value="NoValidKeyInChoices"
1119
        data-title="Data" data-pk="12345"
1120
        data-url="/core/set-object-field-value?context=list&amp;field=fd_name&amp;objectId=12345&amp;code=sonata_admin_foo_service"
1121
        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;}]" >
1122
        NoValidKeyInChoices
1123
    </span>
1124
</td>
1125
EOT
1126
                ,
1127
                'choice',
1128
                'NoValidKeyInChoices',
1129
                [
1130
                    'editable' => true,
1131
                    'choices' => [
1132
                        'Status1' => 'Alias1',
1133
                        'Status2' => 'Alias2',
1134
                        'Status3' => 'Alias3',
1135
                    ],
1136
                ],
1137
            ],
1138
            [
1139
                <<<'EOT'
1140
<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345">
1141
    <span
1142
        class="x-editable"
1143
        data-type="select"
1144
        data-value="Foo"
1145
        data-title="Data"
1146
        data-pk="12345"
1147
        data-url="/core/set-object-field-value?context=list&amp;field=fd_name&amp;objectId=12345&amp;code=sonata_admin_foo_service"
1148
        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;}]" >
1149
         Delete
1150
    </span>
1151
</td>
1152
EOT
1153
                ,
1154
                'choice',
1155
                'Foo',
1156
                [
1157
                    'editable' => true,
1158
                    'catalogue' => 'SonataAdminBundle',
1159
                    'choices' => [
1160
                        'Foo' => 'action_delete',
1161
                        'Status2' => 'Alias2',
1162
                        'Status3' => 'Alias3',
1163
                    ],
1164
                ],
1165
            ],
1166
            [
1167
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345"> &nbsp; </td>',
1168
                'url',
1169
                null,
1170
                [],
1171
            ],
1172
            [
1173
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345"> &nbsp; </td>',
1174
                'url',
1175
                null,
1176
                ['url' => 'http://example.com'],
1177
            ],
1178
            [
1179
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345"> &nbsp; </td>',
1180
                'url',
1181
                null,
1182
                ['route' => ['name' => 'sonata_admin_foo']],
1183
            ],
1184
            [
1185
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
1186
                <a href="http://example.com">http://example.com</a>
1187
                </td>',
1188
                'url',
1189
                'http://example.com',
1190
                [],
1191
            ],
1192
            [
1193
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
1194
                <a href="https://example.com">https://example.com</a>
1195
                </td>',
1196
                'url',
1197
                'https://example.com',
1198
                [],
1199
            ],
1200
            [
1201
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
1202
                <a href="https://example.com" target="_blank">https://example.com</a>
1203
                </td>',
1204
                'url',
1205
                'https://example.com',
1206
                ['attributes' => ['target' => '_blank']],
1207
            ],
1208
            [
1209
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
1210
                <a href="https://example.com" target="_blank" class="fooLink">https://example.com</a>
1211
                </td>',
1212
                'url',
1213
                'https://example.com',
1214
                ['attributes' => ['target' => '_blank', 'class' => 'fooLink']],
1215
            ],
1216
            [
1217
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
1218
                <a href="http://example.com">example.com</a>
1219
                </td>',
1220
                'url',
1221
                'http://example.com',
1222
                ['hide_protocol' => true],
1223
            ],
1224
            [
1225
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
1226
                <a href="https://example.com">example.com</a>
1227
                </td>',
1228
                'url',
1229
                'https://example.com',
1230
                ['hide_protocol' => true],
1231
            ],
1232
            [
1233
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
1234
                <a href="http://example.com">http://example.com</a>
1235
                </td>',
1236
                'url',
1237
                'http://example.com',
1238
                ['hide_protocol' => false],
1239
            ],
1240
            [
1241
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
1242
                <a href="https://example.com">https://example.com</a>
1243
                </td>',
1244
                'url',
1245
                'https://example.com',
1246
                ['hide_protocol' => false],
1247
            ],
1248
            [
1249
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
1250
                <a href="http://example.com">Foo</a>
1251
                </td>',
1252
                'url',
1253
                'Foo',
1254
                ['url' => 'http://example.com'],
1255
            ],
1256
            [
1257
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
1258
                <a href="http://example.com">&lt;b&gt;Foo&lt;/b&gt;</a>
1259
                </td>',
1260
                'url',
1261
                '<b>Foo</b>',
1262
                ['url' => 'http://example.com'],
1263
            ],
1264
            [
1265
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
1266
                <a href="/foo">Foo</a>
1267
                </td>',
1268
                'url',
1269
                'Foo',
1270
                ['route' => ['name' => 'sonata_admin_foo']],
1271
            ],
1272
            [
1273
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
1274
                <a href="http://localhost/foo">Foo</a>
1275
                </td>',
1276
                'url',
1277
                'Foo',
1278
                ['route' => ['name' => 'sonata_admin_foo', 'absolute' => true]],
1279
            ],
1280
            [
1281
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
1282
                <a href="/foo">foo/bar?a=b&amp;c=123456789</a>
1283
                </td>',
1284
                'url',
1285
                'http://foo/bar?a=b&c=123456789',
1286
                ['route' => ['name' => 'sonata_admin_foo'],
1287
                'hide_protocol' => true, ],
1288
            ],
1289
            [
1290
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
1291
                <a href="http://localhost/foo">foo/bar?a=b&amp;c=123456789</a>
1292
                </td>',
1293
                'url',
1294
                'http://foo/bar?a=b&c=123456789',
1295
                [
1296
                    'route' => ['name' => 'sonata_admin_foo', 'absolute' => true],
1297
                    'hide_protocol' => true,
1298
                ],
1299
            ],
1300
            [
1301
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
1302
                <a href="/foo/abcd/efgh?param3=ijkl">Foo</a>
1303
                </td>',
1304
                'url',
1305
                'Foo',
1306
                [
1307
                    'route' => ['name' => 'sonata_admin_foo_param',
1308
                    'parameters' => ['param1' => 'abcd', 'param2' => 'efgh', 'param3' => 'ijkl'], ],
1309
                ],
1310
            ],
1311
            [
1312
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
1313
                <a href="http://localhost/foo/abcd/efgh?param3=ijkl">Foo</a>
1314
                </td>',
1315
                'url',
1316
                'Foo',
1317
                [
1318
                    'route' => ['name' => 'sonata_admin_foo_param',
1319
                    'absolute' => true,
1320
                    'parameters' => ['param1' => 'abcd', 'param2' => 'efgh', 'param3' => 'ijkl'], ],
1321
                ],
1322
            ],
1323
            [
1324
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
1325
                <a href="/foo/obj/abcd/12345/efgh?param3=ijkl">Foo</a>
1326
                </td>',
1327
                'url',
1328
                'Foo',
1329
                [
1330
                    'route' => ['name' => 'sonata_admin_foo_object',
1331
                    'parameters' => ['param1' => 'abcd', 'param2' => 'efgh', 'param3' => 'ijkl'],
1332
                    'identifier_parameter_name' => 'barId', ],
1333
                ],
1334
            ],
1335
            [
1336
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
1337
                <a href="http://localhost/foo/obj/abcd/12345/efgh?param3=ijkl">Foo</a>
1338
                </td>',
1339
                'url',
1340
                'Foo',
1341
                [
1342
                    'route' => ['name' => 'sonata_admin_foo_object',
1343
                    'absolute' => true,
1344
                    'parameters' => ['param1' => 'abcd', 'param2' => 'efgh', 'param3' => 'ijkl'],
1345
                    'identifier_parameter_name' => 'barId', ],
1346
                ],
1347
            ],
1348
            [
1349
                '<td class="sonata-ba-list-field sonata-ba-list-field-html" objectId="12345">
1350
                <p><strong>Creating a Template for the Field</strong> and form</p>
1351
                </td>',
1352
                'html',
1353
                '<p><strong>Creating a Template for the Field</strong> and form</p>',
1354
                [],
1355
            ],
1356
            [
1357
                '<td class="sonata-ba-list-field sonata-ba-list-field-html" objectId="12345">
1358
                Creating a Template for the Field and form
1359
                </td>',
1360
                'html',
1361
                '<p><strong>Creating a Template for the Field</strong> and form</p>',
1362
                ['strip' => true],
1363
            ],
1364
            [
1365
                '<td class="sonata-ba-list-field sonata-ba-list-field-html" objectId="12345">
1366
                Creating a Template for the...
1367
                </td>',
1368
                'html',
1369
                '<p><strong>Creating a Template for the Field</strong> and form</p>',
1370
                ['truncate' => true],
1371
            ],
1372
            [
1373
                '<td class="sonata-ba-list-field sonata-ba-list-field-html" objectId="12345"> Creatin... </td>',
1374
                'html',
1375
                '<p><strong>Creating a Template for the Field</strong> and form</p>',
1376
                ['truncate' => ['length' => 10]],
1377
            ],
1378
            [
1379
                '<td class="sonata-ba-list-field sonata-ba-list-field-html" objectId="12345">
1380
                Creating a Template for the Field...
1381
                </td>',
1382
                'html',
1383
                '<p><strong>Creating a Template for the Field</strong> and form</p>',
1384
                ['truncate' => ['cut' => false]],
1385
            ],
1386
            [
1387
                '<td class="sonata-ba-list-field sonata-ba-list-field-html" objectId="12345">
1388
                Creating a Template for t etc.
1389
                </td>',
1390
                'html',
1391
                '<p><strong>Creating a Template for the Field</strong> and form</p>',
1392
                ['truncate' => ['ellipsis' => ' etc.']],
1393
            ],
1394
            [
1395
                '<td class="sonata-ba-list-field sonata-ba-list-field-html" objectId="12345">
1396
                Creating a Template[...]
1397
                </td>',
1398
                'html',
1399
                '<p><strong>Creating a Template for the Field</strong> and form</p>',
1400
                [
1401
                    'truncate' => [
1402
                        'length' => 20,
1403
                        'cut' => false,
1404
                        'ellipsis' => '[...]',
1405
                    ],
1406
                ],
1407
            ],
1408
1409
            [
1410
                <<<'EOT'
1411
<td class="sonata-ba-list-field sonata-ba-list-field-text" objectId="12345">
1412
<div
1413
    class="sonata-readmore"
1414
    data-readmore-height="40"
1415
    data-readmore-more="Read more"
1416
    data-readmore-less="Close">A very long string</div>
1417
</td>
1418
EOT
1419
                ,
1420
                'text',
1421
                'A very long string',
1422
                [
1423
                    'collapse' => true,
1424
                ],
1425
            ],
1426
            [
1427
                <<<'EOT'
1428
<td class="sonata-ba-list-field sonata-ba-list-field-text" objectId="12345">
1429
<div
1430
    class="sonata-readmore"
1431
    data-readmore-height="10"
1432
    data-readmore-more="More"
1433
    data-readmore-less="Less">A very long string</div>
1434
</td>
1435
EOT
1436
                ,
1437
                'text',
1438
                'A very long string',
1439
                [
1440
                    'collapse' => [
1441
                        'height' => 10,
1442
                        'more' => 'More',
1443
                        'less' => 'Less',
1444
                    ],
1445
                ],
1446
            ],
1447
            [
1448
                <<<'EOT'
1449
<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345">
1450
    <span
1451
        class="x-editable"
1452
        data-type="checklist"
1453
        data-value="[&quot;Status1&quot;,&quot;Status2&quot;]"
1454
        data-title="Data"
1455
        data-pk="12345"
1456
        data-url="/core/set-object-field-value?context=list&amp;field=fd_name&amp;objectId=12345&amp;code=sonata_admin_foo_service"
1457
        data-source="[{&quot;value&quot;:&quot;Status1&quot;,&quot;text&quot;:&quot;Delete&quot;},{&quot;value&quot;:&quot;Status2&quot;,&quot;text&quot;:&quot;Alias2&quot;},{&quot;value&quot;:&quot;Status3&quot;,&quot;text&quot;:&quot;Alias3&quot;}]" >
1458
         Delete, Alias2
1459
    </span>
1460
</td>
1461
EOT
1462
                ,
1463
                'choice',
1464
                [
1465
                    'Status1',
1466
                    'Status2',
1467
                ],
1468
                [
1469
                    'editable' => true,
1470
                    'multiple' => true,
1471
                    'catalogue' => 'SonataAdminBundle',
1472
                    'choices' => [
1473
                        'Status1' => 'action_delete',
1474
                        'Status2' => 'Alias2',
1475
                        'Status3' => 'Alias3',
1476
                    ],
1477
                ],
1478
            ],
1479
        ];
1480
    }
1481
1482
    /**
1483
     * @group legacy
1484
     */
1485
    public function testRenderListElementNonExistentTemplate(): void
1486
    {
1487
        // NEXT_MAJOR: Remove this line
1488
        $this->admin->method('getTemplate')
0 ignored issues
show
Bug introduced by
The method method() does not seem to exist on object<Sonata\AdminBundle\Admin\AdminInterface>.

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

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

Loading history...
1489
            ->with('base_list_field')
1490
            ->willReturn('@SonataAdmin/CRUD/base_list_field.html.twig');
1491
1492
        $this->templateRegistry->getTemplate('base_list_field')->willReturn('@SonataAdmin/CRUD/base_list_field.html.twig');
0 ignored issues
show
Bug introduced by
The method willReturn cannot be called on $this->templateRegistry-...late('base_list_field') (of type string).

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

Loading history...
1493
1494
        $this->fieldDescription->expects($this->once())
0 ignored issues
show
Bug introduced by
The method expects() does not seem to exist on object<Sonata\AdminBundl...ldDescriptionInterface>.

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

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

Loading history...
1495
            ->method('getValue')
1496
            ->willReturn('Foo');
1497
1498
        $this->fieldDescription->expects($this->once())
0 ignored issues
show
Bug introduced by
The method expects() does not seem to exist on object<Sonata\AdminBundl...ldDescriptionInterface>.

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

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

Loading history...
1499
            ->method('getFieldName')
1500
            ->willReturn('Foo_name');
1501
1502
        $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...
1503
            ->method('getType')
1504
            ->willReturn('nonexistent');
1505
1506
        $this->fieldDescription->expects($this->once())
0 ignored issues
show
Bug introduced by
The method expects() does not seem to exist on object<Sonata\AdminBundl...ldDescriptionInterface>.

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

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

Loading history...
1507
            ->method('getTemplate')
1508
            ->willReturn('@SonataAdmin/CRUD/list_nonexistent_template.html.twig');
1509
1510
        $this->logger->expects($this->once())
0 ignored issues
show
Bug introduced by
The method expects() does not seem to exist on object<Psr\Log\LoggerInterface>.

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

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

Loading history...
1511
            ->method('warning')
1512
            ->with(($this->stringStartsWith($this->removeExtraWhitespace(
1513
                'An error occured trying to load the template
1514
                "@SonataAdmin/CRUD/list_nonexistent_template.html.twig"
1515
                for the field "Foo_name", the default template
1516
                    "@SonataAdmin/CRUD/base_list_field.html.twig" was used
1517
                    instead.'
1518
            ))));
1519
1520
        $this->twigExtension->renderListElement($this->environment, $this->object, $this->fieldDescription);
1521
    }
1522
1523
    /**
1524
     * @group                    legacy
1525
     */
1526
    public function testRenderListElementErrorLoadingTemplate(): void
1527
    {
1528
        $this->expectException(LoaderError::class);
1529
        $this->expectExceptionMessage('Unable to find template "@SonataAdmin/CRUD/base_list_nonexistent_field.html.twig"');
1530
1531
        // NEXT_MAJOR: Remove this line
1532
        $this->admin->method('getTemplate')
0 ignored issues
show
Bug introduced by
The method method() does not seem to exist on object<Sonata\AdminBundle\Admin\AdminInterface>.

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

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

Loading history...
1533
            ->with('base_list_field')
1534
            ->willReturn('@SonataAdmin/CRUD/base_list_nonexistent_field.html.twig');
1535
1536
        $this->templateRegistry->getTemplate('base_list_field')->willReturn('@SonataAdmin/CRUD/base_list_nonexistent_field.html.twig');
0 ignored issues
show
Bug introduced by
The method willReturn cannot be called on $this->templateRegistry-...late('base_list_field') (of type string).

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

Loading history...
1537
1538
        $this->fieldDescription->expects($this->once())
0 ignored issues
show
Bug introduced by
The method expects() does not seem to exist on object<Sonata\AdminBundl...ldDescriptionInterface>.

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

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

Loading history...
1539
            ->method('getTemplate')
1540
            ->willReturn('@SonataAdmin/CRUD/list_nonexistent_template.html.twig');
1541
1542
        $this->twigExtension->renderListElement($this->environment, $this->object, $this->fieldDescription);
1543
1544
        $this->templateRegistry->getTemplate('base_list_field')->shouldHaveBeenCalled();
0 ignored issues
show
Bug introduced by
The method shouldHaveBeenCalled cannot be called on $this->templateRegistry-...late('base_list_field') (of type string).

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

Loading history...
1545
    }
1546
1547
    /**
1548
     * @dataProvider getRenderViewElementTests
1549
     */
1550
    public function testRenderViewElement(string $expected, string $type, $value, array $options): void
1551
    {
1552
        $this->admin
0 ignored issues
show
Bug introduced by
The method method() does not seem to exist on object<Sonata\AdminBundle\Admin\AdminInterface>.

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

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

Loading history...
1553
            ->method('getTemplate')
1554
            ->willReturn('@SonataAdmin/CRUD/base_show_field.html.twig');
1555
1556
        $this->fieldDescription
0 ignored issues
show
Bug introduced by
The method method() does not seem to exist on object<Sonata\AdminBundl...ldDescriptionInterface>.

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

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

Loading history...
1557
            ->method('getValue')
1558
            ->willReturn($value);
1559
1560
        $this->fieldDescription
0 ignored issues
show
Bug introduced by
The method method() does not seem to exist on object<Sonata\AdminBundl...ldDescriptionInterface>.

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

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

Loading history...
1561
            ->method('getType')
1562
            ->willReturn($type);
1563
1564
        $this->fieldDescription
0 ignored issues
show
Bug introduced by
The method method() does not seem to exist on object<Sonata\AdminBundl...ldDescriptionInterface>.

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

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

Loading history...
1565
            ->method('getOptions')
1566
            ->willReturn($options);
1567
1568
        $this->fieldDescription
0 ignored issues
show
Bug introduced by
The method method() does not seem to exist on object<Sonata\AdminBundl...ldDescriptionInterface>.

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

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

Loading history...
1569
            ->method('getTemplate')
1570
            ->willReturnCallback(static function () use ($type): ?string {
1571
                switch ($type) {
1572
                    case 'boolean':
1573
                        return '@SonataAdmin/CRUD/show_boolean.html.twig';
1574
                    case 'datetime':
1575
                        return '@SonataAdmin/CRUD/show_datetime.html.twig';
1576
                    case 'date':
1577
                        return '@SonataAdmin/CRUD/show_date.html.twig';
1578
                    case 'time':
1579
                        return '@SonataAdmin/CRUD/show_time.html.twig';
1580
                    case 'currency':
1581
                        return '@SonataAdmin/CRUD/show_currency.html.twig';
1582
                    case 'percent':
1583
                        return '@SonataAdmin/CRUD/show_percent.html.twig';
1584
                    case 'email':
1585
                        return '@SonataAdmin/CRUD/show_email.html.twig';
1586
                    case 'choice':
1587
                        return '@SonataAdmin/CRUD/show_choice.html.twig';
1588
                    case 'array':
1589
                        return '@SonataAdmin/CRUD/show_array.html.twig';
1590
                    case 'trans':
1591
                        return '@SonataAdmin/CRUD/show_trans.html.twig';
1592
                    case 'url':
1593
                        return '@SonataAdmin/CRUD/show_url.html.twig';
1594
                    case 'html':
1595
                        return '@SonataAdmin/CRUD/show_html.html.twig';
1596
                    default:
1597
                        return null;
1598
                }
1599
            });
1600
1601
        $this->assertSame(
1602
            $this->removeExtraWhitespace($expected),
1603
            $this->removeExtraWhitespace(
1604
                $this->twigExtension->renderViewElement(
1605
                    $this->environment,
1606
                    $this->fieldDescription,
1607
                    $this->object
1608
                )
1609
            )
1610
        );
1611
    }
1612
1613
    public function getRenderViewElementTests()
1614
    {
1615
        return [
1616
            ['<th>Data</th> <td>Example</td>', 'string', 'Example', ['safe' => false]],
1617
            ['<th>Data</th> <td>Example</td>', 'text', 'Example', ['safe' => false]],
1618
            ['<th>Data</th> <td>Example</td>', 'textarea', 'Example', ['safe' => false]],
1619
            [
1620
                '<th>Data</th> <td><time datetime="2013-12-24T10:11:12+00:00" title="2013-12-24T10:11:12+00:00"> December 24, 2013 10:11 </time></td>',
1621
                'datetime',
1622
                new \DateTime('2013-12-24 10:11:12', new \DateTimeZone('Europe/London')), [],
1623
            ],
1624
            [
1625
                '<th>Data</th> <td><time datetime="2013-12-24T10:11:12+00:00" title="2013-12-24T10:11:12+00:00"> 24.12.2013 10:11:12 </time></td>',
1626
                'datetime',
1627
                new \DateTime('2013-12-24 10:11:12', new \DateTimeZone('Europe/London')),
1628
                ['format' => 'd.m.Y H:i:s'],
1629
            ],
1630
            [
1631
                '<th>Data</th> <td><time datetime="2013-12-24T10:11:12+00:00" title="2013-12-24T10:11:12+00:00"> December 24, 2013 18:11 </time></td>',
1632
                'datetime',
1633
                new \DateTime('2013-12-24 10:11:12', new \DateTimeZone('UTC')),
1634
                ['timezone' => 'Asia/Hong_Kong'],
1635
            ],
1636
            [
1637
                '<th>Data</th> <td><time datetime="2013-12-24" title="2013-12-24"> December 24, 2013 </time></td>',
1638
                'date',
1639
                new \DateTime('2013-12-24 10:11:12', new \DateTimeZone('Europe/London')),
1640
                [],
1641
            ],
1642
            [
1643
                '<th>Data</th> <td><time datetime="2013-12-24" title="2013-12-24"> 24.12.2013 </time></td>',
1644
                'date',
1645
                new \DateTime('2013-12-24 10:11:12', new \DateTimeZone('Europe/London')),
1646
                ['format' => 'd.m.Y'],
1647
            ],
1648
            [
1649
                '<th>Data</th> <td><time datetime="10:11:12+00:00" title="10:11:12+00:00"> 10:11:12 </time></td>',
1650
                'time',
1651
                new \DateTime('2013-12-24 10:11:12', new \DateTimeZone('Europe/London')),
1652
                [],
1653
            ],
1654
            [
1655
                '<th>Data</th> <td><time datetime="10:11:12+00:00" title="10:11:12+00:00"> 18:11:12 </time></td>',
1656
                'time',
1657
                new \DateTime('2013-12-24 10:11:12', new \DateTimeZone('UTC')),
1658
                ['timezone' => 'Asia/Hong_Kong'],
1659
            ],
1660
            ['<th>Data</th> <td>10.746135</td>', 'number', 10.746135, ['safe' => false]],
1661
            ['<th>Data</th> <td>5678</td>', 'integer', 5678, ['safe' => false]],
1662
            ['<th>Data</th> <td> 1074.6135 % </td>', 'percent', 10.746135, []],
1663
            ['<th>Data</th> <td> EUR 10.746135 </td>', 'currency', 10.746135, ['currency' => 'EUR']],
1664
            ['<th>Data</th> <td> GBP 51.23456 </td>', 'currency', 51.23456, ['currency' => 'GBP']],
1665
            [
1666
                '<th>Data</th> <td> <ul><li>1&nbsp;=>&nbsp;First</li><li>2&nbsp;=>&nbsp;Second</li></ul> </td>',
1667
                'array',
1668
                [1 => 'First', 2 => 'Second'],
1669
                ['safe' => false],
1670
            ],
1671
            [
1672
                '<th>Data</th> <td> [1&nbsp;=>&nbsp;First, 2&nbsp;=>&nbsp;Second] </td>',
1673
                'array',
1674
                [1 => 'First', 2 => 'Second'],
1675
                ['safe' => false, 'inline' => true],
1676
            ],
1677
            [
1678
                '<th>Data</th> <td><span class="label label-success">yes</span></td>',
1679
                'boolean',
1680
                true,
1681
                [],
1682
            ],
1683
            [
1684
                '<th>Data</th> <td><span class="label label-danger">yes</span></td>',
1685
                'boolean',
1686
                true,
1687
                ['inverse' => true],
1688
            ],
1689
            ['<th>Data</th> <td><span class="label label-danger">no</span></td>', 'boolean', false, []],
1690
            [
1691
                '<th>Data</th> <td><span class="label label-success">no</span></td>',
1692
                'boolean',
1693
                false,
1694
                ['inverse' => true],
1695
            ],
1696
            [
1697
                '<th>Data</th> <td> Delete </td>',
1698
                'trans',
1699
                'action_delete',
1700
                ['safe' => false, 'catalogue' => 'SonataAdminBundle'],
1701
            ],
1702
            [
1703
                '<th>Data</th> <td> Delete </td>',
1704
                'trans',
1705
                'delete',
1706
                ['safe' => false, 'catalogue' => 'SonataAdminBundle', 'format' => 'action_%s'],
1707
            ],
1708
            ['<th>Data</th> <td>Status1</td>', 'choice', 'Status1', ['safe' => false]],
1709
            [
1710
                '<th>Data</th> <td>Alias1</td>',
1711
                'choice',
1712
                'Status1',
1713
                ['safe' => false, 'choices' => [
1714
                    'Status1' => 'Alias1',
1715
                    'Status2' => 'Alias2',
1716
                    'Status3' => 'Alias3',
1717
                ]],
1718
            ],
1719
            [
1720
                '<th>Data</th> <td>NoValidKeyInChoices</td>',
1721
                'choice',
1722
                'NoValidKeyInChoices',
1723
                ['safe' => false, 'choices' => [
1724
                    'Status1' => 'Alias1',
1725
                    'Status2' => 'Alias2',
1726
                    'Status3' => 'Alias3',
1727
                ]],
1728
            ],
1729
            [
1730
                '<th>Data</th> <td>Delete</td>',
1731
                'choice',
1732
                'Foo',
1733
                ['safe' => false, 'catalogue' => 'SonataAdminBundle', 'choices' => [
1734
                    'Foo' => 'action_delete',
1735
                    'Status2' => 'Alias2',
1736
                    'Status3' => 'Alias3',
1737
                ]],
1738
            ],
1739
            [
1740
                '<th>Data</th> <td>NoValidKeyInChoices</td>',
1741
                'choice',
1742
                ['NoValidKeyInChoices'],
1743
                ['safe' => false, 'choices' => [
1744
                    'Status1' => 'Alias1',
1745
                    'Status2' => 'Alias2',
1746
                    'Status3' => 'Alias3',
1747
                ], 'multiple' => true],
1748
            ],
1749
            [
1750
                '<th>Data</th> <td>NoValidKeyInChoices, Alias2</td>',
1751
                'choice',
1752
                ['NoValidKeyInChoices', 'Status2'],
1753
                ['safe' => false, 'choices' => [
1754
                    'Status1' => 'Alias1',
1755
                    'Status2' => 'Alias2',
1756
                    'Status3' => 'Alias3',
1757
                ], 'multiple' => true],
1758
            ],
1759
            [
1760
                '<th>Data</th> <td>Alias1, Alias3</td>',
1761
                'choice',
1762
                ['Status1', 'Status3'],
1763
                ['safe' => false, 'choices' => [
1764
                    'Status1' => 'Alias1',
1765
                    'Status2' => 'Alias2',
1766
                    'Status3' => 'Alias3',
1767
                ], 'multiple' => true],
1768
            ],
1769
            [
1770
                '<th>Data</th> <td>Alias1 | Alias3</td>',
1771
                'choice',
1772
                ['Status1', 'Status3'], ['safe' => false, 'choices' => [
1773
                    'Status1' => 'Alias1',
1774
                    'Status2' => 'Alias2',
1775
                    'Status3' => 'Alias3',
1776
                ], 'multiple' => true, 'delimiter' => ' | '],
1777
            ],
1778
            [
1779
                '<th>Data</th> <td>Delete, Alias3</td>',
1780
                'choice',
1781
                ['Foo', 'Status3'],
1782
                ['safe' => false, 'catalogue' => 'SonataAdminBundle', 'choices' => [
1783
                    'Foo' => 'action_delete',
1784
                    'Status2' => 'Alias2',
1785
                    'Status3' => 'Alias3',
1786
                ], 'multiple' => true],
1787
            ],
1788
            [
1789
                '<th>Data</th> <td><b>Alias1</b>, <b>Alias3</b></td>',
1790
                'choice',
1791
                ['Status1', 'Status3'],
1792
                ['safe' => true, 'choices' => [
1793
                    'Status1' => '<b>Alias1</b>',
1794
                    'Status2' => '<b>Alias2</b>',
1795
                    'Status3' => '<b>Alias3</b>',
1796
                ], 'multiple' => true],
1797
            ],
1798
            [
1799
                '<th>Data</th> <td>&lt;b&gt;Alias1&lt;/b&gt;, &lt;b&gt;Alias3&lt;/b&gt;</td>',
1800
                'choice',
1801
                ['Status1', 'Status3'],
1802
                ['safe' => false, 'choices' => [
1803
                    'Status1' => '<b>Alias1</b>',
1804
                    'Status2' => '<b>Alias2</b>',
1805
                    'Status3' => '<b>Alias3</b>',
1806
                ], 'multiple' => true],
1807
            ],
1808
            [
1809
                '<th>Data</th> <td><a href="http://example.com">http://example.com</a></td>',
1810
                'url',
1811
                'http://example.com',
1812
                ['safe' => false],
1813
            ],
1814
            [
1815
                '<th>Data</th> <td><a href="http://example.com" target="_blank">http://example.com</a></td>',
1816
                'url',
1817
                'http://example.com',
1818
                ['safe' => false, 'attributes' => ['target' => '_blank']],
1819
            ],
1820
            [
1821
                '<th>Data</th> <td><a href="http://example.com" target="_blank" class="fooLink">http://example.com</a></td>',
1822
                'url',
1823
                'http://example.com',
1824
                ['safe' => false, 'attributes' => ['target' => '_blank', 'class' => 'fooLink']],
1825
            ],
1826
            [
1827
                '<th>Data</th> <td><a href="https://example.com">https://example.com</a></td>',
1828
                'url',
1829
                'https://example.com',
1830
                ['safe' => false],
1831
            ],
1832
            [
1833
                '<th>Data</th> <td><a href="http://example.com">example.com</a></td>',
1834
                'url',
1835
                'http://example.com',
1836
                ['safe' => false, 'hide_protocol' => true],
1837
            ],
1838
            [
1839
                '<th>Data</th> <td><a href="https://example.com">example.com</a></td>',
1840
                'url',
1841
                'https://example.com',
1842
                ['safe' => false, 'hide_protocol' => true],
1843
            ],
1844
            [
1845
                '<th>Data</th> <td><a href="http://example.com">http://example.com</a></td>',
1846
                'url',
1847
                'http://example.com',
1848
                ['safe' => false, 'hide_protocol' => false],
1849
            ],
1850
            [
1851
                '<th>Data</th> <td><a href="https://example.com">https://example.com</a></td>',
1852
                'url',
1853
                'https://example.com',
1854
                ['safe' => false,
1855
                'hide_protocol' => false, ],
1856
            ],
1857
            [
1858
                '<th>Data</th> <td><a href="http://example.com">Foo</a></td>',
1859
                'url',
1860
                'Foo',
1861
                ['safe' => false, 'url' => 'http://example.com'],
1862
            ],
1863
            [
1864
                '<th>Data</th> <td><a href="http://example.com">&lt;b&gt;Foo&lt;/b&gt;</a></td>',
1865
                'url',
1866
                '<b>Foo</b>',
1867
                ['safe' => false, 'url' => 'http://example.com'],
1868
            ],
1869
            [
1870
                '<th>Data</th> <td><a href="http://example.com"><b>Foo</b></a></td>',
1871
                'url',
1872
                '<b>Foo</b>',
1873
                ['safe' => true, 'url' => 'http://example.com'],
1874
            ],
1875
            [
1876
                '<th>Data</th> <td><a href="/foo">Foo</a></td>',
1877
                'url',
1878
                'Foo',
1879
                ['safe' => false, 'route' => ['name' => 'sonata_admin_foo']],
1880
            ],
1881
            [
1882
                '<th>Data</th> <td><a href="http://localhost/foo">Foo</a></td>',
1883
                'url',
1884
                'Foo',
1885
                ['safe' => false, 'route' => [
1886
                    'name' => 'sonata_admin_foo',
1887
                    'absolute' => true,
1888
                ]],
1889
            ],
1890
            [
1891
                '<th>Data</th> <td><a href="/foo">foo/bar?a=b&amp;c=123456789</a></td>',
1892
                'url',
1893
                'http://foo/bar?a=b&c=123456789',
1894
                [
1895
                    'safe' => false,
1896
                    'route' => ['name' => 'sonata_admin_foo'],
1897
                    'hide_protocol' => true,
1898
                ],
1899
            ],
1900
            [
1901
                '<th>Data</th> <td><a href="http://localhost/foo">foo/bar?a=b&amp;c=123456789</a></td>',
1902
                'url',
1903
                'http://foo/bar?a=b&c=123456789',
1904
                ['safe' => false, 'route' => [
1905
                    'name' => 'sonata_admin_foo',
1906
                    'absolute' => true,
1907
                ], 'hide_protocol' => true],
1908
            ],
1909
            [
1910
                '<th>Data</th> <td><a href="/foo/abcd/efgh?param3=ijkl">Foo</a></td>',
1911
                'url',
1912
                'Foo',
1913
                ['safe' => false, 'route' => [
1914
                    'name' => 'sonata_admin_foo_param',
1915
                    'parameters' => ['param1' => 'abcd', 'param2' => 'efgh', 'param3' => 'ijkl'],
1916
                ]],
1917
            ],
1918
            [
1919
                '<th>Data</th> <td><a href="http://localhost/foo/abcd/efgh?param3=ijkl">Foo</a></td>',
1920
                'url',
1921
                'Foo',
1922
                ['safe' => false, 'route' => [
1923
                    'name' => 'sonata_admin_foo_param',
1924
                    'absolute' => true,
1925
                    'parameters' => [
1926
                        'param1' => 'abcd',
1927
                        'param2' => 'efgh',
1928
                        'param3' => 'ijkl',
1929
                    ],
1930
                ]],
1931
            ],
1932
            [
1933
                '<th>Data</th> <td><a href="/foo/obj/abcd/12345/efgh?param3=ijkl">Foo</a></td>',
1934
                'url',
1935
                'Foo',
1936
                ['safe' => false, 'route' => [
1937
                    'name' => 'sonata_admin_foo_object',
1938
                    'parameters' => [
1939
                        'param1' => 'abcd',
1940
                        'param2' => 'efgh',
1941
                        'param3' => 'ijkl',
1942
                    ],
1943
                    'identifier_parameter_name' => 'barId',
1944
                ]],
1945
            ],
1946
            [
1947
                '<th>Data</th> <td><a href="http://localhost/foo/obj/abcd/12345/efgh?param3=ijkl">Foo</a></td>',
1948
                'url',
1949
                'Foo',
1950
                ['safe' => false, 'route' => [
1951
                    'name' => 'sonata_admin_foo_object',
1952
                    'absolute' => true,
1953
                    'parameters' => [
1954
                        'param1' => 'abcd',
1955
                        'param2' => 'efgh',
1956
                        'param3' => 'ijkl',
1957
                    ],
1958
                    'identifier_parameter_name' => 'barId',
1959
                ]],
1960
            ],
1961
            [
1962
                '<th>Data</th> <td> &nbsp;</td>',
1963
                'email',
1964
                null,
1965
                [],
1966
            ],
1967
            [
1968
                '<th>Data</th> <td> <a href="mailto:[email protected]">[email protected]</a></td>',
1969
                'email',
1970
                '[email protected]',
1971
                [],
1972
            ],
1973
            [
1974
                '<th>Data</th> <td> <a href="mailto:[email protected]?'.$this->buildTwigLikeUrl(['subject' => 'Main Theme', 'body' => 'Message Body']).'">[email protected]</a></td>',
1975
                'email',
1976
                '[email protected]',
1977
                ['subject' => 'Main Theme', 'body' => 'Message Body'],
1978
            ],
1979
            [
1980
                '<th>Data</th> <td> <a href="mailto:[email protected]?'.$this->buildTwigLikeUrl(['subject' => 'Main Theme']).'">[email protected]</a></td>',
1981
                'email',
1982
                '[email protected]',
1983
                ['subject' => 'Main Theme'],
1984
            ],
1985
            [
1986
                '<th>Data</th> <td> <a href="mailto:[email protected]?'.$this->buildTwigLikeUrl(['body' => 'Message Body']).'">[email protected]</a></td>',
1987
                'email',
1988
                '[email protected]',
1989
                ['body' => 'Message Body'],
1990
            ],
1991
            [
1992
                '<th>Data</th> <td> [email protected]</td>',
1993
                'email',
1994
                '[email protected]',
1995
                ['as_string' => true, 'subject' => 'Main Theme', 'body' => 'Message Body'],
1996
            ],
1997
            [
1998
                '<th>Data</th> <td> [email protected]</td>',
1999
                'email',
2000
                '[email protected]',
2001
                ['as_string' => true, 'subject' => 'Main Theme'],
2002
            ],
2003
            [
2004
                '<th>Data</th> <td> [email protected]</td>',
2005
                'email',
2006
                '[email protected]',
2007
                ['as_string' => true, 'body' => 'Message Body'],
2008
            ],
2009
            [
2010
                '<th>Data</th> <td> <a href="mailto:[email protected]">[email protected]</a></td>',
2011
                'email',
2012
                '[email protected]',
2013
                ['as_string' => false],
2014
            ],
2015
            [
2016
                '<th>Data</th> <td> [email protected]</td>',
2017
                'email',
2018
                '[email protected]',
2019
                ['as_string' => true],
2020
            ],
2021
            [
2022
                '<th>Data</th> <td><p><strong>Creating a Template for the Field</strong> and form</p> </td>',
2023
                'html',
2024
                '<p><strong>Creating a Template for the Field</strong> and form</p>',
2025
                [],
2026
            ],
2027
            [
2028
                '<th>Data</th> <td>Creating a Template for the Field and form </td>',
2029
                'html',
2030
                '<p><strong>Creating a Template for the Field</strong> and form</p>',
2031
                ['strip' => true],
2032
            ],
2033
            [
2034
                '<th>Data</th> <td> Creating a Template for the... </td>',
2035
                'html',
2036
                '<p><strong>Creating a Template for the Field</strong> and form</p>',
2037
                ['truncate' => true],
2038
            ],
2039
            [
2040
                '<th>Data</th> <td> Creatin... </td>',
2041
                'html',
2042
                '<p><strong>Creating a Template for the Field</strong> and form</p>',
2043
                ['truncate' => ['length' => 10]],
2044
            ],
2045
            [
2046
                '<th>Data</th> <td> Creating a Template for the Field... </td>',
2047
                'html',
2048
                '<p><strong>Creating a Template for the Field</strong> and form</p>',
2049
                ['truncate' => ['cut' => false]],
2050
            ],
2051
            [
2052
                '<th>Data</th> <td> Creating a Template for t etc. </td>',
2053
                'html',
2054
                '<p><strong>Creating a Template for the Field</strong> and form</p>',
2055
                ['truncate' => ['ellipsis' => ' etc.']],
2056
            ],
2057
            [
2058
                '<th>Data</th> <td> Creating a Template[...] </td>',
2059
                'html',
2060
                '<p><strong>Creating a Template for the Field</strong> and form</p>',
2061
                [
2062
                    'truncate' => [
2063
                        'length' => 20,
2064
                        'cut' => false,
2065
                        'ellipsis' => '[...]',
2066
                    ],
2067
                ],
2068
            ],
2069
            [
2070
                <<<'EOT'
2071
<th>Data</th> <td><div
2072
        class="sonata-readmore"
2073
        data-readmore-height="40"
2074
        data-readmore-more="Read more"
2075
        data-readmore-less="Close">
2076
            A very long string
2077
</div></td>
2078
EOT
2079
                ,
2080
                'text',
2081
                ' A very long string ',
2082
                [
2083
                    'collapse' => true,
2084
                    'safe' => false,
2085
                ],
2086
            ],
2087
            [
2088
                <<<'EOT'
2089
<th>Data</th> <td><div
2090
        class="sonata-readmore"
2091
        data-readmore-height="10"
2092
        data-readmore-more="More"
2093
        data-readmore-less="Less">
2094
            A very long string
2095
</div></td>
2096
EOT
2097
                ,
2098
                'text',
2099
                ' A very long string ',
2100
                [
2101
                    'collapse' => [
2102
                        'height' => 10,
2103
                        'more' => 'More',
2104
                        'less' => 'Less',
2105
                    ],
2106
                    'safe' => false,
2107
                ],
2108
            ],
2109
        ];
2110
    }
2111
2112
    /**
2113
     * @group legacy
2114
     * @assertDeprecation Accessing a non existing value is deprecated since sonata-project/admin-bundle 3.67 and will throw an exception in 4.0.
2115
     *
2116
     * @dataProvider getRenderViewElementWithNoValueTests
2117
     */
2118
    public function testRenderViewElementWithNoValue(string $expected, string $type, array $options): void
2119
    {
2120
        $this->admin
0 ignored issues
show
Bug introduced by
The method method() does not seem to exist on object<Sonata\AdminBundle\Admin\AdminInterface>.

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

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

Loading history...
2121
            ->method('getTemplate')
2122
            ->willReturn('@SonataAdmin/CRUD/base_show_field.html.twig');
2123
2124
        $this->fieldDescription
0 ignored issues
show
Bug introduced by
The method method() does not seem to exist on object<Sonata\AdminBundl...ldDescriptionInterface>.

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

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

Loading history...
2125
            ->method('getValue')
2126
            ->willThrowException(new NoValueException());
2127
2128
        $this->fieldDescription
0 ignored issues
show
Bug introduced by
The method method() does not seem to exist on object<Sonata\AdminBundl...ldDescriptionInterface>.

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

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

Loading history...
2129
            ->method('getType')
2130
            ->willReturn($type);
2131
2132
        $this->fieldDescription
0 ignored issues
show
Bug introduced by
The method method() does not seem to exist on object<Sonata\AdminBundl...ldDescriptionInterface>.

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

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

Loading history...
2133
            ->method('getOptions')
2134
            ->willReturn($options);
2135
2136
        $this->fieldDescription
0 ignored issues
show
Bug introduced by
The method method() does not seem to exist on object<Sonata\AdminBundl...ldDescriptionInterface>.

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

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

Loading history...
2137
            ->method('getTemplate')
2138
            ->willReturnCallback(static function () use ($type): ?string {
2139
                switch ($type) {
2140
                    case 'boolean':
2141
                        return '@SonataAdmin/CRUD/show_boolean.html.twig';
2142
                    case 'datetime':
2143
                        return '@SonataAdmin/CRUD/show_datetime.html.twig';
2144
                    case 'date':
2145
                        return '@SonataAdmin/CRUD/show_date.html.twig';
2146
                    case 'time':
2147
                        return '@SonataAdmin/CRUD/show_time.html.twig';
2148
                    case 'currency':
2149
                        return '@SonataAdmin/CRUD/show_currency.html.twig';
2150
                    case 'percent':
2151
                        return '@SonataAdmin/CRUD/show_percent.html.twig';
2152
                    case 'email':
2153
                        return '@SonataAdmin/CRUD/show_email.html.twig';
2154
                    case 'choice':
2155
                        return '@SonataAdmin/CRUD/show_choice.html.twig';
2156
                    case 'array':
2157
                        return '@SonataAdmin/CRUD/show_array.html.twig';
2158
                    case 'trans':
2159
                        return '@SonataAdmin/CRUD/show_trans.html.twig';
2160
                    case 'url':
2161
                        return '@SonataAdmin/CRUD/show_url.html.twig';
2162
                    case 'html':
2163
                        return '@SonataAdmin/CRUD/show_html.html.twig';
2164
                    default:
2165
                        return null;
2166
                }
2167
            });
2168
2169
        $this->assertSame(
2170
            $this->removeExtraWhitespace($expected),
2171
            $this->removeExtraWhitespace(
2172
                $this->twigExtension->renderViewElement(
2173
                    $this->environment,
2174
                    $this->fieldDescription,
2175
                    $this->object
2176
                )
2177
            )
2178
        );
2179
    }
2180
2181
    public function getRenderViewElementWithNoValueTests(): iterable
2182
    {
2183
        return [
2184
            // NoValueException
2185
            ['<th>Data</th> <td></td>', 'string', ['safe' => false]],
2186
            ['<th>Data</th> <td></td>', 'text', ['safe' => false]],
2187
            ['<th>Data</th> <td></td>', 'textarea', ['safe' => false]],
2188
            ['<th>Data</th> <td>&nbsp;</td>', 'datetime', []],
2189
            [
2190
                '<th>Data</th> <td>&nbsp;</td>',
2191
                'datetime',
2192
                ['format' => 'd.m.Y H:i:s'],
2193
            ],
2194
            ['<th>Data</th> <td>&nbsp;</td>', 'date', []],
2195
            ['<th>Data</th> <td>&nbsp;</td>', 'date', ['format' => 'd.m.Y']],
2196
            ['<th>Data</th> <td>&nbsp;</td>', 'time', []],
2197
            ['<th>Data</th> <td></td>', 'number', ['safe' => false]],
2198
            ['<th>Data</th> <td></td>', 'integer', ['safe' => false]],
2199
            ['<th>Data</th> <td> 0 % </td>', 'percent', []],
2200
            ['<th>Data</th> <td> </td>', 'currency', ['currency' => 'EUR']],
2201
            ['<th>Data</th> <td> </td>', 'currency', ['currency' => 'GBP']],
2202
            ['<th>Data</th> <td> <ul></ul> </td>', 'array', ['safe' => false]],
2203
            [
2204
                '<th>Data</th> <td><span class="label label-danger">no</span></td>',
2205
                'boolean',
2206
                [],
2207
            ],
2208
            [
2209
                '<th>Data</th> <td> </td>',
2210
                'trans',
2211
                ['safe' => false, 'catalogue' => 'SonataAdminBundle'],
2212
            ],
2213
            [
2214
                '<th>Data</th> <td></td>',
2215
                'choice',
2216
                ['safe' => false, 'choices' => []],
2217
            ],
2218
            [
2219
                '<th>Data</th> <td></td>',
2220
                'choice',
2221
                ['safe' => false, 'choices' => [], 'multiple' => true],
2222
            ],
2223
            ['<th>Data</th> <td>&nbsp;</td>', 'url', []],
2224
            [
2225
                '<th>Data</th> <td>&nbsp;</td>',
2226
                'url',
2227
                ['url' => 'http://example.com'],
2228
            ],
2229
            [
2230
                '<th>Data</th> <td>&nbsp;</td>',
2231
                'url',
2232
                ['route' => ['name' => 'sonata_admin_foo']],
2233
            ],
2234
        ];
2235
    }
2236
2237
    /**
2238
     * NEXT_MAJOR: Remove this method.
2239
     *
2240
     * @group legacy
2241
     *
2242
     * @dataProvider getDeprecatedTextExtensionItems
2243
     *
2244
     * @expectedDeprecation The "truncate.preserve" option is deprecated since sonata-project/admin-bundle 3.65, to be removed in 4.0. Use "truncate.cut" instead. ("@SonataAdmin/CRUD/show_html.html.twig" at line %d).
2245
     *
2246
     * @expectedDeprecation The "truncate.separator" option is deprecated since sonata-project/admin-bundle 3.65, to be removed in 4.0. Use "truncate.ellipsis" instead. ("@SonataAdmin/CRUD/show_html.html.twig" at line %d).
2247
     */
2248
    public function testDeprecatedTextExtension(string $expected, string $type, $value, array $options): void
2249
    {
2250
        $loader = new StubFilesystemLoader([
2251
            sprintf('%s/../../../src/Resources/views/CRUD', __DIR__),
2252
        ]);
2253
        $loader->addPath(sprintf('%s/../../../src/Resources/views/', __DIR__), 'SonataAdmin');
2254
        $environment = new Environment($loader, [
2255
            'strict_variables' => true,
2256
            'cache' => false,
2257
            'autoescape' => 'html',
2258
            'optimizations' => 0,
2259
        ]);
2260
        $environment->addExtension($this->twigExtension);
2261
        $environment->addExtension(new TranslationExtension($this->translator));
2262
        $environment->addExtension(new StringExtension());
2263
2264
        $this->admin
0 ignored issues
show
Bug introduced by
The method method() does not seem to exist on object<Sonata\AdminBundle\Admin\AdminInterface>.

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

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

Loading history...
2265
            ->method('getTemplate')
2266
            ->willReturn('@SonataAdmin/CRUD/base_show_field.html.twig');
2267
2268
        $this->fieldDescription
0 ignored issues
show
Bug introduced by
The method method() does not seem to exist on object<Sonata\AdminBundl...ldDescriptionInterface>.

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

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

Loading history...
2269
            ->method('getValue')
2270
            ->willReturn($value);
2271
2272
        $this->fieldDescription
0 ignored issues
show
Bug introduced by
The method method() does not seem to exist on object<Sonata\AdminBundl...ldDescriptionInterface>.

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

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

Loading history...
2273
            ->method('getType')
2274
            ->willReturn($type);
2275
2276
        $this->fieldDescription
0 ignored issues
show
Bug introduced by
The method method() does not seem to exist on object<Sonata\AdminBundl...ldDescriptionInterface>.

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

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

Loading history...
2277
            ->method('getOptions')
2278
            ->willReturn($options);
2279
2280
        $this->fieldDescription
0 ignored issues
show
Bug introduced by
The method method() does not seem to exist on object<Sonata\AdminBundl...ldDescriptionInterface>.

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

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

Loading history...
2281
            ->method('getTemplate')
2282
            ->willReturn('@SonataAdmin/CRUD/show_html.html.twig');
2283
2284
        $this->assertSame(
2285
            $this->removeExtraWhitespace($expected),
2286
            $this->removeExtraWhitespace(
2287
                $this->twigExtension->renderViewElement(
2288
                    $environment,
2289
                    $this->fieldDescription,
2290
                    $this->object
2291
                )
2292
            )
2293
        );
2294
    }
2295
2296
    /**
2297
     * NEXT_MAJOR: Remove this method.
2298
     */
2299
    public function getDeprecatedTextExtensionItems(): iterable
2300
    {
2301
        yield 'default_separator' => [
2302
            '<th>Data</th> <td> Creating a Template for the Field... </td>',
2303
            'html',
2304
            '<p><strong>Creating a Template for the Field</strong> and form</p>',
2305
            ['truncate' => ['preserve' => true, 'separator' => '...']],
2306
        ];
2307
2308
        yield 'custom_length' => [
2309
            '<th>Data</th> <td> Creating a Template[...] </td>',
2310
            'html',
2311
            '<p><strong>Creating a Template for the Field</strong> and form</p>',
2312
            [
2313
                'truncate' => [
2314
                    'length' => 20,
2315
                    'preserve' => true,
2316
                    'separator' => '[...]',
2317
                ],
2318
            ],
2319
        ];
2320
    }
2321
2322
    /**
2323
     * NEXT_MAJOR: Remove this test.
2324
     *
2325
     * @group legacy
2326
     */
2327
    public function testGetValueFromFieldDescription(): void
2328
    {
2329
        $object = new \stdClass();
2330
        $fieldDescription = $this->getMockForAbstractClass(FieldDescriptionInterface::class);
2331
2332
        $fieldDescription
2333
            ->method('getValue')
2334
            ->willReturn('test123');
2335
2336
        $this->assertSame('test123', $this->twigExtension->getValueFromFieldDescription($object, $fieldDescription));
0 ignored issues
show
Deprecated Code introduced by
The method Sonata\AdminBundle\Twig\...eFromFieldDescription() has been deprecated with message: This method is deprecated with no replacement since sonata-project/admin-bundle 3.x and will be removed in 4.0.

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

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

Loading history...
2337
    }
2338
2339
    /**
2340
     * NEXT_MAJOR: Remove this test.
2341
     *
2342
     * @group legacy
2343
     */
2344
    public function testGetValueFromFieldDescriptionWithRemoveLoopException(): void
2345
    {
2346
        $object = $this->createMock(\ArrayAccess::class);
2347
        $fieldDescription = $this->getMockForAbstractClass(FieldDescriptionInterface::class);
2348
2349
        $this->expectException(\RuntimeException::class);
2350
        $this->expectExceptionMessage('remove the loop requirement');
2351
2352
        $this->assertSame(
2353
            'anything',
2354
            $this->twigExtension->getValueFromFieldDescription($object, $fieldDescription, ['loop' => true])
0 ignored issues
show
Deprecated Code introduced by
The method Sonata\AdminBundle\Twig\...eFromFieldDescription() has been deprecated with message: This method is deprecated with no replacement since sonata-project/admin-bundle 3.x and will be removed in 4.0.

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

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

Loading history...
2355
        );
2356
    }
2357
2358
    /**
2359
     * NEXT_MAJOR: Remove this test.
2360
     *
2361
     * @group legacy
2362
     * @expectedDeprecation Accessing a non existing value is deprecated since sonata-project/admin-bundle 3.67 and will throw an exception in 4.0.
2363
     */
2364
    public function testGetValueFromFieldDescriptionWithNoValueException(): void
2365
    {
2366
        $object = new \stdClass();
2367
        $fieldDescription = $this->getMockForAbstractClass(FieldDescriptionInterface::class);
2368
2369
        $fieldDescription
2370
            ->method('getValue')
2371
            ->willReturnCallback(static function (): void {
2372
                throw new NoValueException();
2373
            });
2374
2375
        $fieldDescription
2376
            ->method('getAssociationAdmin')
2377
            ->willReturn(null);
2378
2379
        $this->assertNull($this->twigExtension->getValueFromFieldDescription($object, $fieldDescription));
0 ignored issues
show
Deprecated Code introduced by
The method Sonata\AdminBundle\Twig\...eFromFieldDescription() has been deprecated with message: This method is deprecated with no replacement since sonata-project/admin-bundle 3.x and will be removed in 4.0.

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

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

Loading history...
2380
    }
2381
2382
    /**
2383
     * NEXT_MAJOR: Remove this test.
2384
     *
2385
     * @group legacy
2386
     */
2387
    public function testGetValueFromFieldDescriptionWithNoValueExceptionNewAdminInstance(): void
2388
    {
2389
        $object = new \stdClass();
2390
        $fieldDescription = $this->getMockForAbstractClass(FieldDescriptionInterface::class);
2391
2392
        $fieldDescription
2393
            ->method('getValue')
2394
            ->willReturnCallback(static function (): void {
2395
                throw new NoValueException();
2396
            });
2397
2398
        $fieldDescription
2399
            ->method('getAssociationAdmin')
2400
            ->willReturn($this->admin);
2401
2402
        $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...
2403
            ->method('getNewInstance')
2404
            ->willReturn('foo');
2405
2406
        $this->assertSame('foo', $this->twigExtension->getValueFromFieldDescription($object, $fieldDescription));
0 ignored issues
show
Deprecated Code introduced by
The method Sonata\AdminBundle\Twig\...eFromFieldDescription() has been deprecated with message: This method is deprecated with no replacement since sonata-project/admin-bundle 3.x and will be removed in 4.0.

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

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

Loading history...
2407
    }
2408
2409
    /**
2410
     * @group legacy
2411
     */
2412
    public function testOutput(): void
2413
    {
2414
        $this->fieldDescription
0 ignored issues
show
Bug introduced by
The method method() does not seem to exist on object<Sonata\AdminBundl...ldDescriptionInterface>.

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

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

Loading history...
2415
            ->method('getTemplate')
2416
            ->willReturn('@SonataAdmin/CRUD/base_list_field.html.twig');
2417
2418
        $this->fieldDescription
0 ignored issues
show
Bug introduced by
The method method() does not seem to exist on object<Sonata\AdminBundl...ldDescriptionInterface>.

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

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

Loading history...
2419
            ->method('getFieldName')
2420
            ->willReturn('fd_name');
2421
2422
        $this->environment->disableDebug();
2423
2424
        $parameters = [
2425
            'admin' => $this->admin,
2426
            'value' => 'foo',
2427
            'field_description' => $this->fieldDescription,
2428
            'object' => $this->object,
2429
        ];
2430
2431
        $template = $this->environment->loadTemplate('@SonataAdmin/CRUD/base_list_field.html.twig');
2432
2433
        $this->assertSame(
2434
            '<td class="sonata-ba-list-field sonata-ba-list-field-" objectId="12345"> foo </td>',
2435
            $this->removeExtraWhitespace($this->twigExtension->output(
0 ignored issues
show
Deprecated Code introduced by
The method Sonata\AdminBundle\Twig\...dminExtension::output() has been deprecated with message: since sonata-project/admin-bundle 3.33, to be removed in 4.0. Use render instead

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

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

Loading history...
2436
                $this->fieldDescription,
2437
                $template,
2438
                $parameters,
2439
                $this->environment
2440
            ))
2441
        );
2442
2443
        $this->environment->enableDebug();
2444
        $this->assertSame(
2445
            $this->removeExtraWhitespace(
2446
                <<<'EOT'
2447
<!-- START
2448
    fieldName: fd_name
2449
    template: @SonataAdmin/CRUD/base_list_field.html.twig
2450
    compiled template: @SonataAdmin/CRUD/base_list_field.html.twig
2451
-->
2452
    <td class="sonata-ba-list-field sonata-ba-list-field-" objectId="12345"> foo </td>
2453
<!-- END - fieldName: fd_name -->
2454
EOT
2455
            ),
2456
            $this->removeExtraWhitespace(
2457
                $this->twigExtension->output($this->fieldDescription, $template, $parameters, $this->environment)
0 ignored issues
show
Deprecated Code introduced by
The method Sonata\AdminBundle\Twig\...dminExtension::output() has been deprecated with message: since sonata-project/admin-bundle 3.33, to be removed in 4.0. Use render instead

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

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

Loading history...
2458
            )
2459
        );
2460
    }
2461
2462
    /**
2463
     * @group legacy
2464
     * @expectedDeprecation The Sonata\AdminBundle\Admin\AbstractAdmin::getTemplate method is deprecated (since sonata-project/admin-bundle 3.34, will be dropped in 4.0. Use TemplateRegistry services instead).
2465
     */
2466
    public function testRenderWithDebug(): void
2467
    {
2468
        $this->fieldDescription
0 ignored issues
show
Bug introduced by
The method method() does not seem to exist on object<Sonata\AdminBundl...ldDescriptionInterface>.

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

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

Loading history...
2469
            ->method('getTemplate')
2470
            ->willReturn('@SonataAdmin/CRUD/base_list_field.html.twig');
2471
2472
        $this->fieldDescription
0 ignored issues
show
Bug introduced by
The method method() does not seem to exist on object<Sonata\AdminBundl...ldDescriptionInterface>.

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

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

Loading history...
2473
            ->method('getFieldName')
2474
            ->willReturn('fd_name');
2475
2476
        $this->fieldDescription
0 ignored issues
show
Bug introduced by
The method method() does not seem to exist on object<Sonata\AdminBundl...ldDescriptionInterface>.

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

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

Loading history...
2477
            ->method('getValue')
2478
            ->willReturn('foo');
2479
2480
        $parameters = [
2481
            'admin' => $this->admin,
2482
            'value' => 'foo',
2483
            'field_description' => $this->fieldDescription,
2484
            'object' => $this->object,
2485
        ];
2486
2487
        $this->environment->enableDebug();
2488
2489
        $this->assertSame(
2490
            $this->removeExtraWhitespace(
2491
                <<<'EOT'
2492
<!-- START
2493
    fieldName: fd_name
2494
    template: @SonataAdmin/CRUD/base_list_field.html.twig
2495
    compiled template: @SonataAdmin/CRUD/base_list_field.html.twig
2496
-->
2497
    <td class="sonata-ba-list-field sonata-ba-list-field-" objectId="12345"> foo </td>
2498
<!-- END - fieldName: fd_name -->
2499
EOT
2500
            ),
2501
            $this->removeExtraWhitespace(
2502
                $this->twigExtension->renderListElement($this->environment, $this->object, $this->fieldDescription, $parameters)
2503
            )
2504
        );
2505
    }
2506
2507
    public function testRenderRelationElementNoObject(): void
2508
    {
2509
        $this->assertSame('foo', $this->twigExtension->renderRelationElement('foo', $this->fieldDescription));
2510
    }
2511
2512
    public function testRenderRelationElementToString(): void
2513
    {
2514
        $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...
2515
            ->method('getOption')
2516
            ->willReturnCallback(static function ($value, $default = null) {
2517
                if ('associated_property' === $value) {
2518
                    return $default;
2519
                }
2520
            });
2521
2522
        $element = new FooToString();
2523
        $this->assertSame('salut', $this->twigExtension->renderRelationElement($element, $this->fieldDescription));
2524
    }
2525
2526
    /**
2527
     * @group legacy
2528
     */
2529
    public function testDeprecatedRelationElementToString(): void
2530
    {
2531
        $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...
2532
            ->method('getOption')
2533
            ->willReturnCallback(static function ($value, $default = null) {
0 ignored issues
show
Unused Code introduced by
The parameter $default is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
2534
                if ('associated_tostring' === $value) {
2535
                    return '__toString';
2536
                }
2537
            });
2538
2539
        $element = new FooToString();
2540
        $this->assertSame(
2541
            'salut',
2542
            $this->twigExtension->renderRelationElement($element, $this->fieldDescription)
2543
        );
2544
    }
2545
2546
    /**
2547
     * @group legacy
2548
     */
2549
    public function testRenderRelationElementCustomToString(): void
2550
    {
2551
        $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...
2552
            ->method('getOption')
2553
            ->willReturnCallback(static function ($value, $default = null) {
2554
                if ('associated_property' === $value) {
2555
                    return $default;
2556
                }
2557
2558
                if ('associated_tostring' === $value) {
2559
                    return 'customToString';
2560
                }
2561
            });
2562
2563
        $element = $this->getMockBuilder(\stdClass::class)
2564
            ->setMethods(['customToString'])
2565
            ->getMock();
2566
        $element
2567
            ->method('customToString')
2568
            ->willReturn('fooBar');
2569
2570
        $this->assertSame('fooBar', $this->twigExtension->renderRelationElement($element, $this->fieldDescription));
2571
    }
2572
2573
    /**
2574
     * @group legacy
2575
     */
2576
    public function testRenderRelationElementMethodNotExist(): void
2577
    {
2578
        $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...
2579
            ->method('getOption')
2580
2581
            ->willReturnCallback(static function ($value, $default = null) {
0 ignored issues
show
Unused Code introduced by
The parameter $default is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
2582
                if ('associated_tostring' === $value) {
2583
                    return 'nonExistedMethod';
2584
                }
2585
            });
2586
2587
        $element = new \stdClass();
2588
        $this->expectException(\RuntimeException::class);
2589
        $this->expectExceptionMessage('You must define an `associated_property` option or create a `stdClass::__toString');
2590
2591
        $this->twigExtension->renderRelationElement($element, $this->fieldDescription);
2592
    }
2593
2594
    public function testRenderRelationElementWithPropertyPath(): void
2595
    {
2596
        $this->fieldDescription->expects($this->once())
0 ignored issues
show
Bug introduced by
The method expects() does not seem to exist on object<Sonata\AdminBundl...ldDescriptionInterface>.

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

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

Loading history...
2597
            ->method('getOption')
2598
2599
            ->willReturnCallback(static function ($value, $default = null) {
0 ignored issues
show
Unused Code introduced by
The parameter $default is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
2600
                if ('associated_property' === $value) {
2601
                    return 'foo';
2602
                }
2603
            });
2604
2605
        $element = new \stdClass();
2606
        $element->foo = 'bar';
2607
2608
        $this->assertSame('bar', $this->twigExtension->renderRelationElement($element, $this->fieldDescription));
2609
    }
2610
2611
    public function testRenderRelationElementWithClosure(): void
2612
    {
2613
        $this->fieldDescription->expects($this->once())
0 ignored issues
show
Bug introduced by
The method expects() does not seem to exist on object<Sonata\AdminBundl...ldDescriptionInterface>.

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

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

Loading history...
2614
            ->method('getOption')
2615
2616
            ->willReturnCallback(static function ($value, $default = null) {
0 ignored issues
show
Unused Code introduced by
The parameter $default is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
2617
                if ('associated_property' === $value) {
2618
                    return static function ($element): string {
2619
                        return sprintf('closure %s', $element->foo);
2620
                    };
2621
                }
2622
            });
2623
2624
        $element = new \stdClass();
2625
        $element->foo = 'bar';
2626
2627
        $this->assertSame(
2628
            'closure bar',
2629
            $this->twigExtension->renderRelationElement($element, $this->fieldDescription)
2630
        );
2631
    }
2632
2633
    public function testGetUrlsafeIdentifier(): void
2634
    {
2635
        $model = new \stdClass();
2636
2637
        // set admin to pool
2638
        $this->pool->setAdminServiceIds(['sonata_admin_foo_service']);
2639
        $this->pool->setAdminClasses([\stdClass::class => ['sonata_admin_foo_service']]);
2640
2641
        $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...
2642
            ->method('getUrlSafeIdentifier')
2643
            ->with($this->equalTo($model))
2644
            ->willReturn(1234567);
2645
2646
        $this->assertSame(1234567, $this->twigExtension->getUrlSafeIdentifier($model));
2647
    }
2648
2649
    public function testGetUrlsafeIdentifier_GivenAdmin_Foo(): void
2650
    {
2651
        $model = new \stdClass();
2652
2653
        // set admin to pool
2654
        $this->pool->setAdminServiceIds([
2655
            'sonata_admin_foo_service',
2656
            'sonata_admin_bar_service',
2657
        ]);
2658
        $this->pool->setAdminClasses([\stdClass::class => [
2659
            'sonata_admin_foo_service',
2660
            'sonata_admin_bar_service',
2661
        ]]);
2662
2663
        $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...
2664
            ->method('getUrlSafeIdentifier')
2665
            ->with($this->equalTo($model))
2666
            ->willReturn(1234567);
2667
2668
        $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...
2669
            ->method('getUrlSafeIdentifier');
2670
2671
        $this->assertSame(1234567, $this->twigExtension->getUrlSafeIdentifier($model, $this->admin));
2672
    }
2673
2674
    public function testGetUrlsafeIdentifier_GivenAdmin_Bar(): void
2675
    {
2676
        $model = new \stdClass();
2677
2678
        // set admin to pool
2679
        $this->pool->setAdminServiceIds(['sonata_admin_foo_service', 'sonata_admin_bar_service']);
2680
        $this->pool->setAdminClasses([\stdClass::class => [
2681
            'sonata_admin_foo_service',
2682
            'sonata_admin_bar_service',
2683
        ]]);
2684
2685
        $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...
2686
            ->method('getUrlSafeIdentifier');
2687
2688
        $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...
2689
            ->method('getUrlSafeIdentifier')
2690
            ->with($this->equalTo($model))
2691
            ->willReturn(1234567);
2692
2693
        $this->assertSame(1234567, $this->twigExtension->getUrlSafeIdentifier($model, $this->adminBar));
2694
    }
2695
2696
    public function xEditableChoicesProvider()
2697
    {
2698
        return [
2699
            'needs processing' => [
2700
                ['choices' => ['Status1' => 'Alias1', 'Status2' => 'Alias2']],
2701
                [
2702
                    ['value' => 'Status1', 'text' => 'Alias1'],
2703
                    ['value' => 'Status2', 'text' => 'Alias2'],
2704
                ],
2705
            ],
2706
            'already processed' => [
2707
                ['choices' => [
2708
                    ['value' => 'Status1', 'text' => 'Alias1'],
2709
                    ['value' => 'Status2', 'text' => 'Alias2'],
2710
                ]],
2711
                [
2712
                    ['value' => 'Status1', 'text' => 'Alias1'],
2713
                    ['value' => 'Status2', 'text' => 'Alias2'],
2714
                ],
2715
            ],
2716
            'not required' => [
2717
                [
2718
                    'required' => false,
2719
                    'choices' => ['' => '', 'Status1' => 'Alias1', 'Status2' => 'Alias2'],
2720
                ],
2721
                [
2722
                    ['value' => '', 'text' => ''],
2723
                    ['value' => 'Status1', 'text' => 'Alias1'],
2724
                    ['value' => 'Status2', 'text' => 'Alias2'],
2725
                ],
2726
            ],
2727
            'not required multiple' => [
2728
                [
2729
                    'required' => false,
2730
                    'multiple' => true,
2731
                    'choices' => ['Status1' => 'Alias1', 'Status2' => 'Alias2'],
2732
                ],
2733
                [
2734
                    ['value' => 'Status1', 'text' => 'Alias1'],
2735
                    ['value' => 'Status2', 'text' => 'Alias2'],
2736
                ],
2737
            ],
2738
        ];
2739
    }
2740
2741
    /**
2742
     * @dataProvider xEditablechoicesProvider
2743
     */
2744
    public function testGetXEditableChoicesIsIdempotent(array $options, array $expectedChoices): void
2745
    {
2746
        $fieldDescription = $this->getMockForAbstractClass(FieldDescriptionInterface::class);
2747
        $fieldDescription
2748
            ->method('getOption')
2749
            ->withConsecutive(
2750
                ['choices', []],
2751
                ['catalogue'],
2752
                ['required'],
2753
                ['multiple']
2754
            )
2755
            ->will($this->onConsecutiveCalls(
2756
                $options['choices'],
2757
                'MyCatalogue',
2758
                $options['multiple'] ?? null
2759
            ));
2760
2761
        $this->assertSame($expectedChoices, $this->twigExtension->getXEditableChoices($fieldDescription));
2762
    }
2763
2764
    public function select2LocalesProvider()
2765
    {
2766
        return [
2767
            ['ar', 'ar'],
2768
            ['az', 'az'],
2769
            ['bg', 'bg'],
2770
            ['ca', 'ca'],
2771
            ['cs', 'cs'],
2772
            ['da', 'da'],
2773
            ['de', 'de'],
2774
            ['el', 'el'],
2775
            [null, 'en'],
2776
            ['es', 'es'],
2777
            ['et', 'et'],
2778
            ['eu', 'eu'],
2779
            ['fa', 'fa'],
2780
            ['fi', 'fi'],
2781
            ['fr', 'fr'],
2782
            ['gl', 'gl'],
2783
            ['he', 'he'],
2784
            ['hr', 'hr'],
2785
            ['hu', 'hu'],
2786
            ['id', 'id'],
2787
            ['is', 'is'],
2788
            ['it', 'it'],
2789
            ['ja', 'ja'],
2790
            ['ka', 'ka'],
2791
            ['ko', 'ko'],
2792
            ['lt', 'lt'],
2793
            ['lv', 'lv'],
2794
            ['mk', 'mk'],
2795
            ['ms', 'ms'],
2796
            ['nb', 'nb'],
2797
            ['nl', 'nl'],
2798
            ['pl', 'pl'],
2799
            ['pt-PT', 'pt'],
2800
            ['pt-BR', 'pt-BR'],
2801
            ['pt-PT', 'pt-PT'],
2802
            ['ro', 'ro'],
2803
            ['rs', 'rs'],
2804
            ['ru', 'ru'],
2805
            ['sk', 'sk'],
2806
            ['sv', 'sv'],
2807
            ['th', 'th'],
2808
            ['tr', 'tr'],
2809
            ['ug-CN', 'ug'],
2810
            ['ug-CN', 'ug-CN'],
2811
            ['uk', 'uk'],
2812
            ['vi', 'vi'],
2813
            ['zh-CN', 'zh'],
2814
            ['zh-CN', 'zh-CN'],
2815
            ['zh-TW', 'zh-TW'],
2816
        ];
2817
    }
2818
2819
    /**
2820
     * @dataProvider select2LocalesProvider
2821
     */
2822
    public function testCanonicalizedLocaleForSelect2(?string $expected, string $original): void
2823
    {
2824
        $this->assertSame($expected, $this->twigExtension->getCanonicalizedLocaleForSelect2($this->mockExtensionContext($original)));
2825
    }
2826
2827
    public function momentLocalesProvider(): array
2828
    {
2829
        return [
2830
            ['af', 'af'],
2831
            ['ar-dz', 'ar-dz'],
2832
            ['ar', 'ar'],
2833
            ['ar-ly', 'ar-ly'],
2834
            ['ar-ma', 'ar-ma'],
2835
            ['ar-sa', 'ar-sa'],
2836
            ['ar-tn', 'ar-tn'],
2837
            ['az', 'az'],
2838
            ['be', 'be'],
2839
            ['bg', 'bg'],
2840
            ['bn', 'bn'],
2841
            ['bo', 'bo'],
2842
            ['br', 'br'],
2843
            ['bs', 'bs'],
2844
            ['ca', 'ca'],
2845
            ['cs', 'cs'],
2846
            ['cv', 'cv'],
2847
            ['cy', 'cy'],
2848
            ['da', 'da'],
2849
            ['de-at', 'de-at'],
2850
            ['de', 'de'],
2851
            ['de', 'de-de'],
2852
            ['dv', 'dv'],
2853
            ['el', 'el'],
2854
            [null, 'en'],
2855
            [null, 'en-us'],
2856
            ['en-au', 'en-au'],
2857
            ['en-ca', 'en-ca'],
2858
            ['en-gb', 'en-gb'],
2859
            ['en-ie', 'en-ie'],
2860
            ['en-nz', 'en-nz'],
2861
            ['eo', 'eo'],
2862
            ['es-do', 'es-do'],
2863
            ['es', 'es-ar'],
2864
            ['es', 'es-mx'],
2865
            ['es', 'es'],
2866
            ['et', 'et'],
2867
            ['eu', 'eu'],
2868
            ['fa', 'fa'],
2869
            ['fi', 'fi'],
2870
            ['fo', 'fo'],
2871
            ['fr-ca', 'fr-ca'],
2872
            ['fr-ch', 'fr-ch'],
2873
            ['fr', 'fr-fr'],
2874
            ['fr', 'fr'],
2875
            ['fy', 'fy'],
2876
            ['gd', 'gd'],
2877
            ['gl', 'gl'],
2878
            ['he', 'he'],
2879
            ['hi', 'hi'],
2880
            ['hr', 'hr'],
2881
            ['hu', 'hu'],
2882
            ['hy-am', 'hy-am'],
2883
            ['id', 'id'],
2884
            ['is', 'is'],
2885
            ['it', 'it'],
2886
            ['ja', 'ja'],
2887
            ['jv', 'jv'],
2888
            ['ka', 'ka'],
2889
            ['kk', 'kk'],
2890
            ['km', 'km'],
2891
            ['ko', 'ko'],
2892
            ['ky', 'ky'],
2893
            ['lb', 'lb'],
2894
            ['lo', 'lo'],
2895
            ['lt', 'lt'],
2896
            ['lv', 'lv'],
2897
            ['me', 'me'],
2898
            ['mi', 'mi'],
2899
            ['mk', 'mk'],
2900
            ['ml', 'ml'],
2901
            ['mr', 'mr'],
2902
            ['ms', 'ms'],
2903
            ['ms-my', 'ms-my'],
2904
            ['my', 'my'],
2905
            ['nb', 'nb'],
2906
            ['ne', 'ne'],
2907
            ['nl-be', 'nl-be'],
2908
            ['nl', 'nl'],
2909
            ['nl', 'nl-nl'],
2910
            ['nn', 'nn'],
2911
            ['pa-in', 'pa-in'],
2912
            ['pl', 'pl'],
2913
            ['pt-br', 'pt-br'],
2914
            ['pt', 'pt'],
2915
            ['ro', 'ro'],
2916
            ['ru', 'ru'],
2917
            ['se', 'se'],
2918
            ['si', 'si'],
2919
            ['sk', 'sk'],
2920
            ['sl', 'sl'],
2921
            ['sq', 'sq'],
2922
            ['sr-cyrl', 'sr-cyrl'],
2923
            ['sr', 'sr'],
2924
            ['ss', 'ss'],
2925
            ['sv', 'sv'],
2926
            ['sw', 'sw'],
2927
            ['ta', 'ta'],
2928
            ['te', 'te'],
2929
            ['tet', 'tet'],
2930
            ['th', 'th'],
2931
            ['tlh', 'tlh'],
2932
            ['tl-ph', 'tl-ph'],
2933
            ['tr', 'tr'],
2934
            ['tzl', 'tzl'],
2935
            ['tzm', 'tzm'],
2936
            ['tzm-latn', 'tzm-latn'],
2937
            ['uk', 'uk'],
2938
            ['uz', 'uz'],
2939
            ['vi', 'vi'],
2940
            ['x-pseudo', 'x-pseudo'],
2941
            ['yo', 'yo'],
2942
            ['zh-cn', 'zh-cn'],
2943
            ['zh-hk', 'zh-hk'],
2944
            ['zh-tw', 'zh-tw'],
2945
        ];
2946
    }
2947
2948
    /**
2949
     * @dataProvider momentLocalesProvider
2950
     */
2951
    public function testCanonicalizedLocaleForMoment(?string $expected, string $original): void
2952
    {
2953
        $this->assertSame($expected, $this->twigExtension->getCanonicalizedLocaleForMoment($this->mockExtensionContext($original)));
2954
    }
2955
2956
    public function testIsGrantedAffirmative(): void
2957
    {
2958
        $this->assertTrue(
2959
            $this->twigExtension->isGrantedAffirmative(['foo', 'bar'])
2960
        );
2961
        $this->assertTrue($this->twigExtension->isGrantedAffirmative('foo'));
2962
        $this->assertTrue($this->twigExtension->isGrantedAffirmative('bar'));
2963
    }
2964
2965
    /**
2966
     * @dataProvider getRenderViewElementCompareTests
2967
     */
2968
    public function testRenderViewElementCompare(string $expected, string $type, $value, array $options, ?string $objectName = null): void
2969
    {
2970
        $this->admin
0 ignored issues
show
Bug introduced by
The method method() does not seem to exist on object<Sonata\AdminBundle\Admin\AdminInterface>.

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

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

Loading history...
2971
            ->method('getTemplate')
2972
            ->willReturn('@SonataAdmin/CRUD/base_show_compare.html.twig');
2973
2974
        $this->fieldDescription
0 ignored issues
show
Bug introduced by
The method method() does not seem to exist on object<Sonata\AdminBundl...ldDescriptionInterface>.

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

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

Loading history...
2975
            ->method('getValue')
2976
            ->willReturn($value);
2977
2978
        $this->fieldDescription
0 ignored issues
show
Bug introduced by
The method method() does not seem to exist on object<Sonata\AdminBundl...ldDescriptionInterface>.

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

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

Loading history...
2979
            ->method('getType')
2980
            ->willReturn($type);
2981
2982
        $this->fieldDescription
0 ignored issues
show
Bug introduced by
The method method() does not seem to exist on object<Sonata\AdminBundl...ldDescriptionInterface>.

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

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

Loading history...
2983
            ->method('getOptions')
2984
            ->willReturn($options);
2985
2986
        $this->fieldDescription
0 ignored issues
show
Bug introduced by
The method method() does not seem to exist on object<Sonata\AdminBundl...ldDescriptionInterface>.

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

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

Loading history...
2987
            ->method('getTemplate')
2988
            ->willReturnCallback(static function () use ($type, $options): ?string {
2989
                if (isset($options['template'])) {
2990
                    return $options['template'];
2991
                }
2992
2993
                switch ($type) {
2994
                    case 'boolean':
2995
                        return '@SonataAdmin/CRUD/show_boolean.html.twig';
2996
                    case 'datetime':
2997
                        return '@SonataAdmin/CRUD/show_datetime.html.twig';
2998
                    case 'date':
2999
                        return '@SonataAdmin/CRUD/show_date.html.twig';
3000
                    case 'time':
3001
                        return '@SonataAdmin/CRUD/show_time.html.twig';
3002
                    case 'currency':
3003
                        return '@SonataAdmin/CRUD/show_currency.html.twig';
3004
                    case 'percent':
3005
                        return '@SonataAdmin/CRUD/show_percent.html.twig';
3006
                    case 'email':
3007
                        return '@SonataAdmin/CRUD/show_email.html.twig';
3008
                    case 'choice':
3009
                        return '@SonataAdmin/CRUD/show_choice.html.twig';
3010
                    case 'array':
3011
                        return '@SonataAdmin/CRUD/show_array.html.twig';
3012
                    case 'trans':
3013
                        return '@SonataAdmin/CRUD/show_trans.html.twig';
3014
                    case 'url':
3015
                        return '@SonataAdmin/CRUD/show_url.html.twig';
3016
                    case 'html':
3017
                        return '@SonataAdmin/CRUD/show_html.html.twig';
3018
                    default:
3019
                        return null;
3020
                }
3021
            });
3022
3023
        $this->object->name = 'SonataAdmin';
3024
3025
        $comparedObject = clone $this->object;
3026
3027
        if (null !== $objectName) {
3028
            $comparedObject->name = $objectName;
3029
        }
3030
3031
        $this->assertSame(
3032
            $this->removeExtraWhitespace($expected),
3033
            $this->removeExtraWhitespace(
3034
                $this->twigExtension->renderViewElementCompare(
3035
                    $this->environment,
3036
                    $this->fieldDescription,
3037
                    $this->object,
3038
                    $comparedObject
3039
                )
3040
            )
3041
        );
3042
    }
3043
3044
    public function getRenderViewElementCompareTests(): iterable
3045
    {
3046
        return [
3047
            ['<th>Data</th> <td>Example</td><td>Example</td>', 'string', 'Example', ['safe' => false]],
3048
            ['<th>Data</th> <td>Example</td><td>Example</td>', 'text', 'Example', ['safe' => false]],
3049
            ['<th>Data</th> <td>Example</td><td>Example</td>', 'textarea', 'Example', ['safe' => false]],
3050
            ['<th>Data</th> <td>SonataAdmin<br/>Example</td><td>SonataAdmin<br/>Example</td>', 'virtual_field', 'Example', ['template' => 'custom_show_field.html.twig', 'safe' => false, 'SonataAdmin']],
3051
            ['<th class="diff">Data</th> <td>SonataAdmin<br/>Example</td><td>SonataAdmin<br/>Example</td>', 'virtual_field', 'Example', ['template' => 'custom_show_field.html.twig', 'safe' => false], 'sonata-project/admin-bundle'],
3052
            [
3053
                '<th>Data</th> <td><time datetime="2020-05-27T09:11:12+00:00" title="2020-05-27T09:11:12+00:00"> May 27, 2020 10:11 </time></td>'
3054
                .'<td><time datetime="2020-05-27T09:11:12+00:00" title="2020-05-27T09:11:12+00:00"> May 27, 2020 10:11 </time></td>',
3055
                'datetime',
3056
                new \DateTime('2020-05-27 10:11:12', new \DateTimeZone('Europe/London')), [],
3057
            ],
3058
            [
3059
                '<th>Data</th> <td><time datetime="2020-05-27T09:11:12+00:00" title="2020-05-27T09:11:12+00:00"> 27.05.2020 10:11:12 </time></td>'
3060
                .'<td><time datetime="2020-05-27T09:11:12+00:00" title="2020-05-27T09:11:12+00:00"> 27.05.2020 10:11:12 </time></td>',
3061
                'datetime',
3062
                new \DateTime('2020-05-27 10:11:12', new \DateTimeZone('Europe/London')),
3063
                ['format' => 'd.m.Y H:i:s'],
3064
            ],
3065
            [
3066
                '<th>Data</th> <td><time datetime="2020-05-27T10:11:12+00:00" title="2020-05-27T10:11:12+00:00"> May 27, 2020 18:11 </time></td>'
3067
                .'<td><time datetime="2020-05-27T10:11:12+00:00" title="2020-05-27T10:11:12+00:00"> May 27, 2020 18:11 </time></td>',
3068
                'datetime',
3069
                new \DateTime('2020-05-27 10:11:12', new \DateTimeZone('UTC')),
3070
                ['timezone' => 'Asia/Hong_Kong'],
3071
            ],
3072
            [
3073
                '<th>Data</th> <td><time datetime="2020-05-27" title="2020-05-27"> May 27, 2020 </time></td>'
3074
                .'<td><time datetime="2020-05-27" title="2020-05-27"> May 27, 2020 </time></td>',
3075
                'date',
3076
                new \DateTime('2020-05-27 10:11:12', new \DateTimeZone('Europe/London')),
3077
                [],
3078
            ],
3079
        ];
3080
    }
3081
3082
    /**
3083
     * This method generates url part for Twig layout.
3084
     */
3085
    private function buildTwigLikeUrl(array $url): string
3086
    {
3087
        return htmlspecialchars(http_build_query($url, '', '&', PHP_QUERY_RFC3986));
3088
    }
3089
3090
    private function removeExtraWhitespace(string $string): string
3091
    {
3092
        return trim(preg_replace(
3093
            '/\s+/',
3094
            ' ',
3095
            $string
3096
        ));
3097
    }
3098
3099
    private function mockExtensionContext(string $locale): array
3100
    {
3101
        $request = $this->createMock(Request::class);
3102
        $request->method('getLocale')->willReturn($locale);
3103
        $appVariable = $this->createMock(AppVariable::class);
3104
        $appVariable->method('getRequest')->willReturn($request);
3105
3106
        return ['app' => $appVariable];
3107
    }
3108
}
3109