Completed
Push — master ( 6f1066...9b6aac )
by Maciej
44:22
created

SchemaManager   D

Complexity

Total Complexity 103

Size/Duplication

Total Lines 471
Duplicated Lines 20.59 %

Coupling/Cohesion

Components 1
Dependencies 7

Test Coverage

Coverage 90.13%

Importance

Changes 3
Bugs 0 Features 1
Metric Value
wmc 103
c 3
b 0
f 1
lcom 1
cbo 7
dl 97
loc 471
ccs 210
cts 233
cp 0.9013
rs 4.8718

19 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 5 1
A ensureIndexes() 9 9 4
A updateIndexes() 9 9 4
C updateDocumentIndexes() 0 45 8
A getDocumentIndexes() 0 5 1
C doGetDocumentIndexes() 0 52 16
B prepareIndexes() 0 26 4
C ensureDocumentIndexes() 0 29 12
A deleteIndexes() 9 9 4
A deleteDocumentIndexes() 8 8 3
A createCollections() 9 9 4
B createDocumentCollection() 0 22 4
A dropCollections() 9 9 4
A dropDocumentCollection() 10 10 3
A dropDatabases() 9 9 4
A dropDocumentDatabase() 8 8 3
A createDatabases() 9 9 4
A createDocumentDatabase() 8 8 3
D isMongoIndexEquivalentToDocumentIndex() 0 46 17

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like SchemaManager often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use SchemaManager, and based on these observations, apply Extract Interface, too.

1
<?php
2
/*
3
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
4
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
5
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
6
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
7
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
8
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
9
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
10
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
11
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
12
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
13
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
14
 *
15
 * This software consists of voluntary contributions made by many individuals
16
 * and is licensed under the MIT license. For more information, see
17
 * <http://www.doctrine-project.org>.
18
 */
19
20
namespace Doctrine\ODM\MongoDB;
21
22
use Doctrine\ODM\MongoDB\Mapping\ClassMetadata;
23
use Doctrine\ODM\MongoDB\Mapping\ClassMetadataFactory;
24
25
class SchemaManager
26
{
27
    /**
28
     * @var DocumentManager
29
     */
30
    protected $dm;
31
32
    /**
33
     *
34
     * @var ClassMetadataFactory
35
     */
36
    protected $metadataFactory;
37
38
    /**
39
     * @param DocumentManager $dm
40
     * @param ClassMetadataFactory $cmf
41
     */
42 983
    public function __construct(DocumentManager $dm, ClassMetadataFactory $cmf)
43
    {
44 983
        $this->dm = $dm;
45 983
        $this->metadataFactory = $cmf;
46 983
    }
47
48
    /**
49
     * Ensure indexes are created for all documents that can be loaded with the
50
     * metadata factory.
51
     *
52
     * @param integer $timeout Timeout (ms) for acknowledged index creation
53
     */
54 1 View Code Duplication
    public function ensureIndexes($timeout = null)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
55
    {
56 1
        foreach ($this->metadataFactory->getAllMetadata() as $class) {
57 1
            if ($class->isMappedSuperclass || $class->isEmbeddedDocument) {
58 1
                continue;
59
            }
60 1
            $this->ensureDocumentIndexes($class->name, $timeout);
61 1
        }
62 1
    }
63
64
    /**
65
     * Ensure indexes exist for all mapped document classes.
66
     *
67
     * Indexes that exist in MongoDB but not the document metadata will be
68
     * deleted.
69
     *
70
     * @param integer $timeout Timeout (ms) for acknowledged index creation
71
     */
72 View Code Duplication
    public function updateIndexes($timeout = null)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
73
    {
74
        foreach ($this->metadataFactory->getAllMetadata() as $class) {
75
            if ($class->isMappedSuperclass || $class->isEmbeddedDocument) {
76
                continue;
77
            }
78
            $this->updateDocumentIndexes($class->name, $timeout);
79
        }
80
    }
81
82
    /**
83
     * Ensure indexes exist for the mapped document class.
84
     *
85
     * Indexes that exist in MongoDB but not the document metadata will be
86
     * deleted.
87
     *
88
     * @param string $documentName
89
     * @param integer $timeout Timeout (ms) for acknowledged index creation
90
     * @throws \InvalidArgumentException
91
     */
92 3
    public function updateDocumentIndexes($documentName, $timeout = null)
93
    {
94 3
        $class = $this->dm->getClassMetadata($documentName);
95
96 3
        if ($class->isMappedSuperclass || $class->isEmbeddedDocument) {
97
            throw new \InvalidArgumentException('Cannot update document indexes for mapped super classes or embedded documents.');
98
        }
99
100 3
        $documentIndexes = $this->getDocumentIndexes($documentName);
101 3
        $collection = $this->dm->getDocumentCollection($documentName);
102 3
        $mongoIndexes = $collection->getIndexInfo();
103
104
        /* Determine which Mongo indexes should be deleted. Exclude the ID index
105
         * and those that are equivalent to any in the class metadata.
106
         */
107 3
        $self = $this;
108 3
        $mongoIndexes = array_filter($mongoIndexes, function ($mongoIndex) use ($documentIndexes, $self) {
109 1
            if ('_id_' === $mongoIndex['name']) {
110
                return false;
111
            }
112
113 1
            foreach ($documentIndexes as $documentIndex) {
114 1
                if ($self->isMongoIndexEquivalentToDocumentIndex($mongoIndex, $documentIndex)) {
115
                    return false;
116
                }
117 1
            }
118
119 1
            return true;
120 3
        });
121
122
        // Delete indexes that do not exist in class metadata
123 3
        foreach ($mongoIndexes as $mongoIndex) {
124 1
            if (isset($mongoIndex['name'])) {
125
                /* Note: MongoCollection::deleteIndex() cannot delete
126
                 * custom-named indexes, so use the deleteIndexes command.
127
                 */
128 1
                $collection->getDatabase()->command(array(
129 1
                    'deleteIndexes' => $collection->getName(),
130 1
                    'index' => $mongoIndex['name'],
131 1
                ));
132 1
            }
133 3
        }
134
135 3
        $this->ensureDocumentIndexes($documentName, $timeout);
136 3
    }
137
138
    /**
139
     * @param string $documentName
140
     * @return array
141
     */
142 47
    public function getDocumentIndexes($documentName)
143
    {
144 47
        $visited = array();
145 47
        return $this->doGetDocumentIndexes($documentName, $visited);
146
    }
147
148
    /**
149
     * @param string $documentName
150
     * @param array $visited
151
     * @return array
152
     */
153 47
    private function doGetDocumentIndexes($documentName, array &$visited)
154
    {
155 47
        if (isset($visited[$documentName])) {
156 1
            return array();
157
        }
158
159 47
        $visited[$documentName] = true;
160
161 47
        $class = $this->dm->getClassMetadata($documentName);
162 47
        $indexes = $this->prepareIndexes($class);
163 47
        $embeddedDocumentIndexes = array();
164
165
        // Add indexes from embedded & referenced documents
166 47
        foreach ($class->fieldMappings as $fieldMapping) {
167 47
            if (isset($fieldMapping['embedded'])) {
168 31
                if (isset($fieldMapping['targetDocument'])) {
169 31
                    $possibleEmbeds = array($fieldMapping['targetDocument']);
170 31
                } elseif (isset($fieldMapping['discriminatorMap'])) {
171 1
                    $possibleEmbeds = array_unique($fieldMapping['discriminatorMap']);
172 1
                } else {
173 1
                    continue;
174
                }
175 31
                foreach ($possibleEmbeds as $embed) {
176 31
                    if (isset($embeddedDocumentIndexes[$embed])) {
177 25
                        $embeddedIndexes = $embeddedDocumentIndexes[$embed];
178 25
                    } else {
179 31
                        $embeddedIndexes = $this->doGetDocumentIndexes($embed, $visited);
180 31
                        $embeddedDocumentIndexes[$embed] = $embeddedIndexes;
181
                    }
182 31
                    foreach ($embeddedIndexes as $embeddedIndex) {
183 25
                        foreach ($embeddedIndex['keys'] as $key => $value) {
184 25
                            $embeddedIndex['keys'][$fieldMapping['name'] . '.' . $key] = $value;
185 25
                            unset($embeddedIndex['keys'][$key]);
186 25
                        }
187 25
                        $indexes[] = $embeddedIndex;
188 31
                    }
189 31
                }
190 47
            } elseif (isset($fieldMapping['reference']) && isset($fieldMapping['targetDocument'])) {
191 31
                foreach ($indexes as $idx => $index) {
192 31
                    $newKeys = array();
193 31
                    foreach ($index['keys'] as $key => $v) {
194 31
                        if ($key == $fieldMapping['name']) {
195 2
                            $key = $fieldMapping['simple'] ? $key : $key . '.$id';
196 2
                        }
197 31
                        $newKeys[$key] = $v;
198 31
                    }
199 31
                    $indexes[$idx]['keys'] = $newKeys;
200 31
                }
201 31
            }
202 47
        }
203 47
        return $indexes;
204
    }
205
206
    /**
207
     * @param ClassMetadata $class
208
     * @return array
209
     */
210 47
    private function prepareIndexes(ClassMetadata $class)
211
    {
212 47
        $persister = $this->dm->getUnitOfWork()->getDocumentPersister($class->name);
213 47
        $indexes = $class->getIndexes();
214 47
        $newIndexes = array();
215
216 47
        foreach ($indexes as $index) {
217
            $newIndex = array(
218 47
                'keys' => array(),
219 47
                'options' => $index['options']
220 47
            );
221 47
            foreach ($index['keys'] as $key => $value) {
222 47
                $key = $persister->prepareFieldName($key);
223 47
                if ($class->hasField($key)) {
224 45
                    $mapping = $class->getFieldMapping($key);
225 45
                    $newIndex['keys'][$mapping['name']] = $value;
226 45
                } else {
227 5
                    $newIndex['keys'][$key] = $value;
228
                }
229 47
            }
230
231 47
            $newIndexes[] = $newIndex;
232 47
        }
233
234 47
        return $newIndexes;
235
    }
236
237
    /**
238
     * Ensure the given document's indexes are created.
239
     *
240
     * @param string $documentName
241
     * @param integer $timeout Timeout (ms) for acknowledged index creation
242
     * @throws \InvalidArgumentException
243
     */
244 43
    public function ensureDocumentIndexes($documentName, $timeout = null)
245
    {
246 43
        $class = $this->dm->getClassMetadata($documentName);
247 43
        if ($class->isMappedSuperclass || $class->isEmbeddedDocument) {
248
            throw new \InvalidArgumentException('Cannot create document indexes for mapped super classes or embedded documents.');
249
        }
250 43
        if ($indexes = $this->getDocumentIndexes($documentName)) {
251 43
            $collection = $this->dm->getDocumentCollection($class->name);
252 43
            foreach ($indexes as $index) {
253 43
                $keys = $index['keys'];
254 43
                $options = $index['options'];
255
256 43
                if ( ! isset($options['safe']) && ! isset($options['w'])) {
257 42
                    $options['w'] = 1;
258 42
                }
259
260 43
                if (isset($options['safe']) && ! isset($options['w'])) {
261 1
                    $options['w'] = is_bool($options['safe']) ? (integer) $options['safe'] : $options['safe'];
262 1
                    unset($options['safe']);
263 1
                }
264
265 43
                if ( ! isset($options['timeout']) && isset($timeout)) {
266 1
                    $options['timeout'] = $timeout;
267 1
                }
268
269 43
                $collection->ensureIndex($keys, $options);
270 43
            }
271 43
        }
272 43
    }
273
274
    /**
275
     * Delete indexes for all documents that can be loaded with the
276
     * metadata factory.
277
     */
278 1 View Code Duplication
    public function deleteIndexes()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
279
    {
280 1
        foreach ($this->metadataFactory->getAllMetadata() as $class) {
281 1
            if ($class->isMappedSuperclass || $class->isEmbeddedDocument) {
282 1
                continue;
283
            }
284 1
            $this->deleteDocumentIndexes($class->name);
285 1
        }
286 1
    }
287
288
    /**
289
     * Delete the given document's indexes.
290
     *
291
     * @param string $documentName
292
     * @throws \InvalidArgumentException
293
     */
294 2 View Code Duplication
    public function deleteDocumentIndexes($documentName)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
295
    {
296 2
        $class = $this->dm->getClassMetadata($documentName);
297 2
        if ($class->isMappedSuperclass || $class->isEmbeddedDocument) {
298
            throw new \InvalidArgumentException('Cannot delete document indexes for mapped super classes or embedded documents.');
299
        }
300 2
        $this->dm->getDocumentCollection($documentName)->deleteIndexes();
301 2
    }
302
303
    /**
304
     * Create all the mapped document collections in the metadata factory.
305
     */
306 1 View Code Duplication
    public function createCollections()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
307
    {
308 1
        foreach ($this->metadataFactory->getAllMetadata() as $class) {
309 1
            if ($class->isMappedSuperclass || $class->isEmbeddedDocument) {
310 1
                continue;
311
            }
312 1
            $this->createDocumentCollection($class->name);
313 1
        }
314 1
    }
315
316
    /**
317
     * Create the document collection for a mapped class.
318
     *
319
     * @param string $documentName
320
     * @throws \InvalidArgumentException
321
     */
322 4
    public function createDocumentCollection($documentName)
323
    {
324 4
        $class = $this->dm->getClassMetadata($documentName);
325
326 4
        if ($class->isMappedSuperclass || $class->isEmbeddedDocument) {
327
            throw new \InvalidArgumentException('Cannot create document collection for mapped super classes or embedded documents.');
328
        }
329
330 4
        if ($class->isFile()) {
331 2
            $this->dm->getDocumentDatabase($documentName)->createCollection($class->getCollection() . '.files');
332 2
            $this->dm->getDocumentDatabase($documentName)->createCollection($class->getCollection() . '.chunks');
333
334 2
            return;
335
        }
336
337 3
        $this->dm->getDocumentDatabase($documentName)->createCollection(
338 3
            $class->getCollection(),
339 3
            $class->getCollectionCapped(),
340 3
            $class->getCollectionSize(),
341 3
            $class->getCollectionMax()
342 3
        );
343 3
    }
344
345
    /**
346
     * Drop all the mapped document collections in the metadata factory.
347
     */
348 1 View Code Duplication
    public function dropCollections()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
349
    {
350 1
        foreach ($this->metadataFactory->getAllMetadata() as $class) {
351 1
            if ($class->isMappedSuperclass || $class->isEmbeddedDocument) {
352 1
                continue;
353
            }
354 1
            $this->dropDocumentCollection($class->name);
355 1
        }
356 1
    }
357
358
    /**
359
     * Drop the document collection for a mapped class.
360
     *
361
     * @param string $documentName
362
     * @throws \InvalidArgumentException
363
     */
364 3 View Code Duplication
    public function dropDocumentCollection($documentName)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
365
    {
366 3
        $class = $this->dm->getClassMetadata($documentName);
367 3
        if ($class->isMappedSuperclass || $class->isEmbeddedDocument) {
368
            throw new \InvalidArgumentException('Cannot delete document indexes for mapped super classes or embedded documents.');
369
        }
370 3
        $this->dm->getDocumentDatabase($documentName)->dropCollection(
371 3
            $class->getCollection()
372 3
        );
373 3
    }
374
375
    /**
376
     * Drop all the mapped document databases in the metadata factory.
377
     */
378 1 View Code Duplication
    public function dropDatabases()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
379
    {
380 1
        foreach ($this->metadataFactory->getAllMetadata() as $class) {
381 1
            if ($class->isMappedSuperclass || $class->isEmbeddedDocument) {
382 1
                continue;
383
            }
384 1
            $this->dropDocumentDatabase($class->name);
385 1
        }
386 1
    }
387
388
    /**
389
     * Drop the document database for a mapped class.
390
     *
391
     * @param string $documentName
392
     * @throws \InvalidArgumentException
393
     */
394 2 View Code Duplication
    public function dropDocumentDatabase($documentName)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
395
    {
396 2
        $class = $this->dm->getClassMetadata($documentName);
397 2
        if ($class->isMappedSuperclass || $class->isEmbeddedDocument) {
398
            throw new \InvalidArgumentException('Cannot drop document database for mapped super classes or embedded documents.');
399
        }
400 2
        $this->dm->getDocumentDatabase($documentName)->drop();
401 2
    }
402
403
    /**
404
     * Create all the mapped document databases in the metadata factory.
405
     */
406 View Code Duplication
    public function createDatabases()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
407
    {
408
        foreach ($this->metadataFactory->getAllMetadata() as $class) {
409
            if ($class->isMappedSuperclass || $class->isEmbeddedDocument) {
410
                continue;
411
            }
412
            $this->createDocumentDatabase($class->name);
413
        }
414
    }
415
416
    /**
417
     * Create the document database for a mapped class.
418
     *
419
     * @param string $documentName
420
     * @throws \InvalidArgumentException
421
     */
422 1 View Code Duplication
    public function createDocumentDatabase($documentName)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
423
    {
424 1
        $class = $this->dm->getClassMetadata($documentName);
425 1
        if ($class->isMappedSuperclass || $class->isEmbeddedDocument) {
426
            throw new \InvalidArgumentException('Cannot delete document indexes for mapped super classes or embedded documents.');
427
        }
428 1
        $this->dm->getDocumentDatabase($documentName)->execute("function() { return true; }");
429 1
    }
430
431
    /**
432
     * Determine if an index returned by MongoCollection::getIndexInfo() can be
433
     * considered equivalent to an index in class metadata.
434
     *
435
     * Indexes are considered different if:
436
     *
437
     *   (a) Key/direction pairs differ or are not in the same order
438
     *   (b) Sparse or unique options differ
439
     *   (c) Mongo index is unique without dropDups and mapped index is unique
440
     *       with dropDups
441
     *   (d) Geospatial options differ (bits, max, min)
442
     *   (e) The partialFilterExpression differs
443
     *
444
     * Regarding (c), the inverse case is not a reason to delete and
445
     * recreate the index, since dropDups only affects creation of
446
     * the unique index. Additionally, the background option is only
447
     * relevant to index creation and is not considered.
448
     */
449 30
    public function isMongoIndexEquivalentToDocumentIndex($mongoIndex, $documentIndex)
450
    {
451 30
        $documentIndexOptions = $documentIndex['options'];
452
453 30
        if ($mongoIndex['key'] != $documentIndex['keys']) {
454 2
            return false;
455
        }
456
457 28
        if (empty($mongoIndex['sparse']) xor empty($documentIndexOptions['sparse'])) {
458 2
            return false;
459
        }
460
461 26
        if (empty($mongoIndex['unique']) xor empty($documentIndexOptions['unique'])) {
462 2
            return false;
463
        }
464
465 24
        if ( ! empty($mongoIndex['unique']) && empty($mongoIndex['dropDups']) &&
466 24
            ! empty($documentIndexOptions['unique']) && ! empty($documentIndexOptions['dropDups'])) {
467
468 1
            return false;
469
        }
470
471 23
        foreach (array('bits', 'max', 'min') as $option) {
472 23
            if (isset($mongoIndex[$option]) xor isset($documentIndexOptions[$option])) {
473 6
                return false;
474
            }
475
476 21
            if (isset($mongoIndex[$option]) && isset($documentIndexOptions[$option]) &&
477 21
                $mongoIndex[$option] !== $documentIndexOptions[$option]) {
478
479 3
                return false;
480
            }
481 20
        }
482
483 14
        if (empty($mongoIndex['partialFilterExpression']) xor empty($documentIndexOptions['partialFilterExpression'])) {
484 2
            return false;
485
        }
486
487 12
        if (isset($mongoIndex['partialFilterExpression']) && isset($documentIndexOptions['partialFilterExpression']) &&
488 12
            $mongoIndex['partialFilterExpression'] !== $documentIndexOptions['partialFilterExpression']) {
489
490 1
            return false;
491
        }
492
493 11
        return true;
494
    }
495
}
496