Completed
Push — 3.x ( 4822ba...dd9422 )
by Christian
01:45
created

ModelManagerTest   B

Complexity

Total Complexity 41

Size/Duplication

Total Lines 806
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 13

Importance

Changes 0
Metric Value
wmc 41
lcom 1
cbo 13
dl 0
loc 806
rs 8.914
c 0
b 0
f 0

32 Methods

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