Completed
Pull Request — 3.x (#368)
by
unknown
01:24
created

ModelManagerTest::testFilterEmpty()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 6
rs 10
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\DoctrineMongoDBAdminBundle\Tests\Model;
15
16
use Doctrine\Common\Collections\ArrayCollection;
17
use Doctrine\Common\Persistence\Mapping\ClassMetadataFactory;
18
use Doctrine\Common\Persistence\ObjectManager;
19
use Doctrine\ODM\MongoDB\DocumentManager;
20
use Doctrine\ODM\MongoDB\Mapping\ClassMetadata;
21
use PHPUnit\Framework\TestCase;
22
use Sonata\AdminBundle\Admin\FieldDescriptionInterface;
23
use Sonata\AdminBundle\Datagrid\Datagrid;
24
use Sonata\AdminBundle\Datagrid\DatagridInterface;
25
use Sonata\DoctrineMongoDBAdminBundle\Admin\FieldDescription;
26
use Sonata\DoctrineMongoDBAdminBundle\Model\ModelManager;
27
use Sonata\DoctrineMongoDBAdminBundle\Tests\Fixtures\Document\AbstractDocument;
28
use Sonata\DoctrineMongoDBAdminBundle\Tests\Fixtures\Document\AssociatedDocument;
29
use Sonata\DoctrineMongoDBAdminBundle\Tests\Fixtures\Document\ContainerDocument;
30
use Sonata\DoctrineMongoDBAdminBundle\Tests\Fixtures\Document\EmbeddedDocument;
31
use Sonata\DoctrineMongoDBAdminBundle\Tests\Fixtures\Document\ProtectedDocument;
32
use Sonata\DoctrineMongoDBAdminBundle\Tests\Fixtures\Document\SimpleDocument;
33
use Symfony\Bridge\Doctrine\ManagerRegistry;
34
35
class ModelManagerTest extends TestCase
36
{
37
    /**
38
     * @dataProvider getWrongDocuments
39
     *
40
     * @param mixed $document
41
     */
42
    public function testNormalizedIdentifierException($document): void
43
    {
44
        $registry = $this->createStub(ManagerRegistry::class);
45
46
        $model = new ModelManager($registry);
47
48
        $this->expectException(\RuntimeException::class);
49
50
        $model->getNormalizedIdentifier($document);
51
    }
52
53
    public function getWrongDocuments(): iterable
54
    {
55
        yield [0];
56
        yield [1];
57
        yield [false];
58
        yield [true];
59
        yield [[]];
60
        yield [''];
61
        yield ['sonata-project'];
62
    }
63
64
    public function testGetNormalizedIdentifierNull(): void
65
    {
66
        $registry = $this->createStub(ManagerRegistry::class);
67
68
        $model = new ModelManager($registry);
69
70
        $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...
71
    }
72
73
    public function testSortParameters(): void
74
    {
75
        $registry = $this->createStub(ManagerRegistry::class);
76
77
        $manager = new ModelManager($registry);
78
79
        $datagrid1 = $this->createStub(Datagrid::class);
80
        $datagrid2 = $this->createStub(Datagrid::class);
81
82
        $field1 = new FieldDescription();
83
        $field1->setName('field1');
84
85
        $field2 = new FieldDescription();
86
        $field2->setName('field2');
87
88
        $field3 = new FieldDescription();
89
        $field3->setName('field3');
90
        $field3->setOption('sortable', 'field3sortBy');
91
92
        $datagrid1
93
            ->method('getValues')
94
            ->willReturn([
95
                '_sort_by' => $field1,
96
                '_sort_order' => 'ASC',
97
            ]);
98
99
        $datagrid2
100
            ->method('getValues')
101
            ->willReturn([
102
                '_sort_by' => $field3,
103
                '_sort_order' => 'ASC',
104
            ]);
105
106
        $parameters = $manager->getSortParameters($field1, $datagrid1);
107
108
        $this->assertSame('DESC', $parameters['filter']['_sort_order']);
109
        $this->assertSame('field1', $parameters['filter']['_sort_by']);
110
111
        $parameters = $manager->getSortParameters($field2, $datagrid1);
112
113
        $this->assertSame('ASC', $parameters['filter']['_sort_order']);
114
        $this->assertSame('field2', $parameters['filter']['_sort_by']);
115
116
        $parameters = $manager->getSortParameters($field3, $datagrid1);
117
118
        $this->assertSame('ASC', $parameters['filter']['_sort_order']);
119
        $this->assertSame('field3sortBy', $parameters['filter']['_sort_by']);
120
121
        $parameters = $manager->getSortParameters($field3, $datagrid2);
122
123
        $this->assertSame('DESC', $parameters['filter']['_sort_order']);
124
        $this->assertSame('field3sortBy', $parameters['filter']['_sort_by']);
125
    }
126
127
    public function testGetParentMetadataForProperty(): void
128
    {
129
        $containerDocumentClass = ContainerDocument::class;
130
        $associatedDocumentClass = AssociatedDocument::class;
131
        $embeddedDocumentClass = EmbeddedDocument::class;
132
133
        $dm = $this->createStub(DocumentManager::class);
134
135
        $registry = $this->createStub(ManagerRegistry::class);
136
137
        $modelManager = new ModelManager($registry);
138
139
        $registry
140
            ->method('getManagerForClass')
141
            ->willReturn($dm);
142
143
        $metadataFactory = $this->createStub(ClassMetadataFactory::class);
144
145
        $dm
146
            ->method('getMetadataFactory')
147
            ->willReturn($metadataFactory);
148
149
        $containerDocumentMetadata = $this->getMetadataForContainerDocument();
150
        $associatedDocumentMetadata = $this->getMetadataForAssociatedDocument();
151
        $embeddedDocumentMetadata = $this->getMetadataForEmbeddedDocument();
152
153
        $metadataFactory->method('getMetadataFor')
154
            ->willReturnMap(
155
                [
156
                    [$containerDocumentClass, $containerDocumentMetadata],
157
                    [$embeddedDocumentClass, $embeddedDocumentMetadata],
158
                    [$associatedDocumentClass, $associatedDocumentMetadata],
159
                ]
160
            );
161
162
        /** @var ClassMetadata $metadata */
163
        [$metadata, $lastPropertyName] = $modelManager
0 ignored issues
show
Bug introduced by
The variable $metadata does not exist. Did you mean $metadataFactory?

This check looks for variables that are accessed but have not been defined. It raises an issue if it finds another variable that has a similar name.

The variable may have been renamed without also renaming all references.

Loading history...
Bug introduced by
The variable $lastPropertyName does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
164
            ->getParentMetadataForProperty($containerDocumentClass, 'plainField');
165
        $this->assertSame($metadata->fieldMappings[$lastPropertyName]['type'], 'integer');
0 ignored issues
show
Bug introduced by
The variable $metadata does not exist. Did you mean $metadataFactory?

This check looks for variables that are accessed but have not been defined. It raises an issue if it finds another variable that has a similar name.

The variable may have been renamed without also renaming all references.

Loading history...
166
167
        [$metadata, $lastPropertyName] = $modelManager
0 ignored issues
show
Bug introduced by
The variable $metadata does not exist. Did you mean $metadataFactory?

This check looks for variables that are accessed but have not been defined. It raises an issue if it finds another variable that has a similar name.

The variable may have been renamed without also renaming all references.

Loading history...
168
            ->getParentMetadataForProperty($containerDocumentClass, 'associatedDocument.plainField');
169
        $this->assertSame($metadata->fieldMappings[$lastPropertyName]['type'], 'string');
0 ignored issues
show
Bug introduced by
The variable $metadata does not exist. Did you mean $metadataFactory?

This check looks for variables that are accessed but have not been defined. It raises an issue if it finds another variable that has a similar name.

The variable may have been renamed without also renaming all references.

Loading history...
170
171
        [$metadata, $lastPropertyName] = $modelManager
0 ignored issues
show
Bug introduced by
The variable $metadata does not exist. Did you mean $metadataFactory?

This check looks for variables that are accessed but have not been defined. It raises an issue if it finds another variable that has a similar name.

The variable may have been renamed without also renaming all references.

Loading history...
172
            ->getParentMetadataForProperty($containerDocumentClass, 'embeddedDocument.plainField');
173
        $this->assertSame($metadata->fieldMappings[$lastPropertyName]['type'], 'boolean');
0 ignored issues
show
Bug introduced by
The variable $metadata does not exist. Did you mean $metadataFactory?

This check looks for variables that are accessed but have not been defined. It raises an issue if it finds another variable that has a similar name.

The variable may have been renamed without also renaming all references.

Loading history...
174
175
        $this->assertSame($metadata->fieldMappings[$lastPropertyName]['type'], 'boolean');
0 ignored issues
show
Bug introduced by
The variable $metadata does not exist. Did you mean $metadataFactory?

This check looks for variables that are accessed but have not been defined. It raises an issue if it finds another variable that has a similar name.

The variable may have been renamed without also renaming all references.

Loading history...
176
    }
177
178
    public function testModelReverseTransform(): void
179
    {
180
        $class = SimpleDocument::class;
181
182
        $metadataFactory = $this->createMock(ClassMetadataFactory::class);
183
        $modelManager = $this->createMock(ObjectManager::class);
184
        $registry = $this->createMock(ManagerRegistry::class);
185
186
        $classMetadata = new ClassMetadata($class);
187
        $classMetadata->reflClass = new \ReflectionClass($class);
188
189
        $modelManager->expects($this->once())
190
            ->method('getMetadataFactory')
191
            ->willReturn($metadataFactory);
192
        $metadataFactory->expects($this->once())
193
            ->method('getMetadataFor')
194
            ->with($class)
195
            ->willReturn($classMetadata);
196
        $registry->expects($this->once())
197
            ->method('getManagerForClass')
198
            ->with($class)
199
            ->willReturn($modelManager);
200
201
        $manager = new ModelManager($registry);
202
        $this->assertInstanceOf($class, $object = $manager->modelReverseTransform(
203
            $class,
204
            [
205
                'schmeckles' => 42,
206
                'multi_word_property' => 'hello',
207
            ]
208
        ));
209
        $this->assertSame(42, $object->getSchmeckles());
210
        $this->assertSame('hello', $object->getMultiWordProperty());
211
    }
212
213
    public function testCollections(): void
214
    {
215
        $registry = $this->createStub(ManagerRegistry::class);
216
        $model = new ModelManager($registry);
217
218
        $collection = $model->getModelCollectionInstance('whyDoWeEvenHaveThisParameter');
219
        $this->assertInstanceOf(ArrayCollection::class, $collection);
220
221
        $item1 = new \stdClass();
222
        $item2 = new \stdClass();
223
        $model->collectionAddElement($collection, $item1);
0 ignored issues
show
Bug introduced by
It seems like $collection defined by $model->getModelCollecti...EvenHaveThisParameter') on line 218 can also be of type object<ArrayAccess>; however, Sonata\DoctrineMongoDBAd...:collectionAddElement() does only seem to accept array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
224
        $model->collectionAddElement($collection, $item2);
225
226
        $this->assertTrue($model->collectionHasElement($collection, $item1));
227
228
        $model->collectionRemoveElement($collection, $item1);
229
230
        $this->assertFalse($model->collectionHasElement($collection, $item1));
231
232
        $model->collectionClear($collection);
233
234
        $this->assertTrue($collection->isEmpty());
0 ignored issues
show
Bug introduced by
The method isEmpty cannot be called on $collection (of type array).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
235
    }
236
237
    public function testModelTransform(): void
238
    {
239
        $registry = $this->createStub(ManagerRegistry::class);
240
        $model = new ModelManager($registry);
241
242
        $instance = new \stdClass();
243
        $result = $model->modelTransform('thisIsNotUsed', $instance);
244
245
        $this->assertSame($instance, $result);
246
    }
247
248
    public function testGetPaginationParameters(): void
249
    {
250
        $datagrid = $this->createMock(DatagridInterface::class);
251
        $fieldDescription = $this->createMock(FieldDescriptionInterface::class);
252
        $registry = $this->createStub(ManagerRegistry::class);
253
254
        $datagrid->expects($this->once())
255
            ->method('getValues')
256
            ->willReturn(['_sort_by' => $fieldDescription]);
257
258
        $fieldDescription->expects($this->once())
259
            ->method('getName')
260
            ->willReturn($name = 'test');
261
262
        $model = new ModelManager($registry);
263
264
        $result = $model->getPaginationParameters($datagrid, $page = 5);
265
266
        $this->assertSame($page, $result['filter']['_page']);
267
        $this->assertSame($name, $result['filter']['_sort_by']);
268
    }
269
270
    public function testGetModelInstanceException(): void
271
    {
272
        $registry = $this->createStub(ManagerRegistry::class);
273
274
        $model = new ModelManager($registry);
275
276
        $this->expectException(\InvalidArgumentException::class);
277
278
        $model->getModelInstance(AbstractDocument::class);
279
    }
280
281
    public function testGetModelInstanceForProtectedDocument(): void
282
    {
283
        $registry = $this->createStub(ManagerRegistry::class);
284
285
        $model = new ModelManager($registry);
286
287
        $this->assertInstanceOf(ProtectedDocument::class, $model->getModelInstance(ProtectedDocument::class));
288
    }
289
290
    public function testFindBadId(): void
291
    {
292
        $registry = $this->createStub(ManagerRegistry::class);
293
294
        $model = new ModelManager($registry);
295
296
        $this->assertNull($model->find('notImportant', null));
297
    }
298
299
    public function testGetUrlSafeIdentifierException(): void
300
    {
301
        $registry = $this->createStub(ManagerRegistry::class);
302
303
        $model = new ModelManager($registry);
304
305
        $this->expectException(\RuntimeException::class);
306
307
        $model->getNormalizedIdentifier(new \stdClass());
308
    }
309
310
    public function testGetUrlSafeIdentifierNull(): void
311
    {
312
        $registry = $this->createStub(ManagerRegistry::class);
313
314
        $model = new ModelManager($registry);
315
316
        $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...
317
    }
318
319
    private function getMetadataForEmbeddedDocument(): ClassMetadata
320
    {
321
        $metadata = new ClassMetadata(EmbeddedDocument::class);
322
323
        $metadata->fieldMappings = [
324
            'plainField' => [
325
                'fieldName' => 'plainField',
326
                'columnName' => 'plainField',
327
                'type' => 'boolean',
328
            ],
329
        ];
330
331
        return $metadata;
332
    }
333
334
    private function getMetadataForAssociatedDocument(): ClassMetadata
335
    {
336
        $embeddedDocumentClass = EmbeddedDocument::class;
337
338
        $metadata = new ClassMetadata(AssociatedDocument::class);
339
340
        $metadata->fieldMappings = [
341
            'plainField' => [
342
                'fieldName' => 'plainField',
343
                'name' => 'plainField',
344
                'columnName' => 'plainField',
345
                'type' => 'string',
346
            ],
347
        ];
348
349
        $metadata->mapOneEmbedded([
350
            'fieldName' => 'embeddedDocument',
351
            'name' => 'embeddedDocument',
352
            'targetDocument' => $embeddedDocumentClass,
353
        ]);
354
355
        return $metadata;
356
    }
357
358
    private function getMetadataForContainerDocument(): ClassMetadata
359
    {
360
        $containerDocumentClass = ContainerDocument::class;
361
        $associatedDocumentClass = AssociatedDocument::class;
362
        $embeddedDocumentClass = EmbeddedDocument::class;
363
364
        $metadata = new ClassMetadata($containerDocumentClass);
365
366
        $metadata->fieldMappings = [
367
            'plainField' => [
368
                'fieldName' => 'plainField',
369
                'name' => 'plainField',
370
                'columnName' => 'plainField',
371
                'type' => 'integer',
372
            ],
373
        ];
374
375
        $metadata->associationMappings['associatedDocument'] = [
376
            'fieldName' => 'associatedDocument',
377
            'name' => 'associatedDocument',
378
            'targetDocument' => $associatedDocumentClass,
379
            'sourceDocument' => $containerDocumentClass,
380
        ];
381
382
        $metadata->mapOneEmbedded([
383
            'fieldName' => 'embeddedDocument',
384
            'name' => 'embeddedDocument',
385
            'targetDocument' => $embeddedDocumentClass,
386
        ]);
387
388
        return $metadata;
389
    }
390
}
391