Completed
Push — 3.x ( dca2a5...0d5aea )
by Grégoire
08:20
created

SonataAdminExtensionTest   F

Complexity

Total Complexity 106

Size/Duplication

Total Lines 3062
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 18

Importance

Changes 0
Metric Value
wmc 106
lcom 1
cbo 18
dl 0
loc 3062
rs 0.8
c 0
b 0
f 0

45 Methods

Rating   Name   Duplication   Size   Complexity  
A testConstructThrowsExceptionWithWrongTranslationArgument() 0 10 1
A testConstructWithLegacyTranslator() 0 8 1
C testRenderListElement() 0 83 15
B setUp() 0 152 3
A testRenderListElementWithAdditionalValuesInArray() 0 23 1
A testRenderListElementWithNoValueException() 0 25 1
A testDeprecatedRenderListElement() 0 45 1
A getDeprecatedRenderListElementTests() 0 15 1
B getRenderListElementTests() 0 968 1
A testRenderListElementNonExistentTemplate() 0 37 1
A testRenderListElementErrorLoadingTemplate() 0 20 1
C testRenderViewElement() 0 62 13
B getRenderViewElementTests() 0 498 1
C testRenderViewElementWithNoValue() 0 62 13
B getRenderViewElementWithNoValueTests() 0 55 1
A testDeprecatedTextExtension() 0 47 1
A getDeprecatedTextExtensionItems() 0 22 1
A testGetValueFromFieldDescription() 0 11 1
A testGetValueFromFieldDescriptionWithRemoveLoopException() 0 13 1
A testGetValueFromFieldDescriptionWithNoValueException() 0 17 1
A testGetValueFromFieldDescriptionWithNoValueExceptionNewAdminInstance() 0 21 1
A testOutput() 0 49 1
A testRenderWithDebug() 0 40 1
A testRenderRelationElementNoObject() 0 4 1
A testRenderRelationElementToString() 0 13 2
A testDeprecatedRelationElementToString() 0 16 2
A testRenderRelationElementCustomToString() 0 23 3
A testRenderRelationElementMethodNotExist() 0 17 2
A testRenderRelationElementWithPropertyPath() 0 16 2
A testRenderRelationElementWithClosure() 0 21 2
A testGetUrlsafeIdentifier() 0 15 1
A testGetUrlsafeIdentifier_GivenAdmin_Foo() 0 24 1
A testGetUrlsafeIdentifier_GivenAdmin_Bar() 0 21 1
A xEditableChoicesProvider() 0 44 1
A testGetXEditableChoicesIsIdempotent() 0 19 1
A select2LocalesProvider() 0 54 1
A testCanonicalizedLocaleForSelect2() 0 4 1
B momentLocalesProvider() 0 120 1
A testCanonicalizedLocaleForMoment() 0 4 1
A testIsGrantedAffirmative() 0 8 1
C testRenderViewElementCompare() 0 75 15
A getRenderViewElementCompareTests() 0 37 1
A buildTwigLikeUrl() 0 4 1
A removeExtraWhitespace() 0 8 1
A mockExtensionContext() 0 9 1

How to fix   Complexity   

Complex Class

Complex classes like SonataAdminExtensionTest often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use SonataAdminExtensionTest, and based on these observations, apply Extract Interface, too.

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
     * NEXT_MAJOR: Remove @expectedDeprecation.
391
     *
392
     * @group legacy
393
     * @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).
394
     */
395
    public function testRenderListElementWithAdditionalValuesInArray(): void
396
    {
397
        // NEXT_MAJOR: Remove this line
398
        $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...
399
            ->method('getTemplate')
400
            ->with('base_list_field')
401
            ->willReturn('@SonataAdmin/CRUD/base_list_field.html.twig');
402
403
        $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...
404
405
        $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...
406
            ->method('getTemplate')
407
            ->willReturn('@SonataAdmin/CRUD/list_string.html.twig');
408
409
        $this->assertSame(
410
            $this->removeExtraWhitespace('<td class="sonata-ba-list-field sonata-ba-list-field-" objectId="12345"> Extra value </td>'),
411
            $this->removeExtraWhitespace($this->twigExtension->renderListElement(
412
                $this->environment,
413
                [$this->object, 'fd_name' => 'Extra value'],
414
                $this->fieldDescription
415
            ))
416
        );
417
    }
418
419
    /**
420
     * NEXT_MAJOR: Remove @expectedDeprecation.
421
     *
422
     * @group legacy
423
     * @expectedDeprecation Accessing a non existing value is deprecated since sonata-project/admin-bundle 3.67 and will throw an exception in 4.0.
424
     */
425
    public function testRenderListElementWithNoValueException(): void
426
    {
427
        // NEXT_MAJOR: Remove this line
428
        $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...
429
            ->method('getTemplate')
430
            ->with('base_list_field')
431
            ->willReturn('@SonataAdmin/CRUD/base_list_field.html.twig');
432
433
        $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...
434
435
        $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...
436
            ->method('getValue')
437
            ->willReturnCallback(static function (): void {
438
                throw new NoValueException();
439
            });
440
441
        $this->assertSame(
442
            $this->removeExtraWhitespace('<td class="sonata-ba-list-field sonata-ba-list-field-" objectId="12345"> </td>'),
443
            $this->removeExtraWhitespace($this->twigExtension->renderListElement(
444
                $this->environment,
445
                $this->object,
446
                $this->fieldDescription
447
            ))
448
        );
449
    }
450
451
    /**
452
     * @dataProvider getDeprecatedRenderListElementTests
453
     * @group legacy
454
     */
455
    public function testDeprecatedRenderListElement(string $expected, ?string $value, array $options): void
456
    {
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('hasAccess')
459
            ->willReturn(true);
460
461
        // NEXT_MAJOR: Remove this line
462
        $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...
463
            ->method('getTemplate')
464
            ->with('base_list_field')
465
            ->willReturn('@SonataAdmin/CRUD/base_list_field.html.twig');
466
467
        $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...
468
469
        $this->fieldDescription
0 ignored issues
show
Bug introduced by
The method method() does not seem to exist on object<Sonata\AdminBundl...ldDescriptionInterface>.

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

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

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

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

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

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

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

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

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

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

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

Loading history...
1499
            ->method('getValue')
1500
            ->willReturn('Foo');
1501
1502
        $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...
1503
            ->method('getFieldName')
1504
            ->willReturn('Foo_name');
1505
1506
        $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...
1507
            ->method('getType')
1508
            ->willReturn('nonexistent');
1509
1510
        $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...
1511
            ->method('getTemplate')
1512
            ->willReturn('@SonataAdmin/CRUD/list_nonexistent_template.html.twig');
1513
1514
        $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...
1515
            ->method('warning')
1516
            ->with(($this->stringStartsWith($this->removeExtraWhitespace(
1517
                'An error occured trying to load the template
1518
                "@SonataAdmin/CRUD/list_nonexistent_template.html.twig"
1519
                for the field "Foo_name", the default template
1520
                    "@SonataAdmin/CRUD/base_list_field.html.twig" was used
1521
                    instead.'
1522
            ))));
1523
1524
        $this->twigExtension->renderListElement($this->environment, $this->object, $this->fieldDescription);
1525
    }
1526
1527
    /**
1528
     * @group                    legacy
1529
     */
1530
    public function testRenderListElementErrorLoadingTemplate(): void
1531
    {
1532
        $this->expectException(LoaderError::class);
1533
        $this->expectExceptionMessage('Unable to find template "@SonataAdmin/CRUD/base_list_nonexistent_field.html.twig"');
1534
1535
        // NEXT_MAJOR: Remove this line
1536
        $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...
1537
            ->with('base_list_field')
1538
            ->willReturn('@SonataAdmin/CRUD/base_list_nonexistent_field.html.twig');
1539
1540
        $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...
1541
1542
        $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...
1543
            ->method('getTemplate')
1544
            ->willReturn('@SonataAdmin/CRUD/list_nonexistent_template.html.twig');
1545
1546
        $this->twigExtension->renderListElement($this->environment, $this->object, $this->fieldDescription);
1547
1548
        $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...
1549
    }
1550
1551
    /**
1552
     * @dataProvider getRenderViewElementTests
1553
     */
1554
    public function testRenderViewElement(string $expected, string $type, $value, array $options): void
1555
    {
1556
        $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...
1557
            ->method('getTemplate')
1558
            ->willReturn('@SonataAdmin/CRUD/base_show_field.html.twig');
1559
1560
        $this->fieldDescription
0 ignored issues
show
Bug introduced by
The method method() does not seem to exist on object<Sonata\AdminBundl...ldDescriptionInterface>.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Loading history...
2281
            ->method('getOptions')
2282
            ->willReturn($options);
2283
2284
        $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...
2285
            ->method('getTemplate')
2286
            ->willReturn('@SonataAdmin/CRUD/show_html.html.twig');
2287
2288
        $this->assertSame(
2289
            $this->removeExtraWhitespace($expected),
2290
            $this->removeExtraWhitespace(
2291
                $this->twigExtension->renderViewElement(
2292
                    $environment,
2293
                    $this->fieldDescription,
2294
                    $this->object
2295
                )
2296
            )
2297
        );
2298
    }
2299
2300
    /**
2301
     * NEXT_MAJOR: Remove this method.
2302
     */
2303
    public function getDeprecatedTextExtensionItems(): iterable
2304
    {
2305
        yield 'default_separator' => [
2306
            '<th>Data</th> <td> Creating a Template for the Field... </td>',
2307
            'html',
2308
            '<p><strong>Creating a Template for the Field</strong> and form</p>',
2309
            ['truncate' => ['preserve' => true, 'separator' => '...']],
2310
        ];
2311
2312
        yield 'custom_length' => [
2313
            '<th>Data</th> <td> Creating a Template[...] </td>',
2314
            'html',
2315
            '<p><strong>Creating a Template for the Field</strong> and form</p>',
2316
            [
2317
                'truncate' => [
2318
                    'length' => 20,
2319
                    'preserve' => true,
2320
                    'separator' => '[...]',
2321
                ],
2322
            ],
2323
        ];
2324
    }
2325
2326
    /**
2327
     * NEXT_MAJOR: Remove this test.
2328
     *
2329
     * @group legacy
2330
     */
2331
    public function testGetValueFromFieldDescription(): void
2332
    {
2333
        $object = new \stdClass();
2334
        $fieldDescription = $this->getMockForAbstractClass(FieldDescriptionInterface::class);
2335
2336
        $fieldDescription
2337
            ->method('getValue')
2338
            ->willReturn('test123');
2339
2340
        $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...
2341
    }
2342
2343
    /**
2344
     * NEXT_MAJOR: Remove this test.
2345
     *
2346
     * @group legacy
2347
     */
2348
    public function testGetValueFromFieldDescriptionWithRemoveLoopException(): void
2349
    {
2350
        $object = $this->createMock(\ArrayAccess::class);
2351
        $fieldDescription = $this->getMockForAbstractClass(FieldDescriptionInterface::class);
2352
2353
        $this->expectException(\RuntimeException::class);
2354
        $this->expectExceptionMessage('remove the loop requirement');
2355
2356
        $this->assertSame(
2357
            'anything',
2358
            $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...
2359
        );
2360
    }
2361
2362
    /**
2363
     * NEXT_MAJOR: Remove this test.
2364
     *
2365
     * @group legacy
2366
     * @expectedDeprecation Accessing a non existing value is deprecated since sonata-project/admin-bundle 3.67 and will throw an exception in 4.0.
2367
     */
2368
    public function testGetValueFromFieldDescriptionWithNoValueException(): void
2369
    {
2370
        $object = new \stdClass();
2371
        $fieldDescription = $this->getMockForAbstractClass(FieldDescriptionInterface::class);
2372
2373
        $fieldDescription
2374
            ->method('getValue')
2375
            ->willReturnCallback(static function (): void {
2376
                throw new NoValueException();
2377
            });
2378
2379
        $fieldDescription
2380
            ->method('getAssociationAdmin')
2381
            ->willReturn(null);
2382
2383
        $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...
2384
    }
2385
2386
    /**
2387
     * NEXT_MAJOR: Remove this test.
2388
     *
2389
     * @group legacy
2390
     */
2391
    public function testGetValueFromFieldDescriptionWithNoValueExceptionNewAdminInstance(): void
2392
    {
2393
        $object = new \stdClass();
2394
        $fieldDescription = $this->getMockForAbstractClass(FieldDescriptionInterface::class);
2395
2396
        $fieldDescription
2397
            ->method('getValue')
2398
            ->willReturnCallback(static function (): void {
2399
                throw new NoValueException();
2400
            });
2401
2402
        $fieldDescription
2403
            ->method('getAssociationAdmin')
2404
            ->willReturn($this->admin);
2405
2406
        $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...
2407
            ->method('getNewInstance')
2408
            ->willReturn('foo');
2409
2410
        $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...
2411
    }
2412
2413
    /**
2414
     * @group legacy
2415
     */
2416
    public function testOutput(): void
2417
    {
2418
        $this->fieldDescription
0 ignored issues
show
Bug introduced by
The method method() does not seem to exist on object<Sonata\AdminBundl...ldDescriptionInterface>.

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

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

Loading history...
2419
            ->method('getTemplate')
2420
            ->willReturn('@SonataAdmin/CRUD/base_list_field.html.twig');
2421
2422
        $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...
2423
            ->method('getFieldName')
2424
            ->willReturn('fd_name');
2425
2426
        $this->environment->disableDebug();
2427
2428
        $parameters = [
2429
            'admin' => $this->admin,
2430
            'value' => 'foo',
2431
            'field_description' => $this->fieldDescription,
2432
            'object' => $this->object,
2433
        ];
2434
2435
        $template = $this->environment->loadTemplate('@SonataAdmin/CRUD/base_list_field.html.twig');
2436
2437
        $this->assertSame(
2438
            '<td class="sonata-ba-list-field sonata-ba-list-field-" objectId="12345"> foo </td>',
2439
            $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...
2440
                $this->fieldDescription,
2441
                $template,
2442
                $parameters,
2443
                $this->environment
2444
            ))
2445
        );
2446
2447
        $this->environment->enableDebug();
2448
        $this->assertSame(
2449
            $this->removeExtraWhitespace(
2450
                <<<'EOT'
2451
<!-- START
2452
    fieldName: fd_name
2453
    template: @SonataAdmin/CRUD/base_list_field.html.twig
2454
    compiled template: @SonataAdmin/CRUD/base_list_field.html.twig
2455
-->
2456
    <td class="sonata-ba-list-field sonata-ba-list-field-" objectId="12345"> foo </td>
2457
<!-- END - fieldName: fd_name -->
2458
EOT
2459
            ),
2460
            $this->removeExtraWhitespace(
2461
                $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...
2462
            )
2463
        );
2464
    }
2465
2466
    /**
2467
     * @group legacy
2468
     * @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).
2469
     */
2470
    public function testRenderWithDebug(): void
2471
    {
2472
        $this->fieldDescription
0 ignored issues
show
Bug introduced by
The method method() does not seem to exist on object<Sonata\AdminBundl...ldDescriptionInterface>.

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

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

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

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

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

Loading history...
2477
            ->method('getFieldName')
2478
            ->willReturn('fd_name');
2479
2480
        $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...
2481
            ->method('getValue')
2482
            ->willReturn('foo');
2483
2484
        $parameters = [
2485
            'admin' => $this->admin,
2486
            'value' => 'foo',
2487
            'field_description' => $this->fieldDescription,
2488
            'object' => $this->object,
2489
        ];
2490
2491
        $this->environment->enableDebug();
2492
2493
        $this->assertSame(
2494
            $this->removeExtraWhitespace(
2495
                <<<'EOT'
2496
<!-- START
2497
    fieldName: fd_name
2498
    template: @SonataAdmin/CRUD/base_list_field.html.twig
2499
    compiled template: @SonataAdmin/CRUD/base_list_field.html.twig
2500
-->
2501
    <td class="sonata-ba-list-field sonata-ba-list-field-" objectId="12345"> foo </td>
2502
<!-- END - fieldName: fd_name -->
2503
EOT
2504
            ),
2505
            $this->removeExtraWhitespace(
2506
                $this->twigExtension->renderListElement($this->environment, $this->object, $this->fieldDescription, $parameters)
2507
            )
2508
        );
2509
    }
2510
2511
    public function testRenderRelationElementNoObject(): void
2512
    {
2513
        $this->assertSame('foo', $this->twigExtension->renderRelationElement('foo', $this->fieldDescription));
2514
    }
2515
2516
    public function testRenderRelationElementToString(): void
2517
    {
2518
        $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...
2519
            ->method('getOption')
2520
            ->willReturnCallback(static function ($value, $default = null) {
2521
                if ('associated_property' === $value) {
2522
                    return $default;
2523
                }
2524
            });
2525
2526
        $element = new FooToString();
2527
        $this->assertSame('salut', $this->twigExtension->renderRelationElement($element, $this->fieldDescription));
2528
    }
2529
2530
    /**
2531
     * @group legacy
2532
     */
2533
    public function testDeprecatedRelationElementToString(): void
2534
    {
2535
        $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...
2536
            ->method('getOption')
2537
            ->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...
2538
                if ('associated_tostring' === $value) {
2539
                    return '__toString';
2540
                }
2541
            });
2542
2543
        $element = new FooToString();
2544
        $this->assertSame(
2545
            'salut',
2546
            $this->twigExtension->renderRelationElement($element, $this->fieldDescription)
2547
        );
2548
    }
2549
2550
    /**
2551
     * @group legacy
2552
     */
2553
    public function testRenderRelationElementCustomToString(): void
2554
    {
2555
        $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...
2556
            ->method('getOption')
2557
            ->willReturnCallback(static function ($value, $default = null) {
2558
                if ('associated_property' === $value) {
2559
                    return $default;
2560
                }
2561
2562
                if ('associated_tostring' === $value) {
2563
                    return 'customToString';
2564
                }
2565
            });
2566
2567
        $element = $this->getMockBuilder(\stdClass::class)
2568
            ->setMethods(['customToString'])
2569
            ->getMock();
2570
        $element
2571
            ->method('customToString')
2572
            ->willReturn('fooBar');
2573
2574
        $this->assertSame('fooBar', $this->twigExtension->renderRelationElement($element, $this->fieldDescription));
2575
    }
2576
2577
    /**
2578
     * @group legacy
2579
     */
2580
    public function testRenderRelationElementMethodNotExist(): void
2581
    {
2582
        $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...
2583
            ->method('getOption')
2584
2585
            ->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...
2586
                if ('associated_tostring' === $value) {
2587
                    return 'nonExistedMethod';
2588
                }
2589
            });
2590
2591
        $element = new \stdClass();
2592
        $this->expectException(\RuntimeException::class);
2593
        $this->expectExceptionMessage('You must define an `associated_property` option or create a `stdClass::__toString');
2594
2595
        $this->twigExtension->renderRelationElement($element, $this->fieldDescription);
2596
    }
2597
2598
    public function testRenderRelationElementWithPropertyPath(): void
2599
    {
2600
        $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...
2601
            ->method('getOption')
2602
2603
            ->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...
2604
                if ('associated_property' === $value) {
2605
                    return 'foo';
2606
                }
2607
            });
2608
2609
        $element = new \stdClass();
2610
        $element->foo = 'bar';
2611
2612
        $this->assertSame('bar', $this->twigExtension->renderRelationElement($element, $this->fieldDescription));
2613
    }
2614
2615
    public function testRenderRelationElementWithClosure(): void
2616
    {
2617
        $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...
2618
            ->method('getOption')
2619
2620
            ->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...
2621
                if ('associated_property' === $value) {
2622
                    return static function ($element): string {
2623
                        return sprintf('closure %s', $element->foo);
2624
                    };
2625
                }
2626
            });
2627
2628
        $element = new \stdClass();
2629
        $element->foo = 'bar';
2630
2631
        $this->assertSame(
2632
            'closure bar',
2633
            $this->twigExtension->renderRelationElement($element, $this->fieldDescription)
2634
        );
2635
    }
2636
2637
    public function testGetUrlsafeIdentifier(): void
2638
    {
2639
        $model = new \stdClass();
2640
2641
        // set admin to pool
2642
        $this->pool->setAdminServiceIds(['sonata_admin_foo_service']);
2643
        $this->pool->setAdminClasses([\stdClass::class => ['sonata_admin_foo_service']]);
2644
2645
        $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...
2646
            ->method('getUrlSafeIdentifier')
2647
            ->with($this->equalTo($model))
2648
            ->willReturn(1234567);
2649
2650
        $this->assertSame(1234567, $this->twigExtension->getUrlSafeIdentifier($model));
2651
    }
2652
2653
    public function testGetUrlsafeIdentifier_GivenAdmin_Foo(): void
2654
    {
2655
        $model = new \stdClass();
2656
2657
        // set admin to pool
2658
        $this->pool->setAdminServiceIds([
2659
            'sonata_admin_foo_service',
2660
            'sonata_admin_bar_service',
2661
        ]);
2662
        $this->pool->setAdminClasses([\stdClass::class => [
2663
            'sonata_admin_foo_service',
2664
            'sonata_admin_bar_service',
2665
        ]]);
2666
2667
        $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...
2668
            ->method('getUrlSafeIdentifier')
2669
            ->with($this->equalTo($model))
2670
            ->willReturn(1234567);
2671
2672
        $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...
2673
            ->method('getUrlSafeIdentifier');
2674
2675
        $this->assertSame(1234567, $this->twigExtension->getUrlSafeIdentifier($model, $this->admin));
2676
    }
2677
2678
    public function testGetUrlsafeIdentifier_GivenAdmin_Bar(): void
2679
    {
2680
        $model = new \stdClass();
2681
2682
        // set admin to pool
2683
        $this->pool->setAdminServiceIds(['sonata_admin_foo_service', 'sonata_admin_bar_service']);
2684
        $this->pool->setAdminClasses([\stdClass::class => [
2685
            'sonata_admin_foo_service',
2686
            'sonata_admin_bar_service',
2687
        ]]);
2688
2689
        $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...
2690
            ->method('getUrlSafeIdentifier');
2691
2692
        $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...
2693
            ->method('getUrlSafeIdentifier')
2694
            ->with($this->equalTo($model))
2695
            ->willReturn(1234567);
2696
2697
        $this->assertSame(1234567, $this->twigExtension->getUrlSafeIdentifier($model, $this->adminBar));
2698
    }
2699
2700
    public function xEditableChoicesProvider()
2701
    {
2702
        return [
2703
            'needs processing' => [
2704
                ['choices' => ['Status1' => 'Alias1', 'Status2' => 'Alias2']],
2705
                [
2706
                    ['value' => 'Status1', 'text' => 'Alias1'],
2707
                    ['value' => 'Status2', 'text' => 'Alias2'],
2708
                ],
2709
            ],
2710
            'already processed' => [
2711
                ['choices' => [
2712
                    ['value' => 'Status1', 'text' => 'Alias1'],
2713
                    ['value' => 'Status2', 'text' => 'Alias2'],
2714
                ]],
2715
                [
2716
                    ['value' => 'Status1', 'text' => 'Alias1'],
2717
                    ['value' => 'Status2', 'text' => 'Alias2'],
2718
                ],
2719
            ],
2720
            'not required' => [
2721
                [
2722
                    'required' => false,
2723
                    'choices' => ['' => '', 'Status1' => 'Alias1', 'Status2' => 'Alias2'],
2724
                ],
2725
                [
2726
                    ['value' => '', 'text' => ''],
2727
                    ['value' => 'Status1', 'text' => 'Alias1'],
2728
                    ['value' => 'Status2', 'text' => 'Alias2'],
2729
                ],
2730
            ],
2731
            'not required multiple' => [
2732
                [
2733
                    'required' => false,
2734
                    'multiple' => true,
2735
                    'choices' => ['Status1' => 'Alias1', 'Status2' => 'Alias2'],
2736
                ],
2737
                [
2738
                    ['value' => 'Status1', 'text' => 'Alias1'],
2739
                    ['value' => 'Status2', 'text' => 'Alias2'],
2740
                ],
2741
            ],
2742
        ];
2743
    }
2744
2745
    /**
2746
     * @dataProvider xEditablechoicesProvider
2747
     */
2748
    public function testGetXEditableChoicesIsIdempotent(array $options, array $expectedChoices): void
2749
    {
2750
        $fieldDescription = $this->getMockForAbstractClass(FieldDescriptionInterface::class);
2751
        $fieldDescription
2752
            ->method('getOption')
2753
            ->withConsecutive(
2754
                ['choices', []],
2755
                ['catalogue'],
2756
                ['required'],
2757
                ['multiple']
2758
            )
2759
            ->will($this->onConsecutiveCalls(
2760
                $options['choices'],
2761
                'MyCatalogue',
2762
                $options['multiple'] ?? null
2763
            ));
2764
2765
        $this->assertSame($expectedChoices, $this->twigExtension->getXEditableChoices($fieldDescription));
2766
    }
2767
2768
    public function select2LocalesProvider()
2769
    {
2770
        return [
2771
            ['ar', 'ar'],
2772
            ['az', 'az'],
2773
            ['bg', 'bg'],
2774
            ['ca', 'ca'],
2775
            ['cs', 'cs'],
2776
            ['da', 'da'],
2777
            ['de', 'de'],
2778
            ['el', 'el'],
2779
            [null, 'en'],
2780
            ['es', 'es'],
2781
            ['et', 'et'],
2782
            ['eu', 'eu'],
2783
            ['fa', 'fa'],
2784
            ['fi', 'fi'],
2785
            ['fr', 'fr'],
2786
            ['gl', 'gl'],
2787
            ['he', 'he'],
2788
            ['hr', 'hr'],
2789
            ['hu', 'hu'],
2790
            ['id', 'id'],
2791
            ['is', 'is'],
2792
            ['it', 'it'],
2793
            ['ja', 'ja'],
2794
            ['ka', 'ka'],
2795
            ['ko', 'ko'],
2796
            ['lt', 'lt'],
2797
            ['lv', 'lv'],
2798
            ['mk', 'mk'],
2799
            ['ms', 'ms'],
2800
            ['nb', 'nb'],
2801
            ['nl', 'nl'],
2802
            ['pl', 'pl'],
2803
            ['pt-PT', 'pt'],
2804
            ['pt-BR', 'pt-BR'],
2805
            ['pt-PT', 'pt-PT'],
2806
            ['ro', 'ro'],
2807
            ['rs', 'rs'],
2808
            ['ru', 'ru'],
2809
            ['sk', 'sk'],
2810
            ['sv', 'sv'],
2811
            ['th', 'th'],
2812
            ['tr', 'tr'],
2813
            ['ug-CN', 'ug'],
2814
            ['ug-CN', 'ug-CN'],
2815
            ['uk', 'uk'],
2816
            ['vi', 'vi'],
2817
            ['zh-CN', 'zh'],
2818
            ['zh-CN', 'zh-CN'],
2819
            ['zh-TW', 'zh-TW'],
2820
        ];
2821
    }
2822
2823
    /**
2824
     * @dataProvider select2LocalesProvider
2825
     */
2826
    public function testCanonicalizedLocaleForSelect2(?string $expected, string $original): void
2827
    {
2828
        $this->assertSame($expected, $this->twigExtension->getCanonicalizedLocaleForSelect2($this->mockExtensionContext($original)));
2829
    }
2830
2831
    public function momentLocalesProvider(): array
2832
    {
2833
        return [
2834
            ['af', 'af'],
2835
            ['ar-dz', 'ar-dz'],
2836
            ['ar', 'ar'],
2837
            ['ar-ly', 'ar-ly'],
2838
            ['ar-ma', 'ar-ma'],
2839
            ['ar-sa', 'ar-sa'],
2840
            ['ar-tn', 'ar-tn'],
2841
            ['az', 'az'],
2842
            ['be', 'be'],
2843
            ['bg', 'bg'],
2844
            ['bn', 'bn'],
2845
            ['bo', 'bo'],
2846
            ['br', 'br'],
2847
            ['bs', 'bs'],
2848
            ['ca', 'ca'],
2849
            ['cs', 'cs'],
2850
            ['cv', 'cv'],
2851
            ['cy', 'cy'],
2852
            ['da', 'da'],
2853
            ['de-at', 'de-at'],
2854
            ['de', 'de'],
2855
            ['de', 'de-de'],
2856
            ['dv', 'dv'],
2857
            ['el', 'el'],
2858
            [null, 'en'],
2859
            [null, 'en-us'],
2860
            ['en-au', 'en-au'],
2861
            ['en-ca', 'en-ca'],
2862
            ['en-gb', 'en-gb'],
2863
            ['en-ie', 'en-ie'],
2864
            ['en-nz', 'en-nz'],
2865
            ['eo', 'eo'],
2866
            ['es-do', 'es-do'],
2867
            ['es', 'es-ar'],
2868
            ['es', 'es-mx'],
2869
            ['es', 'es'],
2870
            ['et', 'et'],
2871
            ['eu', 'eu'],
2872
            ['fa', 'fa'],
2873
            ['fi', 'fi'],
2874
            ['fo', 'fo'],
2875
            ['fr-ca', 'fr-ca'],
2876
            ['fr-ch', 'fr-ch'],
2877
            ['fr', 'fr-fr'],
2878
            ['fr', 'fr'],
2879
            ['fy', 'fy'],
2880
            ['gd', 'gd'],
2881
            ['gl', 'gl'],
2882
            ['he', 'he'],
2883
            ['hi', 'hi'],
2884
            ['hr', 'hr'],
2885
            ['hu', 'hu'],
2886
            ['hy-am', 'hy-am'],
2887
            ['id', 'id'],
2888
            ['is', 'is'],
2889
            ['it', 'it'],
2890
            ['ja', 'ja'],
2891
            ['jv', 'jv'],
2892
            ['ka', 'ka'],
2893
            ['kk', 'kk'],
2894
            ['km', 'km'],
2895
            ['ko', 'ko'],
2896
            ['ky', 'ky'],
2897
            ['lb', 'lb'],
2898
            ['lo', 'lo'],
2899
            ['lt', 'lt'],
2900
            ['lv', 'lv'],
2901
            ['me', 'me'],
2902
            ['mi', 'mi'],
2903
            ['mk', 'mk'],
2904
            ['ml', 'ml'],
2905
            ['mr', 'mr'],
2906
            ['ms', 'ms'],
2907
            ['ms-my', 'ms-my'],
2908
            ['my', 'my'],
2909
            ['nb', 'nb'],
2910
            ['ne', 'ne'],
2911
            ['nl-be', 'nl-be'],
2912
            ['nl', 'nl'],
2913
            ['nl', 'nl-nl'],
2914
            ['nn', 'nn'],
2915
            ['pa-in', 'pa-in'],
2916
            ['pl', 'pl'],
2917
            ['pt-br', 'pt-br'],
2918
            ['pt', 'pt'],
2919
            ['ro', 'ro'],
2920
            ['ru', 'ru'],
2921
            ['se', 'se'],
2922
            ['si', 'si'],
2923
            ['sk', 'sk'],
2924
            ['sl', 'sl'],
2925
            ['sq', 'sq'],
2926
            ['sr-cyrl', 'sr-cyrl'],
2927
            ['sr', 'sr'],
2928
            ['ss', 'ss'],
2929
            ['sv', 'sv'],
2930
            ['sw', 'sw'],
2931
            ['ta', 'ta'],
2932
            ['te', 'te'],
2933
            ['tet', 'tet'],
2934
            ['th', 'th'],
2935
            ['tlh', 'tlh'],
2936
            ['tl-ph', 'tl-ph'],
2937
            ['tr', 'tr'],
2938
            ['tzl', 'tzl'],
2939
            ['tzm', 'tzm'],
2940
            ['tzm-latn', 'tzm-latn'],
2941
            ['uk', 'uk'],
2942
            ['uz', 'uz'],
2943
            ['vi', 'vi'],
2944
            ['x-pseudo', 'x-pseudo'],
2945
            ['yo', 'yo'],
2946
            ['zh-cn', 'zh-cn'],
2947
            ['zh-hk', 'zh-hk'],
2948
            ['zh-tw', 'zh-tw'],
2949
        ];
2950
    }
2951
2952
    /**
2953
     * @dataProvider momentLocalesProvider
2954
     */
2955
    public function testCanonicalizedLocaleForMoment(?string $expected, string $original): void
2956
    {
2957
        $this->assertSame($expected, $this->twigExtension->getCanonicalizedLocaleForMoment($this->mockExtensionContext($original)));
2958
    }
2959
2960
    public function testIsGrantedAffirmative(): void
2961
    {
2962
        $this->assertTrue(
2963
            $this->twigExtension->isGrantedAffirmative(['foo', 'bar'])
2964
        );
2965
        $this->assertTrue($this->twigExtension->isGrantedAffirmative('foo'));
2966
        $this->assertTrue($this->twigExtension->isGrantedAffirmative('bar'));
2967
    }
2968
2969
    /**
2970
     * @dataProvider getRenderViewElementCompareTests
2971
     */
2972
    public function testRenderViewElementCompare(string $expected, string $type, $value, array $options, ?string $objectName = null): void
2973
    {
2974
        $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...
2975
            ->method('getTemplate')
2976
            ->willReturn('@SonataAdmin/CRUD/base_show_compare.html.twig');
2977
2978
        $this->fieldDescription
0 ignored issues
show
Bug introduced by
The method method() does not seem to exist on object<Sonata\AdminBundl...ldDescriptionInterface>.

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

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

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

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

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

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

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

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

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