-
-
Notifications
You must be signed in to change notification settings - Fork 918
feat(metadata) Customize Resource & operations #7213
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?
feat(metadata) Customize Resource & operations #7213
Conversation
d9fd4f2
to
15dcaa4
Compare
15dcaa4
to
7f165b9
Compare
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.
Really cool, this is a follow up for php configured metadata as this allows to mutate vendor operations. I'll probably demonstrate this shortly.
I'd recommend to add a ResourceMutatorInterface. Obviously we should introduce an AsOperationMutator. I'd suggest that it takes:
public readonly string $operationName
URI Template would be nice as well but it will probably match several operations, therefore it's probably better to just use the $operationName
.
use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; | ||
use Psr\Container\ContainerInterface; | ||
|
||
final class CustomResourceMetadataCollectionFactory implements ResourceMetadataCollectionFactoryInterface |
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.
final class CustomResourceMetadataCollectionFactory implements ResourceMetadataCollectionFactoryInterface | |
final class MutatorResourceMetadataCollectionFactory implements ResourceMetadataCollectionFactoryInterface |
|
||
foreach ($resourceMetadataCollection as $resource) { | ||
foreach ($this->resourceMutators->get($resourceClass) as $mutators) { | ||
$resource = $mutators($resource); |
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.
an interface would be able for typehint to know what the callable arguments are and make the code a little bit cleaner
cb16e36
to
10140bd
Compare
10140bd
to
1b3ab0e
Compare
namespace ApiPlatform\Metadata; | ||
|
||
#[\Attribute(\Attribute::TARGET_CLASS)] | ||
final class AsOperationMutator |
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.
final class AsOperationMutator | |
class AsOperationMutator |
namespace ApiPlatform\Metadata; | ||
|
||
#[\Attribute(\Attribute::TARGET_CLASS)] | ||
final class AsResourceMutator |
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.
final class AsResourceMutator | |
class AsResourceMutator |
use ApiPlatform\Metadata\OperationMutatorInterface; | ||
use Psr\Container\ContainerInterface; | ||
|
||
final class OperationMutatorCollection implements ContainerInterface |
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.
can you comment on this class to explain what its used for? Also mark it @internal
no?
{ | ||
private array $mutators; | ||
|
||
public function addMutator(string $operationName, OperationMutatorInterface $mutator): void |
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.
public function addMutator(string $operationName, OperationMutatorInterface $mutator): void | |
/** | |
* Adds a mutator to the container for a given operation name. | |
*/ | |
public function add(string $operationName, OperationMutatorInterface $mutator): void |
|
||
final class OperationMutatorCollection implements ContainerInterface | ||
{ | ||
private array $mutators; |
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.
private array $mutators; | |
private array $mutators = []; |
*/ | ||
public function __construct( | ||
private readonly ContainerInterface $resourceMutators, | ||
private readonly ContainerInterface $operationMutators, |
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.
I'm not sure container interface has any generic template, you can't phpdoc like you did or we need a new interface that inherits the container interface (which is alright)
@@ -62,5 +64,7 @@ public function build(ContainerBuilder $container): void | |||
$container->addCompilerPass(new TestMercureHubPass()); | |||
$container->addCompilerPass(new AuthenticatorManagerPass()); | |||
$container->addCompilerPass(new SerializerMappingLoaderPass()); | |||
$container->addCompilerPass(new ResourceMutatorPass()); | |||
$container->addCompilerPass(new OperationMutatorPass()); |
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.
we should create only one pass
|
||
foreach ($mutators as $id => $tags) { | ||
foreach ($tags as $tag) { | ||
$definition->addMethodCall('addMutator', [ |
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.
$definition->addMethodCall('addMutator', [ | |
$definition->addMethodCall('add', [ |
|
||
foreach ($mutators as $id => $tags) { | ||
foreach ($tags as $tag) { | ||
$definition->addMethodCall('addMutator', [ |
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.
$definition->addMethodCall('addMutator', [ | |
$definition->addMethodCall('add', [ |
} | ||
} | ||
} | ||
} |
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.
merge both compiler passes
The idea of this feature is to allow customizing built-in endpoints from a third party API (ex Sylius E-commerce API).