-
-
Notifications
You must be signed in to change notification settings - Fork 939
feat(doctrine): add requirements dynamically based on doctrine field #7477
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -18,11 +18,14 @@ | |
| use ApiPlatform\Doctrine\Odm\State\Options; | ||
| use ApiPlatform\Metadata\CollectionOperationInterface; | ||
| use ApiPlatform\Metadata\DeleteOperationInterface; | ||
| use ApiPlatform\Metadata\HttpOperation; | ||
| use ApiPlatform\Metadata\Link; | ||
| use ApiPlatform\Metadata\Operation; | ||
| use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; | ||
| use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; | ||
| use ApiPlatform\State\Util\StateOptionsTrait; | ||
| use Doctrine\ODM\MongoDB\DocumentManager; | ||
| use Doctrine\ODM\MongoDB\Mapping\ClassMetadata; | ||
| use Doctrine\Persistence\ManagerRegistry; | ||
|
|
||
| final class DoctrineMongoDbOdmResourceCollectionMetadataFactory implements ResourceMetadataCollectionFactoryInterface | ||
|
|
@@ -86,6 +89,10 @@ private function addDefaults(Operation $operation): Operation | |
|
|
||
| if (null === $operation->getProvider()) { | ||
| $operation = $operation->withProvider($this->getProvider($operation)); | ||
|
|
||
| if ($operation instanceof HttpOperation) { | ||
| $operation = $operation->withRequirements($this->getRequirements($operation)); | ||
| } | ||
| } | ||
|
|
||
| if (null === $operation->getProcessor()) { | ||
|
|
@@ -95,6 +102,54 @@ private function addDefaults(Operation $operation): Operation | |
| return $operation; | ||
| } | ||
|
|
||
| /** | ||
| * @return array<string, string> | ||
| */ | ||
| private function getRequirements(HttpOperation $operation): array | ||
| { | ||
| $requirements = $operation->getRequirements() ?? []; | ||
| $uriVariables = (array) ($operation->getUriVariables() ?? []); | ||
|
|
||
| foreach ($uriVariables as $paramName => $uriVariable) { | ||
| if (isset($requirements[$paramName])) { | ||
| continue; | ||
| } | ||
|
|
||
| if (!$uriVariable instanceof Link) { | ||
| continue; | ||
| } | ||
|
|
||
| $identifiers = $uriVariable->getIdentifiers(); | ||
| if (1 !== \count($identifiers)) { | ||
| continue; | ||
| } | ||
| $fieldName = $identifiers[0]; | ||
|
|
||
| $fromClass = $uriVariable->getFromClass(); | ||
| if (null === $fromClass) { | ||
| continue; | ||
| } | ||
| $classMetadata = $this->managerRegistry->getManagerForClass($fromClass)?->getClassMetadata($fromClass); | ||
|
|
||
| $requirement = null; | ||
| if ($classMetadata instanceof ClassMetadata && $classMetadata->hasField($fieldName)) { | ||
| $fieldMapping = $classMetadata->getFieldMapping($fieldName); | ||
| $requirement = match ($fieldMapping['type']) { | ||
| 'uuid', 'guid' => '^[0-9a-fA-F]{8}(?:-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}$', | ||
| 'ulid' => '^[0-7][0-9a-hjkmnp-tv-zA-HJKMNP-TV-Z]{25}$', | ||
| 'smallint', 'integer', 'bigint' => '^-?[0-9]+$', | ||
| default => null, | ||
| }; | ||
| } | ||
|
|
||
| if (null !== $requirement) { | ||
| $requirements[$paramName] = $requirement; | ||
| } | ||
| } | ||
|
|
||
| return $requirements; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not sure that this should be enabeld like this, especially with regular expression. I largely prefer using validation constraints (that are now enabled on query parameters and that we should activate on uri variables). IMO this should likely be opt-in. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'll give you my use case (which is maybe wrong). When let's say I declare a Let's say I also declare manually a GET
By adding requirements I solve the conflict. What would recommend you instead ? When people are defining manually they template we could consider it's legit to ask them to add the requirement too. But when it's api platform which auto-generate the url, it's an issue. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. can you not set the requirements yourself? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sure I can do, and will do (manually or with a RequirementResourceMetadataCollectionFactory). But it felt "weird" to me to have a definition like when the route is not explicitly given. And I wanted to avoid to redefine since it's already the default uriTemplate. But, not a big deal |
||
| } | ||
|
|
||
| private function getProvider(Operation $operation): string | ||
| { | ||
| if ($operation instanceof CollectionOperationInterface) { | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.