@@ -53,6 +53,18 @@ public function __construct(
5353 }
5454 }
5555
56+ /**
57+ * Get Type
58+ *
59+ * Returns validator type.
60+ *
61+ * @return string
62+ */
63+ public function getType (): string
64+ {
65+ return self ::TYPE_OBJECT ;
66+ }
67+
5668 /**
5769 * Returns validator description
5870 * @return string
@@ -62,11 +74,69 @@ public function getDescription(): string
6274 return $ this ->message ;
6375 }
6476
77+ /**
78+ * Is array
79+ *
80+ * Function will return true if object is array.
81+ *
82+ * @return bool
83+ */
84+ public function isArray (): bool
85+ {
86+ return false ;
87+ }
88+
89+ /**
90+ * Is valid.
91+ *
92+ * Returns true index if valid.
93+ * @param Document $value
94+ * @return bool
95+ * @throws DatabaseException
96+ */
97+ public function isValid ($ value ): bool
98+ {
99+ if (!$ this ->checkValidAttributes ($ value )) {
100+ return false ;
101+ }
102+ if (!$ this ->checkEmptyIndexAttributes ($ value )) {
103+ return false ;
104+ }
105+ if (!$ this ->checkDuplicatedAttributes ($ value )) {
106+ return false ;
107+ }
108+ if (!$ this ->checkMultipleFulltextIndexes ($ value )) {
109+ return false ;
110+ }
111+ if (!$ this ->checkFulltextIndexNonString ($ value )) {
112+ return false ;
113+ }
114+ if (!$ this ->checkArrayIndexes ($ value )) {
115+ return false ;
116+ }
117+ if (!$ this ->checkIndexLengths ($ value )) {
118+ return false ;
119+ }
120+ if (!$ this ->checkReservedNames ($ value )) {
121+ return false ;
122+ }
123+ if (!$ this ->checkSpatialIndexes ($ value )) {
124+ return false ;
125+ }
126+ if (!$ this ->checkNonSpatialIndexOnSpatialAttributes ($ value )) {
127+ return false ;
128+ }
129+ if (!$ this ->checkVectorIndexes ($ value )) {
130+ return false ;
131+ }
132+ return true ;
133+ }
134+
65135 /**
66136 * @param Document $index
67137 * @return bool
68138 */
69- public function checkAttributesNotFound (Document $ index ): bool
139+ public function checkValidAttributes (Document $ index ): bool
70140 {
71141 foreach ($ index ->getAttribute ('attributes ' , []) as $ attribute ) {
72142 if ($ this ->supportForAttributes && !isset ($ this ->attributes [\strtolower ($ attribute )])) {
@@ -136,7 +206,7 @@ public function checkFulltextIndexNonString(Document $index): bool
136206 * @param Document $index
137207 * @return bool
138208 */
139- public function checkArrayIndex (Document $ index ): bool
209+ public function checkArrayIndexes (Document $ index ): bool
140210 {
141211 if (!$ this ->supportForAttributes ) {
142212 return true ;
@@ -189,7 +259,7 @@ public function checkArrayIndex(Document $index): bool
189259 * @param Document $index
190260 * @return bool
191261 */
192- public function checkIndexLength (Document $ index ): bool
262+ public function checkIndexLengths (Document $ index ): bool
193263 {
194264 if ($ index ->getAttribute ('type ' ) === Database::INDEX_FULLTEXT ) {
195265 return true ;
@@ -271,7 +341,7 @@ public function checkReservedNames(Document $index): bool
271341 * @param Document $index
272342 * @return bool
273343 */
274- public function checkSpatialIndex (Document $ index ): bool
344+ public function checkSpatialIndexes (Document $ index ): bool
275345 {
276346 $ type = $ index ->getAttribute ('type ' );
277347
@@ -315,7 +385,7 @@ public function checkSpatialIndex(Document $index): bool
315385 * @param Document $index
316386 * @return bool
317387 */
318- public function checkNonSpatialIndexOnSpatialAttribute (Document $ index ): bool
388+ public function checkNonSpatialIndexOnSpatialAttributes (Document $ index ): bool
319389 {
320390 $ type = $ index ->getAttribute ('type ' );
321391
@@ -344,7 +414,7 @@ public function checkNonSpatialIndexOnSpatialAttribute(Document $index): bool
344414 * @return bool
345415 * @throws DatabaseException
346416 */
347- public function checkVectorIndex (Document $ index ): bool
417+ public function checkVectorIndexes (Document $ index ): bool
348418 {
349419 $ type = $ index ->getAttribute ('type ' );
350420
@@ -385,69 +455,75 @@ public function checkVectorIndex(Document $index): bool
385455 }
386456
387457 /**
388- * Is valid.
389- *
390- * Returns true index if valid.
391- * @param Document $value
458+ * @param Document $index
392459 * @return bool
393- * @throws DatabaseException
394460 */
395- public function isValid ( $ value ): bool
461+ public function checkMultipleFulltextIndexes ( Document $ index ): bool
396462 {
397- if (!$ this ->checkAttributesNotFound ($ value )) {
398- return false ;
399- }
400- if (!$ this ->checkEmptyIndexAttributes ($ value )) {
401- return false ;
402- }
403- if (!$ this ->checkDuplicatedAttributes ($ value )) {
404- return false ;
405- }
406- if (!$ this ->checkFulltextIndexNonString ($ value )) {
407- return false ;
408- }
409- if (!$ this ->checkArrayIndex ($ value )) {
410- return false ;
411- }
412- if (!$ this ->checkIndexLength ($ value )) {
413- return false ;
414- }
415- if (!$ this ->checkReservedNames ($ value )) {
416- return false ;
417- }
418- if (!$ this ->checkSpatialIndex ($ value )) {
419- return false ;
420- }
421- if (!$ this ->checkNonSpatialIndexOnSpatialAttribute ($ value )) {
422- return false ;
463+ if ($ this ->supportForMultipleFulltextIndexes ) {
464+ return true ;
423465 }
424- if (!$ this ->checkVectorIndex ($ value )) {
425- return false ;
466+
467+ if ($ index ->getAttribute ('type ' ) === Database::INDEX_FULLTEXT ) {
468+ foreach ($ this ->indexes as $ existingIndex ) {
469+ if ($ existingIndex ->getId () === $ index ->getId ()) {
470+ continue ;
471+ }
472+ if ($ existingIndex ->getAttribute ('type ' ) === Database::INDEX_FULLTEXT ) {
473+ $ this ->message = 'There is already a fulltext index in the collection ' ;
474+ return false ;
475+ }
476+ }
426477 }
478+
427479 return true ;
428480 }
429481
430482 /**
431- * Is array
432- *
433- * Function will return true if object is array.
434- *
483+ * @param Document $index
435484 * @return bool
436485 */
437- public function isArray ( ): bool
486+ public function checkIdenticalIndexes ( Document $ index ): bool
438487 {
439- return false ;
440- }
488+ if ($ this ->supportForIdenticalIndexes ) {
489+ return true ;
490+ }
441491
442- /**
443- * Get Type
444- *
445- * Returns validator type.
446- *
447- * @return string
448- */
449- public function getType (): string
450- {
451- return self ::TYPE_OBJECT ;
492+ $ indexAttributes = $ index ->getAttribute ('attributes ' , []);
493+ $ indexOrders = $ index ->getAttribute ('orders ' , []);
494+ $ indexType = $ index ->getAttribute ('type ' , '' );
495+
496+ foreach ($ this ->indexes as $ existingIndex ) {
497+ $ existingAttributes = $ existingIndex ->getAttribute ('attributes ' , []);
498+ $ existingOrders = $ existingIndex ->getAttribute ('orders ' , []);
499+ $ existingType = $ existingIndex ->getAttribute ('type ' , '' );
500+
501+ $ attributesMatch = false ;
502+ if (empty (\array_diff ($ existingAttributes , $ indexAttributes )) &&
503+ empty (\array_diff ($ indexAttributes , $ existingAttributes ))) {
504+ $ attributesMatch = true ;
505+ }
506+
507+ $ ordersMatch = false ;
508+ if (empty (\array_diff ($ existingOrders , $ indexOrders )) &&
509+ empty (\array_diff ($ indexOrders , $ existingOrders ))) {
510+ $ ordersMatch = true ;
511+ }
512+
513+ if ($ attributesMatch && $ ordersMatch ) {
514+ // Allow fulltext + key/unique combinations (different purposes)
515+ $ regularTypes = [Database::INDEX_KEY , Database::INDEX_UNIQUE ];
516+ $ isRegularIndex = \in_array ($ indexType , $ regularTypes );
517+ $ isRegularExisting = \in_array ($ existingType , $ regularTypes );
518+
519+ // Only reject if both are regular index types (key or unique)
520+ if ($ isRegularIndex && $ isRegularExisting ) {
521+ $ this ->message = 'There is already an index with the same attributes and orders ' ;
522+ return false ;
523+ }
524+ }
525+ }
526+
527+ return true ;
452528 }
453529}
0 commit comments