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
|
957 |
|
public function __construct(DocumentManager $dm, ClassMetadataFactory $cmf) |
43
|
|
|
{ |
44
|
957 |
|
$this->dm = $dm; |
45
|
957 |
|
$this->metadataFactory = $cmf; |
46
|
957 |
|
} |
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) |
|
|
|
|
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) |
|
|
|
|
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 |
|
if (version_compare(phpversion('mongo'), '1.3.0', '<')) { |
258
|
|
|
$options['safe'] = true; |
259
|
|
|
} else { |
260
|
42 |
|
$options['w'] = 1; |
261
|
|
|
} |
262
|
42 |
|
} |
263
|
|
|
|
264
|
43 |
|
if (isset($options['safe']) && ! isset($options['w']) && |
265
|
43 |
|
version_compare(phpversion('mongo'), '1.3.0', '>=')) { |
266
|
|
|
|
267
|
1 |
|
$options['w'] = is_bool($options['safe']) ? (integer) $options['safe'] : $options['safe']; |
268
|
1 |
|
unset($options['safe']); |
269
|
1 |
|
} |
270
|
|
|
|
271
|
43 |
|
if ( ! isset($options['timeout']) && isset($timeout)) { |
272
|
1 |
|
$options['timeout'] = $timeout; |
273
|
1 |
|
} |
274
|
|
|
|
275
|
43 |
|
$collection->ensureIndex($keys, $options); |
276
|
43 |
|
} |
277
|
43 |
|
} |
278
|
43 |
|
} |
279
|
|
|
|
280
|
|
|
/** |
281
|
|
|
* Delete indexes for all documents that can be loaded with the |
282
|
|
|
* metadata factory. |
283
|
|
|
*/ |
284
|
1 |
View Code Duplication |
public function deleteIndexes() |
|
|
|
|
285
|
|
|
{ |
286
|
1 |
|
foreach ($this->metadataFactory->getAllMetadata() as $class) { |
287
|
1 |
|
if ($class->isMappedSuperclass || $class->isEmbeddedDocument) { |
288
|
1 |
|
continue; |
289
|
|
|
} |
290
|
1 |
|
$this->deleteDocumentIndexes($class->name); |
291
|
1 |
|
} |
292
|
1 |
|
} |
293
|
|
|
|
294
|
|
|
/** |
295
|
|
|
* Delete the given document's indexes. |
296
|
|
|
* |
297
|
|
|
* @param string $documentName |
298
|
|
|
* @throws \InvalidArgumentException |
299
|
|
|
*/ |
300
|
2 |
View Code Duplication |
public function deleteDocumentIndexes($documentName) |
|
|
|
|
301
|
|
|
{ |
302
|
2 |
|
$class = $this->dm->getClassMetadata($documentName); |
303
|
2 |
|
if ($class->isMappedSuperclass || $class->isEmbeddedDocument) { |
304
|
|
|
throw new \InvalidArgumentException('Cannot delete document indexes for mapped super classes or embedded documents.'); |
305
|
|
|
} |
306
|
2 |
|
$this->dm->getDocumentCollection($documentName)->deleteIndexes(); |
307
|
2 |
|
} |
308
|
|
|
|
309
|
|
|
/** |
310
|
|
|
* Create all the mapped document collections in the metadata factory. |
311
|
|
|
*/ |
312
|
1 |
View Code Duplication |
public function createCollections() |
|
|
|
|
313
|
|
|
{ |
314
|
1 |
|
foreach ($this->metadataFactory->getAllMetadata() as $class) { |
315
|
1 |
|
if ($class->isMappedSuperclass || $class->isEmbeddedDocument) { |
316
|
1 |
|
continue; |
317
|
|
|
} |
318
|
1 |
|
$this->createDocumentCollection($class->name); |
319
|
1 |
|
} |
320
|
1 |
|
} |
321
|
|
|
|
322
|
|
|
/** |
323
|
|
|
* Create the document collection for a mapped class. |
324
|
|
|
* |
325
|
|
|
* @param string $documentName |
326
|
|
|
* @throws \InvalidArgumentException |
327
|
|
|
*/ |
328
|
4 |
|
public function createDocumentCollection($documentName) |
329
|
|
|
{ |
330
|
4 |
|
$class = $this->dm->getClassMetadata($documentName); |
331
|
|
|
|
332
|
4 |
|
if ($class->isMappedSuperclass || $class->isEmbeddedDocument) { |
333
|
|
|
throw new \InvalidArgumentException('Cannot create document collection for mapped super classes or embedded documents.'); |
334
|
|
|
} |
335
|
|
|
|
336
|
4 |
|
if ($class->isFile()) { |
337
|
2 |
|
$this->dm->getDocumentDatabase($documentName)->createCollection($class->getCollection() . '.files'); |
338
|
2 |
|
$this->dm->getDocumentDatabase($documentName)->createCollection($class->getCollection() . '.chunks'); |
339
|
|
|
|
340
|
2 |
|
return; |
341
|
|
|
} |
342
|
|
|
|
343
|
3 |
|
$this->dm->getDocumentDatabase($documentName)->createCollection( |
344
|
3 |
|
$class->getCollection(), |
345
|
3 |
|
$class->getCollectionCapped(), |
346
|
3 |
|
$class->getCollectionSize(), |
347
|
3 |
|
$class->getCollectionMax() |
348
|
3 |
|
); |
349
|
3 |
|
} |
350
|
|
|
|
351
|
|
|
/** |
352
|
|
|
* Drop all the mapped document collections in the metadata factory. |
353
|
|
|
*/ |
354
|
1 |
View Code Duplication |
public function dropCollections() |
|
|
|
|
355
|
|
|
{ |
356
|
1 |
|
foreach ($this->metadataFactory->getAllMetadata() as $class) { |
357
|
1 |
|
if ($class->isMappedSuperclass || $class->isEmbeddedDocument) { |
358
|
1 |
|
continue; |
359
|
|
|
} |
360
|
1 |
|
$this->dropDocumentCollection($class->name); |
361
|
1 |
|
} |
362
|
1 |
|
} |
363
|
|
|
|
364
|
|
|
/** |
365
|
|
|
* Drop the document collection for a mapped class. |
366
|
|
|
* |
367
|
|
|
* @param string $documentName |
368
|
|
|
* @throws \InvalidArgumentException |
369
|
|
|
*/ |
370
|
3 |
View Code Duplication |
public function dropDocumentCollection($documentName) |
|
|
|
|
371
|
|
|
{ |
372
|
3 |
|
$class = $this->dm->getClassMetadata($documentName); |
373
|
3 |
|
if ($class->isMappedSuperclass || $class->isEmbeddedDocument) { |
374
|
|
|
throw new \InvalidArgumentException('Cannot delete document indexes for mapped super classes or embedded documents.'); |
375
|
|
|
} |
376
|
3 |
|
$this->dm->getDocumentDatabase($documentName)->dropCollection( |
377
|
3 |
|
$class->getCollection() |
378
|
3 |
|
); |
379
|
3 |
|
} |
380
|
|
|
|
381
|
|
|
/** |
382
|
|
|
* Drop all the mapped document databases in the metadata factory. |
383
|
|
|
*/ |
384
|
1 |
View Code Duplication |
public function dropDatabases() |
|
|
|
|
385
|
|
|
{ |
386
|
1 |
|
foreach ($this->metadataFactory->getAllMetadata() as $class) { |
387
|
1 |
|
if ($class->isMappedSuperclass || $class->isEmbeddedDocument) { |
388
|
1 |
|
continue; |
389
|
|
|
} |
390
|
1 |
|
$this->dropDocumentDatabase($class->name); |
391
|
1 |
|
} |
392
|
1 |
|
} |
393
|
|
|
|
394
|
|
|
/** |
395
|
|
|
* Drop the document database for a mapped class. |
396
|
|
|
* |
397
|
|
|
* @param string $documentName |
398
|
|
|
* @throws \InvalidArgumentException |
399
|
|
|
*/ |
400
|
2 |
View Code Duplication |
public function dropDocumentDatabase($documentName) |
|
|
|
|
401
|
|
|
{ |
402
|
2 |
|
$class = $this->dm->getClassMetadata($documentName); |
403
|
2 |
|
if ($class->isMappedSuperclass || $class->isEmbeddedDocument) { |
404
|
|
|
throw new \InvalidArgumentException('Cannot drop document database for mapped super classes or embedded documents.'); |
405
|
|
|
} |
406
|
2 |
|
$this->dm->getDocumentDatabase($documentName)->drop(); |
407
|
2 |
|
} |
408
|
|
|
|
409
|
|
|
/** |
410
|
|
|
* Create all the mapped document databases in the metadata factory. |
411
|
|
|
*/ |
412
|
|
View Code Duplication |
public function createDatabases() |
|
|
|
|
413
|
|
|
{ |
414
|
|
|
foreach ($this->metadataFactory->getAllMetadata() as $class) { |
415
|
|
|
if ($class->isMappedSuperclass || $class->isEmbeddedDocument) { |
416
|
|
|
continue; |
417
|
|
|
} |
418
|
|
|
$this->createDocumentDatabase($class->name); |
419
|
|
|
} |
420
|
|
|
} |
421
|
|
|
|
422
|
|
|
/** |
423
|
|
|
* Create the document database for a mapped class. |
424
|
|
|
* |
425
|
|
|
* @param string $documentName |
426
|
|
|
* @throws \InvalidArgumentException |
427
|
|
|
*/ |
428
|
1 |
View Code Duplication |
public function createDocumentDatabase($documentName) |
|
|
|
|
429
|
|
|
{ |
430
|
1 |
|
$class = $this->dm->getClassMetadata($documentName); |
431
|
1 |
|
if ($class->isMappedSuperclass || $class->isEmbeddedDocument) { |
432
|
|
|
throw new \InvalidArgumentException('Cannot delete document indexes for mapped super classes or embedded documents.'); |
433
|
|
|
} |
434
|
1 |
|
$this->dm->getDocumentDatabase($documentName)->execute("function() { return true; }"); |
435
|
1 |
|
} |
436
|
|
|
|
437
|
|
|
/** |
438
|
|
|
* Determine if an index returned by MongoCollection::getIndexInfo() can be |
439
|
|
|
* considered equivalent to an index in class metadata. |
440
|
|
|
* |
441
|
|
|
* Indexes are considered different if: |
442
|
|
|
* |
443
|
|
|
* (a) Key/direction pairs differ or are not in the same order |
444
|
|
|
* (b) Sparse or unique options differ |
445
|
|
|
* (c) Mongo index is unique without dropDups and mapped index is unique |
446
|
|
|
* with dropDups |
447
|
|
|
* (d) Geospatial options differ (bits, max, min) |
448
|
|
|
* |
449
|
|
|
* Regarding (c), the inverse case is not a reason to delete and |
450
|
|
|
* recreate the index, since dropDups only affects creation of |
451
|
|
|
* the unique index. Additionally, the background option is only |
452
|
|
|
* relevant to index creation and is not considered. |
453
|
|
|
*/ |
454
|
1 |
|
public function isMongoIndexEquivalentToDocumentIndex($mongoIndex, $documentIndex) |
455
|
|
|
{ |
456
|
1 |
|
$documentIndexOptions = $documentIndex['options']; |
457
|
|
|
|
458
|
1 |
|
if ($mongoIndex['key'] != $documentIndex['keys']) { |
459
|
1 |
|
return false; |
460
|
|
|
} |
461
|
|
|
|
462
|
|
|
if (empty($mongoIndex['sparse']) xor empty($documentIndexOptions['sparse'])) { |
463
|
|
|
return false; |
464
|
|
|
} |
465
|
|
|
|
466
|
|
|
if (empty($mongoIndex['unique']) xor empty($documentIndexOptions['unique'])) { |
467
|
|
|
return false; |
468
|
|
|
} |
469
|
|
|
|
470
|
|
|
if ( ! empty($mongoIndex['unique']) && empty($mongoIndex['dropDups']) && |
471
|
|
|
! empty($documentIndexOptions['unique']) && ! empty($documentIndexOptions['dropDups'])) { |
472
|
|
|
|
473
|
|
|
return false; |
474
|
|
|
} |
475
|
|
|
|
476
|
|
|
foreach (array('bits', 'max', 'min') as $option) { |
477
|
|
|
if (isset($mongoIndex[$option]) xor isset($documentIndexOptions[$option])) { |
478
|
|
|
return false; |
479
|
|
|
} |
480
|
|
|
|
481
|
|
|
if (isset($mongoIndex[$option]) && isset($documentIndexOptions[$option]) && |
482
|
|
|
$mongoIndex[$option] !== $documentIndexOptions[$option]) { |
483
|
|
|
|
484
|
|
|
return false; |
485
|
|
|
} |
486
|
|
|
} |
487
|
|
|
|
488
|
|
|
return true; |
489
|
|
|
} |
490
|
|
|
} |
491
|
|
|
|
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.