Completed
Push — master ( 3a1d9e...3889ea )
by
unknown
01:54 queued 10s
created

testGetModelInstanceForProtectedEntity()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 8
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 0
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of the Sonata Project package.
7
 *
8
 * (c) Thomas Rabaix <[email protected]>
9
 *
10
 * For the full copyright and license information, please view the LICENSE
11
 * file that was distributed with this source code.
12
 */
13
14
namespace Sonata\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\ProtectedEntity;
47
use Sonata\DoctrineORMAdminBundle\Tests\Fixtures\Entity\SimpleEntity;
48
use Sonata\DoctrineORMAdminBundle\Tests\Fixtures\Entity\UuidEntity;
49
use Sonata\DoctrineORMAdminBundle\Tests\Fixtures\Entity\VersionedEntity;
50
use Sonata\DoctrineORMAdminBundle\Tests\Fixtures\Util\NonIntegerIdentifierTestClass;
51
use Symfony\Bridge\Doctrine\RegistryInterface;
52
53
class ModelManagerTest extends TestCase
54
{
55
    public static function setUpBeforeClass(): void
56
    {
57
        if (!Type::hasType('uuid')) {
58
            Type::addType('uuid', UuidType::class);
59
        }
60
    }
61
62
    public function testSortParameters(): void
63
    {
64
        $registry = $this->createMock(RegistryInterface::class);
65
66
        $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...
67
68
        $datagrid1 = $this->createMock(Datagrid::class);
69
        $datagrid2 = $this->createMock(Datagrid::class);
70
71
        $field1 = new FieldDescription();
72
        $field1->setName('field1');
73
74
        $field2 = new FieldDescription();
75
        $field2->setName('field2');
76
77
        $field3 = new FieldDescription();
78
        $field3->setName('field3');
79
        $field3->setOption('sortable', 'field3sortBy');
80
81
        $datagrid1
82
            ->expects($this->any())
83
            ->method('getValues')
84
            ->will($this->returnValue([
85
                '_sort_by' => $field1,
86
                '_sort_order' => 'ASC',
87
            ]));
88
89
        $datagrid2
90
            ->expects($this->any())
91
            ->method('getValues')
92
            ->will($this->returnValue([
93
                '_sort_by' => $field3,
94
                '_sort_order' => 'ASC',
95
            ]));
96
97
        $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...
98
99
        $this->assertSame('DESC', $parameters['filter']['_sort_order']);
100
        $this->assertSame('field1', $parameters['filter']['_sort_by']);
101
102
        $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...
103
104
        $this->assertSame('ASC', $parameters['filter']['_sort_order']);
105
        $this->assertSame('field2', $parameters['filter']['_sort_by']);
106
107
        $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...
108
109
        $this->assertSame('ASC', $parameters['filter']['_sort_order']);
110
        $this->assertSame('field3sortBy', $parameters['filter']['_sort_by']);
111
112
        $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...
113
114
        $this->assertSame('DESC', $parameters['filter']['_sort_order']);
115
        $this->assertSame('field3sortBy', $parameters['filter']['_sort_by']);
116
    }
117
118
    public function getVersionDataProvider(): array
119
    {
120
        return [
121
            [true],
122
            [false],
123
        ];
124
    }
125
126
    /**
127
     * @dataProvider getVersionDataProvider
128
     */
129
    public function testGetVersion($isVersioned): void
130
    {
131
        $object = new VersionedEntity();
132
133
        $modelManager = $this->getMockBuilder(ModelManager::class)
134
            ->disableOriginalConstructor()
135
            ->setMethods(['getMetadata'])
136
            ->getMock();
137
138
        $metadata = $this->getMetadata(\get_class($object), $isVersioned);
139
140
        $modelManager->expects($this->any())
141
            ->method('getMetadata')
142
            ->will($this->returnValue($metadata));
143
144
        if ($isVersioned) {
145
            $object->version = 123;
146
147
            $this->assertNotNull($modelManager->getLockVersion($object));
148
        } else {
149
            $this->assertNull($modelManager->getLockVersion($object));
150
        }
151
    }
152
153
    public function lockDataProvider(): array
154
    {
155
        return [
156
            [true,  false],
157
            [true,  true],
158
            [false, false],
159
        ];
160
    }
161
162
    /**
163
     * @dataProvider lockDataProvider
164
     */
165
    public function testLock($isVersioned, $expectsException): void
166
    {
167
        $object = new VersionedEntity();
168
169
        $em = $this->getMockBuilder(EntityManager::class)
170
            ->disableOriginalConstructor()
171
            ->setMethods(['lock'])
172
            ->getMock();
173
174
        $modelManager = $this->getMockBuilder(ModelManager::class)
175
            ->disableOriginalConstructor()
176
            ->setMethods(['getMetadata', 'getEntityManager'])
177
            ->getMock();
178
179
        $modelManager->expects($this->any())
180
            ->method('getEntityManager')
181
            ->will($this->returnValue($em));
182
183
        $metadata = $this->getMetadata(\get_class($object), $isVersioned);
184
185
        $modelManager->expects($this->any())
186
            ->method('getMetadata')
187
            ->will($this->returnValue($metadata));
188
189
        $em->expects($isVersioned ? $this->once() : $this->never())
190
            ->method('lock');
191
192
        if ($expectsException) {
193
            $em->expects($this->once())
194
                ->method('lock')
195
                ->will($this->throwException(OptimisticLockException::lockFailed($object)));
196
197
            $this->expectException(LockException::class);
198
        }
199
200
        $modelManager->lock($object, 123);
201
    }
202
203
    public function testGetParentMetadataForProperty(): void
204
    {
205
        if (version_compare(Version::VERSION, '2.5') < 0) {
206
            $this->markTestSkipped('Test for embeddables needs to run on Doctrine >= 2.5');
207
208
            return;
209
        }
210
211
        $containerEntityClass = ContainerEntity::class;
212
        $associatedEntityClass = AssociatedEntity::class;
213
        $embeddedEntityClass = EmbeddedEntity::class;
214
        $modelManagerClass = ModelManager::class;
215
216
        $em = $this->createMock(EntityManager::class);
217
218
        /** @var \PHPUnit_Framework_MockObject_MockObject|ModelManager $modelManager */
219
        $modelManager = $this->getMockBuilder($modelManagerClass)
220
            ->disableOriginalConstructor()
221
            ->setMethods(['getMetadata', 'getEntityManager'])
222
            ->getMock();
223
224
        $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...
225
            ->method('getEntityManager')
226
            ->will($this->returnValue($em));
227
228
        $containerEntityMetadata = $this->getMetadataForContainerEntity();
229
        $associatedEntityMetadata = $this->getMetadataForAssociatedEntity();
230
        $embeddedEntityMetadata = $this->getMetadataForEmbeddedEntity();
231
232
        $modelManager->expects($this->any())->method('getMetadata')
233
            ->will(
234
                $this->returnValueMap(
235
                    [
236
                        [$containerEntityClass, $containerEntityMetadata],
237
                        [$embeddedEntityClass, $embeddedEntityMetadata],
238
                        [$associatedEntityClass, $associatedEntityMetadata],
239
                    ]
240
                )
241
            );
242
243
        /** @var ClassMetadata $metadata */
244
        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...
245
            ->getParentMetadataForProperty($containerEntityClass, 'plainField');
246
        $this->assertSame($metadata->fieldMappings[$lastPropertyName]['type'], 'integer');
247
248
        list($metadata, $lastPropertyName) = $modelManager
249
            ->getParentMetadataForProperty($containerEntityClass, 'associatedEntity.plainField');
250
        $this->assertSame($metadata->fieldMappings[$lastPropertyName]['type'], 'string');
251
252
        list($metadata, $lastPropertyName) = $modelManager
253
            ->getParentMetadataForProperty($containerEntityClass, 'embeddedEntity.plainField');
254
        $this->assertSame($metadata->fieldMappings[$lastPropertyName]['type'], 'boolean');
255
256
        list($metadata, $lastPropertyName) = $modelManager
257
            ->getParentMetadataForProperty($containerEntityClass, 'associatedEntity.embeddedEntity.plainField');
258
        $this->assertSame($metadata->fieldMappings[$lastPropertyName]['type'], 'boolean');
259
260
        list($metadata, $lastPropertyName) = $modelManager
261
            ->getParentMetadataForProperty(
262
                $containerEntityClass,
263
                'associatedEntity.embeddedEntity.subEmbeddedEntity.plainField'
264
            );
265
        $this->assertSame($metadata->fieldMappings[$lastPropertyName]['type'], 'boolean');
266
    }
267
268
    public function getMetadataForEmbeddedEntity()
269
    {
270
        $metadata = new ClassMetadata(EmbeddedEntity::class);
271
272
        $metadata->fieldMappings = [
273
            'plainField' => [
274
                'fieldName' => 'plainField',
275
                'columnName' => 'plainField',
276
                'type' => 'boolean',
277
            ],
278
        ];
279
280
        return $metadata;
281
    }
282
283
    public function getMetadataForSubEmbeddedEntity()
284
    {
285
        $metadata = new ClassMetadata(SubEmbeddedEntity::class);
286
287
        $metadata->fieldMappings = [
288
            'plainField' => [
289
                'fieldName' => 'plainField',
290
                'columnName' => 'plainField',
291
                'type' => 'boolean',
292
            ],
293
        ];
294
295
        return $metadata;
296
    }
297
298
    public function getMetadataForAssociatedEntity()
299
    {
300
        $embeddedEntityClass = EmbeddedEntity::class;
301
        $subEmbeddedEntityClass = SubEmbeddedEntity::class;
302
303
        $metadata = new ClassMetadata(AssociatedEntity::class);
304
305
        $metadata->fieldMappings = [
306
            'plainField' => [
307
                'fieldName' => 'plainField',
308
                'columnName' => 'plainField',
309
                'type' => 'string',
310
            ],
311
        ];
312
313
        $metadata->embeddedClasses['embeddedEntity'] = [
314
            'class' => $embeddedEntityClass,
315
            'columnPrefix' => 'embedded_entity_',
316
        ];
317
        $metadata->embeddedClasses['embeddedEntity.subEmbeddedEntity'] = [
318
            'class' => $subEmbeddedEntityClass,
319
            'columnPrefix' => 'embedded_entity_sub_embedded_entity_',
320
            'declaredField' => 'embeddedEntity',
321
            'originalField' => 'subEmbeddedEntity',
322
        ];
323
324
        $metadata->inlineEmbeddable('embeddedEntity', $this->getMetadataForEmbeddedEntity());
325
        $metadata->inlineEmbeddable('embeddedEntity.subEmbeddedEntity', $this->getMetadataForSubEmbeddedEntity());
326
327
        return $metadata;
328
    }
329
330
    public function getMetadataForContainerEntity()
331
    {
332
        $containerEntityClass = ContainerEntity::class;
333
        $associatedEntityClass = AssociatedEntity::class;
334
        $embeddedEntityClass = EmbeddedEntity::class;
335
        $subEmbeddedEntityClass = SubEmbeddedEntity::class;
336
337
        $metadata = new ClassMetadata($containerEntityClass);
338
339
        $metadata->fieldMappings = [
340
            'plainField' => [
341
                'fieldName' => 'plainField',
342
                'columnName' => 'plainField',
343
                'type' => 'integer',
344
            ],
345
        ];
346
347
        $metadata->associationMappings['associatedEntity'] = [
348
            'fieldName' => 'associatedEntity',
349
            'targetEntity' => $associatedEntityClass,
350
            'sourceEntity' => $containerEntityClass,
351
        ];
352
353
        $metadata->embeddedClasses['embeddedEntity'] = [
354
            'class' => $embeddedEntityClass,
355
            'columnPrefix' => 'embeddedEntity',
356
        ];
357
        $metadata->embeddedClasses['embeddedEntity.subEmbeddedEntity'] = [
358
            'class' => $subEmbeddedEntityClass,
359
            'columnPrefix' => 'embedded_entity_sub_embedded_entity_',
360
            'declaredField' => 'embeddedEntity',
361
            'originalField' => 'subEmbeddedEntity',
362
        ];
363
364
        $metadata->inlineEmbeddable('embeddedEntity', $this->getMetadataForEmbeddedEntity());
365
        $metadata->inlineEmbeddable('embeddedEntity.subEmbeddedEntity', $this->getMetadataForSubEmbeddedEntity());
366
367
        return $metadata;
368
    }
369
370
    public function testNonIntegerIdentifierType(): void
371
    {
372
        $uuid = new NonIntegerIdentifierTestClass('efbcfc4b-8c43-4d42-aa4c-d707e55151ac');
373
        $entity = new UuidEntity($uuid);
374
375
        $meta = $this->createMock(ClassMetadata::class);
376
        $meta->expects($this->any())
377
            ->method('getIdentifierValues')
378
            ->willReturn([$entity->getId()]);
379
        $meta->expects($this->any())
380
            ->method('getTypeOfField')
381
            ->willReturn(UuidType::NAME);
382
383
        $mf = $this->createMock(ClassMetadataFactory::class);
384
        $mf->expects($this->any())
385
            ->method('getMetadataFor')
386
            ->willReturn($meta);
387
388
        $platform = $this->createMock(PostgreSqlPlatform::class);
389
390
        $conn = $this->createMock(Connection::class);
391
        $conn->expects($this->any())
392
            ->method('getDatabasePlatform')
393
            ->willReturn($platform);
394
395
        $em = $this->createMock(EntityManager::class);
396
        $em->expects($this->any())
397
            ->method('getMetadataFactory')
398
            ->willReturn($mf);
399
        $em->expects($this->any())
400
            ->method('getConnection')
401
            ->willReturn($conn);
402
403
        $registry = $this->createMock(RegistryInterface::class);
404
        $registry->expects($this->any())
405
            ->method('getManagerForClass')
406
            ->willReturn($em);
407
408
        $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...
409
        $result = $manager->getIdentifierValues($entity);
410
411
        $this->assertSame($entity->getId()->toString(), $result[0]);
412
    }
413
414
    public function testAssociationIdentifierType(): void
415
    {
416
        $entity = new ContainerEntity(new AssociatedEntity(42, new EmbeddedEntity()), new EmbeddedEntity());
417
418
        $meta = $this->createMock(ClassMetadata::class);
419
        $meta->expects($this->any())
420
            ->method('getIdentifierValues')
421
            ->willReturn([$entity->getAssociatedEntity()->getPlainField()]);
422
        $meta->expects($this->any())
423
            ->method('getTypeOfField')
424
            ->willReturn(null);
425
426
        $mf = $this->createMock(ClassMetadataFactory::class);
427
        $mf->expects($this->any())
428
            ->method('getMetadataFor')
429
            ->willReturn($meta);
430
431
        $platform = $this->createMock(PostgreSqlPlatform::class);
432
433
        $conn = $this->createMock(Connection::class);
434
        $conn->expects($this->any())
435
            ->method('getDatabasePlatform')
436
            ->willReturn($platform);
437
438
        $em = $this->createMock(EntityManager::class);
439
        $em->expects($this->any())
440
            ->method('getMetadataFactory')
441
            ->willReturn($mf);
442
        $em->expects($this->any())
443
            ->method('getConnection')
444
            ->willReturn($conn);
445
446
        $registry = $this->createMock(RegistryInterface::class);
447
        $registry->expects($this->any())
448
            ->method('getManagerForClass')
449
            ->willReturn($em);
450
451
        $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...
452
        $result = $manager->getIdentifierValues($entity);
453
454
        $this->assertSame(42, $result[0]);
455
    }
456
457
    /**
458
     * [sortBy, sortOrder, isAddOrderBy].
459
     *
460
     * @return array
461
     */
462
    public function getSortableInDataSourceIteratorDataProvider(): array
463
    {
464
        return [
465
            [null, null, false],
466
            ['', 'ASC', false],
467
            ['field', 'ASC', true],
468
            ['field', null, true],
469
        ];
470
    }
471
472
    /**
473
     * @dataProvider getSortableInDataSourceIteratorDataProvider
474
     *
475
     * @param string|null $sortBy
476
     * @param string|null $sortOrder
477
     * @param bool        $isAddOrderBy
478
     */
479
    public function testSortableInDataSourceIterator($sortBy, $sortOrder, $isAddOrderBy): void
480
    {
481
        $datagrid = $this->getMockForAbstractClass(DatagridInterface::class);
482
        $configuration = $this->getMockBuilder(Configuration::class)->getMock();
483
        $configuration->expects($this->any())
484
            ->method('getDefaultQueryHints')
485
            ->willReturn([]);
486
487
        $em = $this->getMockBuilder(EntityManager::class)
488
            ->disableOriginalConstructor()
489
            ->getMock();
490
491
        $em->expects($this->any())
492
            ->method('getConfiguration')
493
            ->willReturn($configuration);
494
495
        $queryBuilder = $this->getMockBuilder(QueryBuilder::class)
496
            ->setConstructorArgs([$em])
497
            ->getMock();
498
        $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...
499
500
        $proxyQuery = $this->getMockBuilder(ProxyQuery::class)
501
            ->setConstructorArgs([$queryBuilder])
502
            ->setMethods(['getSortBy', 'getSortOrder', 'getRootAliases'])
503
            ->getMock();
504
505
        $proxyQuery->expects($this->any())
506
            ->method('getSortOrder')
507
            ->willReturn($sortOrder);
508
509
        $proxyQuery->expects($this->any())
510
            ->method('getSortBy')
511
            ->willReturn($sortBy);
512
513
        $queryBuilder->expects($isAddOrderBy ? $this->atLeastOnce() : $this->never())
514
            ->method('addOrderBy');
515
516
        $proxyQuery->expects($this->any())
517
            ->method('getRootAliases')
518
            ->willReturn(['a']);
519
520
        $queryBuilder->expects($this->any())
521
            ->method('getQuery')
522
            ->willReturn($query);
523
524
        $datagrid->expects($this->any())
525
            ->method('getQuery')
526
            ->willReturn($proxyQuery);
527
528
        $registry = $this->getMockBuilder(RegistryInterface::class)->getMock();
529
        $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...
530
        $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...
531
532
        if ($isAddOrderBy) {
533
            $this->assertArrayHasKey($key = 'doctrine.customTreeWalkers', $hints = $query->getHints());
534
            $this->assertContains(OrderByToSelectWalker::class, $hints[$key]);
535
        }
536
    }
537
538
    public function testModelReverseTransform(): void
539
    {
540
        $class = SimpleEntity::class;
541
542
        $metadataFactory = $this->createMock(ClassMetadataFactory::class);
543
        $modelManager = $this->createMock(ObjectManager::class);
544
        $registry = $this->createMock(RegistryInterface::class);
545
546
        $classMetadata = new ClassMetadata($class);
547
        $classMetadata->reflClass = new \ReflectionClass($class);
548
549
        $modelManager->expects($this->once())
550
            ->method('getMetadataFactory')
551
            ->willReturn($metadataFactory);
552
        $metadataFactory->expects($this->once())
553
            ->method('getMetadataFor')
554
            ->with($class)
555
            ->willReturn($classMetadata);
556
        $registry->expects($this->once())
557
            ->method('getManagerForClass')
558
            ->with($class)
559
            ->willReturn($modelManager);
560
561
        $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...
562
        $this->assertInstanceOf($class, $object = $manager->modelReverseTransform(
563
            $class,
564
            [
565
                'schmeckles' => 42,
566
                'multi_word_property' => 'hello',
567
            ]
568
        ));
569
        $this->assertSame(42, $object->getSchmeckles());
570
        $this->assertSame('hello', $object->getMultiWordProperty());
571
    }
572
573
    public function testCollections(): void
574
    {
575
        $registry = $this->createMock(RegistryInterface::class);
576
        $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...
577
578
        $collection = $model->getModelCollectionInstance('whyDoWeEvenHaveThisParameter');
579
        $this->assertInstanceOf(ArrayCollection::class, $collection);
580
581
        $item1 = 'item1';
582
        $item2 = 'item2';
583
        $model->collectionAddElement($collection, $item1);
584
        $model->collectionAddElement($collection, $item2);
585
586
        $this->assertTrue($model->collectionHasElement($collection, $item1));
587
588
        $model->collectionRemoveElement($collection, $item1);
589
590
        $this->assertFalse($model->collectionHasElement($collection, $item1));
591
592
        $model->collectionClear($collection);
593
594
        $this->assertTrue($collection->isEmpty());
595
    }
596
597
    public function testModelTransform(): void
598
    {
599
        $registry = $this->createMock(RegistryInterface::class);
600
        $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...
601
602
        $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...
603
604
        $this->assertSame('doWeNeedThisMethod', $result);
605
    }
606
607
    public function testGetPaginationParameters(): void
608
    {
609
        $datagrid = $this->createMock(DatagridInterface::class);
610
        $filter = $this->createMock(FilterInterface::class);
611
        $registry = $this->createMock(RegistryInterface::class);
612
613
        $datagrid->expects($this->once())
614
            ->method('getValues')
615
            ->willReturn(['_sort_by' => $filter]);
616
617
        $filter->expects($this->once())
618
            ->method('getName')
619
            ->willReturn($name = 'test');
620
621
        $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...
622
623
        $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...
624
625
        $this->assertSame($page, $result['filter']['_page']);
626
        $this->assertSame($name, $result['filter']['_sort_by']);
627
    }
628
629
    public function testGetModelInstanceException(): void
630
    {
631
        $registry = $this->createMock(RegistryInterface::class);
632
633
        $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...
634
635
        $this->expectException(\RuntimeException::class);
636
637
        $model->getModelInstance(AbstractEntity::class);
638
    }
639
640
    public function testGetModelInstanceForProtectedEntity(): void
641
    {
642
        $registry = $this->createMock(RegistryInterface::class);
643
644
        $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...
645
646
        $this->assertInstanceOf(ProtectedEntity::class, $model->getModelInstance(ProtectedEntity::class));
647
    }
648
649
    public function testGetEntityManagerException(): void
650
    {
651
        $registry = $this->createMock(RegistryInterface::class);
652
653
        $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...
654
655
        $this->expectException(\RuntimeException::class);
656
657
        $model->getEntityManager(VersionedEntity::class);
658
    }
659
660
    public function testGetNewFieldDescriptionInstanceException(): void
661
    {
662
        $registry = $this->createMock(RegistryInterface::class);
663
664
        $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...
665
666
        $this->expectException(\RuntimeException::class);
667
668
        $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...
669
    }
670
671
    /**
672
     * @dataProvider createUpdateRemoveData
673
     */
674
    public function testCreate($exception): void
675
    {
676
        $registry = $this->createMock(RegistryInterface::class);
677
678
        $entityManger = $this->createMock(EntityManager::class);
679
680
        $registry->expects($this->once())
681
            ->method('getManagerForClass')
682
            ->willReturn($entityManger);
683
684
        $entityManger->expects($this->once())
685
            ->method('persist');
686
687
        $entityManger->expects($this->once())
688
            ->method('flush')
689
            ->willThrowException($exception);
690
691
        $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...
692
693
        $this->expectException(ModelManagerException::class);
694
695
        $model->create(new VersionedEntity());
696
    }
697
698
    public function createUpdateRemoveData(): array
699
    {
700
        return [
701
            'PDOException' => [
702
                new \PDOException(),
703
            ],
704
            'DBALException' => [
705
                new DBALException(),
706
            ],
707
        ];
708
    }
709
710
    /**
711
     * @dataProvider createUpdateRemoveData
712
     */
713
    public function testUpdate($exception): void
714
    {
715
        $registry = $this->createMock(RegistryInterface::class);
716
717
        $entityManger = $this->createMock(EntityManager::class);
718
719
        $registry->expects($this->once())
720
            ->method('getManagerForClass')
721
            ->willReturn($entityManger);
722
723
        $entityManger->expects($this->once())
724
            ->method('persist');
725
726
        $entityManger->expects($this->once())
727
            ->method('flush')
728
            ->willThrowException($exception);
729
730
        $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...
731
732
        $this->expectException(ModelManagerException::class);
733
734
        $model->update(new VersionedEntity());
735
    }
736
737
    /**
738
     * @dataProvider createUpdateRemoveData
739
     */
740
    public function testRemove($exception): void
741
    {
742
        $registry = $this->createMock(RegistryInterface::class);
743
744
        $entityManger = $this->createMock(EntityManager::class);
745
746
        $registry->expects($this->once())
747
            ->method('getManagerForClass')
748
            ->willReturn($entityManger);
749
750
        $entityManger->expects($this->once())
751
            ->method('remove');
752
753
        $entityManger->expects($this->once())
754
            ->method('flush')
755
            ->willThrowException($exception);
756
757
        $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...
758
759
        $this->expectException(ModelManagerException::class);
760
761
        $model->delete(new VersionedEntity());
762
    }
763
764
    public function testFindBadId(): void
765
    {
766
        $registry = $this->createMock(RegistryInterface::class);
767
768
        $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...
769
770
        $this->assertNull($model->find('notImportant', null));
771
    }
772
773
    public function testGetUrlsafeIdentifierException(): void
774
    {
775
        $registry = $this->createMock(RegistryInterface::class);
776
777
        $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...
778
779
        $this->expectException(\RuntimeException::class);
780
781
        $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...
782
    }
783
784
    public function testGetUrlsafeIdentifierNull(): void
785
    {
786
        $registry = $this->createMock(RegistryInterface::class);
787
788
        $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...
789
790
        $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...
791
    }
792
793
    private function getMetadata($class, $isVersioned)
794
    {
795
        $metadata = new ClassMetadata($class);
796
797
        $metadata->isVersioned = $isVersioned;
798
799
        if ($isVersioned) {
800
            $versionField = 'version';
801
            $metadata->versionField = $versionField;
802
            $metadata->reflFields[$versionField] = new \ReflectionProperty($class, $versionField);
803
        }
804
805
        return $metadata;
806
    }
807
}
808