From ffa5a7ebaeae6a1f9b3acd645ee5fa4e21b4e492 Mon Sep 17 00:00:00 2001 From: Kai Dederichs Date: Mon, 13 Dec 2021 14:11:34 +0100 Subject: [PATCH 01/18] Fix UUID in range --- composer.json | 3 +- features/hydra/collection.feature | 90 +++++++++++++++++++ .../Common/Filter/RangeFilterTrait.php | 8 +- tests/Core/Behat/DoctrineContext.php | 30 +++++++ .../Fixtures/TestBundle/Entity/SoManyUids.php | 56 ++++++++++++ 5 files changed, 183 insertions(+), 4 deletions(-) create mode 100644 tests/Fixtures/TestBundle/Entity/SoManyUids.php diff --git a/composer.json b/composer.json index 92a283f08a1..fbd3e01862f 100644 --- a/composer.json +++ b/composer.json @@ -73,8 +73,8 @@ "symfony/form": "^3.4 || ^4.4 || ^5.1", "symfony/framework-bundle": "^4.4 || ^5.1", "symfony/http-client": "^4.4 || ^5.1", - "symfony/maker-bundle": "^1.24", "symfony/intl": "^4.4 || ^5.3", + "symfony/maker-bundle": "^1.24", "symfony/mercure-bundle": "*", "symfony/messenger": "^4.4 || ^5.1", "symfony/phpunit-bridge": "^5.1.7", @@ -82,6 +82,7 @@ "symfony/security-bundle": "^3.4 || ^4.4 || ^5.1", "symfony/security-core": "^4.4 || ^5.1", "symfony/twig-bundle": "^3.4 || ^4.4 || ^5.1", + "symfony/uid": "^5.1", "symfony/validator": "^3.4 || ^4.4 || ^5.1", "symfony/web-profiler-bundle": "^4.4 || ^5.1", "symfony/yaml": "^3.4 || ^4.4 || ^5.1", diff --git a/features/hydra/collection.feature b/features/hydra/collection.feature index aebca7165d7..38ff898b4e5 100644 --- a/features/hydra/collection.feature +++ b/features/hydra/collection.feature @@ -514,6 +514,96 @@ Feature: Collections support } """ + @createSchema + Scenario: Cursor-based pagination with ranged items and set cursor + Given there are 10 of these so many objects + When I send a "GET" request to "/so_manies?order%5Bid%5D=desc&id%5Blt%5D=7" + Then the response status code should be 200 + And the response should be in JSON + And the header "Content-Type" should be equal to "application/ld+json; charset=utf-8" + And the JSON should be valid according to this schema: + """ + { + "type": "object", + "properties": { + "@context": {"pattern": "^/contexts/SoMany$"}, + "@id": {"pattern": "^/so_manies$"}, + "@type": {"pattern": "^hydra:Collection"}, + "hydra:view": { + "type": "object", + "properties": { + "@id": {"pattern": "^/so_manies\\?order%5Bid%5D=desc&id%5Blt%5D=7$"}, + "@type": {"pattern": "^hydra:PartialCollectionView$"}, + "hydra:previous": {"pattern": "^/so_manies\\?order%5Bid%5D=desc&id%5Bgt%5D=6$"}, + "hydra:next": {"pattern": "^/so_manies\\?order%5Bid%5D=desc&id%5Blt%5D=4$"} + }, + "additionalProperties": false + }, + "hydra:member": { + "type": "array", + "items": { + "type": "object", + "properties": { + "@id": { + "oneOf": [ + {"pattern": "^/so_manies/6$"}, + {"pattern": "^/so_manies/5$"}, + {"pattern": "^/so_manies/4$"} + ] + } + } + }, + "minItems": 3 + } + } + } + """ + + @createSchema + Scenario: Cursor-based pagination with ranged items on uids + Given there are 10 of these so many uid objects + When I send a "GET" request to "/so_many_uids?order%5Bid%5D=desc&id%5Blt%5D=1ec5c128-f3d4-62d0-b528-68fef707f0bd" + Then the response status code should be 200 + And the response should be in JSON + And the header "Content-Type" should be equal to "application/ld+json; charset=utf-8" + And the JSON should be valid according to this schema: + """ + { + "type": "object", + "properties": { + "@context": {"pattern": "^/contexts/SoManyUids"}, + "@id": {"pattern": "^/so_many_uids"}, + "@type": {"pattern": "^hydra:Collection"}, + "hydra:view": { + "type": "object", + "properties": { + "@id": {"pattern": "^/so_many_uids\\?order%5Bid%5D=desc&id%5Blt%5D=1ec5c128-f3d4-62d0-b528-68fef707f0bd$"}, + "@type": {"pattern": "^hydra:PartialCollectionView$"}, + "hydra:previous": {"pattern": "^/so_many_uids\\?order%5Bid%5D=desc&id%5Bgt%5D=1ec5c128-f3d4-61ae-bb3c-68fef707f0bd$"}, + "hydra:next": {"pattern": "^/so_many_uids\\?order%5Bid%5D=desc&id%5Blt%5D=1ec5c128-f3d3-6fc4-8b52-68fef707f0bd$"} + }, + "additionalProperties": false + }, + "hydra:member": { + "type": "array", + "items": { + "type": "object", + "properties": { + "content": { + "oneOf": [ + {"pattern": "^Many #7$"}, + {"pattern": "^Many #6$"}, + {"pattern": "^Many #5$"} + ] + } + } + }, + "minItems": 3 + } + } + } + """ + @createSchema Scenario: Cursor-based pagination with range filtered items Given there are 10 of these so many objects diff --git a/src/Doctrine/Common/Filter/RangeFilterTrait.php b/src/Doctrine/Common/Filter/RangeFilterTrait.php index 6051ac48efd..5aef198cf5c 100644 --- a/src/Doctrine/Common/Filter/RangeFilterTrait.php +++ b/src/Doctrine/Common/Filter/RangeFilterTrait.php @@ -16,6 +16,8 @@ use ApiPlatform\Doctrine\Common\PropertyHelperTrait; use ApiPlatform\Exception\InvalidArgumentException; use Psr\Log\LoggerInterface; +use Ramsey\Uuid\Nonstandard\UuidV6; +use Ramsey\Uuid\Uuid; /** * Trait for filtering the collection by range. @@ -124,11 +126,11 @@ private function normalizeBetweenValues(array $values): ?array /** * Normalize the value. * - * @return int|float|null + * @return int|float|string | null */ private function normalizeValue(string $value, string $operator) { - if (!is_numeric($value)) { + if (!is_numeric($value) && !UuidV6::isValid($value) && !\Symfony\Component\Uid\Uuid::isValid($value)) { $this->getLogger()->notice('Invalid filter ignored', [ 'exception' => new InvalidArgumentException(sprintf('Invalid value for "[%s]", expected number', $operator)), ]); @@ -136,6 +138,6 @@ private function normalizeValue(string $value, string $operator) return null; } - return $value + 0; // coerce $value to the right type. + return $value; } } diff --git a/tests/Core/Behat/DoctrineContext.php b/tests/Core/Behat/DoctrineContext.php index 185a7f91b73..2f07535cbba 100644 --- a/tests/Core/Behat/DoctrineContext.php +++ b/tests/Core/Behat/DoctrineContext.php @@ -159,6 +159,7 @@ use ApiPlatform\Tests\Fixtures\TestBundle\Entity\SecuredDummy; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Site; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\SoMany; +use ApiPlatform\Tests\Fixtures\TestBundle\Entity\SoManyUids; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\SymfonyUuidDummy; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Taxon; use ApiPlatform\Tests\Fixtures\TestBundle\Entity\ThirdLevel; @@ -173,6 +174,7 @@ use Doctrine\ORM\Tools\SchemaTool; use Doctrine\Persistence\ManagerRegistry; use Doctrine\Persistence\ObjectManager; +use Ramsey\Uuid\Nonstandard\UuidV6; use Ramsey\Uuid\Uuid; use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface; use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface; @@ -285,6 +287,34 @@ public function thereAreOfTheseSoManyObjects(int $nb) $this->manager->flush(); } + /** + * @Given there are :nb of these so many uid objects + */ + public function thereAreOfTheseSoManyUidObjects(int $nb) + { + $ids = [ + '1ec5c128-f3d2-643a-8b17-68fef707f0bd', // 1 + '1ec5c128-f3d3-6cf4-a77e-68fef707f0bd', + '1ec5c128-f3d3-6e02-8834-68fef707f0bd', + '1ec5c128-f3d3-6ef2-b5f3-68fef707f0bd', + '1ec5c128-f3d3-6fc4-8b52-68fef707f0bd', + '1ec5c128-f3d4-6096-b820-68fef707f0bd', + '1ec5c128-f3d4-61ae-bb3c-68fef707f0bd', // 7 + '1ec5c128-f3d4-62d0-b528-68fef707f0bd', + '1ec5c128-f3d4-63f2-b845-68fef707f0bd', + '1ec5c128-f3d4-6514-8d2b-68fef707f0bd', // 10 + ]; + + for ($i = 1; $i <= $nb; ++$i) { + $ids[] = UuidV6::uuid6()->toString(); + $dummy = new SoManyUids($ids[$i -1] ?? null); + $dummy->content = 'Many #'.$i; + + $this->manager->persist($dummy); + } + $this->manager->flush(); + } + /** * @When some dummy table inheritance data but not api resource child are created */ diff --git a/tests/Fixtures/TestBundle/Entity/SoManyUids.php b/tests/Fixtures/TestBundle/Entity/SoManyUids.php new file mode 100644 index 00000000000..95dbca4dcb8 --- /dev/null +++ b/tests/Fixtures/TestBundle/Entity/SoManyUids.php @@ -0,0 +1,56 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity; + +use ApiPlatform\Core\Annotation\ApiFilter; +use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Doctrine\Orm\Filter\OrderFilter; +use ApiPlatform\Doctrine\Orm\Filter\RangeFilter; +use Doctrine\ORM\Mapping as ORM; +use Ramsey\Uuid\Nonstandard\UuidV6; + +/** + * @ORM\Entity + * @ApiResource(attributes={ + * "pagination_partial"=true, + * "pagination_via_cursor"={ + * {"field"="id", "direction"="DESC"} + * } + * }) + * + * @ApiFilter(RangeFilter::class, properties={"id"}) + * @ApiFilter(OrderFilter::class, properties={"id"="DESC"}) + */ +class SoManyUids +{ + /** + * @ORM\Id + * @ORM\Column(type="uuid") + */ + public $id; + + /** + * @ORM\Column(nullable=true) + */ + public $content; + + public function __construct($id) + { + if ($id) { + $this->id = UuidV6::fromString($id); + } else { + $this->id = UuidV6::uuid6(); + } + } +} From 88018a08bb5924f5c60dfc8a5c51ac2608317d73 Mon Sep 17 00:00:00 2001 From: Kai Dederichs Date: Mon, 13 Dec 2021 14:11:34 +0100 Subject: [PATCH 02/18] Fix CS --- src/Doctrine/Common/Filter/RangeFilterTrait.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Doctrine/Common/Filter/RangeFilterTrait.php b/src/Doctrine/Common/Filter/RangeFilterTrait.php index 5aef198cf5c..b48c1f65a99 100644 --- a/src/Doctrine/Common/Filter/RangeFilterTrait.php +++ b/src/Doctrine/Common/Filter/RangeFilterTrait.php @@ -17,7 +17,6 @@ use ApiPlatform\Exception\InvalidArgumentException; use Psr\Log\LoggerInterface; use Ramsey\Uuid\Nonstandard\UuidV6; -use Ramsey\Uuid\Uuid; /** * Trait for filtering the collection by range. From 503884b9587245c8b188e227d108bf76beed4188 Mon Sep 17 00:00:00 2001 From: Kai Dederichs Date: Mon, 13 Dec 2021 14:22:07 +0100 Subject: [PATCH 03/18] Don't use Symfony UID since 7.1 is required --- composer.json | 1 - src/Doctrine/Common/Filter/RangeFilterTrait.php | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/composer.json b/composer.json index fbd3e01862f..b0d9149c5f5 100644 --- a/composer.json +++ b/composer.json @@ -82,7 +82,6 @@ "symfony/security-bundle": "^3.4 || ^4.4 || ^5.1", "symfony/security-core": "^4.4 || ^5.1", "symfony/twig-bundle": "^3.4 || ^4.4 || ^5.1", - "symfony/uid": "^5.1", "symfony/validator": "^3.4 || ^4.4 || ^5.1", "symfony/web-profiler-bundle": "^4.4 || ^5.1", "symfony/yaml": "^3.4 || ^4.4 || ^5.1", diff --git a/src/Doctrine/Common/Filter/RangeFilterTrait.php b/src/Doctrine/Common/Filter/RangeFilterTrait.php index b48c1f65a99..ca36b84c3dd 100644 --- a/src/Doctrine/Common/Filter/RangeFilterTrait.php +++ b/src/Doctrine/Common/Filter/RangeFilterTrait.php @@ -129,7 +129,7 @@ private function normalizeBetweenValues(array $values): ?array */ private function normalizeValue(string $value, string $operator) { - if (!is_numeric($value) && !UuidV6::isValid($value) && !\Symfony\Component\Uid\Uuid::isValid($value)) { + if (!is_numeric($value) && !UuidV6::isValid($value)) { $this->getLogger()->notice('Invalid filter ignored', [ 'exception' => new InvalidArgumentException(sprintf('Invalid value for "[%s]", expected number', $operator)), ]); From 452501416f0ac8b22adb99cd7948d15d76cd076a Mon Sep 17 00:00:00 2001 From: Kai Dederichs Date: Tue, 14 Dec 2021 11:42:41 +0100 Subject: [PATCH 04/18] Don't depend on 3rd party for Uid check. --- src/Doctrine/Common/Filter/RangeFilterTrait.php | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/Doctrine/Common/Filter/RangeFilterTrait.php b/src/Doctrine/Common/Filter/RangeFilterTrait.php index ca36b84c3dd..00c17151fbd 100644 --- a/src/Doctrine/Common/Filter/RangeFilterTrait.php +++ b/src/Doctrine/Common/Filter/RangeFilterTrait.php @@ -16,7 +16,6 @@ use ApiPlatform\Doctrine\Common\PropertyHelperTrait; use ApiPlatform\Exception\InvalidArgumentException; use Psr\Log\LoggerInterface; -use Ramsey\Uuid\Nonstandard\UuidV6; /** * Trait for filtering the collection by range. @@ -129,7 +128,7 @@ private function normalizeBetweenValues(array $values): ?array */ private function normalizeValue(string $value, string $operator) { - if (!is_numeric($value) && !UuidV6::isValid($value)) { + if (!is_numeric($value) && !$this->isValidUid($value)) { $this->getLogger()->notice('Invalid filter ignored', [ 'exception' => new InvalidArgumentException(sprintf('Invalid value for "[%s]", expected number', $operator)), ]); @@ -139,4 +138,9 @@ private function normalizeValue(string $value, string $operator) return $value; } + + private function isValidUid($potentialUid): bool + { + return is_string($potentialUid) && preg_match('{^[0-9a-f]{8}(?:-[0-9a-f]{4}){3}-[0-9a-f]{12}$}Di', $potentialUid); + } } From 187602a7ae4d2e4f14eb33d16317e652b0106c60 Mon Sep 17 00:00:00 2001 From: Kai Dederichs Date: Tue, 14 Dec 2021 11:43:08 +0100 Subject: [PATCH 05/18] Change exception message. --- src/Doctrine/Common/Filter/RangeFilterTrait.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Doctrine/Common/Filter/RangeFilterTrait.php b/src/Doctrine/Common/Filter/RangeFilterTrait.php index 00c17151fbd..23441d67717 100644 --- a/src/Doctrine/Common/Filter/RangeFilterTrait.php +++ b/src/Doctrine/Common/Filter/RangeFilterTrait.php @@ -130,7 +130,7 @@ private function normalizeValue(string $value, string $operator) { if (!is_numeric($value) && !$this->isValidUid($value)) { $this->getLogger()->notice('Invalid filter ignored', [ - 'exception' => new InvalidArgumentException(sprintf('Invalid value for "[%s]", expected number', $operator)), + 'exception' => new InvalidArgumentException(sprintf('Invalid value for "[%s]", expected number or uid', $operator)), ]); return null; From 5d21f467ba812456f52647931327383dd8778d95 Mon Sep 17 00:00:00 2001 From: Kai Dederichs Date: Tue, 14 Dec 2021 11:45:36 +0100 Subject: [PATCH 06/18] Check and coerce if numeric --- src/Doctrine/Common/Filter/RangeFilterTrait.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Doctrine/Common/Filter/RangeFilterTrait.php b/src/Doctrine/Common/Filter/RangeFilterTrait.php index 23441d67717..adb0e68133b 100644 --- a/src/Doctrine/Common/Filter/RangeFilterTrait.php +++ b/src/Doctrine/Common/Filter/RangeFilterTrait.php @@ -136,11 +136,15 @@ private function normalizeValue(string $value, string $operator) return null; } + if (is_numeric($value)) { + return $value + 0; // coerce $value to the right type. + } + return $value; } private function isValidUid($potentialUid): bool { - return is_string($potentialUid) && preg_match('{^[0-9a-f]{8}(?:-[0-9a-f]{4}){3}-[0-9a-f]{12}$}Di', $potentialUid); + return \is_string($potentialUid) && preg_match('{^[0-9a-f]{8}(?:-[0-9a-f]{4}){3}-[0-9a-f]{12}$}Di', $potentialUid); } } From df080de0c4e5b1866e94fec8a77e72bbd581fa24 Mon Sep 17 00:00:00 2001 From: Kai Dederichs Date: Tue, 14 Dec 2021 12:06:05 +0100 Subject: [PATCH 07/18] CS Fix --- src/Doctrine/Common/Filter/RangeFilterTrait.php | 2 +- tests/Core/Behat/DoctrineContext.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Doctrine/Common/Filter/RangeFilterTrait.php b/src/Doctrine/Common/Filter/RangeFilterTrait.php index adb0e68133b..9b82bfef394 100644 --- a/src/Doctrine/Common/Filter/RangeFilterTrait.php +++ b/src/Doctrine/Common/Filter/RangeFilterTrait.php @@ -124,7 +124,7 @@ private function normalizeBetweenValues(array $values): ?array /** * Normalize the value. * - * @return int|float|string | null + * @return int|float|string|null */ private function normalizeValue(string $value, string $operator) { diff --git a/tests/Core/Behat/DoctrineContext.php b/tests/Core/Behat/DoctrineContext.php index 2f07535cbba..a39d9538894 100644 --- a/tests/Core/Behat/DoctrineContext.php +++ b/tests/Core/Behat/DoctrineContext.php @@ -307,7 +307,7 @@ public function thereAreOfTheseSoManyUidObjects(int $nb) for ($i = 1; $i <= $nb; ++$i) { $ids[] = UuidV6::uuid6()->toString(); - $dummy = new SoManyUids($ids[$i -1] ?? null); + $dummy = new SoManyUids($ids[$i - 1] ?? null); $dummy->content = 'Many #'.$i; $this->manager->persist($dummy); From d9ebdf25accf06ec630ecd9de2bd80485bedd53b Mon Sep 17 00:00:00 2001 From: Kai Dederichs Date: Tue, 21 Dec 2021 11:56:28 +0100 Subject: [PATCH 08/18] Skip test if class doesn't exist --- behat.yml.dist | 5 +++++ features/hydra/collection.feature | 1 + tests/Core/Behat/SystemContext.php | 17 +++++++++++++++++ 3 files changed, 23 insertions(+) create mode 100644 tests/Core/Behat/SystemContext.php diff --git a/behat.yml.dist b/behat.yml.dist index 3970282b6b1..4d9ec2efb9f 100644 --- a/behat.yml.dist +++ b/behat.yml.dist @@ -13,6 +13,7 @@ default: - 'ApiPlatform\Core\Tests\Behat\JsonHalContext' - 'ApiPlatform\Core\Tests\Behat\MercureContext' - 'ApiPlatform\Core\Tests\Behat\XmlContext' + - 'ApiPlatform\Core\Tests\Behat\SystemContext' - 'Behat\MinkExtension\Context\MinkContext' - 'behatch:context:rest' filters: @@ -49,6 +50,7 @@ postgres: - 'ApiPlatform\Core\Tests\Behat\JsonHalContext' - 'ApiPlatform\Core\Tests\Behat\MercureContext' - 'ApiPlatform\Core\Tests\Behat\XmlContext' + - 'ApiPlatform\Core\Tests\Behat\SystemContext' - 'Behat\MinkExtension\Context\MinkContext' - 'behatch:context:rest' filters: @@ -70,6 +72,7 @@ mongodb: - 'ApiPlatform\Core\Tests\Behat\JsonHalContext' - 'ApiPlatform\Core\Tests\Behat\MercureContext' - 'ApiPlatform\Core\Tests\Behat\XmlContext' + - 'ApiPlatform\Core\Tests\Behat\SystemContext' - 'Behat\MinkExtension\Context\MinkContext' - 'behatch:context:rest' filters: @@ -107,6 +110,7 @@ default-coverage: - 'ApiPlatform\Core\Tests\Behat\MercureContext' - 'ApiPlatform\Core\Tests\Behat\CoverageContext' - 'ApiPlatform\Core\Tests\Behat\XmlContext' + - 'ApiPlatform\Core\Tests\Behat\SystemContext' - 'Behat\MinkExtension\Context\MinkContext' - 'behatch:context:rest' @@ -128,6 +132,7 @@ mongodb-coverage: - 'ApiPlatform\Core\Tests\Behat\MercureContext' - 'ApiPlatform\Core\Tests\Behat\CoverageContext' - 'ApiPlatform\Core\Tests\Behat\XmlContext' + - 'ApiPlatform\Core\Tests\Behat\SystemContext' - 'Behat\MinkExtension\Context\MinkContext' - 'behatch:context:rest' diff --git a/features/hydra/collection.feature b/features/hydra/collection.feature index 38ff898b4e5..e5a5904e75b 100644 --- a/features/hydra/collection.feature +++ b/features/hydra/collection.feature @@ -562,6 +562,7 @@ Feature: Collections support @createSchema Scenario: Cursor-based pagination with ranged items on uids Given there are 10 of these so many uid objects + And class "Ramsey\Uuid\Nonstandard\UuidV6" exists When I send a "GET" request to "/so_many_uids?order%5Bid%5D=desc&id%5Blt%5D=1ec5c128-f3d4-62d0-b528-68fef707f0bd" Then the response status code should be 200 And the response should be in JSON diff --git a/tests/Core/Behat/SystemContext.php b/tests/Core/Behat/SystemContext.php new file mode 100644 index 00000000000..fc1e5845923 --- /dev/null +++ b/tests/Core/Behat/SystemContext.php @@ -0,0 +1,17 @@ + Date: Tue, 21 Dec 2021 11:57:59 +0100 Subject: [PATCH 09/18] CS --- tests/Core/Behat/SystemContext.php | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/tests/Core/Behat/SystemContext.php b/tests/Core/Behat/SystemContext.php index fc1e5845923..c20e31f0efe 100644 --- a/tests/Core/Behat/SystemContext.php +++ b/tests/Core/Behat/SystemContext.php @@ -1,5 +1,16 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + namespace ApiPlatform\Core\Tests\Behat; use Behat\Behat\Context\Context; From 5ceb73c2537bf50609680c33314028cdd04b371e Mon Sep 17 00:00:00 2001 From: Kai Dederichs Date: Tue, 21 Dec 2021 12:10:31 +0100 Subject: [PATCH 10/18] Revert "Skip test if class doesn't exist" This reverts commit d9ebdf25 --- behat.yml.dist | 5 ----- features/hydra/collection.feature | 1 - tests/Core/Behat/SystemContext.php | 28 ---------------------------- 3 files changed, 34 deletions(-) delete mode 100644 tests/Core/Behat/SystemContext.php diff --git a/behat.yml.dist b/behat.yml.dist index 4d9ec2efb9f..3970282b6b1 100644 --- a/behat.yml.dist +++ b/behat.yml.dist @@ -13,7 +13,6 @@ default: - 'ApiPlatform\Core\Tests\Behat\JsonHalContext' - 'ApiPlatform\Core\Tests\Behat\MercureContext' - 'ApiPlatform\Core\Tests\Behat\XmlContext' - - 'ApiPlatform\Core\Tests\Behat\SystemContext' - 'Behat\MinkExtension\Context\MinkContext' - 'behatch:context:rest' filters: @@ -50,7 +49,6 @@ postgres: - 'ApiPlatform\Core\Tests\Behat\JsonHalContext' - 'ApiPlatform\Core\Tests\Behat\MercureContext' - 'ApiPlatform\Core\Tests\Behat\XmlContext' - - 'ApiPlatform\Core\Tests\Behat\SystemContext' - 'Behat\MinkExtension\Context\MinkContext' - 'behatch:context:rest' filters: @@ -72,7 +70,6 @@ mongodb: - 'ApiPlatform\Core\Tests\Behat\JsonHalContext' - 'ApiPlatform\Core\Tests\Behat\MercureContext' - 'ApiPlatform\Core\Tests\Behat\XmlContext' - - 'ApiPlatform\Core\Tests\Behat\SystemContext' - 'Behat\MinkExtension\Context\MinkContext' - 'behatch:context:rest' filters: @@ -110,7 +107,6 @@ default-coverage: - 'ApiPlatform\Core\Tests\Behat\MercureContext' - 'ApiPlatform\Core\Tests\Behat\CoverageContext' - 'ApiPlatform\Core\Tests\Behat\XmlContext' - - 'ApiPlatform\Core\Tests\Behat\SystemContext' - 'Behat\MinkExtension\Context\MinkContext' - 'behatch:context:rest' @@ -132,7 +128,6 @@ mongodb-coverage: - 'ApiPlatform\Core\Tests\Behat\MercureContext' - 'ApiPlatform\Core\Tests\Behat\CoverageContext' - 'ApiPlatform\Core\Tests\Behat\XmlContext' - - 'ApiPlatform\Core\Tests\Behat\SystemContext' - 'Behat\MinkExtension\Context\MinkContext' - 'behatch:context:rest' diff --git a/features/hydra/collection.feature b/features/hydra/collection.feature index e5a5904e75b..38ff898b4e5 100644 --- a/features/hydra/collection.feature +++ b/features/hydra/collection.feature @@ -562,7 +562,6 @@ Feature: Collections support @createSchema Scenario: Cursor-based pagination with ranged items on uids Given there are 10 of these so many uid objects - And class "Ramsey\Uuid\Nonstandard\UuidV6" exists When I send a "GET" request to "/so_many_uids?order%5Bid%5D=desc&id%5Blt%5D=1ec5c128-f3d4-62d0-b528-68fef707f0bd" Then the response status code should be 200 And the response should be in JSON diff --git a/tests/Core/Behat/SystemContext.php b/tests/Core/Behat/SystemContext.php deleted file mode 100644 index c20e31f0efe..00000000000 --- a/tests/Core/Behat/SystemContext.php +++ /dev/null @@ -1,28 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -declare(strict_types=1); - -namespace ApiPlatform\Core\Tests\Behat; - -use Behat\Behat\Context\Context; -use Behat\Behat\Tester\Exception\PendingException; - -class SystemContext implements Context -{ - /** @Given class :clazz exists */ - public function classExists($clazz) - { - if (!class_exists($clazz)) { - throw new PendingException(sprintf('Class %s is not defined, skipping test', $clazz)); - } - } -} From 688ca23bc1b4091fdadce1f53c1606866debbc7c Mon Sep 17 00:00:00 2001 From: Kai Dederichs Date: Tue, 21 Dec 2021 12:14:36 +0100 Subject: [PATCH 11/18] Skip via Tags --- .github/workflows/ci.yml | 2 +- features/hydra/collection.feature | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 712463fe515..413c9306843 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -255,7 +255,7 @@ jobs: vendor/bin/behat --out=std --format=progress --format=junit --out=build/logs/behat/junit --profile=default-coverage --no-interaction --tags='~@php8' else if [ "${{ matrix.php }}" = '7.1' ]; then - vendor/bin/behat --out=std --format=progress --format=junit --out=build/logs/behat/junit --profile=default --no-interaction --tags='~@symfony/uid&&~@php8' + vendor/bin/behat --out=std --format=progress --format=junit --out=build/logs/behat/junit --profile=default --no-interaction --tags='~@symfony/uid&&~@php8&&~@uuid/v6' else vendor/bin/behat --out=std --format=progress --format=junit --out=build/logs/behat/junit --profile=default --no-interaction --tags='~@php8' fi diff --git a/features/hydra/collection.feature b/features/hydra/collection.feature index 38ff898b4e5..ee6e8edb864 100644 --- a/features/hydra/collection.feature +++ b/features/hydra/collection.feature @@ -560,6 +560,7 @@ Feature: Collections support """ @createSchema + @uuid/v6 Scenario: Cursor-based pagination with ranged items on uids Given there are 10 of these so many uid objects When I send a "GET" request to "/so_many_uids?order%5Bid%5D=desc&id%5Blt%5D=1ec5c128-f3d4-62d0-b528-68fef707f0bd" From c7e044c0686c54c26c15246ecc095b26c05f619d Mon Sep 17 00:00:00 2001 From: Kai Dederichs Date: Tue, 21 Dec 2021 12:23:54 +0100 Subject: [PATCH 12/18] Behat lowest also can not run uid tests --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 413c9306843..b7bf952229a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -400,7 +400,7 @@ jobs: run: tests/Fixtures/app/console cache:clear --ansi - name: Run Behat tests # @TODO remove the tag "@symfony/uid" in 3.0 - run: vendor/bin/behat --out=std --format=progress --profile=default --no-interaction --tags='~@symfony/uid&&~php8' + run: vendor/bin/behat --out=std --format=progress --profile=default --no-interaction --tags='~@symfony/uid&&~php8&&~@uuid/v6' postgresql: name: Behat (PHP ${{ matrix.php }}) (PostgreSQL) From 93f67c639f871340348b6ddfeba21c2d1856a741 Mon Sep 17 00:00:00 2001 From: Kai Dederichs Date: Tue, 4 Jan 2022 11:50:11 +0100 Subject: [PATCH 13/18] Add SoManyUids to Document tests --- .../TestBundle/Document/SoManyUids.php | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 tests/Fixtures/TestBundle/Document/SoManyUids.php diff --git a/tests/Fixtures/TestBundle/Document/SoManyUids.php b/tests/Fixtures/TestBundle/Document/SoManyUids.php new file mode 100644 index 00000000000..7a8b0a72aa4 --- /dev/null +++ b/tests/Fixtures/TestBundle/Document/SoManyUids.php @@ -0,0 +1,55 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; + +use ApiPlatform\Core\Annotation\ApiFilter; +use ApiPlatform\Core\Annotation\ApiResource; +use ApiPlatform\Doctrine\Orm\Filter\OrderFilter; +use ApiPlatform\Doctrine\Orm\Filter\RangeFilter; +use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; +use Ramsey\Uuid\Nonstandard\UuidV6; + +/** + * @ODM\Document + * @ApiResource(attributes={ + * "pagination_partial"=true, + * "pagination_via_cursor"={ + * {"field"="id", "direction"="DESC"} + * } + * }) + * + * @ApiFilter(RangeFilter::class, properties={"id"}) + * @ApiFilter(OrderFilter::class, properties={"id"="DESC"}) + */ +class SoManyUids +{ + /** + * @ODM\Id(type="uuid") + */ + public $id; + + /** + * @ODM\Field(nullable=true) + */ + public $content; + + public function __construct($id) + { + if ($id) { + $this->id = UuidV6::fromString($id); + } else { + $this->id = UuidV6::uuid6(); + } + } +} From 0d78705160f09437cd5c6899e550ae2e86083fb1 Mon Sep 17 00:00:00 2001 From: Kai Dederichs Date: Tue, 4 Jan 2022 12:11:27 +0100 Subject: [PATCH 14/18] import correct filters --- tests/Fixtures/TestBundle/Document/SoManyUids.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/Fixtures/TestBundle/Document/SoManyUids.php b/tests/Fixtures/TestBundle/Document/SoManyUids.php index 7a8b0a72aa4..23f28738178 100644 --- a/tests/Fixtures/TestBundle/Document/SoManyUids.php +++ b/tests/Fixtures/TestBundle/Document/SoManyUids.php @@ -15,8 +15,8 @@ use ApiPlatform\Core\Annotation\ApiFilter; use ApiPlatform\Core\Annotation\ApiResource; -use ApiPlatform\Doctrine\Orm\Filter\OrderFilter; -use ApiPlatform\Doctrine\Orm\Filter\RangeFilter; +use ApiPlatform\Doctrine\Odm\Filter\OrderFilter; +use ApiPlatform\Doctrine\Odm\Filter\RangeFilter; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Ramsey\Uuid\Nonstandard\UuidV6; From acaff931197ff78efb66ec6cd0a6537535e5f720 Mon Sep 17 00:00:00 2001 From: Kai Dederichs Date: Tue, 4 Jan 2022 12:25:36 +0100 Subject: [PATCH 15/18] Fix Doctrine context --- tests/Core/Behat/DoctrineContext.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/Core/Behat/DoctrineContext.php b/tests/Core/Behat/DoctrineContext.php index ce5feb016d8..76e7dfaf16f 100644 --- a/tests/Core/Behat/DoctrineContext.php +++ b/tests/Core/Behat/DoctrineContext.php @@ -82,6 +82,7 @@ use ApiPlatform\Tests\Fixtures\TestBundle\Document\RelationEmbedder as RelationEmbedderDocument; use ApiPlatform\Tests\Fixtures\TestBundle\Document\SecuredDummy as SecuredDummyDocument; use ApiPlatform\Tests\Fixtures\TestBundle\Document\SoMany as SoManyDocument; +use ApiPlatform\Tests\Fixtures\TestBundle\Document\SoManyUids as SoManyUidsDocument; use ApiPlatform\Tests\Fixtures\TestBundle\Document\Taxon as TaxonDocument; use ApiPlatform\Tests\Fixtures\TestBundle\Document\ThirdLevel as ThirdLevelDocument; use ApiPlatform\Tests\Fixtures\TestBundle\Document\UrlEncodedId as UrlEncodedIdDocument; @@ -311,7 +312,8 @@ public function thereAreOfTheseSoManyUidObjects(int $nb) for ($i = 1; $i <= $nb; ++$i) { $ids[] = UuidV6::uuid6()->toString(); - $dummy = new SoManyUids($ids[$i - 1] ?? null); + $id = $ids[$i - 1] ?? null; + $dummy = $this->isOrm() ? new SoManyUidsDocument($id) : new SoManyUids($id); $dummy->content = 'Many #'.$i; $this->manager->persist($dummy); From 4b1f27640dbea1a18e3c605a550e30ab251f70a8 Mon Sep 17 00:00:00 2001 From: Kai Dederichs Date: Tue, 4 Jan 2022 12:45:45 +0100 Subject: [PATCH 16/18] Method is not called isOdm :) --- tests/Core/Behat/DoctrineContext.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Core/Behat/DoctrineContext.php b/tests/Core/Behat/DoctrineContext.php index 76e7dfaf16f..e31ab068ad4 100644 --- a/tests/Core/Behat/DoctrineContext.php +++ b/tests/Core/Behat/DoctrineContext.php @@ -313,7 +313,7 @@ public function thereAreOfTheseSoManyUidObjects(int $nb) for ($i = 1; $i <= $nb; ++$i) { $ids[] = UuidV6::uuid6()->toString(); $id = $ids[$i - 1] ?? null; - $dummy = $this->isOrm() ? new SoManyUidsDocument($id) : new SoManyUids($id); + $dummy = $this->isOrm() ? new SoManyUids($id) : new SoManyUidsDocument($id); $dummy->content = 'Many #'.$i; $this->manager->persist($dummy); From 7678169f53ac8323de9ff104bdaa639a57ed35c2 Mon Sep 17 00:00:00 2001 From: Kai Dederichs Date: Tue, 4 Jan 2022 13:22:50 +0100 Subject: [PATCH 17/18] ODM requires strategy NONE --- tests/Fixtures/TestBundle/Document/SoManyUids.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Fixtures/TestBundle/Document/SoManyUids.php b/tests/Fixtures/TestBundle/Document/SoManyUids.php index 23f28738178..4300ebb4eb0 100644 --- a/tests/Fixtures/TestBundle/Document/SoManyUids.php +++ b/tests/Fixtures/TestBundle/Document/SoManyUids.php @@ -35,7 +35,7 @@ class SoManyUids { /** - * @ODM\Id(type="uuid") + * @ODM\Id(strategy="NONE", type="uuid") */ public $id; From a0d1a58441f0d479f2a8e20bcd2bfaed350260c5 Mon Sep 17 00:00:00 2001 From: Kai Dederichs Date: Tue, 4 Jan 2022 13:45:40 +0100 Subject: [PATCH 18/18] Turns out, there's no mapping for those, so exclude them in MongoDB runs.... --- .github/workflows/ci.yml | 6 +- tests/Core/Behat/DoctrineContext.php | 3 +- .../TestBundle/Document/SoManyUids.php | 55 ------------------- 3 files changed, 4 insertions(+), 60 deletions(-) delete mode 100644 tests/Fixtures/TestBundle/Document/SoManyUids.php diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 003302fd5fd..2f69b50407e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -564,9 +564,9 @@ jobs: run: | mkdir -p build/logs/behat if [ "$COVERAGE" = '1' ]; then - vendor/bin/behat --out=std --format=progress --format=junit --out=build/logs/behat/junit --profile=mongodb-coverage --no-interaction --tags='~@php8' + vendor/bin/behat --out=std --format=progress --format=junit --out=build/logs/behat/junit --profile=mongodb-coverage --no-interaction --tags='~@php8&&~@uuid/v6' else - vendor/bin/behat --out=std --format=progress --format=junit --out=build/logs/behat/junit --profile=mongodb --no-interaction --tags='~@php8' + vendor/bin/behat --out=std --format=progress --format=junit --out=build/logs/behat/junit --profile=mongodb --no-interaction --tags='~@php8&&~@uuid/v6' fi - name: Merge code coverage reports run: | @@ -919,7 +919,7 @@ jobs: - name: Run Behat tests run: | mkdir -p build/logs/behat - vendor/bin/behat --out=std --format=progress --format=junit --out=build/logs/behat/junit --profile=mongodb --no-interaction + vendor/bin/behat --out=std --format=progress --format=junit --out=build/logs/behat/junit --profile=mongodb --no-interaction --tags='~@uuid/v6' - name: Upload test artifacts if: always() uses: actions/upload-artifact@v1 diff --git a/tests/Core/Behat/DoctrineContext.php b/tests/Core/Behat/DoctrineContext.php index e31ab068ad4..9896cc773be 100644 --- a/tests/Core/Behat/DoctrineContext.php +++ b/tests/Core/Behat/DoctrineContext.php @@ -82,7 +82,6 @@ use ApiPlatform\Tests\Fixtures\TestBundle\Document\RelationEmbedder as RelationEmbedderDocument; use ApiPlatform\Tests\Fixtures\TestBundle\Document\SecuredDummy as SecuredDummyDocument; use ApiPlatform\Tests\Fixtures\TestBundle\Document\SoMany as SoManyDocument; -use ApiPlatform\Tests\Fixtures\TestBundle\Document\SoManyUids as SoManyUidsDocument; use ApiPlatform\Tests\Fixtures\TestBundle\Document\Taxon as TaxonDocument; use ApiPlatform\Tests\Fixtures\TestBundle\Document\ThirdLevel as ThirdLevelDocument; use ApiPlatform\Tests\Fixtures\TestBundle\Document\UrlEncodedId as UrlEncodedIdDocument; @@ -313,7 +312,7 @@ public function thereAreOfTheseSoManyUidObjects(int $nb) for ($i = 1; $i <= $nb; ++$i) { $ids[] = UuidV6::uuid6()->toString(); $id = $ids[$i - 1] ?? null; - $dummy = $this->isOrm() ? new SoManyUids($id) : new SoManyUidsDocument($id); + $dummy = new SoManyUids($id); $dummy->content = 'Many #'.$i; $this->manager->persist($dummy); diff --git a/tests/Fixtures/TestBundle/Document/SoManyUids.php b/tests/Fixtures/TestBundle/Document/SoManyUids.php deleted file mode 100644 index 4300ebb4eb0..00000000000 --- a/tests/Fixtures/TestBundle/Document/SoManyUids.php +++ /dev/null @@ -1,55 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -declare(strict_types=1); - -namespace ApiPlatform\Tests\Fixtures\TestBundle\Document; - -use ApiPlatform\Core\Annotation\ApiFilter; -use ApiPlatform\Core\Annotation\ApiResource; -use ApiPlatform\Doctrine\Odm\Filter\OrderFilter; -use ApiPlatform\Doctrine\Odm\Filter\RangeFilter; -use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; -use Ramsey\Uuid\Nonstandard\UuidV6; - -/** - * @ODM\Document - * @ApiResource(attributes={ - * "pagination_partial"=true, - * "pagination_via_cursor"={ - * {"field"="id", "direction"="DESC"} - * } - * }) - * - * @ApiFilter(RangeFilter::class, properties={"id"}) - * @ApiFilter(OrderFilter::class, properties={"id"="DESC"}) - */ -class SoManyUids -{ - /** - * @ODM\Id(strategy="NONE", type="uuid") - */ - public $id; - - /** - * @ODM\Field(nullable=true) - */ - public $content; - - public function __construct($id) - { - if ($id) { - $this->id = UuidV6::fromString($id); - } else { - $this->id = UuidV6::uuid6(); - } - } -}