Completed
Push — master ( 76842f...81d46b )
by
unknown
02:15
created

ModelManagerTest::getMetadataForAssociatedEntity()   B

Complexity

Conditions 1
Paths 1

Size

Total Lines 31
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Importance

Changes 3
Bugs 0 Features 0
Metric Value
dl 0
loc 31
c 3
b 0
f 0
rs 8.8571
cc 1
eloc 20
nc 1
nop 0
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of the Sonata Project package.
7
 *
8
 * (c) Thomas Rabaix <[email protected]>
9
 *
10
 * For the full copyright and license information, please view the LICENSE
11
 * file that was distributed with this source code.
12
 */
13
14
namespace Sonata\DoctrineORMAdminBundle\Tests\Model;
15
16
use Doctrine\Common\Collections\ArrayCollection;
17
use Doctrine\Common\Persistence\ObjectManager;
18
use Doctrine\DBAL\Connection;
19
use Doctrine\DBAL\DBALException;
20
use Doctrine\DBAL\Platforms\PostgreSqlPlatform;
21
use Doctrine\DBAL\Types\Type;
22
use Doctrine\ORM\Configuration;
23
use Doctrine\ORM\EntityManager;
24
use Doctrine\ORM\Mapping\ClassMetadata;
25
use Doctrine\ORM\Mapping\ClassMetadataFactory;
26
use Doctrine\ORM\OptimisticLockException;
27
use Doctrine\ORM\Query;
28
use Doctrine\ORM\QueryBuilder;
29
use Doctrine\ORM\Version;
30
use PHPUnit\Framework\TestCase;
31
use Sonata\AdminBundle\Datagrid\Datagrid;
32
use Sonata\AdminBundle\Datagrid\DatagridInterface;
33
use Sonata\AdminBundle\Exception\LockException;
34
use Sonata\AdminBundle\Exception\ModelManagerException;
35
use Sonata\AdminBundle\Filter\FilterInterface;
36
use Sonata\DoctrineORMAdminBundle\Admin\FieldDescription;
37
use Sonata\DoctrineORMAdminBundle\Datagrid\OrderByToSelectWalker;
38
use Sonata\DoctrineORMAdminBundle\Datagrid\ProxyQuery;
39
use Sonata\DoctrineORMAdminBundle\Model\ModelManager;
40
use Sonata\DoctrineORMAdminBundle\Tests\Fixtures\DoctrineType\UuidType;
41
use Sonata\DoctrineORMAdminBundle\Tests\Fixtures\Entity\AbstractEntity;
42
use Sonata\DoctrineORMAdminBundle\Tests\Fixtures\Entity\AssociatedEntity;
43
use Sonata\DoctrineORMAdminBundle\Tests\Fixtures\Entity\ContainerEntity;
44
use Sonata\DoctrineORMAdminBundle\Tests\Fixtures\Entity\Embeddable\EmbeddedEntity;
45
use Sonata\DoctrineORMAdminBundle\Tests\Fixtures\Entity\Embeddable\SubEmbeddedEntity;
46
use Sonata\DoctrineORMAdminBundle\Tests\Fixtures\Entity\SimpleEntity;
47
use Sonata\DoctrineORMAdminBundle\Tests\Fixtures\Entity\UuidEntity;
48
use Sonata\DoctrineORMAdminBundle\Tests\Fixtures\Entity\VersionedEntity;
49
use Sonata\DoctrineORMAdminBundle\Tests\Fixtures\Util\NonIntegerIdentifierTestClass;
50
use Symfony\Bridge\Doctrine\RegistryInterface;
51
52
class ModelManagerTest extends TestCase
53
{
54
    public static function setUpBeforeClass(): void
55
    {
56
        if (!Type::hasType('uuid')) {
57
            Type::addType('uuid', UuidType::class);
58
        }
59
    }
60
61
    public function testSortParameters(): void
62
    {
63
        $registry = $this->createMock(RegistryInterface::class);
64
65
        $manager = new ModelManager($registry);
0 ignored issues
show
Documentation introduced by
$registry is of type object<PHPUnit\Framework\MockObject\MockObject>, but the function expects a object<Symfony\Bridge\Doctrine\RegistryInterface>.

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...
66
67
        $datagrid1 = $this->createMock(Datagrid::class);
68
        $datagrid2 = $this->createMock(Datagrid::class);
69
70
        $field1 = new FieldDescription();
71
        $field1->setName('field1');
72
73
        $field2 = new FieldDescription();
74
        $field2->setName('field2');
75
76
        $field3 = new FieldDescription();
77
        $field3->setName('field3');
78
        $field3->setOption('sortable', 'field3sortBy');
79
80
        $datagrid1
81
            ->expects($this->any())
82
            ->method('getValues')
83
            ->will($this->returnValue([
84
                '_sort_by' => $field1,
85
                '_sort_order' => 'ASC',
86
            ]));
87
88
        $datagrid2
89
            ->expects($this->any())
90
            ->method('getValues')
91
            ->will($this->returnValue([
92
                '_sort_by' => $field3,
93
                '_sort_order' => 'ASC',
94
            ]));
95
96
        $parameters = $manager->getSortParameters($field1, $datagrid1);
0 ignored issues
show
Documentation introduced by
$datagrid1 is of type object<PHPUnit\Framework\MockObject\MockObject>, but the function expects a object<Sonata\AdminBundl...grid\DatagridInterface>.

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...
97
98
        $this->assertEquals('DESC', $parameters['filter']['_sort_order']);
99
        $this->assertEquals('field1', $parameters['filter']['_sort_by']);
100
101
        $parameters = $manager->getSortParameters($field2, $datagrid1);
0 ignored issues
show
Documentation introduced by
$datagrid1 is of type object<PHPUnit\Framework\MockObject\MockObject>, but the function expects a object<Sonata\AdminBundl...grid\DatagridInterface>.

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...
102
103
        $this->assertEquals('ASC', $parameters['filter']['_sort_order']);
104
        $this->assertEquals('field2', $parameters['filter']['_sort_by']);
105
106
        $parameters = $manager->getSortParameters($field3, $datagrid1);
0 ignored issues
show
Documentation introduced by
$datagrid1 is of type object<PHPUnit\Framework\MockObject\MockObject>, but the function expects a object<Sonata\AdminBundl...grid\DatagridInterface>.

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...
107
108
        $this->assertEquals('ASC', $parameters['filter']['_sort_order']);
109
        $this->assertEquals('field3sortBy', $parameters['filter']['_sort_by']);
110
111
        $parameters = $manager->getSortParameters($field3, $datagrid2);
0 ignored issues
show
Documentation introduced by
$datagrid2 is of type object<PHPUnit\Framework\MockObject\MockObject>, but the function expects a object<Sonata\AdminBundl...grid\DatagridInterface>.

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...
112
113
        $this->assertEquals('DESC', $parameters['filter']['_sort_order']);
114
        $this->assertEquals('field3sortBy', $parameters['filter']['_sort_by']);
115
    }
116
117
    public function getVersionDataProvider(): array
118
    {
119
        return [
120
            [true],
121
            [false],
122
        ];
123
    }
124
125
    /**
126
     * @dataProvider getVersionDataProvider
127
     */
128
    public function testGetVersion($isVersioned): void
129
    {
130
        $object = new VersionedEntity();
131
132
        $modelManager = $this->getMockBuilder(ModelManager::class)
133
            ->disableOriginalConstructor()
134
            ->setMethods(['getMetadata'])
135
            ->getMock();
136
137
        $metadata = $this->getMetadata(get_class($object), $isVersioned);
138
139
        $modelManager->expects($this->any())
140
            ->method('getMetadata')
141
            ->will($this->returnValue($metadata));
142
143
        if ($isVersioned) {
144
            $object->version = 123;
145
146
            $this->assertNotNull($modelManager->getLockVersion($object));
147
        } else {
148
            $this->assertNull($modelManager->getLockVersion($object));
149
        }
150
    }
151
152
    public function lockDataProvider(): array
153
    {
154
        return [
155
            [true,  false],
156
            [true,  true],
157
            [false, false],
158
        ];
159
    }
160
161
    /**
162
     * @dataProvider lockDataProvider
163
     */
164
    public function testLock($isVersioned, $expectsException): void
165
    {
166
        $object = new VersionedEntity();
167
168
        $em = $this->getMockBuilder(EntityManager::class)
169
            ->disableOriginalConstructor()
170
            ->setMethods(['lock'])
171
            ->getMock();
172
173
        $modelManager = $this->getMockBuilder(ModelManager::class)
174
            ->disableOriginalConstructor()
175
            ->setMethods(['getMetadata', 'getEntityManager'])
176
            ->getMock();
177
178
        $modelManager->expects($this->any())
179
            ->method('getEntityManager')
180
            ->will($this->returnValue($em));
181
182
        $metadata = $this->getMetadata(get_class($object), $isVersioned);
183
184
        $modelManager->expects($this->any())
185
            ->method('getMetadata')
186
            ->will($this->returnValue($metadata));
187
188
        if ($expectsException) {
189
            $em->expects($this->once())
190
                ->method('lock')
191
                ->will($this->throwException(OptimisticLockException::lockFailed($object)));
192
193
            $this->expectException(LockException::class);
194
        }
195
196
        $modelManager->lock($object, 123);
197
    }
198
199
    public function testGetParentMetadataForProperty(): void
200
    {
201
        if (version_compare(Version::VERSION, '2.5') < 0) {
202
            $this->markTestSkipped('Test for embeddables needs to run on Doctrine >= 2.5');
203
204
            return;
205
        }
206
207
        $containerEntityClass = ContainerEntity::class;
208
        $associatedEntityClass = AssociatedEntity::class;
209
        $embeddedEntityClass = EmbeddedEntity::class;
210
        $modelManagerClass = ModelManager::class;
211
212
        $em = $this->createMock(EntityManager::class);
213
214
        /** @var \PHPUnit_Framework_MockObject_MockObject|ModelManager $modelManager */
215
        $modelManager = $this->getMockBuilder($modelManagerClass)
216
            ->disableOriginalConstructor()
217
            ->setMethods(['getMetadata', 'getEntityManager'])
218
            ->getMock();
219
220
        $modelManager->expects($this->any())
0 ignored issues
show
Bug introduced by
The method expects does only exist in PHPUnit_Framework_MockObject_MockObject, but not in Sonata\DoctrineORMAdminBundle\Model\ModelManager.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
221
            ->method('getEntityManager')
222
            ->will($this->returnValue($em));
223
224
        $containerEntityMetadata = $this->getMetadataForContainerEntity();
225
        $associatedEntityMetadata = $this->getMetadataForAssociatedEntity();
226
        $embeddedEntityMetadata = $this->getMetadataForEmbeddedEntity();
227
228
        $modelManager->expects($this->any())->method('getMetadata')
229
            ->will(
230
                $this->returnValueMap(
231
                    [
232
                        [$containerEntityClass, $containerEntityMetadata],
233
                        [$embeddedEntityClass, $embeddedEntityMetadata],
234
                        [$associatedEntityClass, $associatedEntityMetadata],
235
                    ]
236
                )
237
            );
238
239
        /** @var ClassMetadata $metadata */
240
        list($metadata, $lastPropertyName) = $modelManager
0 ignored issues
show
Bug introduced by
The method getParentMetadataForProperty does only exist in Sonata\DoctrineORMAdminBundle\Model\ModelManager, but not in PHPUnit_Framework_MockObject_MockObject.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
241
            ->getParentMetadataForProperty($containerEntityClass, 'plainField');
242
        $this->assertEquals($metadata->fieldMappings[$lastPropertyName]['type'], 'integer');
243
244
        list($metadata, $lastPropertyName) = $modelManager
245
            ->getParentMetadataForProperty($containerEntityClass, 'associatedEntity.plainField');
246
        $this->assertEquals($metadata->fieldMappings[$lastPropertyName]['type'], 'string');
247
248
        list($metadata, $lastPropertyName) = $modelManager
249
            ->getParentMetadataForProperty($containerEntityClass, 'embeddedEntity.plainField');
250
        $this->assertEquals($metadata->fieldMappings[$lastPropertyName]['type'], 'boolean');
251
252
        list($metadata, $lastPropertyName) = $modelManager
253
            ->getParentMetadataForProperty($containerEntityClass, 'associatedEntity.embeddedEntity.plainField');
254
        $this->assertEquals($metadata->fieldMappings[$lastPropertyName]['type'], 'boolean');
255
256
        list($metadata, $lastPropertyName) = $modelManager
257
            ->getParentMetadataForProperty(
258
                $containerEntityClass,
259
                'associatedEntity.embeddedEntity.subEmbeddedEntity.plainField'
260
            );
261
        $this->assertEquals($metadata->fieldMappings[$lastPropertyName]['type'], 'boolean');
262
    }
263
264
    public function getMetadataForEmbeddedEntity()
265
    {
266
        $metadata = new ClassMetadata(EmbeddedEntity::class);
267
268
        $metadata->fieldMappings = [
269
            'plainField' => [
270
                'fieldName' => 'plainField',
271
                'columnName' => 'plainField',
272
                'type' => 'boolean',
273
            ],
274
        ];
275
276
        return $metadata;
277
    }
278
279
    public function getMetadataForSubEmbeddedEntity()
280
    {
281
        $metadata = new ClassMetadata(SubEmbeddedEntity::class);
282
283
        $metadata->fieldMappings = [
284
            'plainField' => [
285
                'fieldName' => 'plainField',
286
                'columnName' => 'plainField',
287
                'type' => 'boolean',
288
            ],
289
        ];
290
291
        return $metadata;
292
    }
293
294
    public function getMetadataForAssociatedEntity()
295
    {
296
        $embeddedEntityClass = EmbeddedEntity::class;
297
        $subEmbeddedEntityClass = SubEmbeddedEntity::class;
298
299
        $metadata = new ClassMetadata(AssociatedEntity::class);
300
301
        $metadata->fieldMappings = [
302
            'plainField' => [
303
                'fieldName' => 'plainField',
304
                'columnName' => 'plainField',
305
                'type' => 'string',
306
            ],
307
        ];
308
309
        $metadata->embeddedClasses['embeddedEntity'] = [
310
            'class' => $embeddedEntityClass,
311
            'columnPrefix' => 'embedded_entity_',
312
        ];
313
        $metadata->embeddedClasses['embeddedEntity.subEmbeddedEntity'] = [
314
            'class' => $subEmbeddedEntityClass,
315
            'columnPrefix' => 'embedded_entity_sub_embedded_entity_',
316
            'declaredField' => 'embeddedEntity',
317
            'originalField' => 'subEmbeddedEntity',
318
        ];
319
320
        $metadata->inlineEmbeddable('embeddedEntity', $this->getMetadataForEmbeddedEntity());
321
        $metadata->inlineEmbeddable('embeddedEntity.subEmbeddedEntity', $this->getMetadataForSubEmbeddedEntity());
322
323
        return $metadata;
324
    }
325
326
    public function getMetadataForContainerEntity()
327
    {
328
        $containerEntityClass = ContainerEntity::class;
329
        $associatedEntityClass = AssociatedEntity::class;
330
        $embeddedEntityClass = EmbeddedEntity::class;
331
        $subEmbeddedEntityClass = SubEmbeddedEntity::class;
332
333
        $metadata = new ClassMetadata($containerEntityClass);
334
335
        $metadata->fieldMappings = [
336
            'plainField' => [
337
                'fieldName' => 'plainField',
338
                'columnName' => 'plainField',
339
                'type' => 'integer',
340
            ],
341
        ];
342
343
        $metadata->associationMappings['associatedEntity'] = [
344
            'fieldName' => 'associatedEntity',
345
            'targetEntity' => $associatedEntityClass,
346
            'sourceEntity' => $containerEntityClass,
347
        ];
348
349
        $metadata->embeddedClasses['embeddedEntity'] = [
350
            'class' => $embeddedEntityClass,
351
            'columnPrefix' => 'embeddedEntity',
352
        ];
353
        $metadata->embeddedClasses['embeddedEntity.subEmbeddedEntity'] = [
354
            'class' => $subEmbeddedEntityClass,
355
            'columnPrefix' => 'embedded_entity_sub_embedded_entity_',
356
            'declaredField' => 'embeddedEntity',
357
            'originalField' => 'subEmbeddedEntity',
358
        ];
359
360
        $metadata->inlineEmbeddable('embeddedEntity', $this->getMetadataForEmbeddedEntity());
361
        $metadata->inlineEmbeddable('embeddedEntity.subEmbeddedEntity', $this->getMetadataForSubEmbeddedEntity());
362
363
        return $metadata;
364
    }
365
366
    public function testNonIntegerIdentifierType(): void
367
    {
368
        $uuid = new NonIntegerIdentifierTestClass('efbcfc4b-8c43-4d42-aa4c-d707e55151ac');
369
        $entity = new UuidEntity($uuid);
370
371
        $meta = $this->createMock(ClassMetadata::class);
372
        $meta->expects($this->any())
373
            ->method('getIdentifierValues')
374
            ->willReturn([$entity->getId()]);
375
        $meta->expects($this->any())
376
            ->method('getTypeOfField')
377
            ->willReturn(UuidType::NAME);
378
379
        $mf = $this->createMock(ClassMetadataFactory::class);
380
        $mf->expects($this->any())
381
            ->method('getMetadataFor')
382
            ->willReturn($meta);
383
384
        $platform = $this->createMock(PostgreSqlPlatform::class);
385
386
        $conn = $this->createMock(Connection::class);
387
        $conn->expects($this->any())
388
            ->method('getDatabasePlatform')
389
            ->willReturn($platform);
390
391
        $em = $this->createMock(EntityManager::class);
392
        $em->expects($this->any())
393
            ->method('getMetadataFactory')
394
            ->willReturn($mf);
395
        $em->expects($this->any())
396
            ->method('getConnection')
397
            ->willReturn($conn);
398
399
        $registry = $this->createMock(RegistryInterface::class);
400
        $registry->expects($this->any())
401
            ->method('getManagerForClass')
402
            ->willReturn($em);
403
404
        $manager = new ModelManager($registry);
0 ignored issues
show
Documentation introduced by
$registry is of type object<PHPUnit\Framework\MockObject\MockObject>, but the function expects a object<Symfony\Bridge\Doctrine\RegistryInterface>.

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...
405
        $result = $manager->getIdentifierValues($entity);
406
407
        $this->assertEquals($entity->getId()->toString(), $result[0]);
408
    }
409
410
    public function testAssociationIdentifierType(): void
411
    {
412
        $entity = new ContainerEntity(new AssociatedEntity(42, new EmbeddedEntity()), new EmbeddedEntity());
413
414
        $meta = $this->createMock(ClassMetadata::class);
415
        $meta->expects($this->any())
416
            ->method('getIdentifierValues')
417
            ->willReturn([$entity->getAssociatedEntity()->getPlainField()]);
418
        $meta->expects($this->any())
419
            ->method('getTypeOfField')
420
            ->willReturn(null);
421
422
        $mf = $this->createMock(ClassMetadataFactory::class);
423
        $mf->expects($this->any())
424
            ->method('getMetadataFor')
425
            ->willReturn($meta);
426
427
        $platform = $this->createMock(PostgreSqlPlatform::class);
428
429
        $conn = $this->createMock(Connection::class);
430
        $conn->expects($this->any())
431
            ->method('getDatabasePlatform')
432
            ->willReturn($platform);
433
434
        $em = $this->createMock(EntityManager::class);
435
        $em->expects($this->any())
436
            ->method('getMetadataFactory')
437
            ->willReturn($mf);
438
        $em->expects($this->any())
439
            ->method('getConnection')
440
            ->willReturn($conn);
441
442
        $registry = $this->createMock(RegistryInterface::class);
443
        $registry->expects($this->any())
444
            ->method('getManagerForClass')
445
            ->willReturn($em);
446
447
        $manager = new ModelManager($registry);
0 ignored issues
show
Documentation introduced by
$registry is of type object<PHPUnit\Framework\MockObject\MockObject>, but the function expects a object<Symfony\Bridge\Doctrine\RegistryInterface>.

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...
448
        $result = $manager->getIdentifierValues($entity);
449
450
        $this->assertSame(42, $result[0]);
451
    }
452
453
    /**
454
     * [sortBy, sortOrder, isAddOrderBy].
455
     *
456
     * @return array
457
     */
458
    public function getSortableInDataSourceIteratorDataProvider(): array
459
    {
460
        return [
461
            [null, null, false],
462
            ['', 'ASC', false],
463
            ['field', 'ASC', true],
464
            ['field', null, true],
465
        ];
466
    }
467
468
    /**
469
     * @dataProvider getSortableInDataSourceIteratorDataProvider
470
     *
471
     * @param string|null $sortBy
472
     * @param string|null $sortOrder
473
     * @param bool        $isAddOrderBy
474
     */
475
    public function testSortableInDataSourceIterator($sortBy, $sortOrder, $isAddOrderBy): void
476
    {
477
        $datagrid = $this->getMockForAbstractClass(DatagridInterface::class);
478
        $configuration = $this->getMockBuilder(Configuration::class)->getMock();
479
        $configuration->expects($this->any())
480
            ->method('getDefaultQueryHints')
481
            ->willReturn([]);
482
483
        $em = $this->getMockBuilder(EntityManager::class)
484
            ->disableOriginalConstructor()
485
            ->getMock();
486
487
        $em->expects($this->any())
488
            ->method('getConfiguration')
489
            ->willReturn($configuration);
490
491
        $queryBuilder = $this->getMockBuilder(QueryBuilder::class)
492
            ->setConstructorArgs([$em])
493
            ->getMock();
494
        $query = new Query($em);
0 ignored issues
show
Documentation introduced by
$em is of type object<PHPUnit\Framework\MockObject\MockObject>, but the function expects a object<Doctrine\ORM\EntityManagerInterface>.

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...
495
496
        $proxyQuery = $this->getMockBuilder(ProxyQuery::class)
497
            ->setConstructorArgs([$queryBuilder])
498
            ->setMethods(['getSortBy', 'getSortOrder', 'getRootAliases'])
499
            ->getMock();
500
501
        $proxyQuery->expects($this->any())
502
            ->method('getSortOrder')
503
            ->willReturn($sortOrder);
504
505
        $proxyQuery->expects($this->any())
506
            ->method('getSortBy')
507
            ->willReturn($sortBy);
508
509
        $queryBuilder->expects($isAddOrderBy ? $this->atLeastOnce() : $this->never())
510
            ->method('addOrderBy');
511
512
        $proxyQuery->expects($this->any())
513
            ->method('getRootAliases')
514
            ->willReturn(['a']);
515
516
        $queryBuilder->expects($this->any())
517
            ->method('getQuery')
518
            ->willReturn($query);
519
520
        $datagrid->expects($this->any())
521
            ->method('getQuery')
522
            ->willReturn($proxyQuery);
523
524
        $registry = $this->getMockBuilder(RegistryInterface::class)->getMock();
525
        $manager = new ModelManager($registry);
0 ignored issues
show
Documentation introduced by
$registry is of type object<PHPUnit\Framework\MockObject\MockObject>, but the function expects a object<Symfony\Bridge\Doctrine\RegistryInterface>.

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...
526
        $manager->getDataSourceIterator($datagrid, []);
0 ignored issues
show
Documentation introduced by
$datagrid is of type object<PHPUnit\Framework\MockObject\MockObject>, but the function expects a object<Sonata\AdminBundl...grid\DatagridInterface>.

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...
527
528
        if ($isAddOrderBy) {
529
            $this->assertArrayHasKey($key = 'doctrine.customTreeWalkers', $hints = $query->getHints());
530
            $this->assertContains(OrderByToSelectWalker::class, $hints[$key]);
531
        }
532
    }
533
534
    public function testModelReverseTransform(): void
535
    {
536
        $class = SimpleEntity::class;
537
538
        $metadataFactory = $this->createMock(ClassMetadataFactory::class);
539
        $modelManager = $this->createMock(ObjectManager::class);
540
        $registry = $this->createMock(RegistryInterface::class);
541
542
        $classMetadata = new ClassMetadata($class);
543
        $classMetadata->reflClass = new \ReflectionClass($class);
544
545
        $modelManager->expects($this->once())
546
            ->method('getMetadataFactory')
547
            ->willReturn($metadataFactory);
548
        $metadataFactory->expects($this->once())
549
            ->method('getMetadataFor')
550
            ->with($class)
551
            ->willReturn($classMetadata);
552
        $registry->expects($this->once())
553
            ->method('getManagerForClass')
554
            ->with($class)
555
            ->willReturn($modelManager);
556
557
        $manager = new ModelManager($registry);
0 ignored issues
show
Documentation introduced by
$registry is of type object<PHPUnit\Framework\MockObject\MockObject>, but the function expects a object<Symfony\Bridge\Doctrine\RegistryInterface>.

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...
558
        $this->assertInstanceOf($class, $object = $manager->modelReverseTransform(
559
            $class,
560
            [
561
                'schmeckles' => 42,
562
                'multi_word_property' => 'hello',
563
            ]
564
        ));
565
        $this->assertSame(42, $object->getSchmeckles());
566
        $this->assertSame('hello', $object->getMultiWordProperty());
567
    }
568
569
    public function testCollections(): void
570
    {
571
        $registry = $this->createMock(RegistryInterface::class);
572
        $model = new ModelManager($registry);
0 ignored issues
show
Documentation introduced by
$registry is of type object<PHPUnit\Framework\MockObject\MockObject>, but the function expects a object<Symfony\Bridge\Doctrine\RegistryInterface>.

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...
573
574
        $collection = $model->getModelCollectionInstance('whyDoWeEvenHaveThisParameter');
575
        $this->assertInstanceOf(ArrayCollection::class, $collection);
576
577
        $item1 = 'item1';
578
        $item2 = 'item2';
579
        $model->collectionAddElement($collection, $item1);
580
        $model->collectionAddElement($collection, $item2);
581
582
        $this->assertTrue($model->collectionHasElement($collection, $item1));
583
584
        $model->collectionRemoveElement($collection, $item1);
585
586
        $this->assertFalse($model->collectionHasElement($collection, $item1));
587
588
        $model->collectionClear($collection);
589
590
        $this->assertTrue($collection->isEmpty());
591
    }
592
593
    public function testModelTransform(): void
594
    {
595
        $registry = $this->createMock(RegistryInterface::class);
596
        $model = new ModelManager($registry);
0 ignored issues
show
Documentation introduced by
$registry is of type object<PHPUnit\Framework\MockObject\MockObject>, but the function expects a object<Symfony\Bridge\Doctrine\RegistryInterface>.

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...
597
598
        $result = $model->modelTransform('thisIsNotUsed', 'doWeNeedThisMethod');
0 ignored issues
show
Documentation introduced by
'doWeNeedThisMethod' is of type string, but the function expects a object.

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...
599
600
        $this->assertSame('doWeNeedThisMethod', $result);
601
    }
602
603
    public function testGetPaginationParameters(): void
604
    {
605
        $datagrid = $this->createMock(DatagridInterface::class);
606
        $filter = $this->createMock(FilterInterface::class);
607
        $registry = $this->createMock(RegistryInterface::class);
608
609
        $datagrid->expects($this->once())
610
            ->method('getValues')
611
            ->willReturn(['_sort_by' => $filter]);
612
613
        $filter->expects($this->once())
614
            ->method('getName')
615
            ->willReturn($name = 'test');
616
617
        $model = new ModelManager($registry);
0 ignored issues
show
Documentation introduced by
$registry is of type object<PHPUnit\Framework\MockObject\MockObject>, but the function expects a object<Symfony\Bridge\Doctrine\RegistryInterface>.

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...
618
619
        $result = $model->getPaginationParameters($datagrid, $page = 5);
0 ignored issues
show
Documentation introduced by
$datagrid is of type object<PHPUnit\Framework\MockObject\MockObject>, but the function expects a object<Sonata\AdminBundl...grid\DatagridInterface>.

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...
620
621
        $this->assertSame($page, $result['filter']['_page']);
622
        $this->assertSame($name, $result['filter']['_sort_by']);
623
    }
624
625
    public function testGetModelInstanceException(): void
626
    {
627
        $registry = $this->createMock(RegistryInterface::class);
628
629
        $model = new ModelManager($registry);
0 ignored issues
show
Documentation introduced by
$registry is of type object<PHPUnit\Framework\MockObject\MockObject>, but the function expects a object<Symfony\Bridge\Doctrine\RegistryInterface>.

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...
630
631
        $this->expectException(\RuntimeException::class);
632
633
        $model->getModelInstance(AbstractEntity::class);
634
    }
635
636
    public function testGetEntityManagerException(): void
637
    {
638
        $registry = $this->createMock(RegistryInterface::class);
639
640
        $model = new ModelManager($registry);
0 ignored issues
show
Documentation introduced by
$registry is of type object<PHPUnit\Framework\MockObject\MockObject>, but the function expects a object<Symfony\Bridge\Doctrine\RegistryInterface>.

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...
641
642
        $this->expectException(\RuntimeException::class);
643
644
        $model->getEntityManager(VersionedEntity::class);
645
    }
646
647
    public function testGetNewFieldDescriptionInstanceException(): void
648
    {
649
        $registry = $this->createMock(RegistryInterface::class);
650
651
        $model = new ModelManager($registry);
0 ignored issues
show
Documentation introduced by
$registry is of type object<PHPUnit\Framework\MockObject\MockObject>, but the function expects a object<Symfony\Bridge\Doctrine\RegistryInterface>.

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...
652
653
        $this->expectException(\RuntimeException::class);
654
655
        $model->getNewFieldDescriptionInstance(VersionedEntity::class, [], []);
0 ignored issues
show
Documentation introduced by
array() is of type array, but the function expects a string.

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...
656
    }
657
658
    /**
659
     * @dataProvider createUpdateRemoveData
660
     */
661
    public function testCreate($exception): void
662
    {
663
        $registry = $this->createMock(RegistryInterface::class);
664
665
        $entityManger = $this->createMock(EntityManager::class);
666
667
        $registry->expects($this->once())
668
            ->method('getManagerForClass')
669
            ->willReturn($entityManger);
670
671
        $entityManger->expects($this->once())
672
            ->method('persist');
673
674
        $entityManger->expects($this->once())
675
            ->method('flush')
676
            ->willThrowException($exception);
677
678
        $model = new ModelManager($registry);
0 ignored issues
show
Documentation introduced by
$registry is of type object<PHPUnit\Framework\MockObject\MockObject>, but the function expects a object<Symfony\Bridge\Doctrine\RegistryInterface>.

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...
679
680
        $this->expectException(ModelManagerException::class);
681
682
        $model->create(new VersionedEntity());
683
    }
684
685
    public function createUpdateRemoveData(): array
686
    {
687
        return [
688
            'PDOException' => [
689
                new \PDOException(),
690
            ],
691
            'DBALException' => [
692
                new DBALException(),
693
            ],
694
        ];
695
    }
696
697
    /**
698
     * @dataProvider createUpdateRemoveData
699
     */
700
    public function testUpdate($exception): void
701
    {
702
        $registry = $this->createMock(RegistryInterface::class);
703
704
        $entityManger = $this->createMock(EntityManager::class);
705
706
        $registry->expects($this->once())
707
            ->method('getManagerForClass')
708
            ->willReturn($entityManger);
709
710
        $entityManger->expects($this->once())
711
            ->method('persist');
712
713
        $entityManger->expects($this->once())
714
            ->method('flush')
715
            ->willThrowException($exception);
716
717
        $model = new ModelManager($registry);
0 ignored issues
show
Documentation introduced by
$registry is of type object<PHPUnit\Framework\MockObject\MockObject>, but the function expects a object<Symfony\Bridge\Doctrine\RegistryInterface>.

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...
718
719
        $this->expectException(ModelManagerException::class);
720
721
        $model->update(new VersionedEntity());
722
    }
723
724
    /**
725
     * @dataProvider createUpdateRemoveData
726
     */
727
    public function testRemove($exception): void
728
    {
729
        $registry = $this->createMock(RegistryInterface::class);
730
731
        $entityManger = $this->createMock(EntityManager::class);
732
733
        $registry->expects($this->once())
734
            ->method('getManagerForClass')
735
            ->willReturn($entityManger);
736
737
        $entityManger->expects($this->once())
738
            ->method('remove');
739
740
        $entityManger->expects($this->once())
741
            ->method('flush')
742
            ->willThrowException($exception);
743
744
        $model = new ModelManager($registry);
0 ignored issues
show
Documentation introduced by
$registry is of type object<PHPUnit\Framework\MockObject\MockObject>, but the function expects a object<Symfony\Bridge\Doctrine\RegistryInterface>.

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...
745
746
        $this->expectException(ModelManagerException::class);
747
748
        $model->delete(new VersionedEntity());
749
    }
750
751
    public function testFindBadId(): void
752
    {
753
        $registry = $this->createMock(RegistryInterface::class);
754
755
        $model = new ModelManager($registry);
0 ignored issues
show
Documentation introduced by
$registry is of type object<PHPUnit\Framework\MockObject\MockObject>, but the function expects a object<Symfony\Bridge\Doctrine\RegistryInterface>.

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...
756
757
        $this->assertNull($model->find('notImportant', null));
758
    }
759
760
    public function testGetUrlsafeIdentifierException(): void
761
    {
762
        $registry = $this->createMock(RegistryInterface::class);
763
764
        $model = new ModelManager($registry);
0 ignored issues
show
Documentation introduced by
$registry is of type object<PHPUnit\Framework\MockObject\MockObject>, but the function expects a object<Symfony\Bridge\Doctrine\RegistryInterface>.

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...
765
766
        $this->expectException(\RuntimeException::class);
767
768
        $model->getNormalizedIdentifier('test');
0 ignored issues
show
Documentation introduced by
'test' is of type string, but the function expects a object.

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...
769
    }
770
771
    public function testGetUrlsafeIdentifierNull(): void
772
    {
773
        $registry = $this->createMock(RegistryInterface::class);
774
775
        $model = new ModelManager($registry);
0 ignored issues
show
Documentation introduced by
$registry is of type object<PHPUnit\Framework\MockObject\MockObject>, but the function expects a object<Symfony\Bridge\Doctrine\RegistryInterface>.

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...
776
777
        $this->assertNull($model->getNormalizedIdentifier(null));
0 ignored issues
show
Documentation introduced by
null is of type null, but the function expects a object.

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...
778
    }
779
780
    private function getMetadata($class, $isVersioned)
781
    {
782
        $metadata = new ClassMetadata($class);
783
784
        $metadata->isVersioned = $isVersioned;
785
786
        if ($isVersioned) {
787
            $versionField = 'version';
788
            $metadata->versionField = $versionField;
789
            $metadata->reflFields[$versionField] = new \ReflectionProperty($class, $versionField);
790
        }
791
792
        return $metadata;
793
    }
794
}
795