Completed
Pull Request — 3.x (#360)
by
unknown
01:34
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\Datagrid\Datagrid;
23
use Sonata\AdminBundle\Datagrid\DatagridInterface;
24
use Sonata\AdminBundle\Filter\FilterInterface;
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->createMock(ManagerRegistry::class);
40
41
        $manager = new ModelManager($registry);
42
43
        $datagrid1 = $this->createMock(Datagrid::class);
44
        $datagrid2 = $this->createMock(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->createMock(DocumentManager::class);
98
99
        $registry = $this->createMock(ManagerRegistry::class);
100
101
        $modelManager = new ModelManager($registry);
102
103
        $registry
104
            ->method('getManagerForClass')
105
            ->willReturn($dm);
106
107
        $metadataFactory = $this->createMock(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
                [
121
                    [$containerDocumentClass, $containerDocumentMetadata],
122
                    [$embeddedDocumentClass, $embeddedDocumentMetadata],
123
                    [$associatedDocumentClass, $associatedDocumentMetadata],
124
                ]
125
126
            );
127
128
        /** @var ClassMetadata $metadata */
129
        [$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...
130
            ->getParentMetadataForProperty($containerDocumentClass, 'plainField');
131
        $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...
132
133
        [$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...
134
            ->getParentMetadataForProperty($containerDocumentClass, 'associatedDocument.plainField');
135
        $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...
136
137
        [$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...
138
            ->getParentMetadataForProperty($containerDocumentClass, 'embeddedDocument.plainField');
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
        $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...
142
    }
143
144
    public function testModelReverseTransform(): void
145
    {
146
        $class = SimpleDocument::class;
147
148
        $metadataFactory = $this->createMock(ClassMetadataFactory::class);
149
        $modelManager = $this->createMock(ObjectManager::class);
150
        $registry = $this->createMock(ManagerRegistry::class);
151
152
        $classMetadata = new ClassMetadata($class);
153
        $classMetadata->reflClass = new \ReflectionClass($class);
154
155
        $modelManager->expects($this->once())
156
            ->method('getMetadataFactory')
157
            ->willReturn($metadataFactory);
158
        $metadataFactory->expects($this->once())
159
            ->method('getMetadataFor')
160
            ->with($class)
161
            ->willReturn($classMetadata);
162
        $registry->expects($this->once())
163
            ->method('getManagerForClass')
164
            ->with($class)
165
            ->willReturn($modelManager);
166
167
        $manager = new ModelManager($registry);
168
        $this->assertInstanceOf($class, $object = $manager->modelReverseTransform(
169
            $class,
170
            [
171
                'schmeckles' => 42,
172
                'multi_word_property' => 'hello',
173
            ]
174
        ));
175
        $this->assertSame(42, $object->getSchmeckles());
176
        $this->assertSame('hello', $object->getMultiWordProperty());
177
    }
178
179
    public function testCollections(): void
180
    {
181
        $registry = $this->createMock(ManagerRegistry::class);
182
        $model = new ModelManager($registry);
183
184
        $collection = $model->getModelCollectionInstance('whyDoWeEvenHaveThisParameter');
185
        $this->assertInstanceOf(ArrayCollection::class, $collection);
186
187
        $item1 = 'item1';
188
        $item2 = 'item2';
189
        $model->collectionAddElement($collection, $item1);
0 ignored issues
show
Bug introduced by
It seems like $collection defined by $model->getModelCollecti...EvenHaveThisParameter') on line 184 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...
Documentation introduced by
$item1 is of type string, 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...
190
        $model->collectionAddElement($collection, $item2);
0 ignored issues
show
Documentation introduced by
$item2 is of type string, 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...
191
192
        $this->assertTrue($model->collectionHasElement($collection, $item1));
193
194
        $model->collectionRemoveElement($collection, $item1);
195
196
        $this->assertFalse($model->collectionHasElement($collection, $item1));
197
198
        $model->collectionClear($collection);
199
200
        $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...
201
    }
202
203
    public function testModelTransform(): void
204
    {
205
        $registry = $this->createMock(ManagerRegistry::class);
206
        $model = new ModelManager($registry);
207
208
        $result = $model->modelTransform('thisIsNotUsed', 'doWeNeedThisMethod');
0 ignored issues
show
Documentation introduced by
'doWeNeedThisMethod' is of type string, 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...
209
210
        $this->assertSame('doWeNeedThisMethod', $result);
211
    }
212
213
    public function testGetPaginationParameters(): void
214
    {
215
        $datagrid = $this->createMock(DatagridInterface::class);
216
        $filter = $this->createMock(FilterInterface::class);
217
        $registry = $this->createMock(ManagerRegistry::class);
218
219
        $datagrid->expects($this->once())
220
            ->method('getValues')
221
            ->willReturn(['_sort_by' => $filter]);
222
223
        $filter->expects($this->once())
224
            ->method('getName')
225
            ->willReturn($name = 'test');
226
227
        $model = new ModelManager($registry);
228
229
        $result = $model->getPaginationParameters($datagrid, $page = 5);
230
231
        $this->assertSame($page, $result['filter']['_page']);
232
        $this->assertSame($name, $result['filter']['_sort_by']);
233
    }
234
235
    public function testGetModelInstanceException(): void
236
    {
237
        $registry = $this->createMock(ManagerRegistry::class);
238
239
        $model = new ModelManager($registry);
240
241
        $this->expectException(\InvalidArgumentException::class);
242
243
        $model->getModelInstance(AbstractDocument::class);
244
    }
245
246
    public function testGetModelInstanceForProtectedDocument(): void
247
    {
248
        $registry = $this->createMock(ManagerRegistry::class);
249
250
        $model = new ModelManager($registry);
251
252
        $this->assertInstanceOf(ProtectedDocument::class, $model->getModelInstance(ProtectedDocument::class));
253
    }
254
255
    public function testFindBadId(): void
256
    {
257
        $registry = $this->createMock(ManagerRegistry::class);
258
259
        $model = new ModelManager($registry);
260
261
        $this->assertNull($model->find('notImportant', null));
262
    }
263
264
    public function testGetUrlsafeIdentifierException(): void
265
    {
266
        $registry = $this->createMock(ManagerRegistry::class);
267
268
        $model = new ModelManager($registry);
269
270
        $this->expectException(\RuntimeException::class);
271
272
        $model->getNormalizedIdentifier('test');
0 ignored issues
show
Documentation introduced by
'test' is of type string, 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...
273
    }
274
275
    public function testGetUrlsafeIdentifierNull(): void
276
    {
277
        $registry = $this->createMock(ManagerRegistry::class);
278
279
        $model = new ModelManager($registry);
280
281
        $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...
282
    }
283
284
    private function getMetadataForEmbeddedDocument(): ClassMetadata
285
    {
286
        $metadata = new ClassMetadata(EmbeddedDocument::class);
287
288
        $metadata->fieldMappings = [
289
            'plainField' => [
290
                'fieldName' => 'plainField',
291
                'columnName' => 'plainField',
292
                'type' => 'boolean',
293
            ],
294
        ];
295
296
        return $metadata;
297
    }
298
299
    private function getMetadataForAssociatedDocument(): ClassMetadata
300
    {
301
        $embeddedDocumentClass = EmbeddedDocument::class;
302
303
        $metadata = new ClassMetadata(AssociatedDocument::class);
304
305
        $metadata->fieldMappings = [
306
            'plainField' => [
307
                'fieldName' => 'plainField',
308
                'name' => 'plainField',
309
                'columnName' => 'plainField',
310
                'type' => 'string',
311
            ],
312
        ];
313
314
        $metadata->mapOneEmbedded([
315
            'fieldName' => 'embeddedDocument',
316
            'name' => 'embeddedDocument',
317
            'targetDocument' => $embeddedDocumentClass,
318
        ]);
319
320
        return $metadata;
321
    }
322
323
    private function getMetadataForContainerDocument(): ClassMetadata
324
    {
325
        $containerDocumentClass = ContainerDocument::class;
326
        $associatedDocumentClass = AssociatedDocument::class;
327
        $embeddedDocumentClass = EmbeddedDocument::class;
328
329
        $metadata = new ClassMetadata($containerDocumentClass);
330
331
        $metadata->fieldMappings = [
332
            'plainField' => [
333
                'fieldName' => 'plainField',
334
                'name' => 'plainField',
335
                'columnName' => 'plainField',
336
                'type' => 'integer',
337
            ],
338
        ];
339
340
        $metadata->associationMappings['associatedDocument'] = [
341
            'fieldName' => 'associatedDocument',
342
            'name' => 'associatedDocument',
343
            'targetDocument' => $associatedDocumentClass,
344
            'sourceDocument' => $containerDocumentClass,
345
        ];
346
347
        $metadata->mapOneEmbedded([
348
            'fieldName' => 'embeddedDocument',
349
            'name' => 'embeddedDocument',
350
            'targetDocument' => $embeddedDocumentClass,
351
        ]);
352
353
        return $metadata;
354
    }
355
}
356