Completed
Push — master ( 5a7237...3d9ddd )
by Grégoire
12s queued 10s
created

ModelManagerTest   B

Complexity

Total Complexity 42

Size/Duplication

Total Lines 817
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 15

Importance

Changes 0
Metric Value
wmc 42
lcom 1
cbo 15
dl 0
loc 817
rs 8.823
c 0
b 0
f 0

32 Methods

Rating   Name   Duplication   Size   Complexity  
A setUpBeforeClass() 0 12 4
B testSortParameters() 0 55 1
A getVersionDataProvider() 0 7 1
A testGetVersion() 0 23 2
A lockDataProvider() 0 8 1
A testLock() 0 37 3
B testGetParentMetadataForProperty() 0 64 2
A getMetadataForEmbeddedEntity() 0 14 1
A getMetadataForSubEmbeddedEntity() 0 14 1
A getMetadataForAssociatedEntity() 0 31 1
A getMetadataForContainerEntity() 0 39 1
A testNonIntegerIdentifierType() 0 49 1
A testIntegerIdentifierType() 0 49 1
A testAssociationIdentifierType() 0 44 1
A getSortableInDataSourceIteratorDataProvider() 0 9 1
B testSortableInDataSourceIterator() 0 58 3
A testModelReverseTransform() 0 34 1
A testCollections() 0 23 1
A testModelTransform() 0 9 1
A testGetPaginationParameters() 0 21 1
A testGetModelInstanceException() 0 10 1
A testGetModelInstanceForProtectedEntity() 0 8 1
A testGetEntityManagerException() 0 10 1
A testGetNewFieldDescriptionInstanceException() 0 10 1
A testCreate() 0 23 1
A createUpdateRemoveData() 0 11 1
A testUpdate() 0 23 1
A testRemove() 0 23 1
A testFindBadId() 0 8 1
A testGetUrlsafeIdentifierException() 0 10 1
A testGetUrlsafeIdentifierNull() 0 8 1
A getMetadata() 0 14 2

How to fix   Complexity   

Complex Class

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

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

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

1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of the Sonata Project package.
7
 *
8
 * (c) Thomas Rabaix <[email protected]>
9
 *
10
 * For the full copyright and license information, please view the LICENSE
11
 * file that was distributed with this source code.
12
 */
13
14
namespace Sonata\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\ProductIdType;
41
use Sonata\DoctrineORMAdminBundle\Tests\Fixtures\DoctrineType\UuidBinaryType;
42
use Sonata\DoctrineORMAdminBundle\Tests\Fixtures\DoctrineType\UuidType;
43
use Sonata\DoctrineORMAdminBundle\Tests\Fixtures\Entity\AbstractEntity;
44
use Sonata\DoctrineORMAdminBundle\Tests\Fixtures\Entity\AssociatedEntity;
45
use Sonata\DoctrineORMAdminBundle\Tests\Fixtures\Entity\ContainerEntity;
46
use Sonata\DoctrineORMAdminBundle\Tests\Fixtures\Entity\Embeddable\EmbeddedEntity;
47
use Sonata\DoctrineORMAdminBundle\Tests\Fixtures\Entity\Embeddable\SubEmbeddedEntity;
48
use Sonata\DoctrineORMAdminBundle\Tests\Fixtures\Entity\Product;
49
use Sonata\DoctrineORMAdminBundle\Tests\Fixtures\Entity\ProductId;
50
use Sonata\DoctrineORMAdminBundle\Tests\Fixtures\Entity\ProtectedEntity;
51
use Sonata\DoctrineORMAdminBundle\Tests\Fixtures\Entity\SimpleEntity;
52
use Sonata\DoctrineORMAdminBundle\Tests\Fixtures\Entity\UuidEntity;
53
use Sonata\DoctrineORMAdminBundle\Tests\Fixtures\Entity\VersionedEntity;
54
use Sonata\DoctrineORMAdminBundle\Tests\Fixtures\Util\NonIntegerIdentifierTestClass;
55
use Symfony\Bridge\Doctrine\RegistryInterface;
56
57
class ModelManagerTest extends TestCase
58
{
59
    public static function setUpBeforeClass(): void
60
    {
61
        if (!Type::hasType(UuidType::NAME)) {
62
            Type::addType(UuidType::NAME, UuidType::class);
63
        }
64
        if (!Type::hasType(UuidBinaryType::NAME)) {
65
            Type::addType(UuidBinaryType::NAME, UuidBinaryType::class);
66
        }
67
        if (!Type::hasType(ProductIdType::NAME)) {
68
            Type::addType(ProductIdType::NAME, ProductIdType::class);
69
        }
70
    }
71
72
    public function testSortParameters(): void
73
    {
74
        $registry = $this->createMock(RegistryInterface::class);
75
76
        $manager = new ModelManager($registry);
77
78
        $datagrid1 = $this->createMock(Datagrid::class);
79
        $datagrid2 = $this->createMock(Datagrid::class);
80
81
        $field1 = new FieldDescription();
82
        $field1->setName('field1');
83
84
        $field2 = new FieldDescription();
85
        $field2->setName('field2');
86
87
        $field3 = new FieldDescription();
88
        $field3->setName('field3');
89
        $field3->setOption('sortable', 'field3sortBy');
90
91
        $datagrid1
92
            ->expects($this->any())
93
            ->method('getValues')
94
            ->willReturn([
95
                '_sort_by' => $field1,
96
                '_sort_order' => 'ASC',
97
            ]);
98
99
        $datagrid2
100
            ->expects($this->any())
101
            ->method('getValues')
102
            ->willReturn([
103
                '_sort_by' => $field3,
104
                '_sort_order' => 'ASC',
105
            ]);
106
107
        $parameters = $manager->getSortParameters($field1, $datagrid1);
108
109
        $this->assertSame('DESC', $parameters['filter']['_sort_order']);
110
        $this->assertSame('field1', $parameters['filter']['_sort_by']);
111
112
        $parameters = $manager->getSortParameters($field2, $datagrid1);
113
114
        $this->assertSame('ASC', $parameters['filter']['_sort_order']);
115
        $this->assertSame('field2', $parameters['filter']['_sort_by']);
116
117
        $parameters = $manager->getSortParameters($field3, $datagrid1);
118
119
        $this->assertSame('ASC', $parameters['filter']['_sort_order']);
120
        $this->assertSame('field3sortBy', $parameters['filter']['_sort_by']);
121
122
        $parameters = $manager->getSortParameters($field3, $datagrid2);
123
124
        $this->assertSame('DESC', $parameters['filter']['_sort_order']);
125
        $this->assertSame('field3sortBy', $parameters['filter']['_sort_by']);
126
    }
127
128
    public function getVersionDataProvider(): array
129
    {
130
        return [
131
            [true],
132
            [false],
133
        ];
134
    }
135
136
    /**
137
     * @dataProvider getVersionDataProvider
138
     */
139
    public function testGetVersion($isVersioned): void
140
    {
141
        $object = new VersionedEntity();
142
143
        $modelManager = $this->getMockBuilder(ModelManager::class)
144
            ->disableOriginalConstructor()
145
            ->setMethods(['getMetadata'])
146
            ->getMock();
147
148
        $metadata = $this->getMetadata(\get_class($object), $isVersioned);
149
150
        $modelManager->expects($this->any())
151
            ->method('getMetadata')
152
            ->willReturn($metadata);
153
154
        if ($isVersioned) {
155
            $object->version = 123;
156
157
            $this->assertNotNull($modelManager->getLockVersion($object));
158
        } else {
159
            $this->assertNull($modelManager->getLockVersion($object));
160
        }
161
    }
162
163
    public function lockDataProvider(): array
164
    {
165
        return [
166
            [true,  false],
167
            [true,  true],
168
            [false, false],
169
        ];
170
    }
171
172
    /**
173
     * @dataProvider lockDataProvider
174
     */
175
    public function testLock($isVersioned, $expectsException): void
176
    {
177
        $object = new VersionedEntity();
178
179
        $em = $this->getMockBuilder(EntityManager::class)
180
            ->disableOriginalConstructor()
181
            ->setMethods(['lock'])
182
            ->getMock();
183
184
        $modelManager = $this->getMockBuilder(ModelManager::class)
185
            ->disableOriginalConstructor()
186
            ->setMethods(['getMetadata', 'getEntityManager'])
187
            ->getMock();
188
189
        $modelManager->expects($this->any())
190
            ->method('getEntityManager')
191
            ->willReturn($em);
192
193
        $metadata = $this->getMetadata(\get_class($object), $isVersioned);
194
195
        $modelManager->expects($this->any())
196
            ->method('getMetadata')
197
            ->willReturn($metadata);
198
199
        $em->expects($isVersioned ? $this->once() : $this->never())
200
            ->method('lock');
201
202
        if ($expectsException) {
203
            $em->expects($this->once())
204
                ->method('lock')
205
                ->will($this->throwException(OptimisticLockException::lockFailed($object)));
206
207
            $this->expectException(LockException::class);
208
        }
209
210
        $modelManager->lock($object, 123);
211
    }
212
213
    public function testGetParentMetadataForProperty(): void
214
    {
215
        if (version_compare(Version::VERSION, '2.5') < 0) {
216
            $this->markTestSkipped('Test for embeddables needs to run on Doctrine >= 2.5');
217
218
            return;
219
        }
220
221
        $containerEntityClass = ContainerEntity::class;
222
        $associatedEntityClass = AssociatedEntity::class;
223
        $embeddedEntityClass = EmbeddedEntity::class;
224
        $modelManagerClass = ModelManager::class;
225
226
        $em = $this->createMock(EntityManager::class);
227
228
        /** @var \PHPUnit_Framework_MockObject_MockObject|ModelManager $modelManager */
229
        $modelManager = $this->getMockBuilder($modelManagerClass)
230
            ->disableOriginalConstructor()
231
            ->setMethods(['getMetadata', 'getEntityManager'])
232
            ->getMock();
233
234
        $modelManager->expects($this->any())
0 ignored issues
show
Bug introduced by
The method expects() does not seem to exist on object<Sonata\DoctrineOR...dle\Model\ModelManager>.

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

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

Loading history...
235
            ->method('getEntityManager')
236
            ->willReturn($em);
237
238
        $containerEntityMetadata = $this->getMetadataForContainerEntity();
239
        $associatedEntityMetadata = $this->getMetadataForAssociatedEntity();
240
        $embeddedEntityMetadata = $this->getMetadataForEmbeddedEntity();
241
242
        $modelManager->expects($this->any())->method('getMetadata')
0 ignored issues
show
Bug introduced by
The method expects() does not seem to exist on object<Sonata\DoctrineOR...dle\Model\ModelManager>.

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

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

Loading history...
243
            ->willReturnMap(
244
245
                    [
246
                        [$containerEntityClass, $containerEntityMetadata],
247
                        [$embeddedEntityClass, $embeddedEntityMetadata],
248
                        [$associatedEntityClass, $associatedEntityMetadata],
249
                    ]
250
251
            );
252
253
        /** @var ClassMetadata $metadata */
254
        list($metadata, $lastPropertyName) = $modelManager
255
            ->getParentMetadataForProperty($containerEntityClass, 'plainField');
256
        $this->assertSame($metadata->fieldMappings[$lastPropertyName]['type'], 'integer');
257
258
        list($metadata, $lastPropertyName) = $modelManager
259
            ->getParentMetadataForProperty($containerEntityClass, 'associatedEntity.plainField');
260
        $this->assertSame($metadata->fieldMappings[$lastPropertyName]['type'], 'string');
261
262
        list($metadata, $lastPropertyName) = $modelManager
263
            ->getParentMetadataForProperty($containerEntityClass, 'embeddedEntity.plainField');
264
        $this->assertSame($metadata->fieldMappings[$lastPropertyName]['type'], 'boolean');
265
266
        list($metadata, $lastPropertyName) = $modelManager
267
            ->getParentMetadataForProperty($containerEntityClass, 'associatedEntity.embeddedEntity.plainField');
268
        $this->assertSame($metadata->fieldMappings[$lastPropertyName]['type'], 'boolean');
269
270
        list($metadata, $lastPropertyName) = $modelManager
271
            ->getParentMetadataForProperty(
272
                $containerEntityClass,
273
                'associatedEntity.embeddedEntity.subEmbeddedEntity.plainField'
274
            );
275
        $this->assertSame($metadata->fieldMappings[$lastPropertyName]['type'], 'boolean');
276
    }
277
278
    public function getMetadataForEmbeddedEntity()
279
    {
280
        $metadata = new ClassMetadata(EmbeddedEntity::class);
281
282
        $metadata->fieldMappings = [
283
            'plainField' => [
284
                'fieldName' => 'plainField',
285
                'columnName' => 'plainField',
286
                'type' => 'boolean',
287
            ],
288
        ];
289
290
        return $metadata;
291
    }
292
293
    public function getMetadataForSubEmbeddedEntity()
294
    {
295
        $metadata = new ClassMetadata(SubEmbeddedEntity::class);
296
297
        $metadata->fieldMappings = [
298
            'plainField' => [
299
                'fieldName' => 'plainField',
300
                'columnName' => 'plainField',
301
                'type' => 'boolean',
302
            ],
303
        ];
304
305
        return $metadata;
306
    }
307
308
    public function getMetadataForAssociatedEntity()
309
    {
310
        $embeddedEntityClass = EmbeddedEntity::class;
311
        $subEmbeddedEntityClass = SubEmbeddedEntity::class;
312
313
        $metadata = new ClassMetadata(AssociatedEntity::class);
314
315
        $metadata->fieldMappings = [
316
            'plainField' => [
317
                'fieldName' => 'plainField',
318
                'columnName' => 'plainField',
319
                'type' => 'string',
320
            ],
321
        ];
322
323
        $metadata->embeddedClasses['embeddedEntity'] = [
324
            'class' => $embeddedEntityClass,
325
            'columnPrefix' => 'embedded_entity_',
326
        ];
327
        $metadata->embeddedClasses['embeddedEntity.subEmbeddedEntity'] = [
328
            'class' => $subEmbeddedEntityClass,
329
            'columnPrefix' => 'embedded_entity_sub_embedded_entity_',
330
            'declaredField' => 'embeddedEntity',
331
            'originalField' => 'subEmbeddedEntity',
332
        ];
333
334
        $metadata->inlineEmbeddable('embeddedEntity', $this->getMetadataForEmbeddedEntity());
335
        $metadata->inlineEmbeddable('embeddedEntity.subEmbeddedEntity', $this->getMetadataForSubEmbeddedEntity());
336
337
        return $metadata;
338
    }
339
340
    public function getMetadataForContainerEntity()
341
    {
342
        $containerEntityClass = ContainerEntity::class;
343
        $associatedEntityClass = AssociatedEntity::class;
344
        $embeddedEntityClass = EmbeddedEntity::class;
345
        $subEmbeddedEntityClass = SubEmbeddedEntity::class;
346
347
        $metadata = new ClassMetadata($containerEntityClass);
348
349
        $metadata->fieldMappings = [
350
            'plainField' => [
351
                'fieldName' => 'plainField',
352
                'columnName' => 'plainField',
353
                'type' => 'integer',
354
            ],
355
        ];
356
357
        $metadata->associationMappings['associatedEntity'] = [
358
            'fieldName' => 'associatedEntity',
359
            'targetEntity' => $associatedEntityClass,
360
            'sourceEntity' => $containerEntityClass,
361
        ];
362
363
        $metadata->embeddedClasses['embeddedEntity'] = [
364
            'class' => $embeddedEntityClass,
365
            'columnPrefix' => 'embeddedEntity',
366
        ];
367
        $metadata->embeddedClasses['embeddedEntity.subEmbeddedEntity'] = [
368
            'class' => $subEmbeddedEntityClass,
369
            'columnPrefix' => 'embedded_entity_sub_embedded_entity_',
370
            'declaredField' => 'embeddedEntity',
371
            'originalField' => 'subEmbeddedEntity',
372
        ];
373
374
        $metadata->inlineEmbeddable('embeddedEntity', $this->getMetadataForEmbeddedEntity());
375
        $metadata->inlineEmbeddable('embeddedEntity.subEmbeddedEntity', $this->getMetadataForSubEmbeddedEntity());
376
377
        return $metadata;
378
    }
379
380
    public function testNonIntegerIdentifierType(): void
381
    {
382
        $uuid = new NonIntegerIdentifierTestClass('efbcfc4b-8c43-4d42-aa4c-d707e55151ac');
383
        $entity = new UuidEntity($uuid);
384
385
        $meta = $this->createMock(ClassMetadata::class);
386
        $meta->expects($this->any())
387
            ->method('getIdentifierValues')
388
            ->willReturn([$entity->getId()]);
389
        $meta->expects($this->any())
390
            ->method('getTypeOfField')
391
            ->willReturn(UuidType::NAME);
392
393
        $mf = $this->createMock(ClassMetadataFactory::class);
394
        $mf->expects($this->any())
395
            ->method('getMetadataFor')
396
            ->willReturn($meta);
397
398
        $platform = $this->createMock(PostgreSqlPlatform::class);
399
        $platform->expects($this->any())
400
            ->method('hasDoctrineTypeMappingFor')
401
            ->with(UuidType::NAME)
402
            ->willReturn(false);
403
        $platform->expects($this->never())
404
            ->method('getDoctrineTypeMapping');
405
406
        $conn = $this->createMock(Connection::class);
407
        $conn->expects($this->any())
408
            ->method('getDatabasePlatform')
409
            ->willReturn($platform);
410
411
        $em = $this->createMock(EntityManager::class);
412
        $em->expects($this->any())
413
            ->method('getMetadataFactory')
414
            ->willReturn($mf);
415
        $em->expects($this->any())
416
            ->method('getConnection')
417
            ->willReturn($conn);
418
419
        $registry = $this->createMock(RegistryInterface::class);
420
        $registry->expects($this->any())
421
            ->method('getManagerForClass')
422
            ->willReturn($em);
423
424
        $manager = new ModelManager($registry);
425
        $result = $manager->getIdentifierValues($entity);
426
427
        $this->assertSame($entity->getId()->toString(), $result[0]);
428
    }
429
430
    public function testIntegerIdentifierType(): void
431
    {
432
        $id = new ProductId(12345);
433
        $entity = new Product($id, 'Some product');
434
435
        $meta = $this->createMock(ClassMetadata::class);
436
        $meta->expects($this->any())
437
            ->method('getIdentifierValues')
438
            ->willReturn([$entity->getId()]);
439
        $meta->expects($this->any())
440
            ->method('getTypeOfField')
441
            ->willReturn(ProductIdType::NAME);
442
443
        $mf = $this->createMock(ClassMetadataFactory::class);
444
        $mf->expects($this->any())
445
            ->method('getMetadataFor')
446
            ->willReturn($meta);
447
448
        $platform = $this->createMock(PostgreSqlPlatform::class);
449
        $platform->expects($this->any())
450
            ->method('hasDoctrineTypeMappingFor')
451
            ->with(ProductIdType::NAME)
452
            ->willReturn(false);
453
        $platform->expects($this->never())
454
            ->method('getDoctrineTypeMapping');
455
456
        $conn = $this->createMock(Connection::class);
457
        $conn->expects($this->any())
458
            ->method('getDatabasePlatform')
459
            ->willReturn($platform);
460
461
        $em = $this->createMock(EntityManager::class);
462
        $em->expects($this->any())
463
            ->method('getMetadataFactory')
464
            ->willReturn($mf);
465
        $em->expects($this->any())
466
            ->method('getConnection')
467
            ->willReturn($conn);
468
469
        $registry = $this->createMock(RegistryInterface::class);
470
        $registry->expects($this->any())
471
            ->method('getManagerForClass')
472
            ->willReturn($em);
473
474
        $manager = new ModelManager($registry);
475
        $result = $manager->getIdentifierValues($entity);
476
477
        $this->assertSame((string) $entity->getId()->getId(), $result[0]);
478
    }
479
480
    public function testAssociationIdentifierType(): void
481
    {
482
        $entity = new ContainerEntity(new AssociatedEntity(42, new EmbeddedEntity()), new EmbeddedEntity());
483
484
        $meta = $this->createMock(ClassMetadata::class);
485
        $meta->expects($this->any())
486
            ->method('getIdentifierValues')
487
            ->willReturn([$entity->getAssociatedEntity()->getPlainField()]);
488
        $meta->expects($this->any())
489
            ->method('getTypeOfField')
490
            ->willReturn(null);
491
492
        $mf = $this->createMock(ClassMetadataFactory::class);
493
        $mf->expects($this->any())
494
            ->method('getMetadataFor')
495
            ->willReturn($meta);
496
497
        $platform = $this->createMock(PostgreSqlPlatform::class);
498
        $platform->expects($this->never())
499
            ->method('hasDoctrineTypeMappingFor');
500
501
        $conn = $this->createMock(Connection::class);
502
        $conn->expects($this->any())
503
            ->method('getDatabasePlatform')
504
            ->willReturn($platform);
505
506
        $em = $this->createMock(EntityManager::class);
507
        $em->expects($this->any())
508
            ->method('getMetadataFactory')
509
            ->willReturn($mf);
510
        $em->expects($this->any())
511
            ->method('getConnection')
512
            ->willReturn($conn);
513
514
        $registry = $this->createMock(RegistryInterface::class);
515
        $registry->expects($this->any())
516
            ->method('getManagerForClass')
517
            ->willReturn($em);
518
519
        $manager = new ModelManager($registry);
520
        $result = $manager->getIdentifierValues($entity);
521
522
        $this->assertSame(42, $result[0]);
523
    }
524
525
    /**
526
     * [sortBy, sortOrder, isAddOrderBy].
527
     */
528
    public function getSortableInDataSourceIteratorDataProvider(): array
529
    {
530
        return [
531
            [null, null, false],
532
            ['', 'ASC', false],
533
            ['field', 'ASC', true],
534
            ['field', null, true],
535
        ];
536
    }
537
538
    /**
539
     * @dataProvider getSortableInDataSourceIteratorDataProvider
540
     *
541
     * @param string|null $sortBy
542
     * @param string|null $sortOrder
543
     * @param bool        $isAddOrderBy
544
     */
545
    public function testSortableInDataSourceIterator($sortBy, $sortOrder, $isAddOrderBy): void
546
    {
547
        $datagrid = $this->getMockForAbstractClass(DatagridInterface::class);
548
        $configuration = $this->getMockBuilder(Configuration::class)->getMock();
549
        $configuration->expects($this->any())
550
            ->method('getDefaultQueryHints')
551
            ->willReturn([]);
552
553
        $em = $this->getMockBuilder(EntityManager::class)
554
            ->disableOriginalConstructor()
555
            ->getMock();
556
557
        $em->expects($this->any())
558
            ->method('getConfiguration')
559
            ->willReturn($configuration);
560
561
        $queryBuilder = $this->getMockBuilder(QueryBuilder::class)
562
            ->setConstructorArgs([$em])
563
            ->getMock();
564
        $query = new Query($em);
565
566
        $proxyQuery = $this->getMockBuilder(ProxyQuery::class)
567
            ->setConstructorArgs([$queryBuilder])
568
            ->setMethods(['getSortBy', 'getSortOrder', 'getRootAliases'])
569
            ->getMock();
570
571
        $proxyQuery->expects($this->any())
572
            ->method('getSortOrder')
573
            ->willReturn($sortOrder);
574
575
        $proxyQuery->expects($this->any())
576
            ->method('getSortBy')
577
            ->willReturn($sortBy);
578
579
        $queryBuilder->expects($isAddOrderBy ? $this->atLeastOnce() : $this->never())
580
            ->method('addOrderBy');
581
582
        $proxyQuery->expects($this->any())
583
            ->method('getRootAliases')
584
            ->willReturn(['a']);
585
586
        $queryBuilder->expects($this->any())
587
            ->method('getQuery')
588
            ->willReturn($query);
589
590
        $datagrid->expects($this->any())
591
            ->method('getQuery')
592
            ->willReturn($proxyQuery);
593
594
        $registry = $this->getMockBuilder(RegistryInterface::class)->getMock();
595
        $manager = new ModelManager($registry);
596
        $manager->getDataSourceIterator($datagrid, []);
597
598
        if ($isAddOrderBy) {
599
            $this->assertArrayHasKey($key = 'doctrine.customTreeWalkers', $hints = $query->getHints());
600
            $this->assertContains(OrderByToSelectWalker::class, $hints[$key]);
601
        }
602
    }
603
604
    public function testModelReverseTransform(): void
605
    {
606
        $class = SimpleEntity::class;
607
608
        $metadataFactory = $this->createMock(ClassMetadataFactory::class);
609
        $modelManager = $this->createMock(ObjectManager::class);
610
        $registry = $this->createMock(RegistryInterface::class);
611
612
        $classMetadata = new ClassMetadata($class);
613
        $classMetadata->reflClass = new \ReflectionClass($class);
614
615
        $modelManager->expects($this->once())
616
            ->method('getMetadataFactory')
617
            ->willReturn($metadataFactory);
618
        $metadataFactory->expects($this->once())
619
            ->method('getMetadataFor')
620
            ->with($class)
621
            ->willReturn($classMetadata);
622
        $registry->expects($this->once())
623
            ->method('getManagerForClass')
624
            ->with($class)
625
            ->willReturn($modelManager);
626
627
        $manager = new ModelManager($registry);
628
        $this->assertInstanceOf($class, $object = $manager->modelReverseTransform(
629
            $class,
630
            [
631
                'schmeckles' => 42,
632
                'multi_word_property' => 'hello',
633
            ]
634
        ));
635
        $this->assertSame(42, $object->getSchmeckles());
636
        $this->assertSame('hello', $object->getMultiWordProperty());
637
    }
638
639
    public function testCollections(): void
640
    {
641
        $registry = $this->createMock(RegistryInterface::class);
642
        $model = new ModelManager($registry);
643
644
        $collection = $model->getModelCollectionInstance('whyDoWeEvenHaveThisParameter');
645
        $this->assertInstanceOf(ArrayCollection::class, $collection);
646
647
        $item1 = 'item1';
648
        $item2 = 'item2';
649
        $model->collectionAddElement($collection, $item1);
650
        $model->collectionAddElement($collection, $item2);
651
652
        $this->assertTrue($model->collectionHasElement($collection, $item1));
653
654
        $model->collectionRemoveElement($collection, $item1);
655
656
        $this->assertFalse($model->collectionHasElement($collection, $item1));
657
658
        $model->collectionClear($collection);
659
660
        $this->assertTrue($collection->isEmpty());
661
    }
662
663
    public function testModelTransform(): void
664
    {
665
        $registry = $this->createMock(RegistryInterface::class);
666
        $model = new ModelManager($registry);
667
668
        $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...
669
670
        $this->assertSame('doWeNeedThisMethod', $result);
671
    }
672
673
    public function testGetPaginationParameters(): void
674
    {
675
        $datagrid = $this->createMock(DatagridInterface::class);
676
        $filter = $this->createMock(FilterInterface::class);
677
        $registry = $this->createMock(RegistryInterface::class);
678
679
        $datagrid->expects($this->once())
680
            ->method('getValues')
681
            ->willReturn(['_sort_by' => $filter]);
682
683
        $filter->expects($this->once())
684
            ->method('getName')
685
            ->willReturn($name = 'test');
686
687
        $model = new ModelManager($registry);
688
689
        $result = $model->getPaginationParameters($datagrid, $page = 5);
690
691
        $this->assertSame($page, $result['filter']['_page']);
692
        $this->assertSame($name, $result['filter']['_sort_by']);
693
    }
694
695
    public function testGetModelInstanceException(): void
696
    {
697
        $registry = $this->createMock(RegistryInterface::class);
698
699
        $model = new ModelManager($registry);
700
701
        $this->expectException(\RuntimeException::class);
702
703
        $model->getModelInstance(AbstractEntity::class);
704
    }
705
706
    public function testGetModelInstanceForProtectedEntity(): void
707
    {
708
        $registry = $this->createMock(RegistryInterface::class);
709
710
        $model = new ModelManager($registry);
711
712
        $this->assertInstanceOf(ProtectedEntity::class, $model->getModelInstance(ProtectedEntity::class));
713
    }
714
715
    public function testGetEntityManagerException(): void
716
    {
717
        $registry = $this->createMock(RegistryInterface::class);
718
719
        $model = new ModelManager($registry);
720
721
        $this->expectException(\RuntimeException::class);
722
723
        $model->getEntityManager(VersionedEntity::class);
724
    }
725
726
    public function testGetNewFieldDescriptionInstanceException(): void
727
    {
728
        $registry = $this->createMock(RegistryInterface::class);
729
730
        $model = new ModelManager($registry);
731
732
        $this->expectException(\RuntimeException::class);
733
734
        $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...
735
    }
736
737
    /**
738
     * @dataProvider createUpdateRemoveData
739
     */
740
    public function testCreate($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('persist');
752
753
        $entityManger->expects($this->once())
754
            ->method('flush')
755
            ->willThrowException($exception);
756
757
        $model = new ModelManager($registry);
758
759
        $this->expectException(ModelManagerException::class);
760
761
        $model->create(new VersionedEntity());
762
    }
763
764
    public function createUpdateRemoveData(): array
765
    {
766
        return [
767
            'PDOException' => [
768
                new \PDOException(),
769
            ],
770
            'DBALException' => [
771
                new DBALException(),
772
            ],
773
        ];
774
    }
775
776
    /**
777
     * @dataProvider createUpdateRemoveData
778
     */
779
    public function testUpdate($exception): void
780
    {
781
        $registry = $this->createMock(RegistryInterface::class);
782
783
        $entityManger = $this->createMock(EntityManager::class);
784
785
        $registry->expects($this->once())
786
            ->method('getManagerForClass')
787
            ->willReturn($entityManger);
788
789
        $entityManger->expects($this->once())
790
            ->method('persist');
791
792
        $entityManger->expects($this->once())
793
            ->method('flush')
794
            ->willThrowException($exception);
795
796
        $model = new ModelManager($registry);
797
798
        $this->expectException(ModelManagerException::class);
799
800
        $model->update(new VersionedEntity());
801
    }
802
803
    /**
804
     * @dataProvider createUpdateRemoveData
805
     */
806
    public function testRemove($exception): void
807
    {
808
        $registry = $this->createMock(RegistryInterface::class);
809
810
        $entityManger = $this->createMock(EntityManager::class);
811
812
        $registry->expects($this->once())
813
            ->method('getManagerForClass')
814
            ->willReturn($entityManger);
815
816
        $entityManger->expects($this->once())
817
            ->method('remove');
818
819
        $entityManger->expects($this->once())
820
            ->method('flush')
821
            ->willThrowException($exception);
822
823
        $model = new ModelManager($registry);
824
825
        $this->expectException(ModelManagerException::class);
826
827
        $model->delete(new VersionedEntity());
828
    }
829
830
    public function testFindBadId(): void
831
    {
832
        $registry = $this->createMock(RegistryInterface::class);
833
834
        $model = new ModelManager($registry);
835
836
        $this->assertNull($model->find('notImportant', null));
837
    }
838
839
    public function testGetUrlsafeIdentifierException(): void
840
    {
841
        $registry = $this->createMock(RegistryInterface::class);
842
843
        $model = new ModelManager($registry);
844
845
        $this->expectException(\RuntimeException::class);
846
847
        $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...
848
    }
849
850
    public function testGetUrlsafeIdentifierNull(): void
851
    {
852
        $registry = $this->createMock(RegistryInterface::class);
853
854
        $model = new ModelManager($registry);
855
856
        $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...
857
    }
858
859
    private function getMetadata($class, $isVersioned)
860
    {
861
        $metadata = new ClassMetadata($class);
862
863
        $metadata->isVersioned = $isVersioned;
864
865
        if ($isVersioned) {
866
            $versionField = 'version';
867
            $metadata->versionField = $versionField;
868
            $metadata->reflFields[$versionField] = new \ReflectionProperty($class, $versionField);
869
        }
870
871
        return $metadata;
872
    }
873
}
874