Completed
Pull Request — 3.x (#782)
by Grégoire
01:40
created

ModelManagerTest::testLock()   B

Complexity

Conditions 2
Paths 2

Size

Total Lines 34
Code Lines 23

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 34
rs 8.8571
c 0
b 0
f 0
cc 2
eloc 23
nc 2
nop 2
1
<?php
2
3
/*
4
 * This file is part of the Sonata Project package.
5
 *
6
 * (c) Thomas Rabaix <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Sonata\DoctrineORMAdminBundle\Tests\Model;
13
14
use Doctrine\Common\Persistence\ObjectManager;
15
use Doctrine\DBAL\Connection;
16
use Doctrine\DBAL\Platforms\PostgreSqlPlatform;
17
use Doctrine\DBAL\Types\Type;
18
use Doctrine\ORM\Configuration;
19
use Doctrine\ORM\EntityManager;
20
use Doctrine\ORM\Mapping\ClassMetadata;
21
use Doctrine\ORM\Mapping\ClassMetadataFactory;
22
use Doctrine\ORM\Mapping\ClassMetadata;
0 ignored issues
show
Bug introduced by
This code did not parse for me. Apparently, there is an error somewhere around this line:

Cannot use Doctrine\ORM\Mapping\ClassMetadata as ClassMetadata because the name is already in use
Loading history...
23
use Doctrine\ORM\OptimisticLockException;
24
use Doctrine\ORM\Query;
25
use Doctrine\ORM\QueryBuilder;
26
use Doctrine\ORM\Version;
27
use PHPUnit\Framework\TestCase;
28
use Sonata\AdminBundle\Datagrid\Datagrid;
29
use Sonata\AdminBundle\Datagrid\DatagridInterface;
30
use Sonata\AdminBundle\Exception\LockException;
31
use Sonata\DoctrineORMAdminBundle\Admin\FieldDescription;
32
use Sonata\DoctrineORMAdminBundle\Datagrid\ProxyQuery;
33
use Sonata\DoctrineORMAdminBundle\Model\ModelManager;
34
use Sonata\DoctrineORMAdminBundle\Tests\Fixtures\DoctrineType\UuidType;
35
use Sonata\DoctrineORMAdminBundle\Tests\Fixtures\Entity\AssociatedEntity;
36
use Sonata\DoctrineORMAdminBundle\Tests\Fixtures\Entity\ContainerEntity;
37
use Sonata\DoctrineORMAdminBundle\Tests\Fixtures\Entity\Embeddable\EmbeddedEntity;
38
use Sonata\DoctrineORMAdminBundle\Tests\Fixtures\Entity\SimpleEntity;
39
use Sonata\DoctrineORMAdminBundle\Tests\Fixtures\Entity\UuidEntity;
40
use Sonata\DoctrineORMAdminBundle\Tests\Fixtures\Entity\VersionedEntity;
41
use Sonata\DoctrineORMAdminBundle\Tests\Fixtures\Util\NonIntegerIdentifierTestClass;
42
use Symfony\Bridge\Doctrine\RegistryInterface;
43
44
class ModelManagerTest extends TestCase
45
{
46
    public static function setUpBeforeClass()
47
    {
48
        if (!Type::hasType('uuid')) {
49
            Type::addType('uuid', UuidType::class);
50
        }
51
    }
52
53
    public function testSortParameters()
54
    {
55
        $registry = $this->createMock(RegistryInterface::class);
56
57
        $manager = new ModelManager($registry);
58
59
        $datagrid1 = $this->createMock(Datagrid::class);
60
        $datagrid2 = $this->createMock(Datagrid::class);
61
62
        $field1 = new FieldDescription();
63
        $field1->setName('field1');
64
65
        $field2 = new FieldDescription();
66
        $field2->setName('field2');
67
68
        $field3 = new FieldDescription();
69
        $field3->setName('field3');
70
        $field3->setOption('sortable', 'field3sortBy');
71
72
        $datagrid1
73
            ->expects($this->any())
74
            ->method('getValues')
75
            ->will($this->returnValue([
76
                '_sort_by' => $field1,
77
                '_sort_order' => 'ASC',
78
            ]));
79
80
        $datagrid2
81
            ->expects($this->any())
82
            ->method('getValues')
83
            ->will($this->returnValue([
84
                '_sort_by' => $field3,
85
                '_sort_order' => 'ASC',
86
            ]));
87
88
        $parameters = $manager->getSortParameters($field1, $datagrid1);
89
90
        $this->assertEquals('DESC', $parameters['filter']['_sort_order']);
91
        $this->assertEquals('field1', $parameters['filter']['_sort_by']);
92
93
        $parameters = $manager->getSortParameters($field2, $datagrid1);
94
95
        $this->assertEquals('ASC', $parameters['filter']['_sort_order']);
96
        $this->assertEquals('field2', $parameters['filter']['_sort_by']);
97
98
        $parameters = $manager->getSortParameters($field3, $datagrid1);
99
100
        $this->assertEquals('ASC', $parameters['filter']['_sort_order']);
101
        $this->assertEquals('field3sortBy', $parameters['filter']['_sort_by']);
102
103
        $parameters = $manager->getSortParameters($field3, $datagrid2);
104
105
        $this->assertEquals('DESC', $parameters['filter']['_sort_order']);
106
        $this->assertEquals('field3sortBy', $parameters['filter']['_sort_by']);
107
    }
108
109
    public function getVersionDataProvider()
110
    {
111
        return [
112
            [true],
113
            [false],
114
        ];
115
    }
116
117
    /**
118
     * @dataProvider getVersionDataProvider
119
     */
120
    public function testGetVersion($isVersioned)
121
    {
122
        $object = new VersionedEntity();
123
124
        $modelManager = $this->getMockBuilder(ModelManager::class)
125
            ->disableOriginalConstructor()
126
            ->setMethods(['getMetadata'])
127
            ->getMock();
128
129
        $metadata = $this->getMetadata(get_class($object), $isVersioned);
130
131
        $modelManager->expects($this->any())
132
            ->method('getMetadata')
133
            ->will($this->returnValue($metadata));
134
135
        if ($isVersioned) {
136
            $object->version = 123;
137
138
            $this->assertNotNull($modelManager->getLockVersion($object));
139
        } else {
140
            $this->assertNull($modelManager->getLockVersion($object));
141
        }
142
    }
143
144
    public function lockDataProvider()
145
    {
146
        return [
147
            [true,  false],
148
            [true,  true],
149
            [false, false],
150
        ];
151
    }
152
153
    /**
154
     * @dataProvider lockDataProvider
155
     */
156
    public function testLock($isVersioned, $expectsException)
157
    {
158
        $object = new VersionedEntity();
159
160
        $em = $this->getMockBuilder(EntityManager::class)
161
            ->disableOriginalConstructor()
162
            ->setMethods(['lock'])
163
            ->getMock();
164
165
        $modelManager = $this->getMockBuilder(ModelManager::class)
166
            ->disableOriginalConstructor()
167
            ->setMethods(['getMetadata', 'getEntityManager'])
168
            ->getMock();
169
170
        $modelManager->expects($this->any())
171
            ->method('getEntityManager')
172
            ->will($this->returnValue($em));
173
174
        $metadata = $this->getMetadata(get_class($object), $isVersioned);
175
176
        $modelManager->expects($this->any())
177
            ->method('getMetadata')
178
            ->will($this->returnValue($metadata));
179
180
        if ($expectsException) {
181
            $em->expects($this->once())
182
                ->method('lock')
183
                ->will($this->throwException(OptimisticLockException::lockFailed($object)));
184
185
            $this->expectException(LockException::class);
186
        }
187
188
        $modelManager->lock($object, 123);
189
    }
190
191
    public function testGetParentMetadataForProperty()
192
    {
193
        if (version_compare(Version::VERSION, '2.5') < 0) {
194
            $this->markTestSkipped('Test for embeddables needs to run on Doctrine >= 2.5');
195
196
            return;
197
        }
198
199
        $containerEntityClass = ContainerEntity::class;
200
        $associatedEntityClass = AssociatedEntity::class;
201
        $embeddedEntityClass = EmbeddedEntity::class;
202
        $modelManagerClass = ModelManager::class;
203
204
        $object = new ContainerEntity(new AssociatedEntity(null, new EmbeddedEntity()), new EmbeddedEntity());
205
206
        $em = $this->createMock(EntityManager::class);
207
208
        /** @var \PHPUnit_Framework_MockObject_MockObject|ModelManager $modelManager */
209
        $modelManager = $this->getMockBuilder($modelManagerClass)
210
            ->disableOriginalConstructor()
211
            ->setMethods(['getMetadata', 'getEntityManager'])
212
            ->getMock();
213
214
        $modelManager->expects($this->any())
215
            ->method('getEntityManager')
216
            ->will($this->returnValue($em));
217
218
        $containerEntityMetadata = $this->getMetadataForContainerEntity();
219
        $associatedEntityMetadata = $this->getMetadataForAssociatedEntity();
220
        $embeddedEntityMetadata = $this->getMetadataForEmbeddedEntity();
221
222
        $modelManager->expects($this->any())->method('getMetadata')
223
            ->will(
224
                $this->returnValueMap(
225
                    [
226
                        [$containerEntityClass, $containerEntityMetadata],
227
                        [$embeddedEntityClass, $embeddedEntityMetadata],
228
                        [$associatedEntityClass, $associatedEntityMetadata],
229
                    ]
230
                )
231
            );
232
233
        /** @var ClassMetadata $metadata */
234
        list($metadata, $lastPropertyName) = $modelManager
235
            ->getParentMetadataForProperty($containerEntityClass, 'plainField');
236
        $this->assertEquals($metadata->fieldMappings[$lastPropertyName]['type'], 'integer');
237
238
        list($metadata, $lastPropertyName) = $modelManager
239
            ->getParentMetadataForProperty($containerEntityClass, 'associatedEntity.plainField');
240
        $this->assertEquals($metadata->fieldMappings[$lastPropertyName]['type'], 'string');
241
242
        list($metadata, $lastPropertyName) = $modelManager
243
            ->getParentMetadataForProperty($containerEntityClass, 'embeddedEntity.plainField');
244
        $this->assertEquals($metadata->fieldMappings[$lastPropertyName]['type'], 'boolean');
245
246
        list($metadata, $lastPropertyName) = $modelManager
247
            ->getParentMetadataForProperty($containerEntityClass, 'associatedEntity.embeddedEntity.plainField');
248
        $this->assertEquals($metadata->fieldMappings[$lastPropertyName]['type'], 'boolean');
249
    }
250
251
    public function getMetadataForEmbeddedEntity()
252
    {
253
        $metadata = new ClassMetadata(EmbeddedEntity::class);
254
255
        $metadata->fieldMappings = [
256
            'plainField' => [
257
                'fieldName' => 'plainField',
258
                'columnName' => 'plainField',
259
                'type' => 'boolean',
260
            ],
261
        ];
262
263
        return $metadata;
264
    }
265
266
    public function getMetadataForAssociatedEntity()
267
    {
268
        $embeddedEntityClass = EmbeddedEntity::class;
269
270
        $metadata = new ClassMetadata(AssociatedEntity::class);
271
272
        $metadata->fieldMappings = [
273
            'plainField' => [
274
                'fieldName' => 'plainField',
275
                'columnName' => 'plainField',
276
                'type' => 'string',
277
            ],
278
        ];
279
280
        $metadata->embeddedClasses['embeddedEntity'] = [
281
            'class' => $embeddedEntityClass,
282
            'columnPrefix' => 'embeddedEntity',
283
        ];
284
285
        $metadata->inlineEmbeddable('embeddedEntity', $this->getMetadataForEmbeddedEntity());
286
287
        return $metadata;
288
    }
289
290
    public function getMetadataForContainerEntity()
291
    {
292
        $containerEntityClass = ContainerEntity::class;
293
        $associatedEntityClass = AssociatedEntity::class;
294
        $embeddedEntityClass = EmbeddedEntity::class;
295
296
        $metadata = new ClassMetadata($containerEntityClass);
297
298
        $metadata->fieldMappings = [
299
            'plainField' => [
300
                'fieldName' => 'plainField',
301
                'columnName' => 'plainField',
302
                'type' => 'integer',
303
            ],
304
        ];
305
306
        $metadata->associationMappings['associatedEntity'] = [
307
            'fieldName' => 'associatedEntity',
308
            'targetEntity' => $associatedEntityClass,
309
            'sourceEntity' => $containerEntityClass,
310
        ];
311
312
        $metadata->embeddedClasses['embeddedEntity'] = [
313
            'class' => $embeddedEntityClass,
314
            'columnPrefix' => 'embeddedEntity',
315
        ];
316
317
        $metadata->inlineEmbeddable('embeddedEntity', $this->getMetadataForEmbeddedEntity());
318
319
        return $metadata;
320
    }
321
322
    public function testNonIntegerIdentifierType()
323
    {
324
        $uuid = new NonIntegerIdentifierTestClass('efbcfc4b-8c43-4d42-aa4c-d707e55151ac');
325
        $entity = new UuidEntity($uuid);
326
327
        $meta = $this->createMock(ClassMetadata::class);
328
        $meta->expects($this->any())
329
            ->method('getIdentifierValues')
330
            ->willReturn([$entity->getId()]);
331
        $meta->expects($this->any())
332
            ->method('getTypeOfField')
333
            ->willReturn(UuidType::NAME);
334
335
        $mf = $this->createMock(ClassMetadataFactory::class);
336
        $mf->expects($this->any())
337
            ->method('getMetadataFor')
338
            ->willReturn($meta);
339
340
        $platform = $this->createMock(PostgreSqlPlatform::class);
341
342
        $conn = $this->createMock(Connection::class);
343
        $conn->expects($this->any())
344
            ->method('getDatabasePlatform')
345
            ->willReturn($platform);
346
347
        $em = $this->createMock(EntityManager::class);
348
        $em->expects($this->any())
349
            ->method('getMetadataFactory')
350
            ->willReturn($mf);
351
        $em->expects($this->any())
352
            ->method('getConnection')
353
            ->willReturn($conn);
354
355
        $registry = $this->createMock(RegistryInterface::class);
356
        $registry->expects($this->any())
357
            ->method('getManagerForClass')
358
            ->willReturn($em);
359
360
        $manager = new ModelManager($registry);
361
        $result = $manager->getIdentifierValues($entity);
362
363
        $this->assertEquals($entity->getId()->toString(), $result[0]);
364
    }
365
366
    public function testAssociationIdentifierType()
367
    {
368
        $entity = new ContainerEntity(new AssociatedEntity(42, new EmbeddedEntity()), new EmbeddedEntity());
369
370
        $meta = $this->createMock(ClassMetadata::class);
371
        $meta->expects($this->any())
372
            ->method('getIdentifierValues')
373
            ->willReturn([$entity->getAssociatedEntity()->getPlainField()]);
374
        $meta->expects($this->any())
375
            ->method('getTypeOfField')
376
            ->willReturn(null);
377
378
        $mf = $this->createMock(ClassMetadataFactory::class);
379
        $mf->expects($this->any())
380
            ->method('getMetadataFor')
381
            ->willReturn($meta);
382
383
        $platform = $this->createMock(PostgreSqlPlatform::class);
384
385
        $conn = $this->createMock(Connection::class);
386
        $conn->expects($this->any())
387
            ->method('getDatabasePlatform')
388
            ->willReturn($platform);
389
390
        $em = $this->createMock(EntityManager::class);
391
        $em->expects($this->any())
392
            ->method('getMetadataFactory')
393
            ->willReturn($mf);
394
        $em->expects($this->any())
395
            ->method('getConnection')
396
            ->willReturn($conn);
397
398
        $registry = $this->createMock(RegistryInterface::class);
399
        $registry->expects($this->any())
400
            ->method('getManagerForClass')
401
            ->willReturn($em);
402
403
        $manager = new ModelManager($registry);
404
        $result = $manager->getIdentifierValues($entity);
405
406
        $this->assertSame(42, $result[0]);
407
    }
408
409
    /**
410
     * [sortBy, sortOrder, isAddOrderBy].
411
     *
412
     * @return array
413
     */
414
    public function getSortableInDataSourceIteratorDataProvider()
415
    {
416
        return [
417
            [null, null, false],
418
            ['', 'ASC', false],
419
            ['field', 'ASC', true],
420
            ['field', null, true],
421
        ];
422
    }
423
424
    /**
425
     * @dataProvider getSortableInDataSourceIteratorDataProvider
426
     *
427
     * @param string|null $sortBy
428
     * @param string|null $sortOrder
429
     * @param bool        $isAddOrderBy
430
     */
431
    public function testSortableInDataSourceIterator($sortBy, $sortOrder, $isAddOrderBy)
432
    {
433
        $datagrid = $this->getMockForAbstractClass(DatagridInterface::class);
434
        $configuration = $this->getMockBuilder(Configuration::class)->getMock();
435
        $configuration->expects($this->any())
436
            ->method('getDefaultQueryHints')
437
            ->willReturn([]);
438
439
        $em = $this->getMockBuilder(EntityManager::class)
440
            ->disableOriginalConstructor()
441
            ->getMock();
442
443
        $em->expects($this->any())
444
            ->method('getConfiguration')
445
            ->willReturn($configuration);
446
447
        $queryBuilder = $this->getMockBuilder(QueryBuilder::class)
448
            ->setConstructorArgs([$em])
449
            ->getMock();
450
        $query = new Query($em);
451
452
        $proxyQuery = $this->getMockBuilder(ProxyQuery::class)
453
            ->setConstructorArgs([$queryBuilder])
454
            ->setMethods(['getSortBy', 'getSortOrder', 'getRootAliases'])
455
            ->getMock();
456
457
        $proxyQuery->expects($this->any())
458
            ->method('getSortOrder')
459
            ->willReturn($sortOrder);
460
461
        $proxyQuery->expects($this->any())
462
            ->method('getSortBy')
463
            ->willReturn($sortBy);
464
465
        $queryBuilder->expects($isAddOrderBy ? $this->atLeastOnce() : $this->never())
466
            ->method('addOrderBy');
467
468
        $proxyQuery->expects($this->any())
469
            ->method('getRootAliases')
470
            ->willReturn(['a']);
471
472
        $queryBuilder->expects($this->any())
473
            ->method('getQuery')
474
            ->willReturn($query);
475
476
        $datagrid->expects($this->any())
477
            ->method('getQuery')
478
            ->willReturn($proxyQuery);
479
480
        $registry = $this->getMockBuilder(RegistryInterface::class)->getMock();
481
        $manager = new ModelManager($registry);
482
        $manager->getDataSourceIterator($datagrid, []);
483
    }
484
485
    public function testModelReverseTransform()
486
    {
487
        $class = SimpleEntity::class;
488
489
        $metadataFactory = $this->createMock(ClassMetadataFactory::class);
490
        $modelManager = $this->createMock(ObjectManager::class);
491
        $registry = $this->createMock(RegistryInterface::class);
492
493
        $classMetadata = new ClassMetadata($class);
494
        $classMetadata->reflClass = new \ReflectionClass($class);
495
496
        $modelManager->expects($this->once())
497
            ->method('getMetadataFactory')
498
            ->willReturn($metadataFactory);
499
        $metadataFactory->expects($this->once())
500
            ->method('getMetadataFor')
501
            ->with($class)
502
            ->willReturn($classMetadata);
503
        $registry->expects($this->once())
504
            ->method('getManagerForClass')
505
            ->with($class)
506
            ->willReturn($modelManager);
507
508
        $manager = new ModelManager($registry);
509
        $this->assertInstanceOf($class, $object = $manager->modelReverseTransform(
510
            $class,
511
            [
512
                'schmeckles' => 42,
513
                'multi_word_property' => 'hello',
514
            ]
515
        ));
516
        $this->assertSame(42, $object->getSchmeckles());
517
        $this->assertSame('hello', $object->getMultiWordProperty());
518
    }
519
520
    private function getMetadata($class, $isVersioned)
521
    {
522
        $metadata = new ClassMetadata($class);
523
524
        $metadata->isVersioned = $isVersioned;
525
526
        if ($isVersioned) {
527
            $versionField = 'version';
528
            $metadata->versionField = $versionField;
529
            $metadata->reflFields[$versionField] = new \ReflectionProperty($class, $versionField);
530
        }
531
532
        return $metadata;
533
    }
534
}
535