Completed
Pull Request — 3.x (#360)
by
unknown
01:31
created

ModelManagerTest::testGetPaginationParameters()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 21

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 21
rs 9.584
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
    public function testSortParameters(): void
38
    {
39
        $registry = $this->createStub(ManagerRegistry::class);
40
41
        $manager = new ModelManager($registry);
42
43
        $datagrid1 = $this->createStub(Datagrid::class);
44
        $datagrid2 = $this->createStub(Datagrid::class);
45
46
        $field1 = new FieldDescription();
47
        $field1->setName('field1');
48
49
        $field2 = new FieldDescription();
50
        $field2->setName('field2');
51
52
        $field3 = new FieldDescription();
53
        $field3->setName('field3');
54
        $field3->setOption('sortable', 'field3sortBy');
55
56
        $datagrid1
57
            ->method('getValues')
58
            ->willReturn([
59
                '_sort_by' => $field1,
60
                '_sort_order' => 'ASC',
61
            ]);
62
63
        $datagrid2
64
            ->method('getValues')
65
            ->willReturn([
66
                '_sort_by' => $field3,
67
                '_sort_order' => 'ASC',
68
            ]);
69
70
        $parameters = $manager->getSortParameters($field1, $datagrid1);
71
72
        $this->assertSame('DESC', $parameters['filter']['_sort_order']);
73
        $this->assertSame('field1', $parameters['filter']['_sort_by']);
74
75
        $parameters = $manager->getSortParameters($field2, $datagrid1);
76
77
        $this->assertSame('ASC', $parameters['filter']['_sort_order']);
78
        $this->assertSame('field2', $parameters['filter']['_sort_by']);
79
80
        $parameters = $manager->getSortParameters($field3, $datagrid1);
81
82
        $this->assertSame('ASC', $parameters['filter']['_sort_order']);
83
        $this->assertSame('field3sortBy', $parameters['filter']['_sort_by']);
84
85
        $parameters = $manager->getSortParameters($field3, $datagrid2);
86
87
        $this->assertSame('DESC', $parameters['filter']['_sort_order']);
88
        $this->assertSame('field3sortBy', $parameters['filter']['_sort_by']);
89
    }
90
91
    public function testGetParentMetadataForProperty(): void
92
    {
93
        $containerDocumentClass = ContainerDocument::class;
94
        $associatedDocumentClass = AssociatedDocument::class;
95
        $embeddedDocumentClass = EmbeddedDocument::class;
96
97
        $dm = $this->createStub(DocumentManager::class);
98
99
        $registry = $this->createStub(ManagerRegistry::class);
100
101
        $modelManager = new ModelManager($registry);
102
103
        $registry
104
            ->method('getManagerForClass')
105
            ->willReturn($dm);
106
107
        $metadataFactory = $this->createStub(ClassMetadataFactory::class);
108
109
        $dm
110
            ->method('getMetadataFactory')
111
            ->willReturn($metadataFactory);
112
113
        $containerDocumentMetadata = $this->getMetadataForContainerDocument();
114
        $associatedDocumentMetadata = $this->getMetadataForAssociatedDocument();
115
        $embeddedDocumentMetadata = $this->getMetadataForEmbeddedDocument();
116
117
        $metadataFactory->method('getMetadataFor')
118
            ->willReturnMap(
119
                [
120
                    [$containerDocumentClass, $containerDocumentMetadata],
121
                    [$embeddedDocumentClass, $embeddedDocumentMetadata],
122
                    [$associatedDocumentClass, $associatedDocumentMetadata],
123
                ]
124
            );
125
126
        /** @var ClassMetadata $metadata */
127
        [$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...
128
            ->getParentMetadataForProperty($containerDocumentClass, 'plainField');
129
        $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...
130
131
        [$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...
132
            ->getParentMetadataForProperty($containerDocumentClass, 'associatedDocument.plainField');
133
        $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...
134
135
        [$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...
136
            ->getParentMetadataForProperty($containerDocumentClass, 'embeddedDocument.plainField');
137
        $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...
138
139
        $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...
140
    }
141
142
    public function testModelReverseTransform(): void
143
    {
144
        $class = SimpleDocument::class;
145
146
        $metadataFactory = $this->createMock(ClassMetadataFactory::class);
147
        $modelManager = $this->createMock(ObjectManager::class);
148
        $registry = $this->createMock(ManagerRegistry::class);
149
150
        $classMetadata = new ClassMetadata($class);
151
        $classMetadata->reflClass = new \ReflectionClass($class);
152
153
        $modelManager->expects($this->once())
154
            ->method('getMetadataFactory')
155
            ->willReturn($metadataFactory);
156
        $metadataFactory->expects($this->once())
157
            ->method('getMetadataFor')
158
            ->with($class)
159
            ->willReturn($classMetadata);
160
        $registry->expects($this->once())
161
            ->method('getManagerForClass')
162
            ->with($class)
163
            ->willReturn($modelManager);
164
165
        $manager = new ModelManager($registry);
166
        $this->assertInstanceOf($class, $object = $manager->modelReverseTransform(
167
            $class,
168
            [
169
                'schmeckles' => 42,
170
                'multi_word_property' => 'hello',
171
            ]
172
        ));
173
        $this->assertSame(42, $object->getSchmeckles());
174
        $this->assertSame('hello', $object->getMultiWordProperty());
175
    }
176
177
    public function testCollections(): void
178
    {
179
        $registry = $this->createStub(ManagerRegistry::class);
180
        $model = new ModelManager($registry);
181
182
        $collection = $model->getModelCollectionInstance('whyDoWeEvenHaveThisParameter');
183
        $this->assertInstanceOf(ArrayCollection::class, $collection);
184
185
        $item1 = new \StdClass();
186
        $item2 = new \StdClass();
187
        $model->collectionAddElement($collection, $item1);
0 ignored issues
show
Bug introduced by
It seems like $collection defined by $model->getModelCollecti...EvenHaveThisParameter') on line 182 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...
188
        $model->collectionAddElement($collection, $item2);
189
190
        $this->assertTrue($model->collectionHasElement($collection, $item1));
191
192
        $model->collectionRemoveElement($collection, $item1);
193
194
        $this->assertFalse($model->collectionHasElement($collection, $item1));
195
196
        $model->collectionClear($collection);
197
198
        $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...
199
    }
200
201
    public function testModelTransform(): void
202
    {
203
        $registry = $this->createStub(ManagerRegistry::class);
204
        $model = new ModelManager($registry);
205
206
        $instance = new \StdClass();
207
        $result = $model->modelTransform('thisIsNotUsed', $instance);
208
209
        $this->assertSame($instance, $result);
210
    }
211
212
    public function testGetPaginationParameters(): void
213
    {
214
        $datagrid = $this->createMock(DatagridInterface::class);
215
        $fieldDescription = $this->createMock(FieldDescriptionInterface::class);
216
        $registry = $this->createStub(ManagerRegistry::class);
217
218
        $datagrid->expects($this->once())
219
            ->method('getValues')
220
            ->willReturn(['_sort_by' => $fieldDescription]);
221
222
        $fieldDescription->expects($this->once())
223
            ->method('getName')
224
            ->willReturn($name = 'test');
225
226
        $model = new ModelManager($registry);
227
228
        $result = $model->getPaginationParameters($datagrid, $page = 5);
229
230
        $this->assertSame($page, $result['filter']['_page']);
231
        $this->assertSame($name, $result['filter']['_sort_by']);
232
    }
233
234
    public function testGetModelInstanceException(): void
235
    {
236
        $registry = $this->createStub(ManagerRegistry::class);
237
238
        $model = new ModelManager($registry);
239
240
        $this->expectException(\InvalidArgumentException::class);
241
242
        $model->getModelInstance(AbstractDocument::class);
243
    }
244
245
    public function testGetModelInstanceForProtectedDocument(): void
246
    {
247
        $registry = $this->createStub(ManagerRegistry::class);
248
249
        $model = new ModelManager($registry);
250
251
        $this->assertInstanceOf(ProtectedDocument::class, $model->getModelInstance(ProtectedDocument::class));
252
    }
253
254
    public function testFindBadId(): void
255
    {
256
        $registry = $this->createStub(ManagerRegistry::class);
257
258
        $model = new ModelManager($registry);
259
260
        $this->assertNull($model->find('notImportant', null));
261
    }
262
263
    public function testGetUrlsafeIdentifierException(): void
264
    {
265
        $registry = $this->createStub(ManagerRegistry::class);
266
267
        $model = new ModelManager($registry);
268
269
        $this->expectException(\RuntimeException::class);
270
271
        $model->getNormalizedIdentifier(new \StdClass());
272
    }
273
274
    public function testGetUrlSafeIdentifierNull(): void
275
    {
276
        $registry = $this->createStub(ManagerRegistry::class);
277
278
        $model = new ModelManager($registry);
279
280
        $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...
281
    }
282
283
    private function getMetadataForEmbeddedDocument(): ClassMetadata
284
    {
285
        $metadata = new ClassMetadata(EmbeddedDocument::class);
286
287
        $metadata->fieldMappings = [
288
            'plainField' => [
289
                'fieldName' => 'plainField',
290
                'columnName' => 'plainField',
291
                'type' => 'boolean',
292
            ],
293
        ];
294
295
        return $metadata;
296
    }
297
298
    private function getMetadataForAssociatedDocument(): ClassMetadata
299
    {
300
        $embeddedDocumentClass = EmbeddedDocument::class;
301
302
        $metadata = new ClassMetadata(AssociatedDocument::class);
303
304
        $metadata->fieldMappings = [
305
            'plainField' => [
306
                'fieldName' => 'plainField',
307
                'name' => 'plainField',
308
                'columnName' => 'plainField',
309
                'type' => 'string',
310
            ],
311
        ];
312
313
        $metadata->mapOneEmbedded([
314
            'fieldName' => 'embeddedDocument',
315
            'name' => 'embeddedDocument',
316
            'targetDocument' => $embeddedDocumentClass,
317
        ]);
318
319
        return $metadata;
320
    }
321
322
    private function getMetadataForContainerDocument(): ClassMetadata
323
    {
324
        $containerDocumentClass = ContainerDocument::class;
325
        $associatedDocumentClass = AssociatedDocument::class;
326
        $embeddedDocumentClass = EmbeddedDocument::class;
327
328
        $metadata = new ClassMetadata($containerDocumentClass);
329
330
        $metadata->fieldMappings = [
331
            'plainField' => [
332
                'fieldName' => 'plainField',
333
                'name' => 'plainField',
334
                'columnName' => 'plainField',
335
                'type' => 'integer',
336
            ],
337
        ];
338
339
        $metadata->associationMappings['associatedDocument'] = [
340
            'fieldName' => 'associatedDocument',
341
            'name' => 'associatedDocument',
342
            'targetDocument' => $associatedDocumentClass,
343
            'sourceDocument' => $containerDocumentClass,
344
        ];
345
346
        $metadata->mapOneEmbedded([
347
            'fieldName' => 'embeddedDocument',
348
            'name' => 'embeddedDocument',
349
            'targetDocument' => $embeddedDocumentClass,
350
        ]);
351
352
        return $metadata;
353
    }
354
}
355