Completed
Pull Request — 3.x (#928)
by
unknown
02:42
created

ModelManagerTest::testGetEntityManagerException()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

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