Completed
Push — 3.x ( 871dd6...595a7a )
by Marko
05:19
created

SonataAdminExtensionTest   F

Complexity

Total Complexity 75

Size/Duplication

Total Lines 2620
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 19

Importance

Changes 0
Metric Value
wmc 75
lcom 1
cbo 19
dl 0
loc 2620
rs 1.2
c 0
b 0
f 0

35 Methods

Rating   Name   Duplication   Size   Complexity  
B setUp() 0 148 4
D testRenderListElement() 0 83 16
A testDeprecatedRenderListElement() 0 45 2
A getDeprecatedRenderListElementTests() 0 15 1
B getRenderListElementTests() 0 912 1
A testRenderListElementNonExistentTemplate() 0 37 1
A testRenderListElementErrorLoadingTemplate() 0 20 1
C testRenderViewElement() 0 68 14
B getRenderViewElementTests() 0 551 1
A testGetValueFromFieldDescription() 0 11 1
A testGetValueFromFieldDescriptionWithRemoveLoopException() 0 12 1
A testGetValueFromFieldDescriptionWithNoValueException() 0 17 1
A testGetValueFromFieldDescriptionWithNoValueExceptionNewAdminInstance() 0 21 1
A testOutput() 0 48 1
A testRenderWithDebug() 0 39 1
A testRenderRelationElementNoObject() 0 4 1
A testRenderRelationElementToString() 0 13 2
A testDeprecatedRelationElementToString() 0 16 2
A testRenderRelationElementCustomToString() 0 23 3
A testRenderRelationElementMethodNotExist() 0 16 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 2
A select2LocalesProvider() 0 54 1
A testCanonicalizedLocaleForSelect2() 0 4 1
B momentLocalesProvider() 0 118 1
A testCanonicalizedLocaleForMoment() 0 4 1
A testIsGrantedAffirmative() 0 8 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
/*
4
 * This file is part of the Sonata Project package.
5
 *
6
 * (c) Thomas Rabaix <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Sonata\AdminBundle\Tests\Twig\Extension;
13
14
use PHPUnit\Framework\TestCase;
15
use Prophecy\Argument;
16
use Psr\Log\LoggerInterface;
17
use Sonata\AdminBundle\Admin\AbstractAdmin;
18
use Sonata\AdminBundle\Admin\AdminInterface;
19
use Sonata\AdminBundle\Admin\FieldDescriptionInterface;
20
use Sonata\AdminBundle\Admin\Pool;
21
use Sonata\AdminBundle\Exception\NoValueException;
22
use Sonata\AdminBundle\Templating\TemplateRegistryInterface;
23
use Sonata\AdminBundle\Tests\Fixtures\Entity\FooToString;
24
use Sonata\AdminBundle\Twig\Extension\SonataAdminExtension;
25
use Symfony\Bridge\Twig\AppVariable;
26
use Symfony\Bridge\Twig\Extension\RoutingExtension;
27
use Symfony\Bridge\Twig\Extension\TranslationExtension;
28
use Symfony\Bridge\Twig\Tests\Extension\Fixtures\StubFilesystemLoader;
29
use Symfony\Component\Config\FileLocator;
30
use Symfony\Component\DependencyInjection\ContainerInterface;
31
use Symfony\Component\HttpFoundation\Request;
32
use Symfony\Component\Routing\Generator\UrlGenerator;
33
use Symfony\Component\Routing\Loader\XmlFileLoader;
34
use Symfony\Component\Routing\RequestContext;
35
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
36
use Symfony\Component\Translation\DependencyInjection\TranslationDumperPass;
37
use Symfony\Component\Translation\Loader\XliffFileLoader;
38
use Symfony\Component\Translation\MessageSelector;
39
use Symfony\Component\Translation\Translator;
40
use Symfony\Component\Translation\TranslatorInterface;
41
42
/**
43
 * Test for SonataAdminExtension.
44
 *
45
 * @author Andrej Hudec <[email protected]>
46
 */
47
class SonataAdminExtensionTest extends TestCase
48
{
49
    /**
50
     * @var SonataAdminExtension
51
     */
52
    private $twigExtension;
53
54
    /**
55
     * @var \Twig_Environment
56
     */
57
    private $environment;
58
59
    /**
60
     * @var AdminInterface
61
     */
62
    private $admin;
63
64
    /**
65
     * @var AdminInterface
66
     */
67
    private $adminBar;
68
69
    /**
70
     * @var FieldDescriptionInterface
71
     */
72
    private $fieldDescription;
73
74
    /**
75
     * @var \stdClass
76
     */
77
    private $object;
78
79
    /**
80
     * @var Pool
81
     */
82
    private $pool;
83
84
    /**
85
     * @var LoggerInterface
86
     */
87
    private $logger;
88
89
    /**
90
     * @var string[]
91
     */
92
    private $xEditableTypeMapping;
93
94
    /**
95
     * @var TranslatorInterface
96
     */
97
    private $translator;
98
99
    /**
100
     * @var ContainerInterface
101
     */
102
    private $container;
103
104
    /**
105
     * @var TemplateRegistryInterface
106
     */
107
    private $templateRegistry;
108
109
    /**
110
     * @var AuthorizationCheckerInterface
111
     */
112
    private $securityChecker;
113
114
    public function setUp()
115
    {
116
        date_default_timezone_set('Europe/London');
117
118
        $container = $this->getMockForAbstractClass(ContainerInterface::class);
119
120
        $this->pool = new Pool($container, '', '');
121
        $this->pool->setAdminServiceIds(['sonata_admin_foo_service']);
122
        $this->pool->setAdminClasses(['fooClass' => ['sonata_admin_foo_service']]);
123
124
        $this->logger = $this->getMockForAbstractClass(LoggerInterface::class);
125
        $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...
126
            'choice' => 'select',
127
            'boolean' => 'select',
128
            'text' => 'text',
129
            'textarea' => 'textarea',
130
            'html' => 'textarea',
131
            'email' => 'email',
132
            'string' => 'text',
133
            'smallint' => 'text',
134
            'bigint' => 'text',
135
            'integer' => 'number',
136
            'decimal' => 'number',
137
            'currency' => 'number',
138
            'percent' => 'number',
139
            'url' => 'url',
140
        ];
141
142
        // translation extension
143
        $translator = new Translator(
144
            'en',
145
            // NEXT_MAJOR: simplify this when dropping symfony < 3.4
146
            class_exists(TranslationDumperPass::class) ? null : new MessageSelector()
0 ignored issues
show
Documentation introduced by
class_exists(\Symfony\Co...ation\MessageSelector() is of type object<Symfony\Component...lation\MessageSelector>, but the function expects a null|object<Symfony\Comp...sageFormatterInterface>.

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

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

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

function acceptsInteger($int) { }

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

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
147
        );
148
        $translator->addLoader('xlf', new XliffFileLoader());
149
        $translator->addResource(
150
            'xlf',
151
            __DIR__.'/../../../src/Resources/translations/SonataAdminBundle.en.xliff',
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, $this->logger, $this->translator, $this->container->reveal(), $this->securityChecker->reveal()
168
        );
169
        $this->twigExtension->setXEditableTypeMapping($this->xEditableTypeMapping);
170
171
        $request = $this->createMock(Request::class);
172
        $request->expects($this->any())->method('get')->with('_sonata_admin')->willReturn('sonata_admin_foo_service');
173
174
        $loader = new StubFilesystemLoader([
175
            __DIR__.'/../../../src/Resources/views/CRUD',
176
        ]);
177
        $loader->addPath(__DIR__.'/../../../src/Resources/views/', 'SonataAdmin');
178
179
        $this->environment = new \Twig_Environment($loader, [
180
            'strict_variables' => true,
181
            'cache' => false,
182
            'autoescape' => 'html',
183
            'optimizations' => 0,
184
        ]);
185
        $this->environment->addExtension($this->twigExtension);
186
        $this->environment->addExtension(new TranslationExtension($translator));
187
        $this->environment->addExtension(new FakeTemplateRegistryExtension());
188
189
        // routing extension
190
        $xmlFileLoader = new XmlFileLoader(new FileLocator([__DIR__.'/../../../src/Resources/config/routing']));
191
        $routeCollection = $xmlFileLoader->load('sonata_admin.xml');
192
193
        $xmlFileLoader = new XmlFileLoader(new FileLocator([__DIR__.'/../../Fixtures/Resources/config/routing']));
194
        $testRouteCollection = $xmlFileLoader->load('routing.xml');
195
196
        $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...
197
        $requestContext = new RequestContext();
198
        $urlGenerator = new UrlGenerator($routeCollection, $requestContext);
199
        $this->environment->addExtension(new RoutingExtension($urlGenerator));
200
        $this->environment->addExtension(new \Twig_Extensions_Extension_Text());
201
202
        // initialize object
203
        $this->object = new \stdClass();
204
205
        // initialize admin
206
        $this->admin = $this->createMock(AbstractAdmin::class);
207
208
        $this->admin->expects($this->any())
209
            ->method('getCode')
210
            ->will($this->returnValue('sonata_admin_foo_service'));
211
212
        $this->admin->expects($this->any())
213
            ->method('id')
214
            ->with($this->equalTo($this->object))
215
            ->will($this->returnValue(12345));
216
217
        $this->admin->expects($this->any())
218
            ->method('getNormalizedIdentifier')
219
            ->with($this->equalTo($this->object))
220
            ->will($this->returnValue(12345));
221
222
        $this->admin->expects($this->any())
223
            ->method('trans')
224
            ->will($this->returnCallback(function ($id, $parameters = [], $domain = null) use ($translator) {
225
                return $translator->trans($id, $parameters, $domain);
226
            }));
227
228
        $this->adminBar = $this->createMock(AbstractAdmin::class);
229
        $this->adminBar->expects($this->any())
230
            ->method('hasAccess')
231
            ->will($this->returnValue(true));
232
        $this->adminBar->expects($this->any())
233
            ->method('getNormalizedIdentifier')
234
            ->with($this->equalTo($this->object))
235
            ->will($this->returnValue(12345));
236
237
        $container->expects($this->any())
238
            ->method('get')
239
            ->will($this->returnCallback(function ($id) {
240
                if ('sonata_admin_foo_service' == $id) {
241
                    return $this->admin;
242
                } elseif ('sonata_admin_bar_service' == $id) {
243
                    return $this->adminBar;
244
                }
245
            }));
246
247
        // initialize field description
248
        $this->fieldDescription = $this->getMockForAbstractClass(FieldDescriptionInterface::class);
249
250
        $this->fieldDescription->expects($this->any())
251
            ->method('getName')
252
            ->will($this->returnValue('fd_name'));
253
254
        $this->fieldDescription->expects($this->any())
255
            ->method('getAdmin')
256
            ->will($this->returnValue($this->admin));
257
258
        $this->fieldDescription->expects($this->any())
259
            ->method('getLabel')
260
            ->will($this->returnValue('Data'));
261
    }
262
263
    /**
264
     * @group legacy
265
     * @expectedDeprecation The Sonata\AdminBundle\Admin\AbstractAdmin::getTemplate method is deprecated (since 3.34, will be dropped in 4.0. Use TemplateRegistry services instead).
266
     * @dataProvider getRenderListElementTests
267
     */
268
    public function testRenderListElement($expected, $type, $value, array $options)
269
    {
270
        $this->admin->expects($this->any())
0 ignored issues
show
Bug introduced by
The method expects() does not seem to exist on object<Sonata\AdminBundle\Admin\AdminInterface>.

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

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

Loading history...
271
            ->method('getPersistentParameters')
272
            ->will($this->returnValue(['context' => 'foo']));
273
274
        $this->admin->expects($this->any())
0 ignored issues
show
Bug introduced by
The method expects() does not seem to exist on object<Sonata\AdminBundle\Admin\AdminInterface>.

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

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

Loading history...
275
            ->method('hasAccess')
276
            ->will($this->returnValue(true));
277
278
        // NEXT_MAJOR: Remove this line
279
        $this->admin->expects($this->any())
0 ignored issues
show
Bug introduced by
The method expects() does not seem to exist on object<Sonata\AdminBundle\Admin\AdminInterface>.

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

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

Loading history...
280
            ->method('getTemplate')
281
            ->with('base_list_field')
282
            ->willReturn('@SonataAdmin/CRUD/base_list_field.html.twig');
283
284
        $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...
285
286
        $this->fieldDescription->expects($this->any())
0 ignored issues
show
Bug introduced by
The method expects() does not seem to exist on object<Sonata\AdminBundl...ldDescriptionInterface>.

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

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

Loading history...
287
            ->method('getValue')
288
            ->will($this->returnValue($value));
289
290
        $this->fieldDescription->expects($this->any())
0 ignored issues
show
Bug introduced by
The method expects() does not seem to exist on object<Sonata\AdminBundl...ldDescriptionInterface>.

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

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

Loading history...
291
            ->method('getType')
292
            ->will($this->returnValue($type));
293
294
        $this->fieldDescription->expects($this->any())
0 ignored issues
show
Bug introduced by
The method expects() does not seem to exist on object<Sonata\AdminBundl...ldDescriptionInterface>.

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

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

Loading history...
295
            ->method('getOptions')
296
            ->will($this->returnValue($options));
297
298
        $this->fieldDescription->expects($this->any())
0 ignored issues
show
Bug introduced by
The method expects() does not seem to exist on object<Sonata\AdminBundl...ldDescriptionInterface>.

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

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

Loading history...
299
            ->method('getOption')
300
            ->will($this->returnCallback(function ($name, $default = null) use ($options) {
301
                return isset($options[$name]) ? $options[$name] : $default;
302
            }));
303
304
        $this->fieldDescription->expects($this->any())
0 ignored issues
show
Bug introduced by
The method expects() does not seem to exist on object<Sonata\AdminBundl...ldDescriptionInterface>.

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

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

Loading history...
305
            ->method('getTemplate')
306
            ->will($this->returnCallback(function () use ($type) {
307
                switch ($type) {
308
                    case 'string':
309
                        return '@SonataAdmin/CRUD/list_string.html.twig';
310
                    case 'boolean':
311
                        return '@SonataAdmin/CRUD/list_boolean.html.twig';
312
                    case 'datetime':
313
                        return '@SonataAdmin/CRUD/list_datetime.html.twig';
314
                    case 'date':
315
                        return '@SonataAdmin/CRUD/list_date.html.twig';
316
                    case 'time':
317
                        return '@SonataAdmin/CRUD/list_time.html.twig';
318
                    case 'currency':
319
                        return '@SonataAdmin/CRUD/list_currency.html.twig';
320
                    case 'percent':
321
                        return '@SonataAdmin/CRUD/list_percent.html.twig';
322
                    case 'email':
323
                        return '@SonataAdmin/CRUD/list_email.html.twig';
324
                    case 'choice':
325
                        return '@SonataAdmin/CRUD/list_choice.html.twig';
326
                    case 'array':
327
                        return '@SonataAdmin/CRUD/list_array.html.twig';
328
                    case 'trans':
329
                        return '@SonataAdmin/CRUD/list_trans.html.twig';
330
                    case 'url':
331
                        return '@SonataAdmin/CRUD/list_url.html.twig';
332
                    case 'html':
333
                        return '@SonataAdmin/CRUD/list_html.html.twig';
334
                    case 'nonexistent':
335
                        // template doesn`t exist
336
                        return '@SonataAdmin/CRUD/list_nonexistent_template.html.twig';
337
                    default:
338
                        return false;
339
                }
340
            }));
341
342
        $this->assertSame(
343
            $this->removeExtraWhitespace($expected),
344
            $this->removeExtraWhitespace($this->twigExtension->renderListElement(
345
                $this->environment,
0 ignored issues
show
Compatibility introduced by
$this->environment of type object<Twig_Environment> is not a sub-type of object<Twig\Environment>. It seems like you assume a child class of the class Twig_Environment to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
346
                $this->object,
347
                $this->fieldDescription
348
            ))
349
        );
350
    }
351
352
    /**
353
     * @dataProvider getDeprecatedRenderListElementTests
354
     * @group legacy
355
     */
356
    public function testDeprecatedRenderListElement($expected, $value, array $options)
357
    {
358
        $this->admin->expects($this->any())
0 ignored issues
show
Bug introduced by
The method expects() does not seem to exist on object<Sonata\AdminBundle\Admin\AdminInterface>.

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

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

Loading history...
359
            ->method('hasAccess')
360
            ->will($this->returnValue(true));
361
362
        // NEXT_MAJOR: Remove this line
363
        $this->admin->expects($this->any())
0 ignored issues
show
Bug introduced by
The method expects() does not seem to exist on object<Sonata\AdminBundle\Admin\AdminInterface>.

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

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

Loading history...
364
            ->method('getTemplate')
365
            ->with('base_list_field')
366
            ->willReturn('@SonataAdmin/CRUD/base_list_field.html.twig');
367
368
        $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...
369
370
        $this->fieldDescription->expects($this->any())
0 ignored issues
show
Bug introduced by
The method expects() does not seem to exist on object<Sonata\AdminBundl...ldDescriptionInterface>.

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

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

Loading history...
371
            ->method('getValue')
372
            ->will($this->returnValue($value));
373
374
        $this->fieldDescription->expects($this->any())
0 ignored issues
show
Bug introduced by
The method expects() does not seem to exist on object<Sonata\AdminBundl...ldDescriptionInterface>.

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

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

Loading history...
375
            ->method('getType')
376
            ->will($this->returnValue('nonexistent'));
377
378
        $this->fieldDescription->expects($this->any())
0 ignored issues
show
Bug introduced by
The method expects() does not seem to exist on object<Sonata\AdminBundl...ldDescriptionInterface>.

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

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

Loading history...
379
            ->method('getOptions')
380
            ->will($this->returnValue($options));
381
382
        $this->fieldDescription->expects($this->any())
0 ignored issues
show
Bug introduced by
The method expects() does not seem to exist on object<Sonata\AdminBundl...ldDescriptionInterface>.

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

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

Loading history...
383
            ->method('getOption')
384
            ->will($this->returnCallback(function ($name, $default = null) use ($options) {
385
                return isset($options[$name]) ? $options[$name] : $default;
386
            }));
387
388
        $this->fieldDescription->expects($this->any())
0 ignored issues
show
Bug introduced by
The method expects() does not seem to exist on object<Sonata\AdminBundl...ldDescriptionInterface>.

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

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

Loading history...
389
            ->method('getTemplate')
390
            ->will($this->returnValue('@SonataAdmin/CRUD/list_nonexistent_template.html.twig'));
391
392
        $this->assertSame(
393
            $this->removeExtraWhitespace($expected),
394
            $this->removeExtraWhitespace($this->twigExtension->renderListElement(
395
                $this->environment,
0 ignored issues
show
Compatibility introduced by
$this->environment of type object<Twig_Environment> is not a sub-type of object<Twig\Environment>. It seems like you assume a child class of the class Twig_Environment to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

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

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
1370
    }
1371
1372
    /**
1373
     * @group                    legacy
1374
     */
1375
    public function testRenderListElementErrorLoadingTemplate()
1376
    {
1377
        $this->expectException(\Twig_Error_Loader::class);
1378
        $this->expectExceptionMessage('Unable to find template "@SonataAdmin/CRUD/base_list_nonexistent_field.html.twig"');
1379
1380
        // NEXT_MAJOR: Remove this line
1381
        $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...
1382
            ->with('base_list_field')
1383
            ->willReturn('@SonataAdmin/CRUD/base_list_nonexistent_field.html.twig');
1384
1385
        $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...
1386
1387
        $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...
1388
            ->method('getTemplate')
1389
            ->will($this->returnValue('@SonataAdmin/CRUD/list_nonexistent_template.html.twig'));
1390
1391
        $this->twigExtension->renderListElement($this->environment, $this->object, $this->fieldDescription);
0 ignored issues
show
Compatibility introduced by
$this->environment of type object<Twig_Environment> is not a sub-type of object<Twig\Environment>. It seems like you assume a child class of the class Twig_Environment to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
1392
1393
        $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...
1394
    }
1395
1396
    /**
1397
     * @dataProvider getRenderViewElementTests
1398
     */
1399
    public function testRenderViewElement($expected, $type, $value, array $options)
1400
    {
1401
        $this->admin->expects($this->any())
0 ignored issues
show
Bug introduced by
The method expects() does not seem to exist on object<Sonata\AdminBundle\Admin\AdminInterface>.

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

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

Loading history...
1402
            ->method('getTemplate')
1403
            ->will($this->returnValue('@SonataAdmin/CRUD/base_show_field.html.twig'));
1404
1405
        $this->fieldDescription->expects($this->any())
0 ignored issues
show
Bug introduced by
The method expects() does not seem to exist on object<Sonata\AdminBundl...ldDescriptionInterface>.

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

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

Loading history...
1406
            ->method('getValue')
1407
            ->will($this->returnCallback(function () use ($value) {
1408
                if ($value instanceof NoValueException) {
1409
                    throw  $value;
1410
                }
1411
1412
                return $value;
1413
            }));
1414
1415
        $this->fieldDescription->expects($this->any())
0 ignored issues
show
Bug introduced by
The method expects() does not seem to exist on object<Sonata\AdminBundl...ldDescriptionInterface>.

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

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

Loading history...
1416
            ->method('getType')
1417
            ->will($this->returnValue($type));
1418
1419
        $this->fieldDescription->expects($this->any())
0 ignored issues
show
Bug introduced by
The method expects() does not seem to exist on object<Sonata\AdminBundl...ldDescriptionInterface>.

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

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

Loading history...
1420
            ->method('getOptions')
1421
            ->will($this->returnValue($options));
1422
1423
        $this->fieldDescription->expects($this->any())
0 ignored issues
show
Bug introduced by
The method expects() does not seem to exist on object<Sonata\AdminBundl...ldDescriptionInterface>.

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

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

Loading history...
1424
            ->method('getTemplate')
1425
            ->will($this->returnCallback(function () use ($type) {
1426
                switch ($type) {
1427
                    case 'boolean':
1428
                        return '@SonataAdmin/CRUD/show_boolean.html.twig';
1429
                    case 'datetime':
1430
                        return '@SonataAdmin/CRUD/show_datetime.html.twig';
1431
                    case 'date':
1432
                        return '@SonataAdmin/CRUD/show_date.html.twig';
1433
                    case 'time':
1434
                        return '@SonataAdmin/CRUD/show_time.html.twig';
1435
                    case 'currency':
1436
                        return '@SonataAdmin/CRUD/show_currency.html.twig';
1437
                    case 'percent':
1438
                        return '@SonataAdmin/CRUD/show_percent.html.twig';
1439
                    case 'email':
1440
                        return '@SonataAdmin/CRUD/show_email.html.twig';
1441
                    case 'choice':
1442
                        return '@SonataAdmin/CRUD/show_choice.html.twig';
1443
                    case 'array':
1444
                        return '@SonataAdmin/CRUD/show_array.html.twig';
1445
                    case 'trans':
1446
                        return '@SonataAdmin/CRUD/show_trans.html.twig';
1447
                    case 'url':
1448
                        return '@SonataAdmin/CRUD/show_url.html.twig';
1449
                    case 'html':
1450
                        return '@SonataAdmin/CRUD/show_html.html.twig';
1451
                    default:
1452
                        return false;
1453
                }
1454
            }));
1455
1456
        $this->assertSame(
1457
                $this->removeExtraWhitespace($expected),
1458
                $this->removeExtraWhitespace(
1459
                    $this->twigExtension->renderViewElement(
1460
                        $this->environment,
0 ignored issues
show
Compatibility introduced by
$this->environment of type object<Twig_Environment> is not a sub-type of object<Twig\Environment>. It seems like you assume a child class of the class Twig_Environment to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
1461
                        $this->fieldDescription,
1462
                        $this->object
1463
                    )
1464
                )
1465
            );
1466
    }
1467
1468
    public function getRenderViewElementTests()
1469
    {
1470
        return [
1471
            ['<th>Data</th> <td>Example</td>', 'string', 'Example', ['safe' => false]],
1472
            ['<th>Data</th> <td>Example</td>', 'text', 'Example', ['safe' => false]],
1473
            ['<th>Data</th> <td>Example</td>', 'textarea', 'Example', ['safe' => false]],
1474
            [
1475
                '<th>Data</th> <td>December 24, 2013 10:11</td>',
1476
                'datetime',
1477
                new \DateTime('2013-12-24 10:11:12', new \DateTimeZone('Europe/London')), [],
1478
            ],
1479
            [
1480
                '<th>Data</th> <td>24.12.2013 10:11:12</td>',
1481
                'datetime',
1482
                new \DateTime('2013-12-24 10:11:12', new \DateTimeZone('Europe/London')),
1483
                ['format' => 'd.m.Y H:i:s'],
1484
            ],
1485
            [
1486
                '<th>Data</th> <td>December 24, 2013 18:11</td>',
1487
                'datetime',
1488
                new \DateTime('2013-12-24 10:11:12', new \DateTimeZone('UTC')),
1489
                ['timezone' => 'Asia/Hong_Kong'],
1490
            ],
1491
            [
1492
                '<th>Data</th> <td>December 24, 2013</td>',
1493
                'date',
1494
                new \DateTime('2013-12-24 10:11:12', new \DateTimeZone('Europe/London')),
1495
                [],
1496
            ],
1497
            [
1498
                '<th>Data</th> <td>24.12.2013</td>',
1499
                'date',
1500
                new \DateTime('2013-12-24 10:11:12', new \DateTimeZone('Europe/London')),
1501
                ['format' => 'd.m.Y'],
1502
            ],
1503
            [
1504
                '<th>Data</th> <td>10:11:12</td>',
1505
                'time',
1506
                new \DateTime('2013-12-24 10:11:12', new \DateTimeZone('Europe/London')),
1507
                [],
1508
            ],
1509
            [
1510
                '<th>Data</th> <td>18:11:12</td>',
1511
                'time',
1512
                new \DateTime('2013-12-24 10:11:12', new \DateTimeZone('UTC')),
1513
                ['timezone' => 'Asia/Hong_Kong'],
1514
            ],
1515
            ['<th>Data</th> <td>10.746135</td>', 'number', 10.746135, ['safe' => false]],
1516
            ['<th>Data</th> <td>5678</td>', 'integer', 5678, ['safe' => false]],
1517
            ['<th>Data</th> <td> 1074.6135 % </td>', 'percent', 10.746135, []],
1518
            ['<th>Data</th> <td> EUR 10.746135 </td>', 'currency', 10.746135, ['currency' => 'EUR']],
1519
            ['<th>Data</th> <td> GBP 51.23456 </td>', 'currency', 51.23456, ['currency' => 'GBP']],
1520
            [
1521
                '<th>Data</th> <td> [1 => First] <br> [2 => Second] </td>',
1522
                'array',
1523
                [1 => 'First', 2 => 'Second'],
1524
                ['safe' => false],
1525
            ],
1526
            [
1527
                '<th>Data</th> <td> [1 => First] [2 => Second] </td>',
1528
                'array',
1529
                [1 => 'First', 2 => 'Second'],
1530
                ['safe' => false, 'inline' => true],
1531
            ],
1532
            [
1533
                '<th>Data</th> <td><span class="label label-success">yes</span></td>',
1534
                'boolean',
1535
                true,
1536
                [],
1537
            ],
1538
            [
1539
                '<th>Data</th> <td><span class="label label-danger">yes</span></td>',
1540
                'boolean',
1541
                true,
1542
                ['inverse' => true],
1543
            ],
1544
            ['<th>Data</th> <td><span class="label label-danger">no</span></td>', 'boolean', false, []],
1545
            [
1546
                '<th>Data</th> <td><span class="label label-success">no</span></td>',
1547
                'boolean',
1548
                false,
1549
                ['inverse' => true],
1550
            ],
1551
            [
1552
                '<th>Data</th> <td> Delete </td>',
1553
                'trans',
1554
                'action_delete',
1555
                ['safe' => false, 'catalogue' => 'SonataAdminBundle'],
1556
            ],
1557
            ['<th>Data</th> <td>Status1</td>', 'choice', 'Status1', ['safe' => false]],
1558
            [
1559
                '<th>Data</th> <td>Alias1</td>',
1560
                'choice',
1561
                'Status1',
1562
                ['safe' => false, 'choices' => [
1563
                    'Status1' => 'Alias1',
1564
                    'Status2' => 'Alias2',
1565
                    'Status3' => 'Alias3',
1566
                ]],
1567
            ],
1568
            [
1569
                '<th>Data</th> <td>NoValidKeyInChoices</td>',
1570
                'choice',
1571
                'NoValidKeyInChoices',
1572
                ['safe' => false, 'choices' => [
1573
                    'Status1' => 'Alias1',
1574
                    'Status2' => 'Alias2',
1575
                    'Status3' => 'Alias3',
1576
                ]],
1577
            ],
1578
            [
1579
                '<th>Data</th> <td>Delete</td>',
1580
                'choice',
1581
                'Foo',
1582
                ['safe' => false, 'catalogue' => 'SonataAdminBundle', 'choices' => [
1583
                    'Foo' => 'action_delete',
1584
                    'Status2' => 'Alias2',
1585
                    'Status3' => 'Alias3',
1586
                ]],
1587
            ],
1588
            [
1589
                '<th>Data</th> <td>NoValidKeyInChoices</td>',
1590
                'choice',
1591
                ['NoValidKeyInChoices'],
1592
                ['safe' => false, 'choices' => [
1593
                    'Status1' => 'Alias1',
1594
                    'Status2' => 'Alias2',
1595
                    'Status3' => 'Alias3',
1596
                ], 'multiple' => true],
1597
            ],
1598
            [
1599
                '<th>Data</th> <td>NoValidKeyInChoices, Alias2</td>',
1600
                'choice',
1601
                ['NoValidKeyInChoices', 'Status2'],
1602
                ['safe' => false, 'choices' => [
1603
                    'Status1' => 'Alias1',
1604
                    'Status2' => 'Alias2',
1605
                    'Status3' => 'Alias3',
1606
                ], 'multiple' => true],
1607
            ],
1608
            [
1609
                '<th>Data</th> <td>Alias1, Alias3</td>',
1610
                'choice',
1611
                ['Status1', 'Status3'],
1612
                ['safe' => false, 'choices' => [
1613
                    'Status1' => 'Alias1',
1614
                    'Status2' => 'Alias2',
1615
                    'Status3' => 'Alias3',
1616
                ], 'multiple' => true],
1617
            ],
1618
            [
1619
                '<th>Data</th> <td>Alias1 | Alias3</td>',
1620
                'choice',
1621
                ['Status1', 'Status3'], ['safe' => false, 'choices' => [
1622
                    'Status1' => 'Alias1',
1623
                    'Status2' => 'Alias2',
1624
                    'Status3' => 'Alias3',
1625
                ], 'multiple' => true, 'delimiter' => ' | '],
1626
            ],
1627
            [
1628
                '<th>Data</th> <td>Delete, Alias3</td>',
1629
                'choice',
1630
                ['Foo', 'Status3'],
1631
                ['safe' => false, 'catalogue' => 'SonataAdminBundle', 'choices' => [
1632
                    'Foo' => 'action_delete',
1633
                    'Status2' => 'Alias2',
1634
                    'Status3' => 'Alias3',
1635
                ], 'multiple' => true],
1636
            ],
1637
            [
1638
                '<th>Data</th> <td><b>Alias1</b>, <b>Alias3</b></td>',
1639
                'choice',
1640
                ['Status1', 'Status3'],
1641
                ['safe' => true, 'choices' => [
1642
                    'Status1' => '<b>Alias1</b>',
1643
                    'Status2' => '<b>Alias2</b>',
1644
                    'Status3' => '<b>Alias3</b>',
1645
                ], 'multiple' => true],
1646
            ],
1647
            [
1648
                '<th>Data</th> <td>&lt;b&gt;Alias1&lt;/b&gt;, &lt;b&gt;Alias3&lt;/b&gt;</td>',
1649
                'choice',
1650
                ['Status1', 'Status3'],
1651
                ['safe' => false, 'choices' => [
1652
                    'Status1' => '<b>Alias1</b>',
1653
                    'Status2' => '<b>Alias2</b>',
1654
                    'Status3' => '<b>Alias3</b>',
1655
                ], 'multiple' => true],
1656
            ],
1657
            [
1658
                '<th>Data</th> <td><a href="http://example.com">http://example.com</a></td>',
1659
                'url',
1660
                'http://example.com',
1661
                ['safe' => false],
1662
            ],
1663
            [
1664
                '<th>Data</th> <td><a href="http://example.com" target="_blank">http://example.com</a></td>',
1665
                'url',
1666
                'http://example.com',
1667
                ['safe' => false, 'attributes' => ['target' => '_blank']],
1668
            ],
1669
            [
1670
                '<th>Data</th> <td><a href="http://example.com" target="_blank" class="fooLink">http://example.com</a></td>',
1671
                'url',
1672
                'http://example.com',
1673
                ['safe' => false, 'attributes' => ['target' => '_blank', 'class' => 'fooLink']],
1674
            ],
1675
            [
1676
                '<th>Data</th> <td><a href="https://example.com">https://example.com</a></td>',
1677
                'url',
1678
                'https://example.com',
1679
                ['safe' => false],
1680
            ],
1681
            [
1682
                '<th>Data</th> <td><a href="http://example.com">example.com</a></td>',
1683
                'url',
1684
                'http://example.com',
1685
                ['safe' => false, 'hide_protocol' => true],
1686
            ],
1687
            [
1688
                '<th>Data</th> <td><a href="https://example.com">example.com</a></td>',
1689
                'url',
1690
                'https://example.com',
1691
                ['safe' => false, 'hide_protocol' => true],
1692
            ],
1693
            [
1694
                '<th>Data</th> <td><a href="http://example.com">http://example.com</a></td>',
1695
                'url',
1696
                'http://example.com',
1697
                ['safe' => false, 'hide_protocol' => false],
1698
            ],
1699
            [
1700
                '<th>Data</th> <td><a href="https://example.com">https://example.com</a></td>',
1701
                'url',
1702
                'https://example.com',
1703
                ['safe' => false,
1704
                'hide_protocol' => false, ],
1705
            ],
1706
            [
1707
                '<th>Data</th> <td><a href="http://example.com">Foo</a></td>',
1708
                'url',
1709
                'Foo',
1710
                ['safe' => false, 'url' => 'http://example.com'],
1711
            ],
1712
            [
1713
                '<th>Data</th> <td><a href="http://example.com">&lt;b&gt;Foo&lt;/b&gt;</a></td>',
1714
                'url',
1715
                '<b>Foo</b>',
1716
                ['safe' => false, 'url' => 'http://example.com'],
1717
            ],
1718
            [
1719
                '<th>Data</th> <td><a href="http://example.com"><b>Foo</b></a></td>',
1720
                'url',
1721
                '<b>Foo</b>',
1722
                ['safe' => true, 'url' => 'http://example.com'],
1723
            ],
1724
            [
1725
                '<th>Data</th> <td><a href="/foo">Foo</a></td>',
1726
                'url',
1727
                'Foo',
1728
                ['safe' => false, 'route' => ['name' => 'sonata_admin_foo']],
1729
            ],
1730
            [
1731
                '<th>Data</th> <td><a href="http://localhost/foo">Foo</a></td>',
1732
                'url',
1733
                'Foo',
1734
                ['safe' => false, 'route' => [
1735
                    'name' => 'sonata_admin_foo',
1736
                    'absolute' => true,
1737
                ]],
1738
            ],
1739
            [
1740
                '<th>Data</th> <td><a href="/foo">foo/bar?a=b&amp;c=123456789</a></td>',
1741
                'url',
1742
                'http://foo/bar?a=b&c=123456789',
1743
                [
1744
                    'safe' => false,
1745
                    'route' => ['name' => 'sonata_admin_foo'],
1746
                    'hide_protocol' => true,
1747
                ],
1748
            ],
1749
            [
1750
                '<th>Data</th> <td><a href="http://localhost/foo">foo/bar?a=b&amp;c=123456789</a></td>',
1751
                'url',
1752
                'http://foo/bar?a=b&c=123456789',
1753
                ['safe' => false, 'route' => [
1754
                    'name' => 'sonata_admin_foo',
1755
                    'absolute' => true,
1756
                ], 'hide_protocol' => true],
1757
            ],
1758
            [
1759
                '<th>Data</th> <td><a href="/foo/abcd/efgh?param3=ijkl">Foo</a></td>',
1760
                'url',
1761
                'Foo',
1762
                ['safe' => false, 'route' => [
1763
                    'name' => 'sonata_admin_foo_param',
1764
                    'parameters' => ['param1' => 'abcd', 'param2' => 'efgh', 'param3' => 'ijkl'],
1765
                ]],
1766
            ],
1767
            [
1768
                '<th>Data</th> <td><a href="http://localhost/foo/abcd/efgh?param3=ijkl">Foo</a></td>',
1769
                'url',
1770
                'Foo',
1771
                ['safe' => false, 'route' => [
1772
                    'name' => 'sonata_admin_foo_param',
1773
                    'absolute' => true,
1774
                    'parameters' => [
1775
                        'param1' => 'abcd',
1776
                        'param2' => 'efgh',
1777
                        'param3' => 'ijkl',
1778
                    ],
1779
                ]],
1780
            ],
1781
            [
1782
                '<th>Data</th> <td><a href="/foo/obj/abcd/12345/efgh?param3=ijkl">Foo</a></td>',
1783
                'url',
1784
                'Foo',
1785
                ['safe' => false, 'route' => [
1786
                    'name' => 'sonata_admin_foo_object',
1787
                    'parameters' => [
1788
                        'param1' => 'abcd',
1789
                        'param2' => 'efgh',
1790
                        'param3' => 'ijkl',
1791
                    ],
1792
                    'identifier_parameter_name' => 'barId',
1793
                ]],
1794
            ],
1795
            [
1796
                '<th>Data</th> <td><a href="http://localhost/foo/obj/abcd/12345/efgh?param3=ijkl">Foo</a></td>',
1797
                'url',
1798
                'Foo',
1799
                ['safe' => false, 'route' => [
1800
                    'name' => 'sonata_admin_foo_object',
1801
                    'absolute' => true,
1802
                    'parameters' => [
1803
                        'param1' => 'abcd',
1804
                        'param2' => 'efgh',
1805
                        'param3' => 'ijkl',
1806
                    ],
1807
                    'identifier_parameter_name' => 'barId',
1808
                ]],
1809
            ],
1810
            [
1811
                '<th>Data</th> <td> &nbsp;</td>',
1812
                'email',
1813
                null,
1814
                [],
1815
            ],
1816
            [
1817
                '<th>Data</th> <td> <a href="mailto:[email protected]">[email protected]</a></td>',
1818
                'email',
1819
                '[email protected]',
1820
                [],
1821
            ],
1822
            [
1823
                '<th>Data</th> <td> <a href="mailto:[email protected]?'.$this->buildTwigLikeUrl(['subject' => 'Main Theme', 'body' => 'Message Body']).'">[email protected]</a></td>',
1824
                'email',
1825
                '[email protected]',
1826
                ['subject' => 'Main Theme', 'body' => 'Message Body'],
1827
            ],
1828
            [
1829
                '<th>Data</th> <td> <a href="mailto:[email protected]?'.$this->buildTwigLikeUrl(['subject' => 'Main Theme']).'">[email protected]</a></td>',
1830
                'email',
1831
                '[email protected]',
1832
                ['subject' => 'Main Theme'],
1833
            ],
1834
            [
1835
                '<th>Data</th> <td> <a href="mailto:[email protected]?'.$this->buildTwigLikeUrl(['body' => 'Message Body']).'">[email protected]</a></td>',
1836
                'email',
1837
                '[email protected]',
1838
                ['body' => 'Message Body'],
1839
            ],
1840
            [
1841
                '<th>Data</th> <td> [email protected]</td>',
1842
                'email',
1843
                '[email protected]',
1844
                ['as_string' => true, 'subject' => 'Main Theme', 'body' => 'Message Body'],
1845
            ],
1846
            [
1847
                '<th>Data</th> <td> [email protected]</td>',
1848
                'email',
1849
                '[email protected]',
1850
                ['as_string' => true, 'subject' => 'Main Theme'],
1851
            ],
1852
            [
1853
                '<th>Data</th> <td> [email protected]</td>',
1854
                'email',
1855
                '[email protected]',
1856
                ['as_string' => true, 'body' => 'Message Body'],
1857
            ],
1858
            [
1859
                '<th>Data</th> <td> <a href="mailto:[email protected]">[email protected]</a></td>',
1860
                'email',
1861
                '[email protected]',
1862
                ['as_string' => false],
1863
            ],
1864
            [
1865
                '<th>Data</th> <td> [email protected]</td>',
1866
                'email',
1867
                '[email protected]',
1868
                ['as_string' => true],
1869
            ],
1870
            [
1871
                '<th>Data</th> <td><p><strong>Creating a Template for the Field</strong> and form</p> </td>',
1872
                'html',
1873
                '<p><strong>Creating a Template for the Field</strong> and form</p>',
1874
                [],
1875
            ],
1876
            [
1877
                '<th>Data</th> <td>Creating a Template for the Field and form </td>',
1878
                'html',
1879
                '<p><strong>Creating a Template for the Field</strong> and form</p>',
1880
                ['strip' => true],
1881
            ],
1882
            [
1883
                '<th>Data</th> <td> Creating a Template for the Fi... </td>',
1884
                'html',
1885
                '<p><strong>Creating a Template for the Field</strong> and form</p>',
1886
                ['truncate' => true],
1887
            ],
1888
            [
1889
                '<th>Data</th> <td> Creating a... </td>',
1890
                'html',
1891
                '<p><strong>Creating a Template for the Field</strong> and form</p>',
1892
                ['truncate' => ['length' => 10]],
1893
            ],
1894
            [
1895
                '<th>Data</th> <td> Creating a Template for the Field... </td>',
1896
                'html',
1897
                '<p><strong>Creating a Template for the Field</strong> and form</p>',
1898
                ['truncate' => ['preserve' => true]],
1899
            ],
1900
            [
1901
                '<th>Data</th> <td> Creating a Template for the Fi etc. </td>',
1902
                'html',
1903
                '<p><strong>Creating a Template for the Field</strong> and form</p>',
1904
                ['truncate' => ['separator' => ' etc.']],
1905
            ],
1906
            [
1907
                '<th>Data</th> <td> Creating a Template for[...] </td>',
1908
                'html',
1909
                '<p><strong>Creating a Template for the Field</strong> and form</p>',
1910
                [
1911
                    'truncate' => [
1912
                        'length' => 20,
1913
                        'preserve' => true,
1914
                        'separator' => '[...]',
1915
                    ],
1916
                ],
1917
            ],
1918
1919
            // NoValueException
1920
            ['<th>Data</th> <td></td>', 'string', new NoValueException(), ['safe' => false]],
1921
            ['<th>Data</th> <td></td>', 'text', new NoValueException(), ['safe' => false]],
1922
            ['<th>Data</th> <td></td>', 'textarea', new NoValueException(), ['safe' => false]],
1923
            ['<th>Data</th> <td>&nbsp;</td>', 'datetime', new NoValueException(), []],
1924
            [
1925
                '<th>Data</th> <td>&nbsp;</td>',
1926
                'datetime',
1927
                new NoValueException(),
1928
                ['format' => 'd.m.Y H:i:s'],
1929
            ],
1930
            ['<th>Data</th> <td>&nbsp;</td>', 'date', new NoValueException(), []],
1931
            ['<th>Data</th> <td>&nbsp;</td>', 'date', new NoValueException(), ['format' => 'd.m.Y']],
1932
            ['<th>Data</th> <td>&nbsp;</td>', 'time', new NoValueException(), []],
1933
            ['<th>Data</th> <td></td>', 'number', new NoValueException(), ['safe' => false]],
1934
            ['<th>Data</th> <td></td>', 'integer', new NoValueException(), ['safe' => false]],
1935
            ['<th>Data</th> <td> 0 % </td>', 'percent', new NoValueException(), []],
1936
            ['<th>Data</th> <td> </td>', 'currency', new NoValueException(), ['currency' => 'EUR']],
1937
            ['<th>Data</th> <td> </td>', 'currency', new NoValueException(), ['currency' => 'GBP']],
1938
            ['<th>Data</th> <td> </td>', 'array', new NoValueException(), ['safe' => false]],
1939
            [
1940
                '<th>Data</th> <td><span class="label label-danger">no</span></td>',
1941
                'boolean',
1942
                new NoValueException(),
1943
                [],
1944
            ],
1945
            [
1946
                '<th>Data</th> <td> </td>',
1947
                'trans',
1948
                new NoValueException(),
1949
                ['safe' => false, 'catalogue' => 'SonataAdminBundle'],
1950
            ],
1951
            [
1952
                '<th>Data</th> <td></td>',
1953
                'choice',
1954
                new NoValueException(),
1955
                ['safe' => false, 'choices' => []],
1956
            ],
1957
            [
1958
                '<th>Data</th> <td></td>',
1959
                'choice',
1960
                new NoValueException(),
1961
                ['safe' => false, 'choices' => [], 'multiple' => true],
1962
            ],
1963
            ['<th>Data</th> <td>&nbsp;</td>', 'url', new NoValueException(), []],
1964
            [
1965
                '<th>Data</th> <td>&nbsp;</td>',
1966
                'url',
1967
                new NoValueException(),
1968
                ['url' => 'http://example.com'],
1969
            ],
1970
            [
1971
                '<th>Data</th> <td>&nbsp;</td>',
1972
                'url',
1973
                new NoValueException(),
1974
                ['route' => ['name' => 'sonata_admin_foo']],
1975
            ],
1976
1977
            [
1978
                <<<'EOT'
1979
<th>Data</th> <td><div
1980
        class="sonata-readmore"
1981
        data-readmore-height="40"
1982
        data-readmore-more="Read more"
1983
        data-readmore-less="Close">
1984
            A very long string
1985
</div></td>
1986
EOT
1987
                ,
1988
                'text',
1989
                ' A very long string ',
1990
                [
1991
                    'collapse' => true,
1992
                    'safe' => false,
1993
                ],
1994
            ],
1995
            [
1996
                <<<'EOT'
1997
<th>Data</th> <td><div
1998
        class="sonata-readmore"
1999
        data-readmore-height="10"
2000
        data-readmore-more="More"
2001
        data-readmore-less="Less">
2002
            A very long string
2003
</div></td>
2004
EOT
2005
                ,
2006
                'text',
2007
                ' A very long string ',
2008
                [
2009
                    'collapse' => [
2010
                        'height' => 10,
2011
                        'more' => 'More',
2012
                        'less' => 'Less',
2013
                    ],
2014
                    'safe' => false,
2015
                ],
2016
            ],
2017
        ];
2018
    }
2019
2020
    public function testGetValueFromFieldDescription()
2021
    {
2022
        $object = new \stdClass();
2023
        $fieldDescription = $this->getMockForAbstractClass(FieldDescriptionInterface::class);
2024
2025
        $fieldDescription->expects($this->any())
2026
            ->method('getValue')
2027
            ->will($this->returnValue('test123'));
2028
2029
        $this->assertSame('test123', $this->twigExtension->getValueFromFieldDescription($object, $fieldDescription));
2030
    }
2031
2032
    public function testGetValueFromFieldDescriptionWithRemoveLoopException()
2033
    {
2034
        $object = $this->createMock(\ArrayAccess::class);
2035
        $fieldDescription = $this->getMockForAbstractClass(FieldDescriptionInterface::class);
2036
2037
        $this->expectException(\RuntimeException::class, 'remove the loop requirement');
2038
2039
        $this->assertSame(
2040
            'anything',
2041
            $this->twigExtension->getValueFromFieldDescription($object, $fieldDescription, ['loop' => true])
2042
        );
2043
    }
2044
2045
    public function testGetValueFromFieldDescriptionWithNoValueException()
2046
    {
2047
        $object = new \stdClass();
2048
        $fieldDescription = $this->getMockForAbstractClass(FieldDescriptionInterface::class);
2049
2050
        $fieldDescription->expects($this->any())
2051
            ->method('getValue')
2052
            ->will($this->returnCallback(function () {
2053
                throw new NoValueException();
2054
            }));
2055
2056
        $fieldDescription->expects($this->any())
2057
            ->method('getAssociationAdmin')
2058
            ->will($this->returnValue(null));
2059
2060
        $this->assertNull($this->twigExtension->getValueFromFieldDescription($object, $fieldDescription));
2061
    }
2062
2063
    public function testGetValueFromFieldDescriptionWithNoValueExceptionNewAdminInstance()
2064
    {
2065
        $object = new \stdClass();
2066
        $fieldDescription = $this->getMockForAbstractClass(FieldDescriptionInterface::class);
2067
2068
        $fieldDescription->expects($this->any())
2069
            ->method('getValue')
2070
            ->will($this->returnCallback(function () {
2071
                throw new NoValueException();
2072
            }));
2073
2074
        $fieldDescription->expects($this->any())
2075
            ->method('getAssociationAdmin')
2076
            ->will($this->returnValue($this->admin));
2077
2078
        $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...
2079
            ->method('getNewInstance')
2080
            ->will($this->returnValue('foo'));
2081
2082
        $this->assertSame('foo', $this->twigExtension->getValueFromFieldDescription($object, $fieldDescription));
2083
    }
2084
2085
    /**
2086
     * @group legacy
2087
     */
2088
    public function testOutput()
2089
    {
2090
        $this->fieldDescription->expects($this->any())
0 ignored issues
show
Bug introduced by
The method expects() does not seem to exist on object<Sonata\AdminBundl...ldDescriptionInterface>.

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

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

Loading history...
2091
            ->method('getTemplate')
2092
            ->will($this->returnValue('@SonataAdmin/CRUD/base_list_field.html.twig'));
2093
2094
        $this->fieldDescription->expects($this->any())
0 ignored issues
show
Bug introduced by
The method expects() does not seem to exist on object<Sonata\AdminBundl...ldDescriptionInterface>.

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

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

Loading history...
2095
            ->method('getFieldName')
2096
            ->will($this->returnValue('fd_name'));
2097
2098
        $this->environment->disableDebug();
2099
2100
        $parameters = [
2101
            'admin' => $this->admin,
2102
            'value' => 'foo',
2103
            'field_description' => $this->fieldDescription,
2104
            'object' => $this->object,
2105
        ];
2106
2107
        $template = $this->environment->loadTemplate('@SonataAdmin/CRUD/base_list_field.html.twig');
2108
2109
        $this->assertSame(
2110
            '<td class="sonata-ba-list-field sonata-ba-list-field-" objectId="12345"> foo </td>',
2111
            $this->removeExtraWhitespace($this->twigExtension->output(
0 ignored issues
show
Deprecated Code introduced by
The method Sonata\AdminBundle\Twig\...dminExtension::output() has been deprecated with message: since 3.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...
2112
                $this->fieldDescription,
2113
                $template,
0 ignored issues
show
Compatibility introduced by
$template of type object<Twig_Template> is not a sub-type of object<Twig\Template>. It seems like you assume a child class of the class Twig_Template to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
2114
                $parameters,
2115
                $this->environment
0 ignored issues
show
Compatibility introduced by
$this->environment of type object<Twig_Environment> is not a sub-type of object<Twig\Environment>. It seems like you assume a child class of the class Twig_Environment to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
2116
            ))
2117
        );
2118
2119
        $this->environment->enableDebug();
2120
        $this->assertSame(
2121
            $this->removeExtraWhitespace(<<<'EOT'
2122
<!-- START
2123
    fieldName: fd_name
2124
    template: @SonataAdmin/CRUD/base_list_field.html.twig
2125
    compiled template: @SonataAdmin/CRUD/base_list_field.html.twig
2126
-->
2127
    <td class="sonata-ba-list-field sonata-ba-list-field-" objectId="12345"> foo </td>
2128
<!-- END - fieldName: fd_name -->
2129
EOT
2130
            ),
2131
            $this->removeExtraWhitespace(
2132
                $this->twigExtension->output($this->fieldDescription, $template, $parameters, $this->environment)
0 ignored issues
show
Compatibility introduced by
$template of type object<Twig_Template> is not a sub-type of object<Twig\Template>. It seems like you assume a child class of the class Twig_Template to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
Compatibility introduced by
$this->environment of type object<Twig_Environment> is not a sub-type of object<Twig\Environment>. It seems like you assume a child class of the class Twig_Environment to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
Deprecated Code introduced by
The method Sonata\AdminBundle\Twig\...dminExtension::output() has been deprecated with message: since 3.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...
2133
            )
2134
        );
2135
    }
2136
2137
    /**
2138
     * @group legacy
2139
     * @expectedDeprecation The Sonata\AdminBundle\Admin\AbstractAdmin::getTemplate method is deprecated (since 3.34, will be dropped in 4.0. Use TemplateRegistry services instead).
2140
     */
2141
    public function testRenderWithDebug()
2142
    {
2143
        $this->fieldDescription->expects($this->any())
0 ignored issues
show
Bug introduced by
The method expects() does not seem to exist on object<Sonata\AdminBundl...ldDescriptionInterface>.

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

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

Loading history...
2144
            ->method('getTemplate')
2145
            ->will($this->returnValue('@SonataAdmin/CRUD/base_list_field.html.twig'));
2146
2147
        $this->fieldDescription->expects($this->any())
0 ignored issues
show
Bug introduced by
The method expects() does not seem to exist on object<Sonata\AdminBundl...ldDescriptionInterface>.

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

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

Loading history...
2148
            ->method('getFieldName')
2149
            ->will($this->returnValue('fd_name'));
2150
2151
        $this->fieldDescription->expects($this->any())
0 ignored issues
show
Bug introduced by
The method expects() does not seem to exist on object<Sonata\AdminBundl...ldDescriptionInterface>.

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

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

Loading history...
2152
            ->method('getValue')
2153
            ->will($this->returnValue('foo'));
2154
2155
        $parameters = [
2156
            'admin' => $this->admin,
2157
            'value' => 'foo',
2158
            'field_description' => $this->fieldDescription,
2159
            'object' => $this->object,
2160
        ];
2161
2162
        $this->environment->enableDebug();
2163
2164
        $this->assertSame(
2165
            $this->removeExtraWhitespace(<<<'EOT'
2166
<!-- START
2167
    fieldName: fd_name
2168
    template: @SonataAdmin/CRUD/base_list_field.html.twig
2169
    compiled template: @SonataAdmin/CRUD/base_list_field.html.twig
2170
-->
2171
    <td class="sonata-ba-list-field sonata-ba-list-field-" objectId="12345"> foo </td>
2172
<!-- END - fieldName: fd_name -->
2173
EOT
2174
            ),
2175
            $this->removeExtraWhitespace(
2176
                $this->twigExtension->renderListElement($this->environment, $this->object, $this->fieldDescription, $parameters)
0 ignored issues
show
Compatibility introduced by
$this->environment of type object<Twig_Environment> is not a sub-type of object<Twig\Environment>. It seems like you assume a child class of the class Twig_Environment to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
2177
            )
2178
        );
2179
    }
2180
2181
    public function testRenderRelationElementNoObject()
2182
    {
2183
        $this->assertSame('foo', $this->twigExtension->renderRelationElement('foo', $this->fieldDescription));
2184
    }
2185
2186
    public function testRenderRelationElementToString()
2187
    {
2188
        $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...
2189
            ->method('getOption')
2190
            ->will($this->returnCallback(function ($value, $default = null) {
2191
                if ('associated_property' == $value) {
2192
                    return $default;
2193
                }
2194
            }));
2195
2196
        $element = new FooToString();
2197
        $this->assertSame('salut', $this->twigExtension->renderRelationElement($element, $this->fieldDescription));
2198
    }
2199
2200
    /**
2201
     * @group legacy
2202
     */
2203
    public function testDeprecatedRelationElementToString()
2204
    {
2205
        $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...
2206
            ->method('getOption')
2207
            ->will($this->returnCallback(function ($value, $default = null) {
0 ignored issues
show
Unused Code introduced by
The parameter $default is not used and could be removed.

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

Loading history...
2208
                if ('associated_tostring' == $value) {
2209
                    return '__toString';
2210
                }
2211
            }));
2212
2213
        $element = new FooToString();
2214
        $this->assertSame(
2215
            'salut',
2216
            $this->twigExtension->renderRelationElement($element, $this->fieldDescription)
2217
        );
2218
    }
2219
2220
    /**
2221
     * @group legacy
2222
     */
2223
    public function testRenderRelationElementCustomToString()
2224
    {
2225
        $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...
2226
            ->method('getOption')
2227
            ->will($this->returnCallback(function ($value, $default = null) {
2228
                if ('associated_property' == $value) {
2229
                    return $default;
2230
                }
2231
2232
                if ('associated_tostring' == $value) {
2233
                    return 'customToString';
2234
                }
2235
            }));
2236
2237
        $element = $this->getMockBuilder('stdClass')
2238
            ->setMethods(['customToString'])
2239
            ->getMock();
2240
        $element->expects($this->any())
2241
            ->method('customToString')
2242
            ->will($this->returnValue('fooBar'));
2243
2244
        $this->assertSame('fooBar', $this->twigExtension->renderRelationElement($element, $this->fieldDescription));
2245
    }
2246
2247
    /**
2248
     * @group legacy
2249
     */
2250
    public function testRenderRelationElementMethodNotExist()
2251
    {
2252
        $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...
2253
            ->method('getOption')
2254
2255
            ->will($this->returnCallback(function ($value, $default = null) {
0 ignored issues
show
Unused Code introduced by
The parameter $default is not used and could be removed.

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

Loading history...
2256
                if ('associated_tostring' == $value) {
2257
                    return 'nonExistedMethod';
2258
                }
2259
            }));
2260
2261
        $element = new \stdClass();
2262
        $this->expectException(\RuntimeException::class, 'You must define an `associated_property` option or create a `stdClass::__toString');
2263
2264
        $this->twigExtension->renderRelationElement($element, $this->fieldDescription);
2265
    }
2266
2267
    public function testRenderRelationElementWithPropertyPath()
2268
    {
2269
        $this->fieldDescription->expects($this->exactly(1))
0 ignored issues
show
Bug introduced by
The method expects() does not seem to exist on object<Sonata\AdminBundl...ldDescriptionInterface>.

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

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

Loading history...
2270
            ->method('getOption')
2271
2272
            ->will($this->returnCallback(function ($value, $default = null) {
0 ignored issues
show
Unused Code introduced by
The parameter $default is not used and could be removed.

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

Loading history...
2273
                if ('associated_property' == $value) {
2274
                    return 'foo';
2275
                }
2276
            }));
2277
2278
        $element = new \stdClass();
2279
        $element->foo = 'bar';
2280
2281
        $this->assertSame('bar', $this->twigExtension->renderRelationElement($element, $this->fieldDescription));
2282
    }
2283
2284
    public function testRenderRelationElementWithClosure()
2285
    {
2286
        $this->fieldDescription->expects($this->exactly(1))
0 ignored issues
show
Bug introduced by
The method expects() does not seem to exist on object<Sonata\AdminBundl...ldDescriptionInterface>.

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

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

Loading history...
2287
            ->method('getOption')
2288
2289
            ->will($this->returnCallback(function ($value, $default = null) {
0 ignored issues
show
Unused Code introduced by
The parameter $default is not used and could be removed.

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

Loading history...
2290
                if ('associated_property' == $value) {
2291
                    return function ($element) {
2292
                        return 'closure '.$element->foo;
2293
                    };
2294
                }
2295
            }));
2296
2297
        $element = new \stdClass();
2298
        $element->foo = 'bar';
2299
2300
        $this->assertSame(
2301
            'closure bar',
2302
            $this->twigExtension->renderRelationElement($element, $this->fieldDescription)
2303
        );
2304
    }
2305
2306
    public function testGetUrlsafeIdentifier()
2307
    {
2308
        $entity = new \stdClass();
2309
2310
        // set admin to pool
2311
        $this->pool->setAdminServiceIds(['sonata_admin_foo_service']);
2312
        $this->pool->setAdminClasses(['stdClass' => ['sonata_admin_foo_service']]);
2313
2314
        $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...
2315
            ->method('getUrlsafeIdentifier')
2316
            ->with($this->equalTo($entity))
2317
            ->will($this->returnValue(1234567));
2318
2319
        $this->assertSame(1234567, $this->twigExtension->getUrlsafeIdentifier($entity));
2320
    }
2321
2322
    public function testGetUrlsafeIdentifier_GivenAdmin_Foo()
0 ignored issues
show
Coding Style introduced by
Method name "SonataAdminExtensionTest::testGetUrlsafeIdentifier_GivenAdmin_Foo" is not in camel caps format
Loading history...
2323
    {
2324
        $entity = new \stdClass();
2325
2326
        // set admin to pool
2327
        $this->pool->setAdminServiceIds([
2328
            'sonata_admin_foo_service',
2329
            'sonata_admin_bar_service',
2330
        ]);
2331
        $this->pool->setAdminClasses(['stdClass' => [
2332
            'sonata_admin_foo_service',
2333
            'sonata_admin_bar_service',
2334
        ]]);
2335
2336
        $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...
2337
            ->method('getUrlsafeIdentifier')
2338
            ->with($this->equalTo($entity))
2339
            ->will($this->returnValue(1234567));
2340
2341
        $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...
2342
            ->method('getUrlsafeIdentifier');
2343
2344
        $this->assertSame(1234567, $this->twigExtension->getUrlsafeIdentifier($entity, $this->admin));
2345
    }
2346
2347
    public function testGetUrlsafeIdentifier_GivenAdmin_Bar()
0 ignored issues
show
Coding Style introduced by
Method name "SonataAdminExtensionTest::testGetUrlsafeIdentifier_GivenAdmin_Bar" is not in camel caps format
Loading history...
2348
    {
2349
        $entity = new \stdClass();
2350
2351
        // set admin to pool
2352
        $this->pool->setAdminServiceIds(['sonata_admin_foo_service', 'sonata_admin_bar_service']);
2353
        $this->pool->setAdminClasses(['stdClass' => [
2354
            'sonata_admin_foo_service',
2355
            'sonata_admin_bar_service',
2356
        ]]);
2357
2358
        $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...
2359
            ->method('getUrlsafeIdentifier');
2360
2361
        $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...
2362
            ->method('getUrlsafeIdentifier')
2363
            ->with($this->equalTo($entity))
2364
            ->will($this->returnValue(1234567));
2365
2366
        $this->assertSame(1234567, $this->twigExtension->getUrlsafeIdentifier($entity, $this->adminBar));
2367
    }
2368
2369
    public function xEditableChoicesProvider()
2370
    {
2371
        return [
2372
            'needs processing' => [
2373
                ['choices' => ['Status1' => 'Alias1', 'Status2' => 'Alias2']],
2374
                [
2375
                    ['value' => 'Status1', 'text' => 'Alias1'],
2376
                    ['value' => 'Status2', 'text' => 'Alias2'],
2377
                ],
2378
            ],
2379
            'already processed' => [
2380
                ['choices' => [
2381
                    ['value' => 'Status1', 'text' => 'Alias1'],
2382
                    ['value' => 'Status2', 'text' => 'Alias2'],
2383
                ]],
2384
                [
2385
                    ['value' => 'Status1', 'text' => 'Alias1'],
2386
                    ['value' => 'Status2', 'text' => 'Alias2'],
2387
                ],
2388
            ],
2389
            'not required' => [
2390
                [
2391
                    'required' => false,
2392
                    'choices' => ['' => '', 'Status1' => 'Alias1', 'Status2' => 'Alias2'],
2393
                ],
2394
                [
2395
                    ['value' => '', 'text' => ''],
2396
                    ['value' => 'Status1', 'text' => 'Alias1'],
2397
                    ['value' => 'Status2', 'text' => 'Alias2'],
2398
                ],
2399
            ],
2400
            'not required multiple' => [
2401
                [
2402
                    'required' => false,
2403
                    'multiple' => true,
2404
                    'choices' => ['Status1' => 'Alias1', 'Status2' => 'Alias2'],
2405
                ],
2406
                [
2407
                    ['value' => 'Status1', 'text' => 'Alias1'],
2408
                    ['value' => 'Status2', 'text' => 'Alias2'],
2409
                ],
2410
            ],
2411
        ];
2412
    }
2413
2414
    /**
2415
     * @dataProvider xEditablechoicesProvider
2416
     */
2417
    public function testGetXEditableChoicesIsIdempotent(array $options, $expectedChoices)
2418
    {
2419
        $fieldDescription = $this->getMockForAbstractClass(FieldDescriptionInterface::class);
2420
        $fieldDescription->expects($this->any())
2421
            ->method('getOption')
2422
            ->withConsecutive(
2423
                ['choices', []],
2424
                ['catalogue'],
2425
                ['required'],
2426
                ['multiple']
2427
            )
2428
            ->will($this->onConsecutiveCalls(
2429
                $options['choices'],
2430
                'MyCatalogue',
2431
                isset($options['multiple']) ? $options['multiple'] : null
2432
            ));
2433
2434
        $this->assertSame($expectedChoices, $this->twigExtension->getXEditableChoices($fieldDescription));
2435
    }
2436
2437
    public function select2LocalesProvider()
2438
    {
2439
        return [
2440
            ['ar', 'ar'],
2441
            ['az', 'az'],
2442
            ['bg', 'bg'],
2443
            ['ca', 'ca'],
2444
            ['cs', 'cs'],
2445
            ['da', 'da'],
2446
            ['de', 'de'],
2447
            ['el', 'el'],
2448
            [null, 'en'],
2449
            ['es', 'es'],
2450
            ['et', 'et'],
2451
            ['eu', 'eu'],
2452
            ['fa', 'fa'],
2453
            ['fi', 'fi'],
2454
            ['fr', 'fr'],
2455
            ['gl', 'gl'],
2456
            ['he', 'he'],
2457
            ['hr', 'hr'],
2458
            ['hu', 'hu'],
2459
            ['id', 'id'],
2460
            ['is', 'is'],
2461
            ['it', 'it'],
2462
            ['ja', 'ja'],
2463
            ['ka', 'ka'],
2464
            ['ko', 'ko'],
2465
            ['lt', 'lt'],
2466
            ['lv', 'lv'],
2467
            ['mk', 'mk'],
2468
            ['ms', 'ms'],
2469
            ['nb', 'nb'],
2470
            ['nl', 'nl'],
2471
            ['pl', 'pl'],
2472
            ['pt-PT', 'pt'],
2473
            ['pt-BR', 'pt-BR'],
2474
            ['pt-PT', 'pt-PT'],
2475
            ['ro', 'ro'],
2476
            ['rs', 'rs'],
2477
            ['ru', 'ru'],
2478
            ['sk', 'sk'],
2479
            ['sv', 'sv'],
2480
            ['th', 'th'],
2481
            ['tr', 'tr'],
2482
            ['ug-CN', 'ug'],
2483
            ['ug-CN', 'ug-CN'],
2484
            ['uk', 'uk'],
2485
            ['vi', 'vi'],
2486
            ['zh-CN', 'zh'],
2487
            ['zh-CN', 'zh-CN'],
2488
            ['zh-TW', 'zh-TW'],
2489
        ];
2490
    }
2491
2492
    /**
2493
     * @dataProvider select2LocalesProvider
2494
     */
2495
    public function testCanonicalizedLocaleForSelect2($expected, $original)
2496
    {
2497
        $this->assertSame($expected, $this->twigExtension->getCanonicalizedLocaleForSelect2($this->mockExtensionContext($original)));
2498
    }
2499
2500
    public function momentLocalesProvider()
2501
    {
2502
        return [
2503
            ['af', 'af'],
2504
            ['ar-dz', 'ar-dz'],
2505
            ['ar', 'ar'],
2506
            ['ar-ly', 'ar-ly'],
2507
            ['ar-ma', 'ar-ma'],
2508
            ['ar-sa', 'ar-sa'],
2509
            ['ar-tn', 'ar-tn'],
2510
            ['az', 'az'],
2511
            ['be', 'be'],
2512
            ['bg', 'bg'],
2513
            ['bn', 'bn'],
2514
            ['bo', 'bo'],
2515
            ['br', 'br'],
2516
            ['bs', 'bs'],
2517
            ['ca', 'ca'],
2518
            ['cs', 'cs'],
2519
            ['cv', 'cv'],
2520
            ['cy', 'cy'],
2521
            ['da', 'da'],
2522
            ['de-at', 'de-at'],
2523
            ['de', 'de'],
2524
            ['dv', 'dv'],
2525
            ['el', 'el'],
2526
            [null, 'en'],
2527
            [null, 'en-us'],
2528
            ['en-au', 'en-au'],
2529
            ['en-ca', 'en-ca'],
2530
            ['en-gb', 'en-gb'],
2531
            ['en-ie', 'en-ie'],
2532
            ['en-nz', 'en-nz'],
2533
            ['eo', 'eo'],
2534
            ['es-do', 'es-do'],
2535
            ['es', 'es-ar'],
2536
            ['es', 'es-mx'],
2537
            ['es', 'es'],
2538
            ['et', 'et'],
2539
            ['eu', 'eu'],
2540
            ['fa', 'fa'],
2541
            ['fi', 'fi'],
2542
            ['fo', 'fo'],
2543
            ['fr-ca', 'fr-ca'],
2544
            ['fr-ch', 'fr-ch'],
2545
            ['fr', 'fr'],
2546
            ['fy', 'fy'],
2547
            ['gd', 'gd'],
2548
            ['gl', 'gl'],
2549
            ['he', 'he'],
2550
            ['hi', 'hi'],
2551
            ['hr', 'hr'],
2552
            ['hu', 'hu'],
2553
            ['hy-am', 'hy-am'],
2554
            ['id', 'id'],
2555
            ['is', 'is'],
2556
            ['it', 'it'],
2557
            ['ja', 'ja'],
2558
            ['jv', 'jv'],
2559
            ['ka', 'ka'],
2560
            ['kk', 'kk'],
2561
            ['km', 'km'],
2562
            ['ko', 'ko'],
2563
            ['ky', 'ky'],
2564
            ['lb', 'lb'],
2565
            ['lo', 'lo'],
2566
            ['lt', 'lt'],
2567
            ['lv', 'lv'],
2568
            ['me', 'me'],
2569
            ['mi', 'mi'],
2570
            ['mk', 'mk'],
2571
            ['ml', 'ml'],
2572
            ['mr', 'mr'],
2573
            ['ms', 'ms'],
2574
            ['ms-my', 'ms-my'],
2575
            ['my', 'my'],
2576
            ['nb', 'nb'],
2577
            ['ne', 'ne'],
2578
            ['nl-be', 'nl-be'],
2579
            ['nl', 'nl'],
2580
            ['nl', 'nl-nl'],
2581
            ['nn', 'nn'],
2582
            ['pa-in', 'pa-in'],
2583
            ['pl', 'pl'],
2584
            ['pt-br', 'pt-br'],
2585
            ['pt', 'pt'],
2586
            ['ro', 'ro'],
2587
            ['ru', 'ru'],
2588
            ['se', 'se'],
2589
            ['si', 'si'],
2590
            ['sk', 'sk'],
2591
            ['sl', 'sl'],
2592
            ['sq', 'sq'],
2593
            ['sr-cyrl', 'sr-cyrl'],
2594
            ['sr', 'sr'],
2595
            ['ss', 'ss'],
2596
            ['sv', 'sv'],
2597
            ['sw', 'sw'],
2598
            ['ta', 'ta'],
2599
            ['te', 'te'],
2600
            ['tet', 'tet'],
2601
            ['th', 'th'],
2602
            ['tlh', 'tlh'],
2603
            ['tl-ph', 'tl-ph'],
2604
            ['tr', 'tr'],
2605
            ['tzl', 'tzl'],
2606
            ['tzm', 'tzm'],
2607
            ['tzm-latn', 'tzm-latn'],
2608
            ['uk', 'uk'],
2609
            ['uz', 'uz'],
2610
            ['vi', 'vi'],
2611
            ['x-pseudo', 'x-pseudo'],
2612
            ['yo', 'yo'],
2613
            ['zh-cn', 'zh-cn'],
2614
            ['zh-hk', 'zh-hk'],
2615
            ['zh-tw', 'zh-tw'],
2616
        ];
2617
    }
2618
2619
    /**
2620
     * @dataProvider momentLocalesProvider
2621
     */
2622
    public function testCanonicalizedLocaleForMoment($expected, $original)
2623
    {
2624
        $this->assertSame($expected, $this->twigExtension->getCanonicalizedLocaleForMoment($this->mockExtensionContext($original)));
2625
    }
2626
2627
    public function testIsGrantedAffirmative()
2628
    {
2629
        $this->assertTrue(
2630
            $this->twigExtension->isGrantedAffirmative(['foo', 'bar'])
2631
        );
2632
        $this->assertTrue($this->twigExtension->isGrantedAffirmative('foo'));
2633
        $this->assertTrue($this->twigExtension->isGrantedAffirmative('bar'));
2634
    }
2635
2636
    /**
2637
     * This method generates url part for Twig layout.
2638
     *
2639
     * @param array $url
2640
     *
2641
     * @return string
2642
     */
2643
    private function buildTwigLikeUrl($url)
2644
    {
2645
        return htmlspecialchars(http_build_query($url, '', '&', PHP_QUERY_RFC3986));
2646
    }
2647
2648
    private function removeExtraWhitespace($string)
2649
    {
2650
        return trim(preg_replace(
2651
            '/\s+/',
2652
            ' ',
2653
            $string
2654
        ));
2655
    }
2656
2657
    private function mockExtensionContext($locale)
2658
    {
2659
        $request = $this->createMock(Request::class);
2660
        $request->method('getLocale')->willReturn($locale);
2661
        $appVariable = $this->createMock(AppVariable::class);
2662
        $appVariable->method('getRequest')->willReturn($request);
2663
2664
        return ['app' => $appVariable];
2665
    }
2666
}
2667