Completed
Push — 3.x-dev-kit ( 969216...127ac3 )
by Grégoire
04:57
created

ModelManagerTest::lockDataProvider()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 8
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 5
nc 1
nop 0
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');
0 ignored issues
show
Deprecated Code introduced by
The method PHPUnit_Framework_TestCase::setExpectedException() has been deprecated with message: Method deprecated since Release 5.2.0; use expectException() instead

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
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 only exist in PHPUnit_Framework_MockObject_MockObject, but not in Sonata\DoctrineORMAdminBundle\Model\ModelManager.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
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')
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
0 ignored issues
show
Bug introduced by
The method getParentMetadataForProperty does only exist in Sonata\DoctrineORMAdminBundle\Model\ModelManager, but not in PHPUnit_Framework_MockObject_MockObject.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
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