diff --git a/composer.lock b/composer.lock index 5b4b39a9c..07b1321b9 100644 --- a/composer.lock +++ b/composer.lock @@ -145,24 +145,21 @@ }, { "name": "google/protobuf", - "version": "v4.32.0", + "version": "v4.32.1", "source": { "type": "git", "url": "https://github.com/protocolbuffers/protobuf-php.git", - "reference": "9a9a92ecbe9c671dc1863f6d4a91ea3ea12c8646" + "reference": "c4ed1c1f9bbc1e91766e2cd6c0af749324fe87cb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/protocolbuffers/protobuf-php/zipball/9a9a92ecbe9c671dc1863f6d4a91ea3ea12c8646", - "reference": "9a9a92ecbe9c671dc1863f6d4a91ea3ea12c8646", + "url": "https://api.github.com/repos/protocolbuffers/protobuf-php/zipball/c4ed1c1f9bbc1e91766e2cd6c0af749324fe87cb", + "reference": "c4ed1c1f9bbc1e91766e2cd6c0af749324fe87cb", "shasum": "" }, "require": { "php": ">=8.1.0" }, - "provide": { - "ext-protobuf": "*" - }, "require-dev": { "phpunit/phpunit": ">=5.0.0 <8.5.27" }, @@ -186,9 +183,9 @@ "proto" ], "support": { - "source": "https://github.com/protocolbuffers/protobuf-php/tree/v4.32.0" + "source": "https://github.com/protocolbuffers/protobuf-php/tree/v4.32.1" }, - "time": "2025-08-14T20:00:33+00:00" + "time": "2025-09-14T05:14:52+00:00" }, { "name": "mongodb/mongodb", @@ -413,20 +410,20 @@ }, { "name": "open-telemetry/api", - "version": "1.5.0", + "version": "1.6.0", "source": { "type": "git", "url": "https://github.com/opentelemetry-php/api.git", - "reference": "7692075f486c14d8cfd37fba98a08a5667f089e5" + "reference": "ee17d937652eca06c2341b6fadc0f74c1c1a5af2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/opentelemetry-php/api/zipball/7692075f486c14d8cfd37fba98a08a5667f089e5", - "reference": "7692075f486c14d8cfd37fba98a08a5667f089e5", + "url": "https://api.github.com/repos/opentelemetry-php/api/zipball/ee17d937652eca06c2341b6fadc0f74c1c1a5af2", + "reference": "ee17d937652eca06c2341b6fadc0f74c1c1a5af2", "shasum": "" }, "require": { - "open-telemetry/context": "^1.0", + "open-telemetry/context": "^1.4", "php": "^8.1", "psr/log": "^1.1|^2.0|^3.0", "symfony/polyfill-php82": "^1.26" @@ -479,20 +476,20 @@ "issues": "https://github.com/open-telemetry/opentelemetry-php/issues", "source": "https://github.com/open-telemetry/opentelemetry-php" }, - "time": "2025-08-07T23:07:38+00:00" + "time": "2025-09-19T00:05:49+00:00" }, { "name": "open-telemetry/context", - "version": "1.3.1", + "version": "1.4.0", "source": { "type": "git", "url": "https://github.com/opentelemetry-php/context.git", - "reference": "438f71812242db3f196fb4c717c6f92cbc819be6" + "reference": "d4c4470b541ce72000d18c339cfee633e4c8e0cf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/opentelemetry-php/context/zipball/438f71812242db3f196fb4c717c6f92cbc819be6", - "reference": "438f71812242db3f196fb4c717c6f92cbc819be6", + "url": "https://api.github.com/repos/opentelemetry-php/context/zipball/d4c4470b541ce72000d18c339cfee633e4c8e0cf", + "reference": "d4c4470b541ce72000d18c339cfee633e4c8e0cf", "shasum": "" }, "require": { @@ -538,7 +535,7 @@ "issues": "https://github.com/open-telemetry/opentelemetry-php/issues", "source": "https://github.com/open-telemetry/opentelemetry-php" }, - "time": "2025-08-13T01:12:00+00:00" + "time": "2025-09-19T00:05:49+00:00" }, { "name": "open-telemetry/exporter-otlp", @@ -606,16 +603,16 @@ }, { "name": "open-telemetry/gen-otlp-protobuf", - "version": "1.5.0", + "version": "1.8.0", "source": { "type": "git", "url": "https://github.com/opentelemetry-php/gen-otlp-protobuf.git", - "reference": "585bafddd4ae6565de154610b10a787a455c9ba0" + "reference": "673af5b06545b513466081884b47ef15a536edde" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/opentelemetry-php/gen-otlp-protobuf/zipball/585bafddd4ae6565de154610b10a787a455c9ba0", - "reference": "585bafddd4ae6565de154610b10a787a455c9ba0", + "url": "https://api.github.com/repos/opentelemetry-php/gen-otlp-protobuf/zipball/673af5b06545b513466081884b47ef15a536edde", + "reference": "673af5b06545b513466081884b47ef15a536edde", "shasum": "" }, "require": { @@ -665,27 +662,27 @@ "issues": "https://github.com/open-telemetry/opentelemetry-php/issues", "source": "https://github.com/open-telemetry/opentelemetry-php" }, - "time": "2025-01-15T23:07:07+00:00" + "time": "2025-09-17T23:10:12+00:00" }, { "name": "open-telemetry/sdk", - "version": "1.7.1", + "version": "1.8.0", "source": { "type": "git", "url": "https://github.com/opentelemetry-php/sdk.git", - "reference": "52690d4b37ae4f091af773eef3c238ed2bc0aa06" + "reference": "105c6e81e3d86150bd5704b00c7e4e165e957b89" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/opentelemetry-php/sdk/zipball/52690d4b37ae4f091af773eef3c238ed2bc0aa06", - "reference": "52690d4b37ae4f091af773eef3c238ed2bc0aa06", + "url": "https://api.github.com/repos/opentelemetry-php/sdk/zipball/105c6e81e3d86150bd5704b00c7e4e165e957b89", + "reference": "105c6e81e3d86150bd5704b00c7e4e165e957b89", "shasum": "" }, "require": { "ext-json": "*", "nyholm/psr7-server": "^1.1", - "open-telemetry/api": "^1.4", - "open-telemetry/context": "^1.0", + "open-telemetry/api": "^1.6", + "open-telemetry/context": "^1.4", "open-telemetry/sem-conv": "^1.0", "php": "^8.1", "php-http/discovery": "^1.14", @@ -762,7 +759,7 @@ "issues": "https://github.com/open-telemetry/opentelemetry-php/issues", "source": "https://github.com/open-telemetry/opentelemetry-php" }, - "time": "2025-09-05T07:17:06+00:00" + "time": "2025-09-19T00:05:49+00:00" }, { "name": "open-telemetry/sem-conv", @@ -2122,16 +2119,16 @@ }, { "name": "utopia-php/framework", - "version": "0.33.27", + "version": "0.33.28", "source": { "type": "git", "url": "https://github.com/utopia-php/http.git", - "reference": "d9d10a895e85c8c7675220347cc6109db9d3bd37" + "reference": "5aaa94d406577b0059ad28c78022606890dc6de0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/http/zipball/d9d10a895e85c8c7675220347cc6109db9d3bd37", - "reference": "d9d10a895e85c8c7675220347cc6109db9d3bd37", + "url": "https://api.github.com/repos/utopia-php/http/zipball/5aaa94d406577b0059ad28c78022606890dc6de0", + "reference": "5aaa94d406577b0059ad28c78022606890dc6de0", "shasum": "" }, "require": { @@ -2163,9 +2160,9 @@ ], "support": { "issues": "https://github.com/utopia-php/http/issues", - "source": "https://github.com/utopia-php/http/tree/0.33.27" + "source": "https://github.com/utopia-php/http/tree/0.33.28" }, - "time": "2025-09-07T18:40:53+00:00" + "time": "2025-09-25T10:44:24+00:00" }, { "name": "utopia-php/mongo", @@ -2467,16 +2464,16 @@ }, { "name": "laravel/pint", - "version": "v1.24.0", + "version": "v1.25.1", "source": { "type": "git", "url": "https://github.com/laravel/pint.git", - "reference": "0345f3b05f136801af8c339f9d16ef29e6b4df8a" + "reference": "5016e263f95d97670d71b9a987bd8996ade6d8d9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/pint/zipball/0345f3b05f136801af8c339f9d16ef29e6b4df8a", - "reference": "0345f3b05f136801af8c339f9d16ef29e6b4df8a", + "url": "https://api.github.com/repos/laravel/pint/zipball/5016e263f95d97670d71b9a987bd8996ade6d8d9", + "reference": "5016e263f95d97670d71b9a987bd8996ade6d8d9", "shasum": "" }, "require": { @@ -2487,9 +2484,9 @@ "php": "^8.2.0" }, "require-dev": { - "friendsofphp/php-cs-fixer": "^3.82.2", - "illuminate/view": "^11.45.1", - "larastan/larastan": "^3.5.0", + "friendsofphp/php-cs-fixer": "^3.87.2", + "illuminate/view": "^11.46.0", + "larastan/larastan": "^3.7.1", "laravel-zero/framework": "^11.45.0", "mockery/mockery": "^1.6.12", "nunomaduro/termwind": "^2.3.1", @@ -2500,9 +2497,6 @@ ], "type": "project", "autoload": { - "files": [ - "overrides/Runner/Parallel/ProcessFactory.php" - ], "psr-4": { "App\\": "app/", "Database\\Seeders\\": "database/seeders/", @@ -2532,7 +2526,7 @@ "issues": "https://github.com/laravel/pint/issues", "source": "https://github.com/laravel/pint" }, - "time": "2025-07-10T18:09:32+00:00" + "time": "2025-09-19T02:57:12+00:00" }, { "name": "myclabs/deep-copy", @@ -2804,16 +2798,16 @@ }, { "name": "phpstan/phpstan", - "version": "1.12.28", + "version": "1.12.31", "source": { "type": "git", - "url": "https://github.com/phpstan/phpstan.git", - "reference": "fcf8b71aeab4e1a1131d1783cef97b23a51b87a9" + "url": "https://github.com/phpstan/phpstan-phar-composer-source.git", + "reference": "git1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/fcf8b71aeab4e1a1131d1783cef97b23a51b87a9", - "reference": "fcf8b71aeab4e1a1131d1783cef97b23a51b87a9", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/a7630bb5311a41d13a2364634c78c5f4da250d53", + "reference": "a7630bb5311a41d13a2364634c78c5f4da250d53", "shasum": "" }, "require": { @@ -2858,7 +2852,7 @@ "type": "github" } ], - "time": "2025-07-17T17:15:39+00:00" + "time": "2025-09-24T15:58:55+00:00" }, { "name": "phpunit/php-code-coverage", @@ -3181,16 +3175,16 @@ }, { "name": "phpunit/phpunit", - "version": "9.6.26", + "version": "9.6.29", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "a0139ea157533454f611038326f3020b3051f129" + "reference": "9ecfec57835a5581bc888ea7e13b51eb55ab9dd3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/a0139ea157533454f611038326f3020b3051f129", - "reference": "a0139ea157533454f611038326f3020b3051f129", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/9ecfec57835a5581bc888ea7e13b51eb55ab9dd3", + "reference": "9ecfec57835a5581bc888ea7e13b51eb55ab9dd3", "shasum": "" }, "require": { @@ -3215,7 +3209,7 @@ "sebastian/comparator": "^4.0.9", "sebastian/diff": "^4.0.6", "sebastian/environment": "^5.1.5", - "sebastian/exporter": "^4.0.6", + "sebastian/exporter": "^4.0.8", "sebastian/global-state": "^5.0.8", "sebastian/object-enumerator": "^4.0.4", "sebastian/resource-operations": "^3.0.4", @@ -3264,7 +3258,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.26" + "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.29" }, "funding": [ { @@ -3288,7 +3282,7 @@ "type": "tidelift" } ], - "time": "2025-09-11T06:17:45+00:00" + "time": "2025-09-24T06:29:11+00:00" }, { "name": "rregeer/phpunit-coverage-check", @@ -3777,16 +3771,16 @@ }, { "name": "sebastian/exporter", - "version": "4.0.6", + "version": "4.0.8", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "78c00df8f170e02473b682df15bfcdacc3d32d72" + "reference": "14c6ba52f95a36c3d27c835d65efc7123c446e8c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/78c00df8f170e02473b682df15bfcdacc3d32d72", - "reference": "78c00df8f170e02473b682df15bfcdacc3d32d72", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/14c6ba52f95a36c3d27c835d65efc7123c446e8c", + "reference": "14c6ba52f95a36c3d27c835d65efc7123c446e8c", "shasum": "" }, "require": { @@ -3842,15 +3836,27 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/exporter/issues", - "source": "https://github.com/sebastianbergmann/exporter/tree/4.0.6" + "source": "https://github.com/sebastianbergmann/exporter/tree/4.0.8" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/sebastian/exporter", + "type": "tidelift" } ], - "time": "2024-03-02T06:33:00+00:00" + "time": "2025-09-24T06:03:27+00:00" }, { "name": "sebastian/global-state", @@ -4473,7 +4479,7 @@ ], "aliases": [], "minimum-stability": "stable", - "stability-flags": [], + "stability-flags": {}, "prefer-stable": false, "prefer-lowest": false, "platform": { @@ -4481,6 +4487,6 @@ "ext-pdo": "*", "ext-mbstring": "*" }, - "platform-dev": [], - "plugin-api-version": "2.2.0" + "platform-dev": {}, + "plugin-api-version": "2.6.0" } diff --git a/phpunit.xml b/phpunit.xml index 34365d48d..2a0531cfd 100755 --- a/phpunit.xml +++ b/phpunit.xml @@ -7,7 +7,7 @@ convertNoticesToExceptions="true" convertWarningsToExceptions="true" processIsolation="false" - stopOnFailure="true" + stopOnFailure="false" > diff --git a/src/Database/Adapter.php b/src/Database/Adapter.php index 1dd1ae8cb..930fc4584 100644 --- a/src/Database/Adapter.php +++ b/src/Database/Adapter.php @@ -1098,6 +1098,28 @@ abstract public function getSupportForBoundaryInclusiveContains(): bool; */ abstract public function getSupportForDistanceBetweenMultiDimensionGeometryInMeters(): bool; + /** + * Does the adapter support multiple fulltext indexes? + * + * @return bool + */ + abstract public function getSupportForMultipleFulltextIndexes(): bool; + + + /** + * Does the adapter support identical indexes? + * + * @return bool + */ + abstract public function getSupportForIdenticalIndexes(): bool; + + /** + * Does the adapter support random order by? + * + * @return bool + */ + abstract public function getSupportForOrderRandom(): bool; + /** * Get current attribute count from collection document * diff --git a/src/Database/Adapter/Mongo.php b/src/Database/Adapter/Mongo.php index 04d66d588..96fed3ccb 100644 --- a/src/Database/Adapter/Mongo.php +++ b/src/Database/Adapter/Mongo.php @@ -243,7 +243,11 @@ public function createCollection(string $name, array $attributes = [], array $in unset($index); } - $indexesCreated = $this->client->createIndexes($id, $internalIndex); + try { + $indexesCreated = $this->client->createIndexes($id, $internalIndex); + } catch (\Exception $e) { + throw $this->processException($e); + } if (!$indexesCreated) { return false; @@ -327,7 +331,14 @@ public function createCollection(string $name, array $attributes = [], array $in } } - if (!$this->getClient()->createIndexes($id, $newIndexes)) { + + try { + $indexesCreated = $this->getClient()->createIndexes($id, $newIndexes); + } catch (\Exception $e) { + throw $this->processException($e); + } + + if (!$indexesCreated) { return false; } } @@ -714,8 +725,11 @@ public function createIndex(string $collection, string $id, string $type, array $indexes['partialFilterExpression'] = $partialFilter; } } - - return $this->client->createIndexes($name, [$indexes], $options); + try { + return $this->client->createIndexes($name, [$indexes], $options); + } catch (\Exception $e) { + throw $this->processException($e); + } } /** @@ -762,18 +776,14 @@ public function renameIndex(string $collection, string $old, string $new): bool } } - if ($index - && $this->deleteIndex($collection, $old) - && $this->createIndex( - $collection, - $new, - $index['type'], - $index['attributes'], - $index['lengths'] ?? [], - $index['orders'] ?? [], - $indexAttributeTypes, // Use extracted attribute types - [] - )) { + try { + $deletedindex = $this->deleteIndex($collection, $old); + $createdindex = $this->createIndex($collection, $new, $index['type'], $index['attributes'], $index['lengths'] ?? [], $index['orders'] ?? [], $indexAttributeTypes, []); + } catch (\Exception $e) { + throw $this->processException($e); + } + + if ($index && $deletedindex && $createdindex) { return true; } @@ -2542,6 +2552,39 @@ public function getSupportForDistanceBetweenMultiDimensionGeometryInMeters(): bo return false; } + public function getSupportForOptionalSpatialAttributeWithExistingRows(): bool + { + return false; + } + + /** + * Does the adapter support multiple fulltext indexes? + * + * @return bool + */ + public function getSupportForMultipleFulltextIndexes(): bool + { + return false; + } + /** + * Does the adapter support identical indexes? + * + * @return bool + */ + public function getSupportForIdenticalIndexes(): bool + { + return false; + } + + /** + * Does the adapter support random order for queries? + * + * @return bool + */ + public function getSupportForOrderRandom(): bool + { + return false; + } /** * Flattens the array. diff --git a/src/Database/Adapter/Pool.php b/src/Database/Adapter/Pool.php index 9a9b90163..7da636fe1 100644 --- a/src/Database/Adapter/Pool.php +++ b/src/Database/Adapter/Pool.php @@ -524,36 +524,37 @@ public function getSupportForSpatialIndexOrder(): bool { return $this->delegate(__FUNCTION__, \func_get_args()); } - /** - * Does the adapter support calculating distance(in meters) between multidimension geometry(line, polygon,etc)? - * - * @return bool - */ + public function getSupportForDistanceBetweenMultiDimensionGeometryInMeters(): bool { return $this->delegate(__FUNCTION__, \func_get_args()); } - /** - * Does the adapter support spatial axis order specification? - * - * @return bool - */ public function getSupportForSpatialAxisOrder(): bool { return $this->delegate(__FUNCTION__, \func_get_args()); } - /** - * Adapter supports optional spatial attributes with existing rows. - * - * @return bool - */ public function getSupportForOptionalSpatialAttributeWithExistingRows(): bool { return $this->delegate(__FUNCTION__, \func_get_args()); } + public function getSupportForMultipleFulltextIndexes(): bool + { + return $this->delegate(__FUNCTION__, \func_get_args()); + } + + public function getSupportForIdenticalIndexes(): bool + { + return $this->delegate(__FUNCTION__, \func_get_args()); + } + + public function getSupportForOrderRandom(): bool + { + return $this->delegate(__FUNCTION__, \func_get_args()); + } + public function decodePoint(string $wkb): array { return $this->delegate(__FUNCTION__, \func_get_args()); diff --git a/src/Database/Adapter/SQL.php b/src/Database/Adapter/SQL.php index 61b7c4a13..d8387ec29 100644 --- a/src/Database/Adapter/SQL.php +++ b/src/Database/Adapter/SQL.php @@ -1513,15 +1513,45 @@ public function getSupportForSpatialIndexOrder(): bool } /** - * Is internal casting supported? - * - * @return bool - */ + * Is internal casting supported? + * + * @return bool + */ public function getSupportForInternalCasting(): bool { return false; } + /** + * Does the adapter support multiple fulltext indexes? + * + * @return bool + */ + public function getSupportForMultipleFulltextIndexes(): bool + { + return true; + } + + /** + * Does the adapter support identical indexes? + * + * @return bool + */ + public function getSupportForIdenticalIndexes(): bool + { + return true; + } + + /** + * Does the adapter support random order for queries? + * + * @return bool + */ + public function getSupportForOrderRandom(): bool + { + return true; + } + public function isMongo(): bool { return false; diff --git a/src/Database/Database.php b/src/Database/Database.php index ae56b052e..cba41a844 100644 --- a/src/Database/Database.php +++ b/src/Database/Database.php @@ -1407,13 +1407,16 @@ public function createCollection(string $id, array $attributes = [], array $inde if ($this->validate) { $validator = new IndexValidator( $attributes, + [], $this->adapter->getMaxIndexLength(), $this->adapter->getInternalIndexesKeys(), $this->adapter->getSupportForIndexArray(), $this->adapter->getSupportForSpatialAttributes(), $this->adapter->getSupportForSpatialIndexNull(), $this->adapter->getSupportForSpatialIndexOrder(), - $this->adapter->getSupportForAttributes() + $this->adapter->getSupportForAttributes(), + $this->adapter->getSupportForMultipleFulltextIndexes(), + $this->adapter->getSupportForIdenticalIndexes(), ); foreach ($indexes as $index) { if (!$validator->isValid($index)) { @@ -2247,6 +2250,13 @@ public function updateAttributeDefault(string $collection, string $id, mixed $de public function updateAttribute(string $collection, string $id, ?string $type = null, ?int $size = null, ?bool $required = null, mixed $default = null, ?bool $signed = null, ?bool $array = null, ?string $format = null, ?array $formatOptions = null, ?array $filters = null, ?string $newKey = null): Document { return $this->updateAttributeMeta($collection, $id, function ($attribute, $collectionDoc, $attributeIndex) use ($collection, $id, $type, $size, $required, $default, $signed, $array, $format, $formatOptions, $filters, $newKey) { + + // Store original indexes before any modifications (deep copy preserving Document objects) + $originalIndexes = []; + foreach ($collectionDoc->getAttribute('indexes', []) as $index) { + $originalIndexes[] = clone $index; + } + $altering = !\is_null($type) || !\is_null($size) || !\is_null($signed) @@ -2417,13 +2427,16 @@ public function updateAttribute(string $collection, string $id, ?string $type = if ($this->validate) { $validator = new IndexValidator( $attributes, + $originalIndexes, $this->adapter->getMaxIndexLength(), $this->adapter->getInternalIndexesKeys(), $this->adapter->getSupportForIndexArray(), $this->adapter->getSupportForSpatialAttributes(), $this->adapter->getSupportForSpatialIndexNull(), $this->adapter->getSupportForSpatialIndexOrder(), - $this->adapter->getSupportForAttributes() + $this->adapter->getSupportForAttributes(), + $this->adapter->getSupportForMultipleFulltextIndexes(), + $this->adapter->getSupportForIdenticalIndexes(), ); foreach ($indexes as $index) { @@ -3356,24 +3369,28 @@ public function createIndex(string $collection, string $id, string $type, array 'orders' => $orders, ]); - $collection->setAttribute('indexes', $index, Document::SET_TYPE_APPEND); - if ($this->validate) { + $validator = new IndexValidator( $collection->getAttribute('attributes', []), + $collection->getAttribute('indexes', []), $this->adapter->getMaxIndexLength(), $this->adapter->getInternalIndexesKeys(), $this->adapter->getSupportForIndexArray(), $this->adapter->getSupportForSpatialAttributes(), $this->adapter->getSupportForSpatialIndexNull(), $this->adapter->getSupportForSpatialIndexOrder(), - $this->adapter->getSupportForAttributes() + $this->adapter->getSupportForAttributes(), + $this->adapter->getSupportForMultipleFulltextIndexes(), + $this->adapter->getSupportForIdenticalIndexes(), ); if (!$validator->isValid($index)) { throw new IndexException($validator->getDescription()); } } + $collection->setAttribute('indexes', $index, Document::SET_TYPE_APPEND); + try { $created = $this->adapter->createIndex($collection->getId(), $id, $type, $attributes, $lengths, $orders, $indexAttributesWithTypes); diff --git a/src/Database/Validator/Index.php b/src/Database/Validator/Index.php index e22bfaaff..cc2877d65 100644 --- a/src/Database/Validator/Index.php +++ b/src/Database/Validator/Index.php @@ -31,18 +31,43 @@ class Index extends Validator protected bool $spatialIndexOrderSupport; protected bool $supportForAttributes; + + protected bool $multipleFulltextIndexSupport; + + protected bool $identicalIndexSupport; + + /** + * @var array $indexes + */ + protected array $indexes; + /** * @param array $attributes + * @param array $indexes * @param int $maxLength * @param array $reservedKeys * @param bool $arrayIndexSupport * @param bool $spatialIndexSupport * @param bool $spatialIndexNullSupport * @param bool $spatialIndexOrderSupport + * @param bool $supportForAttributes + * @param bool $multipleFulltextIndexSupport + * @param bool $identicalIndexSupport * @throws DatabaseException */ - public function __construct(array $attributes, int $maxLength, array $reservedKeys = [], bool $arrayIndexSupport = false, bool $spatialIndexSupport = false, bool $spatialIndexNullSupport = false, bool $spatialIndexOrderSupport = false, bool $supportForAttributes = true) - { + public function __construct( + array $attributes, + array $indexes, + int $maxLength, + array $reservedKeys = [], + bool $arrayIndexSupport = false, + bool $spatialIndexSupport = false, + bool $spatialIndexNullSupport = false, + bool $spatialIndexOrderSupport = false, + bool $supportForAttributes = true, + bool $multipleFulltextIndexSupport = true, + bool $identicalIndexSupport = true + ) { $this->maxLength = $maxLength; $this->reservedKeys = $reservedKeys; $this->arrayIndexSupport = $arrayIndexSupport; @@ -50,11 +75,15 @@ public function __construct(array $attributes, int $maxLength, array $reservedKe $this->spatialIndexNullSupport = $spatialIndexNullSupport; $this->spatialIndexOrderSupport = $spatialIndexOrderSupport; $this->supportForAttributes = $supportForAttributes; + $this->multipleFulltextIndexSupport = $multipleFulltextIndexSupport; + $this->identicalIndexSupport = $identicalIndexSupport; + $this->indexes = $indexes; foreach ($attributes as $attribute) { $key = \strtolower($attribute->getAttribute('key', $attribute->getAttribute('$id'))); $this->attributes[$key] = $attribute; } + foreach (Database::INTERNAL_ATTRIBUTES as $attribute) { $key = \strtolower($attribute['$id']); $this->attributes[$key] = new Document($attribute); @@ -132,7 +161,7 @@ public function checkFulltextIndexNonString(Document $index): bool foreach ($index->getAttribute('attributes', []) as $attribute) { $attribute = $this->attributes[\strtolower($attribute)] ?? new Document(); if ($attribute->getAttribute('type', '') !== Database::VAR_STRING) { - $this->message = 'Attribute "' . $attribute->getAttribute('key', $attribute->getAttribute('$id')) . '" cannot be part of a FULLTEXT index, must be of type string'; + $this->message = 'Attribute "' . $attribute->getAttribute('key', $attribute->getAttribute('$id')) . '" cannot be part of a fulltext index, must be of type string'; return false; } } @@ -313,6 +342,14 @@ public function isValid($value): bool return false; } + if (!$this->checkMultipleFulltextIndex($value)) { + return false; + } + + if (!$this->checkIdenticalIndex($value)) { + return false; + } + return true; } @@ -340,6 +377,67 @@ public function getType(): string return self::TYPE_OBJECT; } + /** + * @param Document $index + * @return bool + */ + public function checkMultipleFulltextIndex(Document $index): bool + { + if ($this->multipleFulltextIndexSupport) { + return true; + } + + if ($index->getAttribute('type') === Database::INDEX_FULLTEXT) { + foreach ($this->indexes as $existingIndex) { + if ($existingIndex->getAttribute('type') === Database::INDEX_FULLTEXT) { + $this->message = 'There is already a fulltext index in the collection'; + return false; + } + } + } + + return true; + } + + /** + * @param Document $index + * @return bool + */ + public function checkIdenticalIndex(Document $index): bool + { + if ($this->identicalIndexSupport) { + return true; + } + + $indexAttributes = $index->getAttribute('attributes', []); + $indexOrders = $index->getAttribute('orders', []); + + foreach ($this->indexes as $existingIndex) { + $existingAttributes = $existingIndex->getAttribute('attributes', []); + $existingOrders = $existingIndex->getAttribute('orders', []); + + $attributesMatch = false; + if (empty(array_diff($existingAttributes, $indexAttributes)) && + empty(array_diff($indexAttributes, $existingAttributes))) { + $attributesMatch = true; + } + + $ordersMatch = false; + if (empty(array_diff($existingOrders, $indexOrders)) && + empty(array_diff($indexOrders, $existingOrders))) { + $ordersMatch = true; + } + + if ($attributesMatch && $ordersMatch) { + $this->message = 'There is already an index with the same attributes and orders'; + return false; + } + } + + return true; + } + + /** * @param Document $index * @return bool diff --git a/tests/e2e/Adapter/Scopes/AttributeTests.php b/tests/e2e/Adapter/Scopes/AttributeTests.php index 60eb25f77..53bdd54e7 100644 --- a/tests/e2e/Adapter/Scopes/AttributeTests.php +++ b/tests/e2e/Adapter/Scopes/AttributeTests.php @@ -705,12 +705,27 @@ public function testUpdateAttributeRename(): void $this->assertEquals('renamed', $collection->getAttribute('attributes')[0]['$id']); $this->assertEquals('renamed', $collection->getAttribute('indexes')[0]['attributes'][0]); - // Check empty newKey doesn't cause issues - $database->updateAttribute( - collection: 'rename_test', - id: 'renamed', - type: Database::VAR_STRING, - ); + $supportsIdenticalIndexes = $database->getAdapter()->getSupportForIdenticalIndexes(); + + try { + // Check empty newKey doesn't cause issues + $database->updateAttribute( + collection: 'rename_test', + id: 'renamed', + type: Database::VAR_STRING, + ); + + if (!$supportsIdenticalIndexes) { + $this->fail('Expected exception when getSupportForIdenticalIndexes=false but none was thrown'); + } + } catch (Throwable $e) { + if (!$supportsIdenticalIndexes) { + $this->assertTrue(true, 'Exception thrown as expected when getSupportForIdenticalIndexes=false'); + return; // Exit early if exception was expected + } else { + $this->fail('Unexpected exception when getSupportForIdenticalIndexes=true: ' . $e->getMessage()); + } + } $collection = $database->getCollection('rename_test'); @@ -1308,12 +1323,12 @@ public function testArrayAttribute(): void required: false, signed: false )); - /** Is this hack valid? */ + $this->assertEquals(true, $database->createAttribute( $collection, 'tv_show', Database::VAR_STRING, - size: $database->getAdapter()->getMaxIndexLength() - 68, /** Verify with Jake if this solution is valid? */ + size: $database->getAdapter()->getMaxIndexLength() - 68, required: false, signed: false, )); @@ -1426,7 +1441,7 @@ public function testArrayAttribute(): void if ($database->getAdapter()->getSupportForIndexArray()) { /** - * functional index dependency cannot be dropped or rename + * Functional index dependency cannot be dropped or rename */ $database->createIndex($collection, 'idx_cards', Database::INDEX_KEY, ['cards'], [100]); } @@ -1508,8 +1523,6 @@ public function testArrayAttribute(): void )); if ($database->getAdapter()->getSupportForIndexArray()) { - - if ($database->getAdapter()->getMaxIndexLength() > 0) { // If getMaxIndexLength() > 0 We clear length for array attributes $database->createIndex($collection, 'indx1', Database::INDEX_KEY, ['long_size'], [], []); @@ -1524,9 +1537,6 @@ public function testArrayAttribute(): void } } - // We clear orders for array attributes - $database->createIndex($collection, 'indx3', Database::INDEX_KEY, ['names'], [255], ['desc']); - try { if ($database->getAdapter()->getSupportForAttributes()) { $database->createIndex($collection, 'indx4', Database::INDEX_KEY, ['age', 'names'], [10, 255], []); diff --git a/tests/e2e/Adapter/Scopes/DocumentTests.php b/tests/e2e/Adapter/Scopes/DocumentTests.php index ca2a08a29..ac2896226 100644 --- a/tests/e2e/Adapter/Scopes/DocumentTests.php +++ b/tests/e2e/Adapter/Scopes/DocumentTests.php @@ -3525,6 +3525,11 @@ public function testFindOrderRandom(): void /** @var Database $database */ $database = static::getDatabase(); + if (!$database->getAdapter()->getSupportForOrderRandom()) { + $this->expectNotToPerformAssertions(); + return; + } + // Test orderRandom with default limit $documents = $database->find('movies', [ Query::orderRandom(), @@ -5230,7 +5235,7 @@ public function testFulltextIndexWithInteger(): void if (!$this->getDatabase()->getAdapter()->getSupportForFulltextIndex()) { $this->expectExceptionMessage('Fulltext index is not supported'); } else { - $this->expectExceptionMessage('Attribute "integer_signed" cannot be part of a FULLTEXT index, must be of type string'); + $this->expectExceptionMessage('Attribute "integer_signed" cannot be part of a fulltext index, must be of type string'); } $database->createIndex('documents', 'fulltext_integer', Database::INDEX_FULLTEXT, ['string','integer_signed']); diff --git a/tests/e2e/Adapter/Scopes/IndexTests.php b/tests/e2e/Adapter/Scopes/IndexTests.php index 3d2aa5917..ac11e11cd 100644 --- a/tests/e2e/Adapter/Scopes/IndexTests.php +++ b/tests/e2e/Adapter/Scopes/IndexTests.php @@ -164,9 +164,16 @@ public function testIndexValidation(): void $validator = new Index( $attributes, + $indexes, $database->getAdapter()->getMaxIndexLength(), $database->getAdapter()->getInternalIndexesKeys(), - $database->getAdapter()->getSupportForIndexArray() + $database->getAdapter()->getSupportForIndexArray(), + $database->getAdapter()->getSupportForSpatialAttributes(), + $database->getAdapter()->getSupportForSpatialIndexNull(), + $database->getAdapter()->getSupportForSpatialIndexOrder(), + $database->getAdapter()->getSupportForAttributes(), + $database->getAdapter()->getSupportForMultipleFulltextIndexes(), + $database->getAdapter()->getSupportForIdenticalIndexes() ); $errorMessage = 'Index length 701 is larger than the size for title1: 700"'; @@ -239,13 +246,25 @@ public function testIndexValidation(): void $validator = new Index( $attributes, + $indexes, $database->getAdapter()->getMaxIndexLength(), $database->getAdapter()->getInternalIndexesKeys(), - $database->getAdapter()->getSupportForIndexArray() + $database->getAdapter()->getSupportForIndexArray(), + $database->getAdapter()->getSupportForSpatialAttributes(), + $database->getAdapter()->getSupportForSpatialIndexNull(), + $database->getAdapter()->getSupportForSpatialIndexOrder(), + $database->getAdapter()->getSupportForAttributes(), + $database->getAdapter()->getSupportForMultipleFulltextIndexes(), + $database->getAdapter()->getSupportForIdenticalIndexes() ); - $errorMessage = 'Attribute "integer" cannot be part of a FULLTEXT index, must be of type string'; + $this->assertFalse($validator->isValid($indexes[0])); - $this->assertEquals($errorMessage, $validator->getDescription()); + + if (!$database->getAdapter()->getSupportForMultipleFulltextIndexes()) { + $this->assertEquals('There is already a fulltext index in the collection', $validator->getDescription()); + } elseif ($database->getAdapter()->getSupportForAttributes()) { + $this->assertEquals('Attribute "integer" cannot be part of a fulltext index, must be of type string', $validator->getDescription()); + } try { $database->createCollection($collection->getId(), $attributes, $indexes); @@ -253,7 +272,7 @@ public function testIndexValidation(): void $this->fail('Failed to throw exception'); } } catch (Exception $e) { - $this->assertEquals($errorMessage, $e->getMessage()); + $this->assertEquals('Attribute "integer" cannot be part of a fulltext index, must be of type string', $e->getMessage()); } @@ -487,4 +506,129 @@ public function testEmptySearch(): void ]); $this->assertEquals(0, count($documents)); } + + public function testMultipleFulltextIndexValidation(): void + { + + $fulltextSupport = $this->getDatabase()->getAdapter()->getSupportForFulltextIndex(); + if (!$fulltextSupport) { + $this->expectNotToPerformAssertions(); + return; + } + + /** @var Database $database */ + $database = static::getDatabase(); + + $collectionId = 'multiple_fulltext_test'; + try { + $database->createCollection($collectionId); + + $database->createAttribute($collectionId, 'title', Database::VAR_STRING, 256, false); + $database->createAttribute($collectionId, 'content', Database::VAR_STRING, 256, false); + $database->createIndex($collectionId, 'fulltext_title', Database::INDEX_FULLTEXT, ['title']); + + $supportsMultipleFulltext = $database->getAdapter()->getSupportForMultipleFulltextIndexes(); + + // Try to add second fulltext index + try { + $database->createIndex($collectionId, 'fulltext_content', Database::INDEX_FULLTEXT, ['content']); + + if ($supportsMultipleFulltext) { + $this->assertTrue(true, 'Multiple fulltext indexes are supported and second index was created successfully'); + } else { + $this->fail('Expected exception when creating second fulltext index, but none was thrown'); + } + } catch (Throwable $e) { + if (!$supportsMultipleFulltext) { + $this->assertTrue(true, 'Multiple fulltext indexes are not supported and exception was thrown as expected'); + } else { + $this->fail('Unexpected exception when creating second fulltext index: ' . $e->getMessage()); + } + } + + } finally { + // Clean up + $database->deleteCollection($collectionId); + } + } + + public function testIdenticalIndexValidation(): void + { + /** @var Database $database */ + $database = static::getDatabase(); + + $collectionId = 'identical_index_test'; + + try { + $database->createCollection($collectionId); + + $database->createAttribute($collectionId, 'name', Database::VAR_STRING, 256, false); + $database->createAttribute($collectionId, 'age', Database::VAR_INTEGER, 8, false); + + $database->createIndex($collectionId, 'index1', Database::INDEX_KEY, ['name', 'age'], [], [Database::ORDER_ASC, Database::ORDER_DESC]); + + $supportsIdenticalIndexes = $database->getAdapter()->getSupportForIdenticalIndexes(); + + // Try to add identical index (failure) + try { + $database->createIndex($collectionId, 'index2', Database::INDEX_KEY, ['name', 'age'], [], [Database::ORDER_ASC, Database::ORDER_DESC]); + if ($supportsIdenticalIndexes) { + $this->assertTrue(true, 'Identical indexes are supported and second index was created successfully'); + } else { + $this->fail('Expected exception but got none'); + } + + } catch (Throwable $e) { + if (!$supportsIdenticalIndexes) { + $this->assertTrue(true, 'Identical indexes are not supported and exception was thrown as expected'); + } else { + $this->fail('Unexpected exception when creating identical index: ' . $e->getMessage()); + } + + } + + // Test with different attributes order - faliure + try { + $database->createIndex($collectionId, 'index3', Database::INDEX_KEY, ['age', 'name'], [], [ Database::ORDER_ASC, Database::ORDER_DESC]); + $this->assertTrue(true, 'Index with different attributes was created successfully'); + } catch (Throwable $e) { + if (!$supportsIdenticalIndexes) { + $this->assertTrue(true, 'Identical indexes are not supported and exception was thrown as expected'); + } else { + $this->fail('Unexpected exception when creating identical index: ' . $e->getMessage()); + } + } + + // Test with different orders order - faliure + try { + $database->createIndex($collectionId, 'index4', Database::INDEX_KEY, ['age', 'name'], [], [ Database::ORDER_DESC, Database::ORDER_ASC]); + $this->assertTrue(true, 'Index with different attributes was created successfully'); + } catch (Throwable $e) { + if (!$supportsIdenticalIndexes) { + $this->assertTrue(true, 'Identical indexes are not supported and exception was thrown as expected'); + } else { + $this->fail('Unexpected exception when creating identical index: ' . $e->getMessage()); + } + } + + // Test with different attributes - success + try { + $database->createIndex($collectionId, 'index5', Database::INDEX_KEY, ['name'], [], [Database::ORDER_ASC]); + $this->assertTrue(true, 'Index with different attributes was created successfully'); + } catch (Throwable $e) { + $this->fail('Unexpected exception when creating index with different attributes: ' . $e->getMessage()); + } + + // Test with different orders - success + try { + $database->createIndex($collectionId, 'index6', Database::INDEX_KEY, ['name', 'age'], [], [Database::ORDER_ASC]); + $this->assertTrue(true, 'Index with different orders was created successfully'); + } catch (Throwable $e) { + $this->fail('Unexpected exception when creating index with different orders: ' . $e->getMessage()); + } + } finally { + // Clean up + $database->deleteCollection($collectionId); + } + } } diff --git a/tests/e2e/Adapter/Scopes/SpatialTests.php b/tests/e2e/Adapter/Scopes/SpatialTests.php index 31093e724..15fb45b16 100644 --- a/tests/e2e/Adapter/Scopes/SpatialTests.php +++ b/tests/e2e/Adapter/Scopes/SpatialTests.php @@ -21,7 +21,8 @@ public function testSpatialCollection(): void $database = static::getDatabase(); $collectionName = "test_spatial_Col"; if (!$database->getAdapter()->getSupportForSpatialAttributes()) { - $this->markTestSkipped('Adapter does not support spatial attributes'); + $this->expectNotToPerformAssertions(); + return; }; $attributes = [ new Document([ @@ -94,7 +95,8 @@ public function testSpatialTypeDocuments(): void /** @var Database $database */ $database = static::getDatabase(); if (!$database->getAdapter()->getSupportForSpatialAttributes()) { - $this->markTestSkipped('Adapter does not support spatial attributes'); + $this->expectNotToPerformAssertions(); + return; } $collectionName = 'test_spatial_doc_'; @@ -918,7 +920,8 @@ public function testComplexGeometricShapes(): void /** @var Database $database */ $database = static::getDatabase(); if (!$database->getAdapter()->getSupportForSpatialAttributes()) { - $this->markTestSkipped('Adapter does not support spatial attributes'); + $this->expectNotToPerformAssertions(); + return; } $collectionName = 'complex_shapes_'; @@ -1348,7 +1351,8 @@ public function testSpatialQueryCombinations(): void /** @var Database $database */ $database = static::getDatabase(); if (!$database->getAdapter()->getSupportForSpatialAttributes()) { - $this->markTestSkipped('Adapter does not support spatial attributes'); + $this->expectNotToPerformAssertions(); + return; } $collectionName = 'spatial_combinations_'; @@ -1478,7 +1482,8 @@ public function testSpatialBulkOperation(): void /** @var Database $database */ $database = static::getDatabase(); if (!$database->getAdapter()->getSupportForSpatialAttributes()) { - $this->markTestSkipped('Adapter does not support spatial attributes'); + $this->expectNotToPerformAssertions(); + return; } $collectionName = 'test_spatial_bulk_ops'; @@ -1780,7 +1785,8 @@ public function testSptialAggregation(): void /** @var Database $database */ $database = static::getDatabase(); if (!$database->getAdapter()->getSupportForSpatialAttributes()) { - $this->markTestSkipped('Adapter does not support spatial attributes'); + $this->expectNotToPerformAssertions(); + return; } $collectionName = 'spatial_agg_'; try { @@ -1867,7 +1873,8 @@ public function testUpdateSpatialAttributes(): void /** @var Database $database */ $database = static::getDatabase(); if (!$database->getAdapter()->getSupportForSpatialAttributes()) { - $this->markTestSkipped('Adapter does not support spatial attributes'); + $this->expectNotToPerformAssertions(); + return; } $collectionName = 'spatial_update_attrs_'; @@ -1953,7 +1960,8 @@ public function testSpatialAttributeDefaults(): void /** @var Database $database */ $database = static::getDatabase(); if (!$database->getAdapter()->getSupportForSpatialAttributes()) { - $this->markTestSkipped('Adapter does not support spatial attributes'); + $this->expectNotToPerformAssertions(); + return; } $collectionName = 'spatial_defaults_'; @@ -2057,7 +2065,8 @@ public function testInvalidSpatialTypes(): void /** @var Database $database */ $database = static::getDatabase(); if (!$database->getAdapter()->getSupportForSpatialAttributes()) { - $this->markTestSkipped('Adapter does not support spatial attributes'); + $this->expectNotToPerformAssertions(); + return; } $collectionName = 'test_invalid_spatial_types'; @@ -2162,7 +2171,8 @@ public function testSpatialDistanceInMeter(): void /** @var Database $database */ $database = static::getDatabase(); if (!$database->getAdapter()->getSupportForSpatialAttributes()) { - $this->markTestSkipped('Adapter does not support spatial attributes'); + $this->expectNotToPerformAssertions(); + return; } $collectionName = 'spatial_distance_meters_'; @@ -2232,11 +2242,13 @@ public function testSpatialDistanceInMeterForMultiDimensionGeometry(): void /** @var Database $database */ $database = static::getDatabase(); if (!$database->getAdapter()->getSupportForSpatialAttributes()) { - $this->markTestSkipped('Adapter does not support spatial attributes'); + $this->expectNotToPerformAssertions(); + return; } if (!$database->getAdapter()->getSupportForDistanceBetweenMultiDimensionGeometryInMeters()) { - $this->markTestSkipped('Adapter does not support spatial distance(in meter) for multidimension'); + $this->expectNotToPerformAssertions(); + return; } $multiCollection = 'spatial_distance_meters_multi_'; @@ -2362,11 +2374,13 @@ public function testSpatialDistanceInMeterError(): void /** @var Database $database */ $database = static::getDatabase(); if (!$database->getAdapter()->getSupportForSpatialAttributes()) { - $this->markTestSkipped('Adapter does not support spatial attributes'); + $this->expectNotToPerformAssertions(); + return; } if ($database->getAdapter()->getSupportForDistanceBetweenMultiDimensionGeometryInMeters()) { - $this->markTestSkipped('Adapter supports spatial distance (in meter) for multidimension geometries'); + $this->expectNotToPerformAssertions(); + return; } $collection = 'spatial_distance_error_test'; @@ -2445,7 +2459,8 @@ public function testSpatialEncodeDecode(): void /** @var Database $database */ $database = static::getDatabase(); if (!$database->getAdapter()->getSupportForSpatialAttributes()) { - $this->markTestSkipped('Adapter does not support spatial attributes'); + $this->expectNotToPerformAssertions(); + return; } $point = "POINT(1 2)"; $line = "LINESTRING(1 2, 1 2)"; @@ -2635,7 +2650,8 @@ public function testSpatialDocOrder(): void /** @var Database $database */ $database = static::getDatabase(); if (!$database->getAdapter()->getSupportForSpatialAttributes()) { - $this->markTestSkipped('Adapter does not support spatial attributes'); + $this->expectNotToPerformAssertions(); + return; } $collectionName = 'test_spatial_order_axis'; @@ -2666,7 +2682,8 @@ public function testInvalidCoordinateDocuments(): void /** @var Database $database */ $database = static::getDatabase(); if (!$database->getAdapter()->getSupportForSpatialAttributes()) { - $this->markTestSkipped('Adapter does not support spatial attributes'); + $this->expectNotToPerformAssertions(); + return; } $collectionName = 'test_invalid_coord_'; diff --git a/tests/unit/Validator/IndexTest.php b/tests/unit/Validator/IndexTest.php index a2862830c..9e544c6a6 100644 --- a/tests/unit/Validator/IndexTest.php +++ b/tests/unit/Validator/IndexTest.php @@ -51,7 +51,7 @@ public function testAttributeNotFound(): void ], ]); - $validator = new Index($collection->getAttribute('attributes'), 768); + $validator = new Index($collection->getAttribute('attributes'), $collection->getAttribute('indexes'), 768); $index = $collection->getAttribute('indexes')[0]; $this->assertFalse($validator->isValid($index)); $this->assertEquals('Invalid index attribute "not_exist" not found', $validator->getDescription()); @@ -100,10 +100,10 @@ public function testFulltextWithNonString(): void ], ]); - $validator = new Index($collection->getAttribute('attributes'), 768); + $validator = new Index($collection->getAttribute('attributes'), $collection->getAttribute('indexes'), 768); $index = $collection->getAttribute('indexes')[0]; $this->assertFalse($validator->isValid($index)); - $this->assertEquals('Attribute "date" cannot be part of a FULLTEXT index, must be of type string', $validator->getDescription()); + $this->assertEquals('Attribute "date" cannot be part of a fulltext index, must be of type string', $validator->getDescription()); } /** @@ -138,7 +138,7 @@ public function testIndexLength(): void ], ]); - $validator = new Index($collection->getAttribute('attributes'), 768); + $validator = new Index($collection->getAttribute('attributes'), $collection->getAttribute('indexes'), 768); $index = $collection->getAttribute('indexes')[0]; $this->assertFalse($validator->isValid($index)); $this->assertEquals('Index length is longer than the maximum: 768', $validator->getDescription()); @@ -185,7 +185,7 @@ public function testMultipleIndexLength(): void ], ]); - $validator = new Index($collection->getAttribute('attributes'), 768); + $validator = new Index($collection->getAttribute('attributes'), $collection->getAttribute('indexes'), 768); $index = $collection->getAttribute('indexes')[0]; $this->assertTrue($validator->isValid($index)); @@ -232,7 +232,7 @@ public function testEmptyAttributes(): void ], ]); - $validator = new Index($collection->getAttribute('attributes'), 768); + $validator = new Index($collection->getAttribute('attributes'), $collection->getAttribute('indexes'), 768); $index = $collection->getAttribute('indexes')[0]; $this->assertFalse($validator->isValid($index)); $this->assertEquals('No attributes provided for index', $validator->getDescription()); @@ -270,7 +270,7 @@ public function testDuplicatedAttributes(): void ], ]); - $validator = new Index($collection->getAttribute('attributes'), 768); + $validator = new Index($collection->getAttribute('attributes'), $collection->getAttribute('indexes'), 768); $index = $collection->getAttribute('indexes')[0]; $this->assertFalse($validator->isValid($index)); $this->assertEquals('Duplicate attributes provided', $validator->getDescription()); @@ -308,7 +308,7 @@ public function testDuplicatedAttributesDifferentOrder(): void ], ]); - $validator = new Index($collection->getAttribute('attributes'), 768); + $validator = new Index($collection->getAttribute('attributes'), $collection->getAttribute('indexes'), 768); $index = $collection->getAttribute('indexes')[0]; $this->assertFalse($validator->isValid($index)); } @@ -345,7 +345,7 @@ public function testReservedIndexKey(): void ], ]); - $validator = new Index($collection->getAttribute('attributes'), 768, ['PRIMARY']); + $validator = new Index($collection->getAttribute('attributes'), $collection->getAttribute('indexes'), 768, ['PRIMARY']); $index = $collection->getAttribute('indexes')[0]; $this->assertFalse($validator->isValid($index)); }