Completed
Push — master ( 07d8e9...d15c89 )
by Christian
14:52
created

ModelManagerTest::getMetadata()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 14
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 14
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 8
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\DBAL\Types\Type;
15
use Doctrine\ORM\Mapping\ClassMetadata;
16
use Doctrine\ORM\Mapping\ClassMetadataInfo;
17
use Doctrine\ORM\OptimisticLockException;
18
use Doctrine\ORM\Query;
19
use Doctrine\ORM\Version;
20
use PHPUnit\Framework\TestCase;
21
use Sonata\DoctrineORMAdminBundle\Admin\FieldDescription;
22
use Sonata\DoctrineORMAdminBundle\Model\ModelManager;
23
use Sonata\DoctrineORMAdminBundle\Tests\Fixtures\DoctrineType\UuidType;
24
use Sonata\DoctrineORMAdminBundle\Tests\Fixtures\Entity\AssociatedEntity;
25
use Sonata\DoctrineORMAdminBundle\Tests\Fixtures\Entity\ContainerEntity;
26
use Sonata\DoctrineORMAdminBundle\Tests\Fixtures\Entity\Embeddable\EmbeddedEntity;
27
use Sonata\DoctrineORMAdminBundle\Tests\Fixtures\Entity\UuidEntity;
28
use Sonata\DoctrineORMAdminBundle\Tests\Fixtures\Entity\VersionedEntity;
29
use Sonata\DoctrineORMAdminBundle\Tests\Fixtures\Util\NonIntegerIdentifierTestClass;
30
31
class ModelManagerTest extends TestCase
32
{
33
    public static function setUpBeforeClass()
34
    {
35
        if (!Type::hasType('uuid')) {
36
            Type::addType('uuid', 'Sonata\DoctrineORMAdminBundle\Tests\Fixtures\DoctrineType\UuidType');
37
        }
38
    }
39
40
    public function testSortParameters()
41
    {
42
        $registry = $this->createMock('Symfony\Bridge\Doctrine\RegistryInterface');
43
44
        $manager = new ModelManager($registry);
45
46
        $datagrid1 = $this->createMock('Sonata\AdminBundle\Datagrid\Datagrid');
47
        $datagrid2 = $this->createMock('Sonata\AdminBundle\Datagrid\Datagrid');
48
49
        $field1 = new FieldDescription();
50
        $field1->setName('field1');
51
52
        $field2 = new FieldDescription();
53
        $field2->setName('field2');
54
55
        $field3 = new FieldDescription();
56
        $field3->setName('field3');
57
        $field3->setOption('sortable', 'field3sortBy');
58
59
        $datagrid1
60
            ->expects($this->any())
61
            ->method('getValues')
62
            ->will($this->returnValue([
63
                '_sort_by' => $field1,
64
                '_sort_order' => 'ASC',
65
            ]));
66
67
        $datagrid2
68
            ->expects($this->any())
69
            ->method('getValues')
70
            ->will($this->returnValue([
71
                '_sort_by' => $field3,
72
                '_sort_order' => 'ASC',
73
            ]));
74
75
        $parameters = $manager->getSortParameters($field1, $datagrid1);
76
77
        $this->assertEquals('DESC', $parameters['filter']['_sort_order']);
78
        $this->assertEquals('field1', $parameters['filter']['_sort_by']);
79
80
        $parameters = $manager->getSortParameters($field2, $datagrid1);
81
82
        $this->assertEquals('ASC', $parameters['filter']['_sort_order']);
83
        $this->assertEquals('field2', $parameters['filter']['_sort_by']);
84
85
        $parameters = $manager->getSortParameters($field3, $datagrid1);
86
87
        $this->assertEquals('ASC', $parameters['filter']['_sort_order']);
88
        $this->assertEquals('field3sortBy', $parameters['filter']['_sort_by']);
89
90
        $parameters = $manager->getSortParameters($field3, $datagrid2);
91
92
        $this->assertEquals('DESC', $parameters['filter']['_sort_order']);
93
        $this->assertEquals('field3sortBy', $parameters['filter']['_sort_by']);
94
    }
95
96
    public function getVersionDataProvider()
97
    {
98
        return [
99
            [true],
100
            [false],
101
        ];
102
    }
103
104
    /**
105
     * @dataProvider getVersionDataProvider
106
     */
107
    public function testGetVersion($isVersioned)
108
    {
109
        $object = new VersionedEntity();
110
111
        $modelManager = $this->getMockBuilder('Sonata\DoctrineORMAdminBundle\Model\ModelManager')
112
            ->disableOriginalConstructor()
113
            ->setMethods(['getMetadata'])
114
            ->getMock();
115
116
        $metadata = $this->getMetadata(get_class($object), $isVersioned);
117
118
        $modelManager->expects($this->any())
119
            ->method('getMetadata')
120
            ->will($this->returnValue($metadata));
121
122
        if ($isVersioned) {
123
            $object->version = 123;
124
125
            $this->assertNotNull($modelManager->getLockVersion($object));
126
        } else {
127
            $this->assertNull($modelManager->getLockVersion($object));
128
        }
129
    }
130
131
    public function lockDataProvider()
132
    {
133
        return [
134
            [true,  false],
135
            [true,  true],
136
            [false, false],
137
        ];
138
    }
139
140
    /**
141
     * @dataProvider lockDataProvider
142
     */
143
    public function testLock($isVersioned, $expectsException)
144
    {
145
        $object = new VersionedEntity();
146
147
        $em = $this->getMockBuilder('Doctrine\ORM\EntityManager')
148
            ->disableOriginalConstructor()
149
            ->setMethods(['lock'])
150
            ->getMock();
151
152
        $modelManager = $this->getMockBuilder('Sonata\DoctrineORMAdminBundle\Model\ModelManager')
153
            ->disableOriginalConstructor()
154
            ->setMethods(['getMetadata', 'getEntityManager'])
155
            ->getMock();
156
157
        $modelManager->expects($this->any())
158
            ->method('getEntityManager')
159
            ->will($this->returnValue($em));
160
161
        $metadata = $this->getMetadata(get_class($object), $isVersioned);
162
163
        $modelManager->expects($this->any())
164
            ->method('getMetadata')
165
            ->will($this->returnValue($metadata));
166
167
        if ($expectsException) {
168
            $em->expects($this->once())
169
                ->method('lock')
170
                ->will($this->throwException(OptimisticLockException::lockFailed($object)));
171
172
            $this->setExpectedException('Sonata\AdminBundle\Exception\LockException');
173
        }
174
175
        $modelManager->lock($object, 123);
176
    }
177
178
    public function testGetParentMetadataForProperty()
179
    {
180
        if (version_compare(Version::VERSION, '2.5') < 0) {
181
            $this->markTestSkipped('Test for embeddables needs to run on Doctrine >= 2.5');
182
183
            return;
184
        }
185
186
        $containerEntityClass = 'Sonata\DoctrineORMAdminBundle\Tests\Fixtures\Entity\ContainerEntity';
187
        $associatedEntityClass = 'Sonata\DoctrineORMAdminBundle\Tests\Fixtures\Entity\AssociatedEntity';
188
        $embeddedEntityClass = 'Sonata\DoctrineORMAdminBundle\Tests\Fixtures\Entity\Embeddable\EmbeddedEntity';
189
        $modelManagerClass = 'Sonata\DoctrineORMAdminBundle\Model\ModelManager';
190
191
        $object = new ContainerEntity(new AssociatedEntity(null, new EmbeddedEntity()), new EmbeddedEntity());
0 ignored issues
show
Unused Code introduced by
$object is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
192
193
        $em = $this->createMock('Doctrine\ORM\EntityManager');
194
195
        /** @var \PHPUnit_Framework_MockObject_MockObject|ModelManager $modelManager */
196
        $modelManager = $this->getMockBuilder($modelManagerClass)
197
            ->disableOriginalConstructor()
198
            ->setMethods(['getMetadata', 'getEntityManager'])
199
            ->getMock();
200
201
        $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...
202
            ->method('getEntityManager')
203
            ->will($this->returnValue($em));
204
205
        $containerEntityMetadata = $this->getMetadataForContainerEntity();
206
        $associatedEntityMetadata = $this->getMetadataForAssociatedEntity();
207
        $embeddedEntityMetadata = $this->getMetadataForEmbeddedEntity();
208
209
        $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...
210
            ->will(
211
                $this->returnValueMap(
212
                    [
213
                        [$containerEntityClass, $containerEntityMetadata],
214
                        [$embeddedEntityClass, $embeddedEntityMetadata],
215
                        [$associatedEntityClass, $associatedEntityMetadata],
216
                    ]
217
                )
218
            );
219
220
        /** @var ClassMetadata $metadata */
221
        list($metadata, $lastPropertyName) = $modelManager
222
            ->getParentMetadataForProperty($containerEntityClass, 'plainField');
223
        $this->assertEquals($metadata->fieldMappings[$lastPropertyName]['type'], 'integer');
224
225
        list($metadata, $lastPropertyName) = $modelManager
226
            ->getParentMetadataForProperty($containerEntityClass, 'associatedEntity.plainField');
227
        $this->assertEquals($metadata->fieldMappings[$lastPropertyName]['type'], 'string');
228
229
        list($metadata, $lastPropertyName) = $modelManager
230
            ->getParentMetadataForProperty($containerEntityClass, 'embeddedEntity.plainField');
231
        $this->assertEquals($metadata->fieldMappings[$lastPropertyName]['type'], 'boolean');
232
233
        list($metadata, $lastPropertyName) = $modelManager
234
            ->getParentMetadataForProperty($containerEntityClass, 'associatedEntity.embeddedEntity.plainField');
235
        $this->assertEquals($metadata->fieldMappings[$lastPropertyName]['type'], 'boolean');
236
    }
237
238
    public function getMetadataForEmbeddedEntity()
239
    {
240
        $metadata = new ClassMetadata('Sonata\DoctrineORMAdminBundle\Tests\Fixtures\Entity\Embeddable\EmbeddedEntity');
241
242
        $metadata->fieldMappings = [
243
            'plainField' => [
244
                'fieldName' => 'plainField',
245
                'columnName' => 'plainField',
246
                'type' => 'boolean',
247
            ],
248
        ];
249
250
        return $metadata;
251
    }
252
253
    public function getMetadataForAssociatedEntity()
254
    {
255
        $embeddedEntityClass = 'Sonata\DoctrineORMAdminBundle\Tests\Fixtures\Entity\Embeddable\EmbeddedEntity';
256
257
        $metadata = new ClassMetadata('Sonata\DoctrineORMAdminBundle\Tests\Fixtures\Entity\AssociatedEntity');
258
259
        $metadata->fieldMappings = [
260
            'plainField' => [
261
                'fieldName' => 'plainField',
262
                'columnName' => 'plainField',
263
                'type' => 'string',
264
            ],
265
        ];
266
267
        $metadata->embeddedClasses['embeddedEntity'] = [
268
            'class' => $embeddedEntityClass,
269
            'columnPrefix' => 'embeddedEntity',
270
        ];
271
272
        $metadata->inlineEmbeddable('embeddedEntity', $this->getMetadataForEmbeddedEntity());
273
274
        return $metadata;
275
    }
276
277
    public function getMetadataForContainerEntity()
278
    {
279
        $containerEntityClass = 'Sonata\DoctrineORMAdminBundle\Tests\Fixtures\Entity\ContainerEntity';
280
        $associatedEntityClass = 'Sonata\DoctrineORMAdminBundle\Tests\Fixtures\Entity\AssociatedEntity';
281
        $embeddedEntityClass = 'Sonata\DoctrineORMAdminBundle\Tests\Fixtures\Entity\Embeddable\EmbeddedEntity';
282
283
        $metadata = new ClassMetadata($containerEntityClass);
284
285
        $metadata->fieldMappings = [
286
            'plainField' => [
287
                'fieldName' => 'plainField',
288
                'columnName' => 'plainField',
289
                'type' => 'integer',
290
            ],
291
        ];
292
293
        $metadata->associationMappings['associatedEntity'] = [
294
            'fieldName' => 'associatedEntity',
295
            'targetEntity' => $associatedEntityClass,
296
            'sourceEntity' => $containerEntityClass,
297
        ];
298
299
        $metadata->embeddedClasses['embeddedEntity'] = [
300
            'class' => $embeddedEntityClass,
301
            'columnPrefix' => 'embeddedEntity',
302
        ];
303
304
        $metadata->inlineEmbeddable('embeddedEntity', $this->getMetadataForEmbeddedEntity());
305
306
        return $metadata;
307
    }
308
309
    public function testNonIntegerIdentifierType()
310
    {
311
        $uuid = new NonIntegerIdentifierTestClass('efbcfc4b-8c43-4d42-aa4c-d707e55151ac');
312
        $entity = new UuidEntity($uuid);
313
314
        $meta = $this->createMock('Doctrine\ORM\Mapping\ClassMetadataInfo');
315
        $meta->expects($this->any())
316
            ->method('getIdentifierValues')
317
            ->willReturn([$entity->getId()]);
318
        $meta->expects($this->any())
319
            ->method('getTypeOfField')
320
            ->willReturn(UuidType::NAME);
321
322
        $mf = $this->createMock('Doctrine\ORM\Mapping\ClassMetadataFactory');
323
        $mf->expects($this->any())
324
            ->method('getMetadataFor')
325
            ->willReturn($meta);
326
327
        $platform = $this->createMock('Doctrine\DBAL\Platforms\PostgreSqlPlatform');
328
329
        $conn = $this->createMock('Doctrine\DBAL\Connection');
330
        $conn->expects($this->any())
331
            ->method('getDatabasePlatform')
332
            ->willReturn($platform);
333
334
        $em = $this->createMock('Doctrine\ORM\EntityManager');
335
        $em->expects($this->any())
336
            ->method('getMetadataFactory')
337
            ->willReturn($mf);
338
        $em->expects($this->any())
339
            ->method('getConnection')
340
            ->willReturn($conn);
341
342
        $registry = $this->createMock('Symfony\Bridge\Doctrine\RegistryInterface');
343
        $registry->expects($this->any())
344
            ->method('getManagerForClass')
345
            ->willReturn($em);
346
347
        $manager = new ModelManager($registry);
348
        $result = $manager->getIdentifierValues($entity);
349
350
        $this->assertEquals($entity->getId()->toString(), $result[0]);
351
    }
352
353
    public function testAssociationIdentifierType()
354
    {
355
        $entity = new ContainerEntity(new AssociatedEntity(42, new EmbeddedEntity()), new EmbeddedEntity());
356
357
        $meta = $this->createMock('Doctrine\ORM\Mapping\ClassMetadataInfo');
358
        $meta->expects($this->any())
359
            ->method('getIdentifierValues')
360
            ->willReturn([$entity->getAssociatedEntity()->getPlainField()]);
361
        $meta->expects($this->any())
362
            ->method('getTypeOfField')
363
            ->willReturn(null);
364
365
        $mf = $this->createMock('Doctrine\ORM\Mapping\ClassMetadataFactory');
366
        $mf->expects($this->any())
367
            ->method('getMetadataFor')
368
            ->willReturn($meta);
369
370
        $platform = $this->createMock('Doctrine\DBAL\Platforms\PostgreSqlPlatform');
371
372
        $conn = $this->createMock('Doctrine\DBAL\Connection');
373
        $conn->expects($this->any())
374
            ->method('getDatabasePlatform')
375
            ->willReturn($platform);
376
377
        $em = $this->createMock('Doctrine\ORM\EntityManager');
378
        $em->expects($this->any())
379
            ->method('getMetadataFactory')
380
            ->willReturn($mf);
381
        $em->expects($this->any())
382
            ->method('getConnection')
383
            ->willReturn($conn);
384
385
        $registry = $this->createMock('Symfony\Bridge\Doctrine\RegistryInterface');
386
        $registry->expects($this->any())
387
            ->method('getManagerForClass')
388
            ->willReturn($em);
389
390
        $manager = new ModelManager($registry);
391
        $result = $manager->getIdentifierValues($entity);
392
393
        $this->assertSame(42, $result[0]);
394
    }
395
396
    /**
397
     * [sortBy, sortOrder, isAddOrderBy].
398
     *
399
     * @return array
400
     */
401
    public function getSortableInDataSourceIteratorDataProvider()
402
    {
403
        return [
404
            [null, null, false],
405
            ['', 'ASC', false],
406
            ['field', 'ASC', true],
407
            ['field', null, true],
408
        ];
409
    }
410
411
    /**
412
     * @dataProvider getSortableInDataSourceIteratorDataProvider
413
     *
414
     * @param string|null $sortBy
415
     * @param string|null $sortOrder
416
     * @param bool        $isAddOrderBy
417
     */
418
    public function testSortableInDataSourceIterator($sortBy, $sortOrder, $isAddOrderBy)
419
    {
420
        $datagrid = $this->getMockForAbstractClass('Sonata\AdminBundle\Datagrid\DatagridInterface');
421
        $configuration = $this->getMockBuilder('Doctrine\ORM\Configuration')->getMock();
422
        $configuration->expects($this->any())
423
            ->method('getDefaultQueryHints')
424
            ->willReturn([]);
425
426
        $em = $this->getMockBuilder('Doctrine\ORM\EntityManager')
427
            ->disableOriginalConstructor()
428
            ->getMock();
429
430
        $em->expects($this->any())
431
            ->method('getConfiguration')
432
            ->willReturn($configuration);
433
434
        $queryBuilder = $this->getMockBuilder('Doctrine\ORM\QueryBuilder')
435
            ->setConstructorArgs([$em])
436
            ->getMock();
437
        $query = new Query($em);
438
439
        $proxyQuery = $this->getMockBuilder('Sonata\DoctrineORMAdminBundle\Datagrid\ProxyQuery')
440
            ->setConstructorArgs([$queryBuilder])
441
            ->setMethods(['getSortBy', 'getSortOrder'])
442
            ->getMock();
443
444
        $proxyQuery->expects($this->any())
445
            ->method('getSortOrder')
446
            ->willReturn($sortOrder);
447
448
        $proxyQuery->expects($this->any())
449
            ->method('getSortBy')
450
            ->willReturn($sortBy);
451
452
        $queryBuilder->expects($isAddOrderBy ? $this->atLeastOnce() : $this->never())
453
            ->method('addOrderBy');
454
455
        $queryBuilder->expects($this->any())
456
            ->method('getQuery')
457
            ->willReturn($query);
458
459
        $datagrid->expects($this->any())
460
            ->method('getQuery')
461
            ->willReturn($proxyQuery);
462
463
        $registry = $this->getMockBuilder('Symfony\Bridge\Doctrine\RegistryInterface')->getMock();
464
        $manager = new ModelManager($registry);
465
        $manager->getDataSourceIterator($datagrid, []);
466
    }
467
468
    public function testModelReverseTransform()
469
    {
470
        $class = 'Sonata\DoctrineORMAdminBundle\Tests\Fixtures\Entity\SimpleEntity';
471
472
        $metadataFactory = $this->createMock('Doctrine\ORM\Mapping\ClassMetadataFactory');
473
        $modelManager = $this->createMock('Doctrine\Common\Persistence\ObjectManager');
474
        $registry = $this->createMock('Symfony\Bridge\Doctrine\RegistryInterface');
475
476
        $classMetadata = new ClassMetadataInfo($class);
477
        $classMetadata->reflClass = new \ReflectionClass($class);
478
479
        $modelManager->expects($this->once())
480
            ->method('getMetadataFactory')
481
            ->willReturn($metadataFactory);
482
        $metadataFactory->expects($this->once())
483
            ->method('getMetadataFor')
484
            ->with($class)
485
            ->willReturn($classMetadata);
486
        $registry->expects($this->once())
487
            ->method('getManagerForClass')
488
            ->with($class)
489
            ->willReturn($modelManager);
490
491
        $manager = new ModelManager($registry);
492
        $this->assertInstanceOf($class, $object = $manager->modelReverseTransform(
493
            $class,
494
            [
495
                'schmeckles' => 42,
496
                'multi_word_property' => 'hello',
497
            ]
498
        ));
499
        $this->assertSame(42, $object->getSchmeckles());
500
        $this->assertSame('hello', $object->getMultiWordProperty());
501
    }
502
503
    private function getMetadata($class, $isVersioned)
504
    {
505
        $metadata = new ClassMetadata($class);
506
507
        $metadata->isVersioned = $isVersioned;
508
509
        if ($isVersioned) {
510
            $versionField = 'version';
511
            $metadata->versionField = $versionField;
512
            $metadata->reflFields[$versionField] = new \ReflectionProperty($class, $versionField);
513
        }
514
515
        return $metadata;
516
    }
517
}
518