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

testGetValueFromFieldDescriptionWithNoValueExceptionNewAdminInstance()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 21

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 21
rs 9.584
c 0
b 0
f 0
cc 1
nc 1
nop 0
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of the Sonata Project package.
7
 *
8
 * (c) Thomas Rabaix <[email protected]>
9
 *
10
 * For the full copyright and license information, please view the LICENSE
11
 * file that was distributed with this source code.
12
 */
13
14
namespace Sonata\AdminBundle\Tests\Twig\Extension;
15
16
use PHPUnit\Framework\TestCase;
17
use Prophecy\Argument;
18
use Psr\Log\LoggerInterface;
19
use Sonata\AdminBundle\Admin\AbstractAdmin;
20
use Sonata\AdminBundle\Admin\AdminInterface;
21
use Sonata\AdminBundle\Admin\FieldDescriptionInterface;
22
use Sonata\AdminBundle\Admin\Pool;
23
use Sonata\AdminBundle\Exception\NoValueException;
24
use Sonata\AdminBundle\Templating\TemplateRegistryInterface;
25
use Sonata\AdminBundle\Tests\Fixtures\Entity\FooToString;
26
use Sonata\AdminBundle\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
     * @expectedDeprecation Accessing a non existing value is deprecated since sonata-project/admin-bundle 3.67 and will throw an exception in 4.0.
419
     */
420
    public function testRenderListElementWithNoValueException(): void
421
    {
422
        // NEXT_MAJOR: Remove this line
423
        $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...
424
            ->method('getTemplate')
425
            ->with('base_list_field')
426
            ->willReturn('@SonataAdmin/CRUD/base_list_field.html.twig');
427
428
        $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...
429
430
        $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...
431
            ->method('getValue')
432
            ->willReturnCallback(static function (): void {
433
                throw new NoValueException();
434
            });
435
436
        $this->assertSame(
437
            $this->removeExtraWhitespace('<td class="sonata-ba-list-field sonata-ba-list-field-" objectId="12345"> </td>'),
438
            $this->removeExtraWhitespace($this->twigExtension->renderListElement(
439
                $this->environment,
440
                $this->object,
441
                $this->fieldDescription
442
            ))
443
        );
444
    }
445
446
    /**
447
     * @dataProvider getDeprecatedRenderListElementTests
448
     * @group legacy
449
     */
450
    public function testDeprecatedRenderListElement(string $expected, ?string $value, array $options): void
451
    {
452
        $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...
453
            ->method('hasAccess')
454
            ->willReturn(true);
455
456
        // NEXT_MAJOR: Remove this line
457
        $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...
458
            ->method('getTemplate')
459
            ->with('base_list_field')
460
            ->willReturn('@SonataAdmin/CRUD/base_list_field.html.twig');
461
462
        $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...
463
464
        $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...
465
            ->method('getValue')
466
            ->willReturn($value);
467
468
        $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...
469
            ->method('getType')
470
            ->willReturn('nonexistent');
471
472
        $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...
473
            ->method('getOptions')
474
            ->willReturn($options);
475
476
        $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...
477
            ->method('getOption')
478
            ->willReturnCallback(static function ($name, $default = null) use ($options) {
479
                return $options[$name] ?? $default;
480
            });
481
482
        $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...
483
            ->method('getTemplate')
484
            ->willReturn('@SonataAdmin/CRUD/list_nonexistent_template.html.twig');
485
486
        $this->assertSame(
487
            $this->removeExtraWhitespace($expected),
488
            $this->removeExtraWhitespace($this->twigExtension->renderListElement(
489
                $this->environment,
490
                $this->object,
491
                $this->fieldDescription
492
            ))
493
        );
494
    }
495
496
    public function getDeprecatedRenderListElementTests()
497
    {
498
        return [
499
            [
500
                '<td class="sonata-ba-list-field sonata-ba-list-field-nonexistent" objectId="12345"> Example </td>',
501
                'Example',
502
                [],
503
            ],
504
            [
505
                '<td class="sonata-ba-list-field sonata-ba-list-field-nonexistent" objectId="12345"> </td>',
506
                null,
507
                [],
508
            ],
509
        ];
510
    }
511
512
    public function getRenderListElementTests()
513
    {
514
        return [
515
            [
516
                '<td class="sonata-ba-list-field sonata-ba-list-field-string" objectId="12345"> Example </td>',
517
                'string',
518
                'Example',
519
                [],
520
            ],
521
            [
522
                '<td class="sonata-ba-list-field sonata-ba-list-field-string" objectId="12345"> </td>',
523
                'string',
524
                null,
525
                [],
526
            ],
527
            [
528
                '<td class="sonata-ba-list-field sonata-ba-list-field-text" objectId="12345"> Example </td>',
529
                'text',
530
                'Example',
531
                [],
532
            ],
533
            [
534
                '<td class="sonata-ba-list-field sonata-ba-list-field-text" objectId="12345"> </td>',
535
                'text',
536
                null,
537
                [],
538
            ],
539
            [
540
                '<td class="sonata-ba-list-field sonata-ba-list-field-textarea" objectId="12345"> Example </td>',
541
                'textarea',
542
                'Example',
543
                [],
544
            ],
545
            [
546
                '<td class="sonata-ba-list-field sonata-ba-list-field-textarea" objectId="12345"> </td>',
547
                'textarea',
548
                null,
549
                [],
550
            ],
551
            'datetime field' => [
552
                '<td class="sonata-ba-list-field sonata-ba-list-field-datetime" objectId="12345">
553
                    <time datetime="2013-12-24T10:11:12+00:00" title="2013-12-24T10:11:12+00:00">
554
                        December 24, 2013 10:11
555
                    </time>
556
                </td>',
557
                'datetime',
558
                new \DateTime('2013-12-24 10:11:12', new \DateTimeZone('Europe/London')),
559
                [],
560
            ],
561
            [
562
                '<td class="sonata-ba-list-field sonata-ba-list-field-datetime" objectId="12345">
563
                    <time datetime="2013-12-24T10:11:12+00:00" title="2013-12-24T10:11:12+00:00">
564
                        December 24, 2013 18:11
565
                    </time>
566
                </td>',
567
                'datetime',
568
                new \DateTime('2013-12-24 10:11:12', new \DateTimeZone('UTC')),
569
                ['timezone' => 'Asia/Hong_Kong'],
570
            ],
571
            [
572
                '<td class="sonata-ba-list-field sonata-ba-list-field-datetime" objectId="12345"> &nbsp; </td>',
573
                'datetime',
574
                null,
575
                [],
576
            ],
577
            [
578
                '<td class="sonata-ba-list-field sonata-ba-list-field-datetime" objectId="12345">
579
                    <time datetime="2013-12-24T10:11:12+00:00" title="2013-12-24T10:11:12+00:00">
580
                        24.12.2013 10:11:12
581
                    </time>
582
                </td>',
583
                'datetime',
584
                new \DateTime('2013-12-24 10:11:12', new \DateTimeZone('Europe/London')),
585
                ['format' => 'd.m.Y H:i:s'],
586
            ],
587
            [
588
                '<td class="sonata-ba-list-field sonata-ba-list-field-datetime" objectId="12345"> &nbsp; </td>',
589
                'datetime',
590
                null,
591
                ['format' => 'd.m.Y H:i:s'],
592
            ],
593
            [
594
                '<td class="sonata-ba-list-field sonata-ba-list-field-datetime" objectId="12345">
595
                    <time datetime="2013-12-24T10:11:12+00:00" title="2013-12-24T10:11:12+00:00">
596
                        24.12.2013 18:11:12
597
                    </time>
598
                </td>',
599
                'datetime',
600
                new \DateTime('2013-12-24 10:11:12', new \DateTimeZone('UTC')),
601
                ['format' => 'd.m.Y H:i:s', 'timezone' => 'Asia/Hong_Kong'],
602
            ],
603
            [
604
                '<td class="sonata-ba-list-field sonata-ba-list-field-datetime" objectId="12345"> &nbsp; </td>',
605
                'datetime',
606
                null,
607
                ['format' => 'd.m.Y H:i:s', 'timezone' => 'Asia/Hong_Kong'],
608
            ],
609
            [
610
                '<td class="sonata-ba-list-field sonata-ba-list-field-date" objectId="12345">
611
                    <time datetime="2013-12-24" title="2013-12-24">
612
                        December 24, 2013
613
                    </time>
614
                </td>',
615
                'date',
616
                new \DateTime('2013-12-24 10:11:12', new \DateTimeZone('Europe/London')),
617
                [],
618
            ],
619
            [
620
                '<td class="sonata-ba-list-field sonata-ba-list-field-date" objectId="12345"> &nbsp; </td>',
621
                'date',
622
                null,
623
                [],
624
            ],
625
            [
626
                '<td class="sonata-ba-list-field sonata-ba-list-field-date" objectId="12345">
627
                    <time datetime="2013-12-24" title="2013-12-24">
628
                        24.12.2013
629
                    </time>
630
                </td>',
631
                'date',
632
                new \DateTime('2013-12-24 10:11:12', new \DateTimeZone('Europe/London')),
633
                ['format' => 'd.m.Y'],
634
            ],
635
            [
636
                '<td class="sonata-ba-list-field sonata-ba-list-field-date" objectId="12345"> &nbsp; </td>',
637
                'date',
638
                null,
639
                ['format' => 'd.m.Y'],
640
            ],
641
            [
642
                '<td class="sonata-ba-list-field sonata-ba-list-field-time" objectId="12345">
643
                    <time datetime="10:11:12+00:00" title="10:11:12+00:00">
644
                        10:11:12
645
                    </time>
646
                </td>',
647
                'time',
648
                new \DateTime('2013-12-24 10:11:12', new \DateTimeZone('Europe/London')),
649
                [],
650
            ],
651
            [
652
                '<td class="sonata-ba-list-field sonata-ba-list-field-time" objectId="12345">
653
                    <time datetime="10:11:12+00:00" title="10:11:12+00:00">
654
                        18:11:12
655
                    </time>
656
                </td>',
657
                'time',
658
                new \DateTime('2013-12-24 10:11:12', new \DateTimeZone('UTC')),
659
                ['timezone' => 'Asia/Hong_Kong'],
660
            ],
661
            [
662
                '<td class="sonata-ba-list-field sonata-ba-list-field-time" objectId="12345"> &nbsp; </td>',
663
                'time',
664
                null,
665
                [],
666
            ],
667
            [
668
                '<td class="sonata-ba-list-field sonata-ba-list-field-number" objectId="12345"> 10.746135 </td>',
669
                'number', 10.746135,
670
                [],
671
            ],
672
            [
673
                '<td class="sonata-ba-list-field sonata-ba-list-field-number" objectId="12345"> </td>',
674
                'number',
675
                null,
676
                [],
677
            ],
678
            [
679
                '<td class="sonata-ba-list-field sonata-ba-list-field-integer" objectId="12345"> 5678 </td>',
680
                'integer',
681
                5678,
682
                [],
683
            ],
684
            [
685
                '<td class="sonata-ba-list-field sonata-ba-list-field-integer" objectId="12345"> </td>',
686
                'integer',
687
                null,
688
                [],
689
            ],
690
            [
691
                '<td class="sonata-ba-list-field sonata-ba-list-field-percent" objectId="12345"> 1074.6135 % </td>',
692
                'percent',
693
                10.746135,
694
                [],
695
            ],
696
            [
697
                '<td class="sonata-ba-list-field sonata-ba-list-field-percent" objectId="12345"> 0 % </td>',
698
                'percent',
699
                null,
700
                [],
701
            ],
702
            [
703
                '<td class="sonata-ba-list-field sonata-ba-list-field-currency" objectId="12345"> EUR 10.746135 </td>',
704
                'currency',
705
                10.746135,
706
                ['currency' => 'EUR'],
707
            ],
708
            [
709
                '<td class="sonata-ba-list-field sonata-ba-list-field-currency" objectId="12345"> </td>',
710
                'currency',
711
                null,
712
                ['currency' => 'EUR'],
713
            ],
714
            [
715
                '<td class="sonata-ba-list-field sonata-ba-list-field-currency" objectId="12345"> GBP 51.23456 </td>',
716
                'currency',
717
                51.23456,
718
                ['currency' => 'GBP'],
719
            ],
720
            [
721
                '<td class="sonata-ba-list-field sonata-ba-list-field-currency" objectId="12345"> </td>',
722
                'currency',
723
                null,
724
                ['currency' => 'GBP'],
725
            ],
726
            [
727
                '<td class="sonata-ba-list-field sonata-ba-list-field-email" objectId="12345"> &nbsp; </td>',
728
                'email',
729
                null,
730
                [],
731
            ],
732
            [
733
                '<td class="sonata-ba-list-field sonata-ba-list-field-email" objectId="12345"> <a href="mailto:[email protected]">[email protected]</a> </td>',
734
                'email',
735
                '[email protected]',
736
                [],
737
            ],
738
            [
739
                '<td class="sonata-ba-list-field sonata-ba-list-field-email" objectId="12345">
740
                    <a href="mailto:[email protected]">[email protected]</a> </td>',
741
                'email',
742
                '[email protected]',
743
                ['as_string' => false],
744
            ],
745
            [
746
                '<td class="sonata-ba-list-field sonata-ba-list-field-email" objectId="12345"> [email protected] </td>',
747
                'email',
748
                '[email protected]',
749
                ['as_string' => true],
750
            ],
751
            [
752
                '<td class="sonata-ba-list-field sonata-ba-list-field-email" objectId="12345">
753
                    <a href="mailto:[email protected]?'.$this->buildTwigLikeUrl(['subject' => 'Main Theme', 'body' => 'Message Body']).'">[email protected]</a>  </td>',
754
                'email',
755
                '[email protected]',
756
                ['subject' => 'Main Theme', 'body' => 'Message Body'],
757
            ],
758
            [
759
                '<td class="sonata-ba-list-field sonata-ba-list-field-email" objectId="12345">
760
                    <a href="mailto:[email protected]?'.$this->buildTwigLikeUrl(['subject' => 'Main Theme']).'">[email protected]</a>  </td>',
761
                'email',
762
                '[email protected]',
763
                ['subject' => 'Main Theme'],
764
            ],
765
            [
766
                '<td class="sonata-ba-list-field sonata-ba-list-field-email" objectId="12345">
767
                    <a href="mailto:[email protected]?'.$this->buildTwigLikeUrl(['body' => 'Message Body']).'">[email protected]</a>  </td>',
768
                'email',
769
                '[email protected]',
770
                ['body' => 'Message Body'],
771
            ],
772
            [
773
                '<td class="sonata-ba-list-field sonata-ba-list-field-email" objectId="12345"> [email protected] </td>',
774
                'email',
775
                '[email protected]',
776
                ['as_string' => true, 'subject' => 'Main Theme', 'body' => 'Message Body'],
777
            ],
778
            [
779
                '<td class="sonata-ba-list-field sonata-ba-list-field-email" objectId="12345"> [email protected] </td>',
780
                'email',
781
                '[email protected]',
782
                ['as_string' => true, 'body' => 'Message Body'],
783
            ],
784
            [
785
                '<td class="sonata-ba-list-field sonata-ba-list-field-email" objectId="12345"> [email protected] </td>',
786
                'email',
787
                '[email protected]',
788
                ['as_string' => true, 'subject' => 'Main Theme'],
789
            ],
790
            [
791
                '<td class="sonata-ba-list-field sonata-ba-list-field-array" objectId="12345">
792
                    [1&nbsp;=>&nbsp;First, 2&nbsp;=>&nbsp;Second]
793
                </td>',
794
                'array',
795
                [1 => 'First', 2 => 'Second'],
796
                [],
797
            ],
798
            [
799
                '<td class="sonata-ba-list-field sonata-ba-list-field-array" objectId="12345"> [] </td>',
800
                'array',
801
                null,
802
                [],
803
            ],
804
            [
805
                '<td class="sonata-ba-list-field sonata-ba-list-field-boolean" objectId="12345">
806
                    <span class="label label-success">yes</span>
807
                </td>',
808
                'boolean',
809
                true,
810
                ['editable' => false],
811
            ],
812
            [
813
                '<td class="sonata-ba-list-field sonata-ba-list-field-boolean" objectId="12345">
814
                    <span class="label label-danger">no</span>
815
                </td>',
816
                'boolean',
817
                false,
818
                ['editable' => false],
819
            ],
820
            [
821
                '<td class="sonata-ba-list-field sonata-ba-list-field-boolean" objectId="12345">
822
                    <span class="label label-danger">no</span>
823
                </td>',
824
                'boolean',
825
                null,
826
                ['editable' => false],
827
            ],
828
            [
829
                <<<'EOT'
830
<td class="sonata-ba-list-field sonata-ba-list-field-boolean" objectId="12345">
831
    <span
832
        class="x-editable"
833
        data-type="select"
834
        data-value="1"
835
        data-title="Data"
836
        data-pk="12345"
837
        data-url="/core/set-object-field-value?context=list&amp;field=fd_name&amp;objectId=12345&amp;code=sonata_admin_foo_service"
838
        data-source="[{value: 0, text: 'no'},{value: 1, text: 'yes'}]"
839
    >
840
        <span class="label label-success">yes</span>
841
    </span>
842
</td>
843
EOT
844
            ,
845
                'boolean',
846
                true,
847
                ['editable' => true],
848
            ],
849
            [
850
                <<<'EOT'
851
<td class="sonata-ba-list-field sonata-ba-list-field-boolean" objectId="12345">
852
    <span
853
        class="x-editable"
854
        data-type="select"
855
        data-value="0"
856
        data-title="Data"
857
        data-pk="12345"
858
        data-url="/core/set-object-field-value?context=list&amp;field=fd_name&amp;objectId=12345&amp;code=sonata_admin_foo_service"
859
        data-source="[{value: 0, text: 'no'},{value: 1, text: 'yes'}]"
860
    >
861
    <span class="label label-danger">no</span> </span>
862
</td>
863
EOT
864
                ,
865
                'boolean',
866
                false,
867
                ['editable' => true],
868
            ],
869
            [
870
                <<<'EOT'
871
<td class="sonata-ba-list-field sonata-ba-list-field-boolean" objectId="12345">
872
    <span
873
        class="x-editable"
874
        data-type="select"
875
        data-value="0"
876
        data-title="Data"
877
        data-pk="12345"
878
        data-url="/core/set-object-field-value?context=list&amp;field=fd_name&amp;objectId=12345&amp;code=sonata_admin_foo_service"
879
        data-source="[{value: 0, text: 'no'},{value: 1, text: 'yes'}]" >
880
        <span class="label label-danger">no</span> </span>
881
</td>
882
EOT
883
                ,
884
                'boolean',
885
                null,
886
                ['editable' => true],
887
            ],
888
            [
889
                '<td class="sonata-ba-list-field sonata-ba-list-field-trans" objectId="12345"> Delete </td>',
890
                'trans',
891
                'action_delete',
892
                ['catalogue' => 'SonataAdminBundle'],
893
            ],
894
            [
895
                '<td class="sonata-ba-list-field sonata-ba-list-field-trans" objectId="12345"> </td>',
896
                'trans',
897
                null,
898
                ['catalogue' => 'SonataAdminBundle'],
899
            ],
900
            [
901
                '<td class="sonata-ba-list-field sonata-ba-list-field-trans" objectId="12345"> Delete </td>',
902
                'trans',
903
                'action_delete',
904
                ['format' => '%s', 'catalogue' => 'SonataAdminBundle'],
905
            ],
906
            [
907
                '<td class="sonata-ba-list-field sonata-ba-list-field-trans" objectId="12345">
908
                action.action_delete
909
                </td>',
910
                'trans',
911
                'action_delete',
912
                ['format' => 'action.%s'],
913
            ],
914
            [
915
                '<td class="sonata-ba-list-field sonata-ba-list-field-trans" objectId="12345">
916
                action.action_delete
917
                </td>',
918
                'trans',
919
                'action_delete',
920
                ['format' => 'action.%s', 'catalogue' => 'SonataAdminBundle'],
921
            ],
922
            [
923
                '<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345"> Status1 </td>',
924
                'choice',
925
                'Status1',
926
                [],
927
            ],
928
            [
929
                '<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345"> Status1 </td>',
930
                'choice',
931
                ['Status1'],
932
                ['choices' => [], 'multiple' => true],
933
            ],
934
            [
935
                '<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345"> Alias1 </td>',
936
                'choice',
937
                'Status1',
938
                ['choices' => ['Status1' => 'Alias1', 'Status2' => 'Alias2', 'Status3' => 'Alias3']],
939
            ],
940
            [
941
                '<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345"> </td>',
942
                'choice',
943
                null,
944
                ['choices' => ['Status1' => 'Alias1', 'Status2' => 'Alias2', 'Status3' => 'Alias3']],
945
            ],
946
            [
947
                '<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345">
948
                NoValidKeyInChoices
949
                </td>',
950
                'choice',
951
                'NoValidKeyInChoices',
952
                ['choices' => ['Status1' => 'Alias1', 'Status2' => 'Alias2', 'Status3' => 'Alias3']],
953
            ],
954
            [
955
                '<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345"> Delete </td>',
956
                'choice',
957
                'Foo',
958
                ['catalogue' => 'SonataAdminBundle', 'choices' => [
959
                    'Foo' => 'action_delete',
960
                    'Status2' => 'Alias2',
961
                    'Status3' => 'Alias3',
962
                ]],
963
            ],
964
            [
965
                '<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345"> Alias1, Alias3 </td>',
966
                'choice',
967
                ['Status1', 'Status3'],
968
                ['choices' => [
969
                    'Status1' => 'Alias1',
970
                    'Status2' => 'Alias2',
971
                    'Status3' => 'Alias3',
972
                ], 'multiple' => true], ],
973
            [
974
                '<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345"> Alias1 | Alias3 </td>',
975
                'choice',
976
                ['Status1', 'Status3'],
977
                ['choices' => [
978
                    'Status1' => 'Alias1',
979
                    'Status2' => 'Alias2',
980
                    'Status3' => 'Alias3',
981
                ], 'multiple' => true, 'delimiter' => ' | '], ],
982
            [
983
                '<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345"> </td>',
984
                'choice',
985
                null,
986
                ['choices' => [
987
                    'Status1' => 'Alias1',
988
                    'Status2' => 'Alias2',
989
                    'Status3' => 'Alias3',
990
                ], 'multiple' => true],
991
            ],
992
            [
993
                '<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345">
994
                NoValidKeyInChoices
995
                </td>',
996
                'choice',
997
                ['NoValidKeyInChoices'],
998
                ['choices' => [
999
                    'Status1' => 'Alias1',
1000
                    'Status2' => 'Alias2',
1001
                    'Status3' => 'Alias3',
1002
                ], 'multiple' => true],
1003
            ],
1004
            [
1005
                '<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345">
1006
                NoValidKeyInChoices, Alias2
1007
                </td>',
1008
                'choice',
1009
                ['NoValidKeyInChoices', 'Status2'],
1010
                ['choices' => [
1011
                    'Status1' => 'Alias1',
1012
                    'Status2' => 'Alias2',
1013
                    'Status3' => 'Alias3',
1014
                ], 'multiple' => true],
1015
            ],
1016
            [
1017
                '<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345"> Delete, Alias3 </td>',
1018
                'choice',
1019
                ['Foo', 'Status3'],
1020
                ['catalogue' => 'SonataAdminBundle', 'choices' => [
1021
                    'Foo' => 'action_delete',
1022
                    'Status2' => 'Alias2',
1023
                    'Status3' => 'Alias3',
1024
                ], 'multiple' => true],
1025
            ],
1026
            [
1027
                '<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345">
1028
                &lt;b&gt;Alias1&lt;/b&gt;, &lt;b&gt;Alias3&lt;/b&gt;
1029
            </td>',
1030
                'choice',
1031
                ['Status1', 'Status3'],
1032
                ['choices' => [
1033
                    'Status1' => '<b>Alias1</b>',
1034
                    'Status2' => '<b>Alias2</b>',
1035
                    'Status3' => '<b>Alias3</b>',
1036
                ], 'multiple' => true], ],
1037
            [
1038
                <<<'EOT'
1039
<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345">
1040
    <span
1041
        class="x-editable"
1042
        data-type="select"
1043
        data-value="Status1"
1044
        data-title="Data"
1045
        data-pk="12345"
1046
        data-url="/core/set-object-field-value?context=list&amp;field=fd_name&amp;objectId=12345&amp;code=sonata_admin_foo_service"
1047
        data-source="[]"
1048
    >
1049
        Status1
1050
    </span>
1051
</td>
1052
EOT
1053
                ,
1054
                'choice',
1055
                'Status1',
1056
                ['editable' => true],
1057
            ],
1058
            [
1059
                <<<'EOT'
1060
<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345">
1061
    <span
1062
        class="x-editable"
1063
        data-type="select"
1064
        data-value="Status1"
1065
        data-title="Data"
1066
        data-pk="12345"
1067
        data-url="/core/set-object-field-value?context=list&amp;field=fd_name&amp;objectId=12345&amp;code=sonata_admin_foo_service"
1068
        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;}]" >
1069
        Alias1 </span>
1070
</td>
1071
EOT
1072
                ,
1073
                'choice',
1074
                'Status1',
1075
                [
1076
                    'editable' => true,
1077
                    'choices' => [
1078
                        'Status1' => 'Alias1',
1079
                        'Status2' => 'Alias2',
1080
                        'Status3' => 'Alias3',
1081
                    ],
1082
                ],
1083
            ],
1084
            [
1085
                <<<'EOT'
1086
<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345">
1087
    <span
1088
        class="x-editable"
1089
        data-type="select"
1090
        data-value=""
1091
        data-title="Data"
1092
        data-pk="12345"
1093
        data-url="/core/set-object-field-value?context=list&amp;field=fd_name&amp;objectId=12345&amp;code=sonata_admin_foo_service"
1094
        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;}]" >
1095
1096
    </span>
1097
</td>
1098
EOT
1099
                ,
1100
                'choice',
1101
                null,
1102
                [
1103
                    'editable' => true,
1104
                    'choices' => [
1105
                        'Status1' => 'Alias1',
1106
                        'Status2' => 'Alias2',
1107
                        'Status3' => 'Alias3',
1108
                    ],
1109
                ],
1110
            ],
1111
            [
1112
                <<<'EOT'
1113
<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345">
1114
    <span
1115
        class="x-editable"
1116
        data-type="select"
1117
        data-value="NoValidKeyInChoices"
1118
        data-title="Data" data-pk="12345"
1119
        data-url="/core/set-object-field-value?context=list&amp;field=fd_name&amp;objectId=12345&amp;code=sonata_admin_foo_service"
1120
        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;}]" >
1121
        NoValidKeyInChoices
1122
    </span>
1123
</td>
1124
EOT
1125
                ,
1126
                'choice',
1127
                'NoValidKeyInChoices',
1128
                [
1129
                    'editable' => true,
1130
                    'choices' => [
1131
                        'Status1' => 'Alias1',
1132
                        'Status2' => 'Alias2',
1133
                        'Status3' => 'Alias3',
1134
                    ],
1135
                ],
1136
            ],
1137
            [
1138
                <<<'EOT'
1139
<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345">
1140
    <span
1141
        class="x-editable"
1142
        data-type="select"
1143
        data-value="Foo"
1144
        data-title="Data"
1145
        data-pk="12345"
1146
        data-url="/core/set-object-field-value?context=list&amp;field=fd_name&amp;objectId=12345&amp;code=sonata_admin_foo_service"
1147
        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;}]" >
1148
         Delete
1149
    </span>
1150
</td>
1151
EOT
1152
                ,
1153
                'choice',
1154
                'Foo',
1155
                [
1156
                    'editable' => true,
1157
                    'catalogue' => 'SonataAdminBundle',
1158
                    'choices' => [
1159
                        'Foo' => 'action_delete',
1160
                        'Status2' => 'Alias2',
1161
                        'Status3' => 'Alias3',
1162
                    ],
1163
                ],
1164
            ],
1165
            [
1166
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345"> &nbsp; </td>',
1167
                'url',
1168
                null,
1169
                [],
1170
            ],
1171
            [
1172
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345"> &nbsp; </td>',
1173
                'url',
1174
                null,
1175
                ['url' => 'http://example.com'],
1176
            ],
1177
            [
1178
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345"> &nbsp; </td>',
1179
                'url',
1180
                null,
1181
                ['route' => ['name' => 'sonata_admin_foo']],
1182
            ],
1183
            [
1184
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
1185
                <a href="http://example.com">http://example.com</a>
1186
                </td>',
1187
                'url',
1188
                'http://example.com',
1189
                [],
1190
            ],
1191
            [
1192
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
1193
                <a href="https://example.com">https://example.com</a>
1194
                </td>',
1195
                'url',
1196
                'https://example.com',
1197
                [],
1198
            ],
1199
            [
1200
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
1201
                <a href="https://example.com" target="_blank">https://example.com</a>
1202
                </td>',
1203
                'url',
1204
                'https://example.com',
1205
                ['attributes' => ['target' => '_blank']],
1206
            ],
1207
            [
1208
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
1209
                <a href="https://example.com" target="_blank" class="fooLink">https://example.com</a>
1210
                </td>',
1211
                'url',
1212
                'https://example.com',
1213
                ['attributes' => ['target' => '_blank', 'class' => 'fooLink']],
1214
            ],
1215
            [
1216
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
1217
                <a href="http://example.com">example.com</a>
1218
                </td>',
1219
                'url',
1220
                'http://example.com',
1221
                ['hide_protocol' => true],
1222
            ],
1223
            [
1224
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
1225
                <a href="https://example.com">example.com</a>
1226
                </td>',
1227
                'url',
1228
                'https://example.com',
1229
                ['hide_protocol' => true],
1230
            ],
1231
            [
1232
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
1233
                <a href="http://example.com">http://example.com</a>
1234
                </td>',
1235
                'url',
1236
                'http://example.com',
1237
                ['hide_protocol' => false],
1238
            ],
1239
            [
1240
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
1241
                <a href="https://example.com">https://example.com</a>
1242
                </td>',
1243
                'url',
1244
                'https://example.com',
1245
                ['hide_protocol' => false],
1246
            ],
1247
            [
1248
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
1249
                <a href="http://example.com">Foo</a>
1250
                </td>',
1251
                'url',
1252
                'Foo',
1253
                ['url' => 'http://example.com'],
1254
            ],
1255
            [
1256
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
1257
                <a href="http://example.com">&lt;b&gt;Foo&lt;/b&gt;</a>
1258
                </td>',
1259
                'url',
1260
                '<b>Foo</b>',
1261
                ['url' => 'http://example.com'],
1262
            ],
1263
            [
1264
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
1265
                <a href="/foo">Foo</a>
1266
                </td>',
1267
                'url',
1268
                'Foo',
1269
                ['route' => ['name' => 'sonata_admin_foo']],
1270
            ],
1271
            [
1272
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
1273
                <a href="http://localhost/foo">Foo</a>
1274
                </td>',
1275
                'url',
1276
                'Foo',
1277
                ['route' => ['name' => 'sonata_admin_foo', 'absolute' => true]],
1278
            ],
1279
            [
1280
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
1281
                <a href="/foo">foo/bar?a=b&amp;c=123456789</a>
1282
                </td>',
1283
                'url',
1284
                'http://foo/bar?a=b&c=123456789',
1285
                ['route' => ['name' => 'sonata_admin_foo'],
1286
                'hide_protocol' => true, ],
1287
            ],
1288
            [
1289
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
1290
                <a href="http://localhost/foo">foo/bar?a=b&amp;c=123456789</a>
1291
                </td>',
1292
                'url',
1293
                'http://foo/bar?a=b&c=123456789',
1294
                [
1295
                    'route' => ['name' => 'sonata_admin_foo', 'absolute' => true],
1296
                    'hide_protocol' => true,
1297
                ],
1298
            ],
1299
            [
1300
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
1301
                <a href="/foo/abcd/efgh?param3=ijkl">Foo</a>
1302
                </td>',
1303
                'url',
1304
                'Foo',
1305
                [
1306
                    'route' => ['name' => 'sonata_admin_foo_param',
1307
                    'parameters' => ['param1' => 'abcd', 'param2' => 'efgh', 'param3' => 'ijkl'], ],
1308
                ],
1309
            ],
1310
            [
1311
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
1312
                <a href="http://localhost/foo/abcd/efgh?param3=ijkl">Foo</a>
1313
                </td>',
1314
                'url',
1315
                'Foo',
1316
                [
1317
                    'route' => ['name' => 'sonata_admin_foo_param',
1318
                    'absolute' => true,
1319
                    'parameters' => ['param1' => 'abcd', 'param2' => 'efgh', 'param3' => 'ijkl'], ],
1320
                ],
1321
            ],
1322
            [
1323
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
1324
                <a href="/foo/obj/abcd/12345/efgh?param3=ijkl">Foo</a>
1325
                </td>',
1326
                'url',
1327
                'Foo',
1328
                [
1329
                    'route' => ['name' => 'sonata_admin_foo_object',
1330
                    'parameters' => ['param1' => 'abcd', 'param2' => 'efgh', 'param3' => 'ijkl'],
1331
                    'identifier_parameter_name' => 'barId', ],
1332
                ],
1333
            ],
1334
            [
1335
                '<td class="sonata-ba-list-field sonata-ba-list-field-url" objectId="12345">
1336
                <a href="http://localhost/foo/obj/abcd/12345/efgh?param3=ijkl">Foo</a>
1337
                </td>',
1338
                'url',
1339
                'Foo',
1340
                [
1341
                    'route' => ['name' => 'sonata_admin_foo_object',
1342
                    'absolute' => true,
1343
                    'parameters' => ['param1' => 'abcd', 'param2' => 'efgh', 'param3' => 'ijkl'],
1344
                    'identifier_parameter_name' => 'barId', ],
1345
                ],
1346
            ],
1347
            [
1348
                '<td class="sonata-ba-list-field sonata-ba-list-field-html" objectId="12345">
1349
                <p><strong>Creating a Template for the Field</strong> and form</p>
1350
                </td>',
1351
                'html',
1352
                '<p><strong>Creating a Template for the Field</strong> and form</p>',
1353
                [],
1354
            ],
1355
            [
1356
                '<td class="sonata-ba-list-field sonata-ba-list-field-html" objectId="12345">
1357
                Creating a Template for the Field and form
1358
                </td>',
1359
                'html',
1360
                '<p><strong>Creating a Template for the Field</strong> and form</p>',
1361
                ['strip' => true],
1362
            ],
1363
            [
1364
                '<td class="sonata-ba-list-field sonata-ba-list-field-html" objectId="12345">
1365
                Creating a Template for the...
1366
                </td>',
1367
                'html',
1368
                '<p><strong>Creating a Template for the Field</strong> and form</p>',
1369
                ['truncate' => true],
1370
            ],
1371
            [
1372
                '<td class="sonata-ba-list-field sonata-ba-list-field-html" objectId="12345"> Creatin... </td>',
1373
                'html',
1374
                '<p><strong>Creating a Template for the Field</strong> and form</p>',
1375
                ['truncate' => ['length' => 10]],
1376
            ],
1377
            [
1378
                '<td class="sonata-ba-list-field sonata-ba-list-field-html" objectId="12345">
1379
                Creating a Template for the Field...
1380
                </td>',
1381
                'html',
1382
                '<p><strong>Creating a Template for the Field</strong> and form</p>',
1383
                ['truncate' => ['cut' => false]],
1384
            ],
1385
            [
1386
                '<td class="sonata-ba-list-field sonata-ba-list-field-html" objectId="12345">
1387
                Creating a Template for t etc.
1388
                </td>',
1389
                'html',
1390
                '<p><strong>Creating a Template for the Field</strong> and form</p>',
1391
                ['truncate' => ['ellipsis' => ' etc.']],
1392
            ],
1393
            [
1394
                '<td class="sonata-ba-list-field sonata-ba-list-field-html" objectId="12345">
1395
                Creating a Template[...]
1396
                </td>',
1397
                'html',
1398
                '<p><strong>Creating a Template for the Field</strong> and form</p>',
1399
                [
1400
                    'truncate' => [
1401
                        'length' => 20,
1402
                        'cut' => false,
1403
                        'ellipsis' => '[...]',
1404
                    ],
1405
                ],
1406
            ],
1407
1408
            [
1409
                <<<'EOT'
1410
<td class="sonata-ba-list-field sonata-ba-list-field-text" objectId="12345">
1411
<div
1412
    class="sonata-readmore"
1413
    data-readmore-height="40"
1414
    data-readmore-more="Read more"
1415
    data-readmore-less="Close">A very long string</div>
1416
</td>
1417
EOT
1418
                ,
1419
                'text',
1420
                'A very long string',
1421
                [
1422
                    'collapse' => true,
1423
                ],
1424
            ],
1425
            [
1426
                <<<'EOT'
1427
<td class="sonata-ba-list-field sonata-ba-list-field-text" objectId="12345">
1428
<div
1429
    class="sonata-readmore"
1430
    data-readmore-height="10"
1431
    data-readmore-more="More"
1432
    data-readmore-less="Less">A very long string</div>
1433
</td>
1434
EOT
1435
                ,
1436
                'text',
1437
                'A very long string',
1438
                [
1439
                    'collapse' => [
1440
                        'height' => 10,
1441
                        'more' => 'More',
1442
                        'less' => 'Less',
1443
                    ],
1444
                ],
1445
            ],
1446
            [
1447
                <<<'EOT'
1448
<td class="sonata-ba-list-field sonata-ba-list-field-choice" objectId="12345">
1449
    <span
1450
        class="x-editable"
1451
        data-type="checklist"
1452
        data-value="[&quot;Status1&quot;,&quot;Status2&quot;]"
1453
        data-title="Data"
1454
        data-pk="12345"
1455
        data-url="/core/set-object-field-value?context=list&amp;field=fd_name&amp;objectId=12345&amp;code=sonata_admin_foo_service"
1456
        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;}]" >
1457
         Delete, Alias2
1458
    </span>
1459
</td>
1460
EOT
1461
                ,
1462
                'choice',
1463
                [
1464
                    'Status1',
1465
                    'Status2',
1466
                ],
1467
                [
1468
                    'editable' => true,
1469
                    'multiple' => true,
1470
                    'catalogue' => 'SonataAdminBundle',
1471
                    'choices' => [
1472
                        'Status1' => 'action_delete',
1473
                        'Status2' => 'Alias2',
1474
                        'Status3' => 'Alias3',
1475
                    ],
1476
                ],
1477
            ],
1478
        ];
1479
    }
1480
1481
    /**
1482
     * @group legacy
1483
     */
1484
    public function testRenderListElementNonExistentTemplate(): void
1485
    {
1486
        // NEXT_MAJOR: Remove this line
1487
        $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...
1488
            ->with('base_list_field')
1489
            ->willReturn('@SonataAdmin/CRUD/base_list_field.html.twig');
1490
1491
        $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...
1492
1493
        $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...
1494
            ->method('getValue')
1495
            ->willReturn('Foo');
1496
1497
        $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...
1498
            ->method('getFieldName')
1499
            ->willReturn('Foo_name');
1500
1501
        $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...
1502
            ->method('getType')
1503
            ->willReturn('nonexistent');
1504
1505
        $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...
1506
            ->method('getTemplate')
1507
            ->willReturn('@SonataAdmin/CRUD/list_nonexistent_template.html.twig');
1508
1509
        $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...
1510
            ->method('warning')
1511
            ->with(($this->stringStartsWith($this->removeExtraWhitespace(
1512
                'An error occured trying to load the template
1513
                "@SonataAdmin/CRUD/list_nonexistent_template.html.twig"
1514
                for the field "Foo_name", the default template
1515
                    "@SonataAdmin/CRUD/base_list_field.html.twig" was used
1516
                    instead.'
1517
            ))));
1518
1519
        $this->twigExtension->renderListElement($this->environment, $this->object, $this->fieldDescription);
1520
    }
1521
1522
    /**
1523
     * @group                    legacy
1524
     */
1525
    public function testRenderListElementErrorLoadingTemplate(): void
1526
    {
1527
        $this->expectException(LoaderError::class);
1528
        $this->expectExceptionMessage('Unable to find template "@SonataAdmin/CRUD/base_list_nonexistent_field.html.twig"');
1529
1530
        // NEXT_MAJOR: Remove this line
1531
        $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...
1532
            ->with('base_list_field')
1533
            ->willReturn('@SonataAdmin/CRUD/base_list_nonexistent_field.html.twig');
1534
1535
        $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...
1536
1537
        $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...
1538
            ->method('getTemplate')
1539
            ->willReturn('@SonataAdmin/CRUD/list_nonexistent_template.html.twig');
1540
1541
        $this->twigExtension->renderListElement($this->environment, $this->object, $this->fieldDescription);
1542
1543
        $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...
1544
    }
1545
1546
    /**
1547
     * @dataProvider getRenderViewElementTests
1548
     */
1549
    public function testRenderViewElement(string $expected, string $type, $value, array $options): void
1550
    {
1551
        $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...
1552
            ->method('getTemplate')
1553
            ->willReturn('@SonataAdmin/CRUD/base_show_field.html.twig');
1554
1555
        $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...
1556
            ->method('getValue')
1557
            ->willReturn($value);
1558
1559
        $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...
1560
            ->method('getType')
1561
            ->willReturn($type);
1562
1563
        $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...
1564
            ->method('getOptions')
1565
            ->willReturn($options);
1566
1567
        $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...
1568
            ->method('getTemplate')
1569
            ->willReturnCallback(static function () use ($type): ?string {
1570
                switch ($type) {
1571
                    case 'boolean':
1572
                        return '@SonataAdmin/CRUD/show_boolean.html.twig';
1573
                    case 'datetime':
1574
                        return '@SonataAdmin/CRUD/show_datetime.html.twig';
1575
                    case 'date':
1576
                        return '@SonataAdmin/CRUD/show_date.html.twig';
1577
                    case 'time':
1578
                        return '@SonataAdmin/CRUD/show_time.html.twig';
1579
                    case 'currency':
1580
                        return '@SonataAdmin/CRUD/show_currency.html.twig';
1581
                    case 'percent':
1582
                        return '@SonataAdmin/CRUD/show_percent.html.twig';
1583
                    case 'email':
1584
                        return '@SonataAdmin/CRUD/show_email.html.twig';
1585
                    case 'choice':
1586
                        return '@SonataAdmin/CRUD/show_choice.html.twig';
1587
                    case 'array':
1588
                        return '@SonataAdmin/CRUD/show_array.html.twig';
1589
                    case 'trans':
1590
                        return '@SonataAdmin/CRUD/show_trans.html.twig';
1591
                    case 'url':
1592
                        return '@SonataAdmin/CRUD/show_url.html.twig';
1593
                    case 'html':
1594
                        return '@SonataAdmin/CRUD/show_html.html.twig';
1595
                    default:
1596
                        return null;
1597
                }
1598
            });
1599
1600
        $this->assertSame(
1601
            $this->removeExtraWhitespace($expected),
1602
            $this->removeExtraWhitespace(
1603
                $this->twigExtension->renderViewElement(
1604
                    $this->environment,
1605
                    $this->fieldDescription,
1606
                    $this->object
1607
                )
1608
            )
1609
        );
1610
    }
1611
1612
    public function getRenderViewElementTests()
1613
    {
1614
        return [
1615
            ['<th>Data</th> <td>Example</td>', 'string', 'Example', ['safe' => false]],
1616
            ['<th>Data</th> <td>Example</td>', 'text', 'Example', ['safe' => false]],
1617
            ['<th>Data</th> <td>Example</td>', 'textarea', 'Example', ['safe' => false]],
1618
            [
1619
                '<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>',
1620
                'datetime',
1621
                new \DateTime('2013-12-24 10:11:12', new \DateTimeZone('Europe/London')), [],
1622
            ],
1623
            [
1624
                '<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>',
1625
                'datetime',
1626
                new \DateTime('2013-12-24 10:11:12', new \DateTimeZone('Europe/London')),
1627
                ['format' => 'd.m.Y H:i:s'],
1628
            ],
1629
            [
1630
                '<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>',
1631
                'datetime',
1632
                new \DateTime('2013-12-24 10:11:12', new \DateTimeZone('UTC')),
1633
                ['timezone' => 'Asia/Hong_Kong'],
1634
            ],
1635
            [
1636
                '<th>Data</th> <td><time datetime="2013-12-24" title="2013-12-24"> December 24, 2013 </time></td>',
1637
                'date',
1638
                new \DateTime('2013-12-24 10:11:12', new \DateTimeZone('Europe/London')),
1639
                [],
1640
            ],
1641
            [
1642
                '<th>Data</th> <td><time datetime="2013-12-24" title="2013-12-24"> 24.12.2013 </time></td>',
1643
                'date',
1644
                new \DateTime('2013-12-24 10:11:12', new \DateTimeZone('Europe/London')),
1645
                ['format' => 'd.m.Y'],
1646
            ],
1647
            [
1648
                '<th>Data</th> <td><time datetime="10:11:12+00:00" title="10:11:12+00:00"> 10:11:12 </time></td>',
1649
                'time',
1650
                new \DateTime('2013-12-24 10:11:12', new \DateTimeZone('Europe/London')),
1651
                [],
1652
            ],
1653
            [
1654
                '<th>Data</th> <td><time datetime="10:11:12+00:00" title="10:11:12+00:00"> 18:11:12 </time></td>',
1655
                'time',
1656
                new \DateTime('2013-12-24 10:11:12', new \DateTimeZone('UTC')),
1657
                ['timezone' => 'Asia/Hong_Kong'],
1658
            ],
1659
            ['<th>Data</th> <td>10.746135</td>', 'number', 10.746135, ['safe' => false]],
1660
            ['<th>Data</th> <td>5678</td>', 'integer', 5678, ['safe' => false]],
1661
            ['<th>Data</th> <td> 1074.6135 % </td>', 'percent', 10.746135, []],
1662
            ['<th>Data</th> <td> EUR 10.746135 </td>', 'currency', 10.746135, ['currency' => 'EUR']],
1663
            ['<th>Data</th> <td> GBP 51.23456 </td>', 'currency', 51.23456, ['currency' => 'GBP']],
1664
            [
1665
                '<th>Data</th> <td> <ul><li>1&nbsp;=>&nbsp;First</li><li>2&nbsp;=>&nbsp;Second</li></ul> </td>',
1666
                'array',
1667
                [1 => 'First', 2 => 'Second'],
1668
                ['safe' => false],
1669
            ],
1670
            [
1671
                '<th>Data</th> <td> [1&nbsp;=>&nbsp;First, 2&nbsp;=>&nbsp;Second] </td>',
1672
                'array',
1673
                [1 => 'First', 2 => 'Second'],
1674
                ['safe' => false, 'inline' => true],
1675
            ],
1676
            [
1677
                '<th>Data</th> <td><span class="label label-success">yes</span></td>',
1678
                'boolean',
1679
                true,
1680
                [],
1681
            ],
1682
            [
1683
                '<th>Data</th> <td><span class="label label-danger">yes</span></td>',
1684
                'boolean',
1685
                true,
1686
                ['inverse' => true],
1687
            ],
1688
            ['<th>Data</th> <td><span class="label label-danger">no</span></td>', 'boolean', false, []],
1689
            [
1690
                '<th>Data</th> <td><span class="label label-success">no</span></td>',
1691
                'boolean',
1692
                false,
1693
                ['inverse' => true],
1694
            ],
1695
            [
1696
                '<th>Data</th> <td> Delete </td>',
1697
                'trans',
1698
                'action_delete',
1699
                ['safe' => false, 'catalogue' => 'SonataAdminBundle'],
1700
            ],
1701
            [
1702
                '<th>Data</th> <td> Delete </td>',
1703
                'trans',
1704
                'delete',
1705
                ['safe' => false, 'catalogue' => 'SonataAdminBundle', 'format' => 'action_%s'],
1706
            ],
1707
            ['<th>Data</th> <td>Status1</td>', 'choice', 'Status1', ['safe' => false]],
1708
            [
1709
                '<th>Data</th> <td>Alias1</td>',
1710
                'choice',
1711
                'Status1',
1712
                ['safe' => false, 'choices' => [
1713
                    'Status1' => 'Alias1',
1714
                    'Status2' => 'Alias2',
1715
                    'Status3' => 'Alias3',
1716
                ]],
1717
            ],
1718
            [
1719
                '<th>Data</th> <td>NoValidKeyInChoices</td>',
1720
                'choice',
1721
                'NoValidKeyInChoices',
1722
                ['safe' => false, 'choices' => [
1723
                    'Status1' => 'Alias1',
1724
                    'Status2' => 'Alias2',
1725
                    'Status3' => 'Alias3',
1726
                ]],
1727
            ],
1728
            [
1729
                '<th>Data</th> <td>Delete</td>',
1730
                'choice',
1731
                'Foo',
1732
                ['safe' => false, 'catalogue' => 'SonataAdminBundle', 'choices' => [
1733
                    'Foo' => 'action_delete',
1734
                    'Status2' => 'Alias2',
1735
                    'Status3' => 'Alias3',
1736
                ]],
1737
            ],
1738
            [
1739
                '<th>Data</th> <td>NoValidKeyInChoices</td>',
1740
                'choice',
1741
                ['NoValidKeyInChoices'],
1742
                ['safe' => false, 'choices' => [
1743
                    'Status1' => 'Alias1',
1744
                    'Status2' => 'Alias2',
1745
                    'Status3' => 'Alias3',
1746
                ], 'multiple' => true],
1747
            ],
1748
            [
1749
                '<th>Data</th> <td>NoValidKeyInChoices, Alias2</td>',
1750
                'choice',
1751
                ['NoValidKeyInChoices', 'Status2'],
1752
                ['safe' => false, 'choices' => [
1753
                    'Status1' => 'Alias1',
1754
                    'Status2' => 'Alias2',
1755
                    'Status3' => 'Alias3',
1756
                ], 'multiple' => true],
1757
            ],
1758
            [
1759
                '<th>Data</th> <td>Alias1, Alias3</td>',
1760
                'choice',
1761
                ['Status1', 'Status3'],
1762
                ['safe' => false, 'choices' => [
1763
                    'Status1' => 'Alias1',
1764
                    'Status2' => 'Alias2',
1765
                    'Status3' => 'Alias3',
1766
                ], 'multiple' => true],
1767
            ],
1768
            [
1769
                '<th>Data</th> <td>Alias1 | Alias3</td>',
1770
                'choice',
1771
                ['Status1', 'Status3'], ['safe' => false, 'choices' => [
1772
                    'Status1' => 'Alias1',
1773
                    'Status2' => 'Alias2',
1774
                    'Status3' => 'Alias3',
1775
                ], 'multiple' => true, 'delimiter' => ' | '],
1776
            ],
1777
            [
1778
                '<th>Data</th> <td>Delete, Alias3</td>',
1779
                'choice',
1780
                ['Foo', 'Status3'],
1781
                ['safe' => false, 'catalogue' => 'SonataAdminBundle', 'choices' => [
1782
                    'Foo' => 'action_delete',
1783
                    'Status2' => 'Alias2',
1784
                    'Status3' => 'Alias3',
1785
                ], 'multiple' => true],
1786
            ],
1787
            [
1788
                '<th>Data</th> <td><b>Alias1</b>, <b>Alias3</b></td>',
1789
                'choice',
1790
                ['Status1', 'Status3'],
1791
                ['safe' => true, 'choices' => [
1792
                    'Status1' => '<b>Alias1</b>',
1793
                    'Status2' => '<b>Alias2</b>',
1794
                    'Status3' => '<b>Alias3</b>',
1795
                ], 'multiple' => true],
1796
            ],
1797
            [
1798
                '<th>Data</th> <td>&lt;b&gt;Alias1&lt;/b&gt;, &lt;b&gt;Alias3&lt;/b&gt;</td>',
1799
                'choice',
1800
                ['Status1', 'Status3'],
1801
                ['safe' => false, 'choices' => [
1802
                    'Status1' => '<b>Alias1</b>',
1803
                    'Status2' => '<b>Alias2</b>',
1804
                    'Status3' => '<b>Alias3</b>',
1805
                ], 'multiple' => true],
1806
            ],
1807
            [
1808
                '<th>Data</th> <td><a href="http://example.com">http://example.com</a></td>',
1809
                'url',
1810
                'http://example.com',
1811
                ['safe' => false],
1812
            ],
1813
            [
1814
                '<th>Data</th> <td><a href="http://example.com" target="_blank">http://example.com</a></td>',
1815
                'url',
1816
                'http://example.com',
1817
                ['safe' => false, 'attributes' => ['target' => '_blank']],
1818
            ],
1819
            [
1820
                '<th>Data</th> <td><a href="http://example.com" target="_blank" class="fooLink">http://example.com</a></td>',
1821
                'url',
1822
                'http://example.com',
1823
                ['safe' => false, 'attributes' => ['target' => '_blank', 'class' => 'fooLink']],
1824
            ],
1825
            [
1826
                '<th>Data</th> <td><a href="https://example.com">https://example.com</a></td>',
1827
                'url',
1828
                'https://example.com',
1829
                ['safe' => false],
1830
            ],
1831
            [
1832
                '<th>Data</th> <td><a href="http://example.com">example.com</a></td>',
1833
                'url',
1834
                'http://example.com',
1835
                ['safe' => false, 'hide_protocol' => true],
1836
            ],
1837
            [
1838
                '<th>Data</th> <td><a href="https://example.com">example.com</a></td>',
1839
                'url',
1840
                'https://example.com',
1841
                ['safe' => false, 'hide_protocol' => true],
1842
            ],
1843
            [
1844
                '<th>Data</th> <td><a href="http://example.com">http://example.com</a></td>',
1845
                'url',
1846
                'http://example.com',
1847
                ['safe' => false, 'hide_protocol' => false],
1848
            ],
1849
            [
1850
                '<th>Data</th> <td><a href="https://example.com">https://example.com</a></td>',
1851
                'url',
1852
                'https://example.com',
1853
                ['safe' => false,
1854
                'hide_protocol' => false, ],
1855
            ],
1856
            [
1857
                '<th>Data</th> <td><a href="http://example.com">Foo</a></td>',
1858
                'url',
1859
                'Foo',
1860
                ['safe' => false, 'url' => 'http://example.com'],
1861
            ],
1862
            [
1863
                '<th>Data</th> <td><a href="http://example.com">&lt;b&gt;Foo&lt;/b&gt;</a></td>',
1864
                'url',
1865
                '<b>Foo</b>',
1866
                ['safe' => false, 'url' => 'http://example.com'],
1867
            ],
1868
            [
1869
                '<th>Data</th> <td><a href="http://example.com"><b>Foo</b></a></td>',
1870
                'url',
1871
                '<b>Foo</b>',
1872
                ['safe' => true, 'url' => 'http://example.com'],
1873
            ],
1874
            [
1875
                '<th>Data</th> <td><a href="/foo">Foo</a></td>',
1876
                'url',
1877
                'Foo',
1878
                ['safe' => false, 'route' => ['name' => 'sonata_admin_foo']],
1879
            ],
1880
            [
1881
                '<th>Data</th> <td><a href="http://localhost/foo">Foo</a></td>',
1882
                'url',
1883
                'Foo',
1884
                ['safe' => false, 'route' => [
1885
                    'name' => 'sonata_admin_foo',
1886
                    'absolute' => true,
1887
                ]],
1888
            ],
1889
            [
1890
                '<th>Data</th> <td><a href="/foo">foo/bar?a=b&amp;c=123456789</a></td>',
1891
                'url',
1892
                'http://foo/bar?a=b&c=123456789',
1893
                [
1894
                    'safe' => false,
1895
                    'route' => ['name' => 'sonata_admin_foo'],
1896
                    'hide_protocol' => true,
1897
                ],
1898
            ],
1899
            [
1900
                '<th>Data</th> <td><a href="http://localhost/foo">foo/bar?a=b&amp;c=123456789</a></td>',
1901
                'url',
1902
                'http://foo/bar?a=b&c=123456789',
1903
                ['safe' => false, 'route' => [
1904
                    'name' => 'sonata_admin_foo',
1905
                    'absolute' => true,
1906
                ], 'hide_protocol' => true],
1907
            ],
1908
            [
1909
                '<th>Data</th> <td><a href="/foo/abcd/efgh?param3=ijkl">Foo</a></td>',
1910
                'url',
1911
                'Foo',
1912
                ['safe' => false, 'route' => [
1913
                    'name' => 'sonata_admin_foo_param',
1914
                    'parameters' => ['param1' => 'abcd', 'param2' => 'efgh', 'param3' => 'ijkl'],
1915
                ]],
1916
            ],
1917
            [
1918
                '<th>Data</th> <td><a href="http://localhost/foo/abcd/efgh?param3=ijkl">Foo</a></td>',
1919
                'url',
1920
                'Foo',
1921
                ['safe' => false, 'route' => [
1922
                    'name' => 'sonata_admin_foo_param',
1923
                    'absolute' => true,
1924
                    'parameters' => [
1925
                        'param1' => 'abcd',
1926
                        'param2' => 'efgh',
1927
                        'param3' => 'ijkl',
1928
                    ],
1929
                ]],
1930
            ],
1931
            [
1932
                '<th>Data</th> <td><a href="/foo/obj/abcd/12345/efgh?param3=ijkl">Foo</a></td>',
1933
                'url',
1934
                'Foo',
1935
                ['safe' => false, 'route' => [
1936
                    'name' => 'sonata_admin_foo_object',
1937
                    'parameters' => [
1938
                        'param1' => 'abcd',
1939
                        'param2' => 'efgh',
1940
                        'param3' => 'ijkl',
1941
                    ],
1942
                    'identifier_parameter_name' => 'barId',
1943
                ]],
1944
            ],
1945
            [
1946
                '<th>Data</th> <td><a href="http://localhost/foo/obj/abcd/12345/efgh?param3=ijkl">Foo</a></td>',
1947
                'url',
1948
                'Foo',
1949
                ['safe' => false, 'route' => [
1950
                    'name' => 'sonata_admin_foo_object',
1951
                    'absolute' => true,
1952
                    'parameters' => [
1953
                        'param1' => 'abcd',
1954
                        'param2' => 'efgh',
1955
                        'param3' => 'ijkl',
1956
                    ],
1957
                    'identifier_parameter_name' => 'barId',
1958
                ]],
1959
            ],
1960
            [
1961
                '<th>Data</th> <td> &nbsp;</td>',
1962
                'email',
1963
                null,
1964
                [],
1965
            ],
1966
            [
1967
                '<th>Data</th> <td> <a href="mailto:[email protected]">[email protected]</a></td>',
1968
                'email',
1969
                '[email protected]',
1970
                [],
1971
            ],
1972
            [
1973
                '<th>Data</th> <td> <a href="mailto:[email protected]?'.$this->buildTwigLikeUrl(['subject' => 'Main Theme', 'body' => 'Message Body']).'">[email protected]</a></td>',
1974
                'email',
1975
                '[email protected]',
1976
                ['subject' => 'Main Theme', 'body' => 'Message Body'],
1977
            ],
1978
            [
1979
                '<th>Data</th> <td> <a href="mailto:[email protected]?'.$this->buildTwigLikeUrl(['subject' => 'Main Theme']).'">[email protected]</a></td>',
1980
                'email',
1981
                '[email protected]',
1982
                ['subject' => 'Main Theme'],
1983
            ],
1984
            [
1985
                '<th>Data</th> <td> <a href="mailto:[email protected]?'.$this->buildTwigLikeUrl(['body' => 'Message Body']).'">[email protected]</a></td>',
1986
                'email',
1987
                '[email protected]',
1988
                ['body' => 'Message Body'],
1989
            ],
1990
            [
1991
                '<th>Data</th> <td> [email protected]</td>',
1992
                'email',
1993
                '[email protected]',
1994
                ['as_string' => true, 'subject' => 'Main Theme', 'body' => 'Message Body'],
1995
            ],
1996
            [
1997
                '<th>Data</th> <td> [email protected]</td>',
1998
                'email',
1999
                '[email protected]',
2000
                ['as_string' => true, 'subject' => 'Main Theme'],
2001
            ],
2002
            [
2003
                '<th>Data</th> <td> [email protected]</td>',
2004
                'email',
2005
                '[email protected]',
2006
                ['as_string' => true, 'body' => 'Message Body'],
2007
            ],
2008
            [
2009
                '<th>Data</th> <td> <a href="mailto:[email protected]">[email protected]</a></td>',
2010
                'email',
2011
                '[email protected]',
2012
                ['as_string' => false],
2013
            ],
2014
            [
2015
                '<th>Data</th> <td> [email protected]</td>',
2016
                'email',
2017
                '[email protected]',
2018
                ['as_string' => true],
2019
            ],
2020
            [
2021
                '<th>Data</th> <td><p><strong>Creating a Template for the Field</strong> and form</p> </td>',
2022
                'html',
2023
                '<p><strong>Creating a Template for the Field</strong> and form</p>',
2024
                [],
2025
            ],
2026
            [
2027
                '<th>Data</th> <td>Creating a Template for the Field and form </td>',
2028
                'html',
2029
                '<p><strong>Creating a Template for the Field</strong> and form</p>',
2030
                ['strip' => true],
2031
            ],
2032
            [
2033
                '<th>Data</th> <td> Creating a Template for the... </td>',
2034
                'html',
2035
                '<p><strong>Creating a Template for the Field</strong> and form</p>',
2036
                ['truncate' => true],
2037
            ],
2038
            [
2039
                '<th>Data</th> <td> Creatin... </td>',
2040
                'html',
2041
                '<p><strong>Creating a Template for the Field</strong> and form</p>',
2042
                ['truncate' => ['length' => 10]],
2043
            ],
2044
            [
2045
                '<th>Data</th> <td> Creating a Template for the Field... </td>',
2046
                'html',
2047
                '<p><strong>Creating a Template for the Field</strong> and form</p>',
2048
                ['truncate' => ['cut' => false]],
2049
            ],
2050
            [
2051
                '<th>Data</th> <td> Creating a Template for t etc. </td>',
2052
                'html',
2053
                '<p><strong>Creating a Template for the Field</strong> and form</p>',
2054
                ['truncate' => ['ellipsis' => ' etc.']],
2055
            ],
2056
            [
2057
                '<th>Data</th> <td> Creating a Template[...] </td>',
2058
                'html',
2059
                '<p><strong>Creating a Template for the Field</strong> and form</p>',
2060
                [
2061
                    'truncate' => [
2062
                        'length' => 20,
2063
                        'cut' => false,
2064
                        'ellipsis' => '[...]',
2065
                    ],
2066
                ],
2067
            ],
2068
            [
2069
                <<<'EOT'
2070
<th>Data</th> <td><div
2071
        class="sonata-readmore"
2072
        data-readmore-height="40"
2073
        data-readmore-more="Read more"
2074
        data-readmore-less="Close">
2075
            A very long string
2076
</div></td>
2077
EOT
2078
                ,
2079
                'text',
2080
                ' A very long string ',
2081
                [
2082
                    'collapse' => true,
2083
                    'safe' => false,
2084
                ],
2085
            ],
2086
            [
2087
                <<<'EOT'
2088
<th>Data</th> <td><div
2089
        class="sonata-readmore"
2090
        data-readmore-height="10"
2091
        data-readmore-more="More"
2092
        data-readmore-less="Less">
2093
            A very long string
2094
</div></td>
2095
EOT
2096
                ,
2097
                'text',
2098
                ' A very long string ',
2099
                [
2100
                    'collapse' => [
2101
                        'height' => 10,
2102
                        'more' => 'More',
2103
                        'less' => 'Less',
2104
                    ],
2105
                    'safe' => false,
2106
                ],
2107
            ],
2108
        ];
2109
    }
2110
2111
    /**
2112
     * @group legacy
2113
     * @assertDeprecation Accessing a non existing value is deprecated since sonata-project/admin-bundle 3.67 and will throw an exception in 4.0.
2114
     *
2115
     * @dataProvider getRenderViewElementWithNoValueTests
2116
     */
2117
    public function testRenderViewElementWithNoValue(string $expected, string $type, array $options): void
2118
    {
2119
        $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...
2120
            ->method('getTemplate')
2121
            ->willReturn('@SonataAdmin/CRUD/base_show_field.html.twig');
2122
2123
        $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...
2124
            ->method('getValue')
2125
            ->willThrowException(new NoValueException());
2126
2127
        $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...
2128
            ->method('getType')
2129
            ->willReturn($type);
2130
2131
        $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...
2132
            ->method('getOptions')
2133
            ->willReturn($options);
2134
2135
        $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...
2136
            ->method('getTemplate')
2137
            ->willReturnCallback(static function () use ($type): ?string {
2138
                switch ($type) {
2139
                    case 'boolean':
2140
                        return '@SonataAdmin/CRUD/show_boolean.html.twig';
2141
                    case 'datetime':
2142
                        return '@SonataAdmin/CRUD/show_datetime.html.twig';
2143
                    case 'date':
2144
                        return '@SonataAdmin/CRUD/show_date.html.twig';
2145
                    case 'time':
2146
                        return '@SonataAdmin/CRUD/show_time.html.twig';
2147
                    case 'currency':
2148
                        return '@SonataAdmin/CRUD/show_currency.html.twig';
2149
                    case 'percent':
2150
                        return '@SonataAdmin/CRUD/show_percent.html.twig';
2151
                    case 'email':
2152
                        return '@SonataAdmin/CRUD/show_email.html.twig';
2153
                    case 'choice':
2154
                        return '@SonataAdmin/CRUD/show_choice.html.twig';
2155
                    case 'array':
2156
                        return '@SonataAdmin/CRUD/show_array.html.twig';
2157
                    case 'trans':
2158
                        return '@SonataAdmin/CRUD/show_trans.html.twig';
2159
                    case 'url':
2160
                        return '@SonataAdmin/CRUD/show_url.html.twig';
2161
                    case 'html':
2162
                        return '@SonataAdmin/CRUD/show_html.html.twig';
2163
                    default:
2164
                        return null;
2165
                }
2166
            });
2167
2168
        $this->assertSame(
2169
            $this->removeExtraWhitespace($expected),
2170
            $this->removeExtraWhitespace(
2171
                $this->twigExtension->renderViewElement(
2172
                    $this->environment,
2173
                    $this->fieldDescription,
2174
                    $this->object
2175
                )
2176
            )
2177
        );
2178
    }
2179
2180
    public function getRenderViewElementWithNoValueTests(): iterable
2181
    {
2182
        return [
2183
            // NoValueException
2184
            ['<th>Data</th> <td></td>', 'string', ['safe' => false]],
2185
            ['<th>Data</th> <td></td>', 'text', ['safe' => false]],
2186
            ['<th>Data</th> <td></td>', 'textarea', ['safe' => false]],
2187
            ['<th>Data</th> <td>&nbsp;</td>', 'datetime', []],
2188
            [
2189
                '<th>Data</th> <td>&nbsp;</td>',
2190
                'datetime',
2191
                ['format' => 'd.m.Y H:i:s'],
2192
            ],
2193
            ['<th>Data</th> <td>&nbsp;</td>', 'date', []],
2194
            ['<th>Data</th> <td>&nbsp;</td>', 'date', ['format' => 'd.m.Y']],
2195
            ['<th>Data</th> <td>&nbsp;</td>', 'time', []],
2196
            ['<th>Data</th> <td></td>', 'number', ['safe' => false]],
2197
            ['<th>Data</th> <td></td>', 'integer', ['safe' => false]],
2198
            ['<th>Data</th> <td> 0 % </td>', 'percent', []],
2199
            ['<th>Data</th> <td> </td>', 'currency', ['currency' => 'EUR']],
2200
            ['<th>Data</th> <td> </td>', 'currency', ['currency' => 'GBP']],
2201
            ['<th>Data</th> <td> <ul></ul> </td>', 'array', ['safe' => false]],
2202
            [
2203
                '<th>Data</th> <td><span class="label label-danger">no</span></td>',
2204
                'boolean',
2205
                [],
2206
            ],
2207
            [
2208
                '<th>Data</th> <td> </td>',
2209
                'trans',
2210
                ['safe' => false, 'catalogue' => 'SonataAdminBundle'],
2211
            ],
2212
            [
2213
                '<th>Data</th> <td></td>',
2214
                'choice',
2215
                ['safe' => false, 'choices' => []],
2216
            ],
2217
            [
2218
                '<th>Data</th> <td></td>',
2219
                'choice',
2220
                ['safe' => false, 'choices' => [], 'multiple' => true],
2221
            ],
2222
            ['<th>Data</th> <td>&nbsp;</td>', 'url', []],
2223
            [
2224
                '<th>Data</th> <td>&nbsp;</td>',
2225
                'url',
2226
                ['url' => 'http://example.com'],
2227
            ],
2228
            [
2229
                '<th>Data</th> <td>&nbsp;</td>',
2230
                'url',
2231
                ['route' => ['name' => 'sonata_admin_foo']],
2232
            ],
2233
        ];
2234
    }
2235
2236
    /**
2237
     * NEXT_MAJOR: Remove this method.
2238
     *
2239
     * @group legacy
2240
     *
2241
     * @dataProvider getDeprecatedTextExtensionItems
2242
     *
2243
     * @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).
2244
     *
2245
     * @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).
2246
     */
2247
    public function testDeprecatedTextExtension(string $expected, string $type, $value, array $options): void
2248
    {
2249
        $loader = new StubFilesystemLoader([
2250
            sprintf('%s/../../../src/Resources/views/CRUD', __DIR__),
2251
        ]);
2252
        $loader->addPath(sprintf('%s/../../../src/Resources/views/', __DIR__), 'SonataAdmin');
2253
        $environment = new Environment($loader, [
2254
            'strict_variables' => true,
2255
            'cache' => false,
2256
            'autoescape' => 'html',
2257
            'optimizations' => 0,
2258
        ]);
2259
        $environment->addExtension($this->twigExtension);
2260
        $environment->addExtension(new TranslationExtension($this->translator));
2261
        $environment->addExtension(new StringExtension());
2262
2263
        $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...
2264
            ->method('getTemplate')
2265
            ->willReturn('@SonataAdmin/CRUD/base_show_field.html.twig');
2266
2267
        $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...
2268
            ->method('getValue')
2269
            ->willReturn($value);
2270
2271
        $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...
2272
            ->method('getType')
2273
            ->willReturn($type);
2274
2275
        $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...
2276
            ->method('getOptions')
2277
            ->willReturn($options);
2278
2279
        $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...
2280
            ->method('getTemplate')
2281
            ->willReturn('@SonataAdmin/CRUD/show_html.html.twig');
2282
2283
        $this->assertSame(
2284
            $this->removeExtraWhitespace($expected),
2285
            $this->removeExtraWhitespace(
2286
                $this->twigExtension->renderViewElement(
2287
                    $environment,
2288
                    $this->fieldDescription,
2289
                    $this->object
2290
                )
2291
            )
2292
        );
2293
    }
2294
2295
    /**
2296
     * NEXT_MAJOR: Remove this method.
2297
     */
2298
    public function getDeprecatedTextExtensionItems(): iterable
2299
    {
2300
        yield 'default_separator' => [
2301
            '<th>Data</th> <td> Creating a Template for the Field... </td>',
2302
            'html',
2303
            '<p><strong>Creating a Template for the Field</strong> and form</p>',
2304
            ['truncate' => ['preserve' => true, 'separator' => '...']],
2305
        ];
2306
2307
        yield 'custom_length' => [
2308
            '<th>Data</th> <td> Creating a Template[...] </td>',
2309
            'html',
2310
            '<p><strong>Creating a Template for the Field</strong> and form</p>',
2311
            [
2312
                'truncate' => [
2313
                    'length' => 20,
2314
                    'preserve' => true,
2315
                    'separator' => '[...]',
2316
                ],
2317
            ],
2318
        ];
2319
    }
2320
2321
    /**
2322
     * NEXT_MAJOR: Remove this test.
2323
     *
2324
     * @group legacy
2325
     */
2326
    public function testGetValueFromFieldDescription(): void
2327
    {
2328
        $object = new \stdClass();
2329
        $fieldDescription = $this->getMockForAbstractClass(FieldDescriptionInterface::class);
2330
2331
        $fieldDescription
2332
            ->method('getValue')
2333
            ->willReturn('test123');
2334
2335
        $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...
2336
    }
2337
2338
    /**
2339
     * NEXT_MAJOR: Remove this test.
2340
     *
2341
     * @group legacy
2342
     */
2343
    public function testGetValueFromFieldDescriptionWithRemoveLoopException(): void
2344
    {
2345
        $object = $this->createMock(\ArrayAccess::class);
2346
        $fieldDescription = $this->getMockForAbstractClass(FieldDescriptionInterface::class);
2347
2348
        $this->expectException(\RuntimeException::class);
2349
        $this->expectExceptionMessage('remove the loop requirement');
2350
2351
        $this->assertSame(
2352
            'anything',
2353
            $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...
2354
        );
2355
    }
2356
2357
    /**
2358
     * NEXT_MAJOR: Remove this test.
2359
     *
2360
     * @group legacy
2361
     * @expectedDeprecation Accessing a non existing value is deprecated since sonata-project/admin-bundle 3.67 and will throw an exception in 4.0.
2362
     */
2363
    public function testGetValueFromFieldDescriptionWithNoValueException(): void
2364
    {
2365
        $object = new \stdClass();
2366
        $fieldDescription = $this->getMockForAbstractClass(FieldDescriptionInterface::class);
2367
2368
        $fieldDescription
2369
            ->method('getValue')
2370
            ->willReturnCallback(static function (): void {
2371
                throw new NoValueException();
2372
            });
2373
2374
        $fieldDescription
2375
            ->method('getAssociationAdmin')
2376
            ->willReturn(null);
2377
2378
        $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...
2379
    }
2380
2381
    /**
2382
     * NEXT_MAJOR: Remove this test.
2383
     *
2384
     * @group legacy
2385
     */
2386
    public function testGetValueFromFieldDescriptionWithNoValueExceptionNewAdminInstance(): void
2387
    {
2388
        $object = new \stdClass();
2389
        $fieldDescription = $this->getMockForAbstractClass(FieldDescriptionInterface::class);
2390
2391
        $fieldDescription
2392
            ->method('getValue')
2393
            ->willReturnCallback(static function (): void {
2394
                throw new NoValueException();
2395
            });
2396
2397
        $fieldDescription
2398
            ->method('getAssociationAdmin')
2399
            ->willReturn($this->admin);
2400
2401
        $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...
2402
            ->method('getNewInstance')
2403
            ->willReturn('foo');
2404
2405
        $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...
2406
    }
2407
2408
    /**
2409
     * @group legacy
2410
     */
2411
    public function testOutput(): void
2412
    {
2413
        $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...
2414
            ->method('getTemplate')
2415
            ->willReturn('@SonataAdmin/CRUD/base_list_field.html.twig');
2416
2417
        $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...
2418
            ->method('getFieldName')
2419
            ->willReturn('fd_name');
2420
2421
        $this->environment->disableDebug();
2422
2423
        $parameters = [
2424
            'admin' => $this->admin,
2425
            'value' => 'foo',
2426
            'field_description' => $this->fieldDescription,
2427
            'object' => $this->object,
2428
        ];
2429
2430
        $template = $this->environment->loadTemplate('@SonataAdmin/CRUD/base_list_field.html.twig');
2431
2432
        $this->assertSame(
2433
            '<td class="sonata-ba-list-field sonata-ba-list-field-" objectId="12345"> foo </td>',
2434
            $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...
2435
                $this->fieldDescription,
2436
                $template,
2437
                $parameters,
2438
                $this->environment
2439
            ))
2440
        );
2441
2442
        $this->environment->enableDebug();
2443
        $this->assertSame(
2444
            $this->removeExtraWhitespace(
2445
                <<<'EOT'
2446
<!-- START
2447
    fieldName: fd_name
2448
    template: @SonataAdmin/CRUD/base_list_field.html.twig
2449
    compiled template: @SonataAdmin/CRUD/base_list_field.html.twig
2450
-->
2451
    <td class="sonata-ba-list-field sonata-ba-list-field-" objectId="12345"> foo </td>
2452
<!-- END - fieldName: fd_name -->
2453
EOT
2454
            ),
2455
            $this->removeExtraWhitespace(
2456
                $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...
2457
            )
2458
        );
2459
    }
2460
2461
    /**
2462
     * @group legacy
2463
     * @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).
2464
     */
2465
    public function testRenderWithDebug(): void
2466
    {
2467
        $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...
2468
            ->method('getTemplate')
2469
            ->willReturn('@SonataAdmin/CRUD/base_list_field.html.twig');
2470
2471
        $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...
2472
            ->method('getFieldName')
2473
            ->willReturn('fd_name');
2474
2475
        $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...
2476
            ->method('getValue')
2477
            ->willReturn('foo');
2478
2479
        $parameters = [
2480
            'admin' => $this->admin,
2481
            'value' => 'foo',
2482
            'field_description' => $this->fieldDescription,
2483
            'object' => $this->object,
2484
        ];
2485
2486
        $this->environment->enableDebug();
2487
2488
        $this->assertSame(
2489
            $this->removeExtraWhitespace(
2490
                <<<'EOT'
2491
<!-- START
2492
    fieldName: fd_name
2493
    template: @SonataAdmin/CRUD/base_list_field.html.twig
2494
    compiled template: @SonataAdmin/CRUD/base_list_field.html.twig
2495
-->
2496
    <td class="sonata-ba-list-field sonata-ba-list-field-" objectId="12345"> foo </td>
2497
<!-- END - fieldName: fd_name -->
2498
EOT
2499
            ),
2500
            $this->removeExtraWhitespace(
2501
                $this->twigExtension->renderListElement($this->environment, $this->object, $this->fieldDescription, $parameters)
2502
            )
2503
        );
2504
    }
2505
2506
    public function testRenderRelationElementNoObject(): void
2507
    {
2508
        $this->assertSame('foo', $this->twigExtension->renderRelationElement('foo', $this->fieldDescription));
2509
    }
2510
2511
    public function testRenderRelationElementToString(): void
2512
    {
2513
        $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...
2514
            ->method('getOption')
2515
            ->willReturnCallback(static function ($value, $default = null) {
2516
                if ('associated_property' === $value) {
2517
                    return $default;
2518
                }
2519
            });
2520
2521
        $element = new FooToString();
2522
        $this->assertSame('salut', $this->twigExtension->renderRelationElement($element, $this->fieldDescription));
2523
    }
2524
2525
    /**
2526
     * @group legacy
2527
     */
2528
    public function testDeprecatedRelationElementToString(): void
2529
    {
2530
        $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...
2531
            ->method('getOption')
2532
            ->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...
2533
                if ('associated_tostring' === $value) {
2534
                    return '__toString';
2535
                }
2536
            });
2537
2538
        $element = new FooToString();
2539
        $this->assertSame(
2540
            'salut',
2541
            $this->twigExtension->renderRelationElement($element, $this->fieldDescription)
2542
        );
2543
    }
2544
2545
    /**
2546
     * @group legacy
2547
     */
2548
    public function testRenderRelationElementCustomToString(): void
2549
    {
2550
        $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...
2551
            ->method('getOption')
2552
            ->willReturnCallback(static function ($value, $default = null) {
2553
                if ('associated_property' === $value) {
2554
                    return $default;
2555
                }
2556
2557
                if ('associated_tostring' === $value) {
2558
                    return 'customToString';
2559
                }
2560
            });
2561
2562
        $element = $this->getMockBuilder(\stdClass::class)
2563
            ->setMethods(['customToString'])
2564
            ->getMock();
2565
        $element
2566
            ->method('customToString')
2567
            ->willReturn('fooBar');
2568
2569
        $this->assertSame('fooBar', $this->twigExtension->renderRelationElement($element, $this->fieldDescription));
2570
    }
2571
2572
    /**
2573
     * @group legacy
2574
     */
2575
    public function testRenderRelationElementMethodNotExist(): void
2576
    {
2577
        $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...
2578
            ->method('getOption')
2579
2580
            ->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...
2581
                if ('associated_tostring' === $value) {
2582
                    return 'nonExistedMethod';
2583
                }
2584
            });
2585
2586
        $element = new \stdClass();
2587
        $this->expectException(\RuntimeException::class);
2588
        $this->expectExceptionMessage('You must define an `associated_property` option or create a `stdClass::__toString');
2589
2590
        $this->twigExtension->renderRelationElement($element, $this->fieldDescription);
2591
    }
2592
2593
    public function testRenderRelationElementWithPropertyPath(): void
2594
    {
2595
        $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...
2596
            ->method('getOption')
2597
2598
            ->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...
2599
                if ('associated_property' === $value) {
2600
                    return 'foo';
2601
                }
2602
            });
2603
2604
        $element = new \stdClass();
2605
        $element->foo = 'bar';
2606
2607
        $this->assertSame('bar', $this->twigExtension->renderRelationElement($element, $this->fieldDescription));
2608
    }
2609
2610
    public function testRenderRelationElementWithClosure(): void
2611
    {
2612
        $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...
2613
            ->method('getOption')
2614
2615
            ->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...
2616
                if ('associated_property' === $value) {
2617
                    return static function ($element): string {
2618
                        return sprintf('closure %s', $element->foo);
2619
                    };
2620
                }
2621
            });
2622
2623
        $element = new \stdClass();
2624
        $element->foo = 'bar';
2625
2626
        $this->assertSame(
2627
            'closure bar',
2628
            $this->twigExtension->renderRelationElement($element, $this->fieldDescription)
2629
        );
2630
    }
2631
2632
    public function testGetUrlsafeIdentifier(): void
2633
    {
2634
        $model = new \stdClass();
2635
2636
        // set admin to pool
2637
        $this->pool->setAdminServiceIds(['sonata_admin_foo_service']);
2638
        $this->pool->setAdminClasses([\stdClass::class => ['sonata_admin_foo_service']]);
2639
2640
        $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...
2641
            ->method('getUrlSafeIdentifier')
2642
            ->with($this->equalTo($model))
2643
            ->willReturn(1234567);
2644
2645
        $this->assertSame(1234567, $this->twigExtension->getUrlSafeIdentifier($model));
2646
    }
2647
2648
    public function testGetUrlsafeIdentifier_GivenAdmin_Foo(): void
2649
    {
2650
        $model = new \stdClass();
2651
2652
        // set admin to pool
2653
        $this->pool->setAdminServiceIds([
2654
            'sonata_admin_foo_service',
2655
            'sonata_admin_bar_service',
2656
        ]);
2657
        $this->pool->setAdminClasses([\stdClass::class => [
2658
            'sonata_admin_foo_service',
2659
            'sonata_admin_bar_service',
2660
        ]]);
2661
2662
        $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...
2663
            ->method('getUrlSafeIdentifier')
2664
            ->with($this->equalTo($model))
2665
            ->willReturn(1234567);
2666
2667
        $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...
2668
            ->method('getUrlSafeIdentifier');
2669
2670
        $this->assertSame(1234567, $this->twigExtension->getUrlSafeIdentifier($model, $this->admin));
2671
    }
2672
2673
    public function testGetUrlsafeIdentifier_GivenAdmin_Bar(): void
2674
    {
2675
        $model = new \stdClass();
2676
2677
        // set admin to pool
2678
        $this->pool->setAdminServiceIds(['sonata_admin_foo_service', 'sonata_admin_bar_service']);
2679
        $this->pool->setAdminClasses([\stdClass::class => [
2680
            'sonata_admin_foo_service',
2681
            'sonata_admin_bar_service',
2682
        ]]);
2683
2684
        $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...
2685
            ->method('getUrlSafeIdentifier');
2686
2687
        $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...
2688
            ->method('getUrlSafeIdentifier')
2689
            ->with($this->equalTo($model))
2690
            ->willReturn(1234567);
2691
2692
        $this->assertSame(1234567, $this->twigExtension->getUrlSafeIdentifier($model, $this->adminBar));
2693
    }
2694
2695
    public function xEditableChoicesProvider()
2696
    {
2697
        return [
2698
            'needs processing' => [
2699
                ['choices' => ['Status1' => 'Alias1', 'Status2' => 'Alias2']],
2700
                [
2701
                    ['value' => 'Status1', 'text' => 'Alias1'],
2702
                    ['value' => 'Status2', 'text' => 'Alias2'],
2703
                ],
2704
            ],
2705
            'already processed' => [
2706
                ['choices' => [
2707
                    ['value' => 'Status1', 'text' => 'Alias1'],
2708
                    ['value' => 'Status2', 'text' => 'Alias2'],
2709
                ]],
2710
                [
2711
                    ['value' => 'Status1', 'text' => 'Alias1'],
2712
                    ['value' => 'Status2', 'text' => 'Alias2'],
2713
                ],
2714
            ],
2715
            'not required' => [
2716
                [
2717
                    'required' => false,
2718
                    'choices' => ['' => '', 'Status1' => 'Alias1', 'Status2' => 'Alias2'],
2719
                ],
2720
                [
2721
                    ['value' => '', 'text' => ''],
2722
                    ['value' => 'Status1', 'text' => 'Alias1'],
2723
                    ['value' => 'Status2', 'text' => 'Alias2'],
2724
                ],
2725
            ],
2726
            'not required multiple' => [
2727
                [
2728
                    'required' => false,
2729
                    'multiple' => true,
2730
                    'choices' => ['Status1' => 'Alias1', 'Status2' => 'Alias2'],
2731
                ],
2732
                [
2733
                    ['value' => 'Status1', 'text' => 'Alias1'],
2734
                    ['value' => 'Status2', 'text' => 'Alias2'],
2735
                ],
2736
            ],
2737
        ];
2738
    }
2739
2740
    /**
2741
     * @dataProvider xEditablechoicesProvider
2742
     */
2743
    public function testGetXEditableChoicesIsIdempotent(array $options, array $expectedChoices): void
2744
    {
2745
        $fieldDescription = $this->getMockForAbstractClass(FieldDescriptionInterface::class);
2746
        $fieldDescription
2747
            ->method('getOption')
2748
            ->withConsecutive(
2749
                ['choices', []],
2750
                ['catalogue'],
2751
                ['required'],
2752
                ['multiple']
2753
            )
2754
            ->will($this->onConsecutiveCalls(
2755
                $options['choices'],
2756
                'MyCatalogue',
2757
                $options['multiple'] ?? null
2758
            ));
2759
2760
        $this->assertSame($expectedChoices, $this->twigExtension->getXEditableChoices($fieldDescription));
2761
    }
2762
2763
    public function select2LocalesProvider()
2764
    {
2765
        return [
2766
            ['ar', 'ar'],
2767
            ['az', 'az'],
2768
            ['bg', 'bg'],
2769
            ['ca', 'ca'],
2770
            ['cs', 'cs'],
2771
            ['da', 'da'],
2772
            ['de', 'de'],
2773
            ['el', 'el'],
2774
            [null, 'en'],
2775
            ['es', 'es'],
2776
            ['et', 'et'],
2777
            ['eu', 'eu'],
2778
            ['fa', 'fa'],
2779
            ['fi', 'fi'],
2780
            ['fr', 'fr'],
2781
            ['gl', 'gl'],
2782
            ['he', 'he'],
2783
            ['hr', 'hr'],
2784
            ['hu', 'hu'],
2785
            ['id', 'id'],
2786
            ['is', 'is'],
2787
            ['it', 'it'],
2788
            ['ja', 'ja'],
2789
            ['ka', 'ka'],
2790
            ['ko', 'ko'],
2791
            ['lt', 'lt'],
2792
            ['lv', 'lv'],
2793
            ['mk', 'mk'],
2794
            ['ms', 'ms'],
2795
            ['nb', 'nb'],
2796
            ['nl', 'nl'],
2797
            ['pl', 'pl'],
2798
            ['pt-PT', 'pt'],
2799
            ['pt-BR', 'pt-BR'],
2800
            ['pt-PT', 'pt-PT'],
2801
            ['ro', 'ro'],
2802
            ['rs', 'rs'],
2803
            ['ru', 'ru'],
2804
            ['sk', 'sk'],
2805
            ['sv', 'sv'],
2806
            ['th', 'th'],
2807
            ['tr', 'tr'],
2808
            ['ug-CN', 'ug'],
2809
            ['ug-CN', 'ug-CN'],
2810
            ['uk', 'uk'],
2811
            ['vi', 'vi'],
2812
            ['zh-CN', 'zh'],
2813
            ['zh-CN', 'zh-CN'],
2814
            ['zh-TW', 'zh-TW'],
2815
        ];
2816
    }
2817
2818
    /**
2819
     * @dataProvider select2LocalesProvider
2820
     */
2821
    public function testCanonicalizedLocaleForSelect2(?string $expected, string $original): void
2822
    {
2823
        $this->assertSame($expected, $this->twigExtension->getCanonicalizedLocaleForSelect2($this->mockExtensionContext($original)));
2824
    }
2825
2826
    public function momentLocalesProvider(): array
2827
    {
2828
        return [
2829
            ['af', 'af'],
2830
            ['ar-dz', 'ar-dz'],
2831
            ['ar', 'ar'],
2832
            ['ar-ly', 'ar-ly'],
2833
            ['ar-ma', 'ar-ma'],
2834
            ['ar-sa', 'ar-sa'],
2835
            ['ar-tn', 'ar-tn'],
2836
            ['az', 'az'],
2837
            ['be', 'be'],
2838
            ['bg', 'bg'],
2839
            ['bn', 'bn'],
2840
            ['bo', 'bo'],
2841
            ['br', 'br'],
2842
            ['bs', 'bs'],
2843
            ['ca', 'ca'],
2844
            ['cs', 'cs'],
2845
            ['cv', 'cv'],
2846
            ['cy', 'cy'],
2847
            ['da', 'da'],
2848
            ['de-at', 'de-at'],
2849
            ['de', 'de'],
2850
            ['de', 'de-de'],
2851
            ['dv', 'dv'],
2852
            ['el', 'el'],
2853
            [null, 'en'],
2854
            [null, 'en-us'],
2855
            ['en-au', 'en-au'],
2856
            ['en-ca', 'en-ca'],
2857
            ['en-gb', 'en-gb'],
2858
            ['en-ie', 'en-ie'],
2859
            ['en-nz', 'en-nz'],
2860
            ['eo', 'eo'],
2861
            ['es-do', 'es-do'],
2862
            ['es', 'es-ar'],
2863
            ['es', 'es-mx'],
2864
            ['es', 'es'],
2865
            ['et', 'et'],
2866
            ['eu', 'eu'],
2867
            ['fa', 'fa'],
2868
            ['fi', 'fi'],
2869
            ['fo', 'fo'],
2870
            ['fr-ca', 'fr-ca'],
2871
            ['fr-ch', 'fr-ch'],
2872
            ['fr', 'fr-fr'],
2873
            ['fr', 'fr'],
2874
            ['fy', 'fy'],
2875
            ['gd', 'gd'],
2876
            ['gl', 'gl'],
2877
            ['he', 'he'],
2878
            ['hi', 'hi'],
2879
            ['hr', 'hr'],
2880
            ['hu', 'hu'],
2881
            ['hy-am', 'hy-am'],
2882
            ['id', 'id'],
2883
            ['is', 'is'],
2884
            ['it', 'it'],
2885
            ['ja', 'ja'],
2886
            ['jv', 'jv'],
2887
            ['ka', 'ka'],
2888
            ['kk', 'kk'],
2889
            ['km', 'km'],
2890
            ['ko', 'ko'],
2891
            ['ky', 'ky'],
2892
            ['lb', 'lb'],
2893
            ['lo', 'lo'],
2894
            ['lt', 'lt'],
2895
            ['lv', 'lv'],
2896
            ['me', 'me'],
2897
            ['mi', 'mi'],
2898
            ['mk', 'mk'],
2899
            ['ml', 'ml'],
2900
            ['mr', 'mr'],
2901
            ['ms', 'ms'],
2902
            ['ms-my', 'ms-my'],
2903
            ['my', 'my'],
2904
            ['nb', 'nb'],
2905
            ['ne', 'ne'],
2906
            ['nl-be', 'nl-be'],
2907
            ['nl', 'nl'],
2908
            ['nl', 'nl-nl'],
2909
            ['nn', 'nn'],
2910
            ['pa-in', 'pa-in'],
2911
            ['pl', 'pl'],
2912
            ['pt-br', 'pt-br'],
2913
            ['pt', 'pt'],
2914
            ['ro', 'ro'],
2915
            ['ru', 'ru'],
2916
            ['se', 'se'],
2917
            ['si', 'si'],
2918
            ['sk', 'sk'],
2919
            ['sl', 'sl'],
2920
            ['sq', 'sq'],
2921
            ['sr-cyrl', 'sr-cyrl'],
2922
            ['sr', 'sr'],
2923
            ['ss', 'ss'],
2924
            ['sv', 'sv'],
2925
            ['sw', 'sw'],
2926
            ['ta', 'ta'],
2927
            ['te', 'te'],
2928
            ['tet', 'tet'],
2929
            ['th', 'th'],
2930
            ['tlh', 'tlh'],
2931
            ['tl-ph', 'tl-ph'],
2932
            ['tr', 'tr'],
2933
            ['tzl', 'tzl'],
2934
            ['tzm', 'tzm'],
2935
            ['tzm-latn', 'tzm-latn'],
2936
            ['uk', 'uk'],
2937
            ['uz', 'uz'],
2938
            ['vi', 'vi'],
2939
            ['x-pseudo', 'x-pseudo'],
2940
            ['yo', 'yo'],
2941
            ['zh-cn', 'zh-cn'],
2942
            ['zh-hk', 'zh-hk'],
2943
            ['zh-tw', 'zh-tw'],
2944
        ];
2945
    }
2946
2947
    /**
2948
     * @dataProvider momentLocalesProvider
2949
     */
2950
    public function testCanonicalizedLocaleForMoment(?string $expected, string $original): void
2951
    {
2952
        $this->assertSame($expected, $this->twigExtension->getCanonicalizedLocaleForMoment($this->mockExtensionContext($original)));
2953
    }
2954
2955
    public function testIsGrantedAffirmative(): void
2956
    {
2957
        $this->assertTrue(
2958
            $this->twigExtension->isGrantedAffirmative(['foo', 'bar'])
2959
        );
2960
        $this->assertTrue($this->twigExtension->isGrantedAffirmative('foo'));
2961
        $this->assertTrue($this->twigExtension->isGrantedAffirmative('bar'));
2962
    }
2963
2964
    /**
2965
     * @dataProvider getRenderViewElementCompareTests
2966
     */
2967
    public function testRenderViewElementCompare(string $expected, string $type, $value, array $options, ?string $objectName = null): void
2968
    {
2969
        $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...
2970
            ->method('getTemplate')
2971
            ->willReturn('@SonataAdmin/CRUD/base_show_compare.html.twig');
2972
2973
        $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...
2974
            ->method('getValue')
2975
            ->willReturn($value);
2976
2977
        $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...
2978
            ->method('getType')
2979
            ->willReturn($type);
2980
2981
        $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...
2982
            ->method('getOptions')
2983
            ->willReturn($options);
2984
2985
        $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...
2986
            ->method('getTemplate')
2987
            ->willReturnCallback(static function () use ($type, $options): ?string {
2988
                if (isset($options['template'])) {
2989
                    return $options['template'];
2990
                }
2991
2992
                switch ($type) {
2993
                    case 'boolean':
2994
                        return '@SonataAdmin/CRUD/show_boolean.html.twig';
2995
                    case 'datetime':
2996
                        return '@SonataAdmin/CRUD/show_datetime.html.twig';
2997
                    case 'date':
2998
                        return '@SonataAdmin/CRUD/show_date.html.twig';
2999
                    case 'time':
3000
                        return '@SonataAdmin/CRUD/show_time.html.twig';
3001
                    case 'currency':
3002
                        return '@SonataAdmin/CRUD/show_currency.html.twig';
3003
                    case 'percent':
3004
                        return '@SonataAdmin/CRUD/show_percent.html.twig';
3005
                    case 'email':
3006
                        return '@SonataAdmin/CRUD/show_email.html.twig';
3007
                    case 'choice':
3008
                        return '@SonataAdmin/CRUD/show_choice.html.twig';
3009
                    case 'array':
3010
                        return '@SonataAdmin/CRUD/show_array.html.twig';
3011
                    case 'trans':
3012
                        return '@SonataAdmin/CRUD/show_trans.html.twig';
3013
                    case 'url':
3014
                        return '@SonataAdmin/CRUD/show_url.html.twig';
3015
                    case 'html':
3016
                        return '@SonataAdmin/CRUD/show_html.html.twig';
3017
                    default:
3018
                        return null;
3019
                }
3020
            });
3021
3022
        $this->object->name = 'SonataAdmin';
3023
3024
        $comparedObject = clone $this->object;
3025
3026
        if (null !== $objectName) {
3027
            $comparedObject->name = $objectName;
3028
        }
3029
3030
        $this->assertSame(
3031
            $this->removeExtraWhitespace($expected),
3032
            $this->removeExtraWhitespace(
3033
                $this->twigExtension->renderViewElementCompare(
3034
                    $this->environment,
3035
                    $this->fieldDescription,
3036
                    $this->object,
3037
                    $comparedObject
3038
                )
3039
            )
3040
        );
3041
    }
3042
3043
    public function getRenderViewElementCompareTests(): iterable
3044
    {
3045
        return [
3046
            ['<th>Data</th> <td>Example</td><td>Example</td>', 'string', 'Example', ['safe' => false]],
3047
            ['<th>Data</th> <td>Example</td><td>Example</td>', 'text', 'Example', ['safe' => false]],
3048
            ['<th>Data</th> <td>Example</td><td>Example</td>', 'textarea', 'Example', ['safe' => false]],
3049
            ['<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']],
3050
            ['<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'],
3051
            [
3052
                '<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>'
3053
                .'<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
                'datetime',
3055
                new \DateTime('2020-05-27 10:11:12', new \DateTimeZone('Europe/London')), [],
3056
            ],
3057
            [
3058
                '<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>'
3059
                .'<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
                'datetime',
3061
                new \DateTime('2020-05-27 10:11:12', new \DateTimeZone('Europe/London')),
3062
                ['format' => 'd.m.Y H:i:s'],
3063
            ],
3064
            [
3065
                '<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>'
3066
                .'<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
                'datetime',
3068
                new \DateTime('2020-05-27 10:11:12', new \DateTimeZone('UTC')),
3069
                ['timezone' => 'Asia/Hong_Kong'],
3070
            ],
3071
            [
3072
                '<th>Data</th> <td><time datetime="2020-05-27" title="2020-05-27"> May 27, 2020 </time></td>'
3073
                .'<td><time datetime="2020-05-27" title="2020-05-27"> May 27, 2020 </time></td>',
3074
                'date',
3075
                new \DateTime('2020-05-27 10:11:12', new \DateTimeZone('Europe/London')),
3076
                [],
3077
            ],
3078
        ];
3079
    }
3080
3081
    /**
3082
     * This method generates url part for Twig layout.
3083
     */
3084
    private function buildTwigLikeUrl(array $url): string
3085
    {
3086
        return htmlspecialchars(http_build_query($url, '', '&', PHP_QUERY_RFC3986));
3087
    }
3088
3089
    private function removeExtraWhitespace(string $string): string
3090
    {
3091
        return trim(preg_replace(
3092
            '/\s+/',
3093
            ' ',
3094
            $string
3095
        ));
3096
    }
3097
3098
    private function mockExtensionContext(string $locale): array
3099
    {
3100
        $request = $this->createMock(Request::class);
3101
        $request->method('getLocale')->willReturn($locale);
3102
        $appVariable = $this->createMock(AppVariable::class);
3103
        $appVariable->method('getRequest')->willReturn($request);
3104
3105
        return ['app' => $appVariable];
3106
    }
3107
}
3108