Skip to content

Commit 9e9cf64

Browse files
loic425soyuka
andauthored
feat(metadata): introduce metadata mutators for resource & operations (#7213)
Co-authored-by: Antoine Bluchet <soyuka@users.noreply.github.com>
1 parent 77b292b commit 9e9cf64

16 files changed

+521
-0
lines changed

src/Metadata/AsOperationMutator.php

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the API Platform project.
5+
*
6+
* (c) Kévin Dunglas <dunglas@gmail.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
declare(strict_types=1);
13+
14+
namespace ApiPlatform\Metadata;
15+
16+
#[\Attribute(\Attribute::TARGET_CLASS)]
17+
class AsOperationMutator
18+
{
19+
public function __construct(
20+
public readonly string $operationName,
21+
) {
22+
}
23+
}

src/Metadata/AsResourceMutator.php

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the API Platform project.
5+
*
6+
* (c) Kévin Dunglas <dunglas@gmail.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
declare(strict_types=1);
13+
14+
namespace ApiPlatform\Metadata;
15+
16+
#[\Attribute(\Attribute::TARGET_CLASS)]
17+
class AsResourceMutator
18+
{
19+
/**
20+
* @param class-string $resourceClass
21+
*/
22+
public function __construct(
23+
public readonly string $resourceClass,
24+
) {
25+
}
26+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the API Platform project.
5+
*
6+
* (c) Kévin Dunglas <dunglas@gmail.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
declare(strict_types=1);
13+
14+
namespace ApiPlatform\Metadata\Mutator;
15+
16+
use ApiPlatform\Metadata\OperationMutatorInterface;
17+
use Psr\Container\ContainerInterface;
18+
19+
/**
20+
* Collection of Operation mutators to mutate Operation metadata.
21+
*/
22+
interface OperationMutatorCollectionInterface extends ContainerInterface
23+
{
24+
/**
25+
* @return list<OperationMutatorInterface>
26+
*/
27+
public function get(string $id): mixed;
28+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the API Platform project.
5+
*
6+
* (c) Kévin Dunglas <dunglas@gmail.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
declare(strict_types=1);
13+
14+
namespace ApiPlatform\Metadata\Mutator;
15+
16+
use ApiPlatform\Metadata\OperationMutatorInterface;
17+
18+
/**
19+
* @internal
20+
*/
21+
final class OperationResourceMutatorCollection implements OperationMutatorCollectionInterface
22+
{
23+
private array $mutators = [];
24+
25+
/**
26+
* Adds a mutator to the container for a given operation name.
27+
*/
28+
public function add(string $operationName, OperationMutatorInterface $mutator): void
29+
{
30+
$this->mutators[$operationName][] = $mutator;
31+
}
32+
33+
public function get(string $id): array
34+
{
35+
return $this->mutators[$id] ?? [];
36+
}
37+
38+
public function has(string $id): bool
39+
{
40+
return isset($this->mutators[$id]);
41+
}
42+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the API Platform project.
5+
*
6+
* (c) Kévin Dunglas <dunglas@gmail.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
declare(strict_types=1);
13+
14+
namespace ApiPlatform\Metadata\Mutator;
15+
16+
use ApiPlatform\Metadata\ResourceMutatorInterface;
17+
use Psr\Container\ContainerInterface;
18+
19+
/**
20+
* Collection of Resource mutators to mutate ApiResource metadata.
21+
*/
22+
interface ResourceMutatorCollectionInterface extends ContainerInterface
23+
{
24+
/**
25+
* @return list<ResourceMutatorInterface>
26+
*/
27+
public function get(string $id): array;
28+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the API Platform project.
5+
*
6+
* (c) Kévin Dunglas <dunglas@gmail.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
declare(strict_types=1);
13+
14+
namespace ApiPlatform\Metadata\Mutator;
15+
16+
use ApiPlatform\Metadata\ResourceMutatorInterface;
17+
18+
/**
19+
* @internal
20+
*/
21+
final class ResourceResourceMutatorCollection implements ResourceMutatorCollectionInterface
22+
{
23+
private array $mutators;
24+
25+
public function addMutator(string $resourceClass, ResourceMutatorInterface $mutator): void
26+
{
27+
$this->mutators[$resourceClass][] = $mutator;
28+
}
29+
30+
public function get(string $id): array
31+
{
32+
return $this->mutators[$id] ?? [];
33+
}
34+
35+
public function has(string $id): bool
36+
{
37+
return isset($this->mutators[$id]);
38+
}
39+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the API Platform project.
5+
*
6+
* (c) Kévin Dunglas <dunglas@gmail.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
declare(strict_types=1);
13+
14+
namespace ApiPlatform\Metadata;
15+
16+
interface OperationMutatorInterface
17+
{
18+
public function __invoke(Operation $operation): Operation;
19+
}
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the API Platform project.
5+
*
6+
* (c) Kévin Dunglas <dunglas@gmail.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
declare(strict_types=1);
13+
14+
namespace ApiPlatform\Metadata\Resource\Factory;
15+
16+
use ApiPlatform\Metadata\ApiResource;
17+
use ApiPlatform\Metadata\Mutator\OperationMutatorCollectionInterface;
18+
use ApiPlatform\Metadata\Mutator\ResourceMutatorCollectionInterface;
19+
use ApiPlatform\Metadata\Operation;
20+
use ApiPlatform\Metadata\Operations;
21+
use ApiPlatform\Metadata\Resource\ResourceMetadataCollection;
22+
23+
final class MutatorResourceMetadataCollectionFactory implements ResourceMetadataCollectionFactoryInterface
24+
{
25+
public function __construct(
26+
private readonly ResourceMutatorCollectionInterface $resourceMutators,
27+
private readonly OperationMutatorCollectionInterface $operationMutators,
28+
private readonly ?ResourceMetadataCollectionFactoryInterface $decorated = null,
29+
) {
30+
}
31+
32+
public function create(string $resourceClass): ResourceMetadataCollection
33+
{
34+
$resourceMetadataCollection = new ResourceMetadataCollection($resourceClass);
35+
if ($this->decorated) {
36+
$resourceMetadataCollection = $this->decorated->create($resourceClass);
37+
}
38+
39+
$newMetadataCollection = new ResourceMetadataCollection($resourceClass);
40+
41+
foreach ($resourceMetadataCollection as $resource) {
42+
$resource = $this->mutateResource($resource, $resourceClass);
43+
$operations = $this->mutateOperations($resource->getOperations() ?? new Operations());
44+
$resource = $resource->withOperations($operations);
45+
46+
$newMetadataCollection[] = $resource;
47+
}
48+
49+
return $newMetadataCollection;
50+
}
51+
52+
private function mutateResource(ApiResource $resource, string $resourceClass): ApiResource
53+
{
54+
foreach ($this->resourceMutators->get($resourceClass) as $mutator) {
55+
$resource = $mutator($resource);
56+
}
57+
58+
return $resource;
59+
}
60+
61+
private function mutateOperations(Operations $operations): Operations
62+
{
63+
$newOperations = new Operations();
64+
65+
/** @var Operation $operation */
66+
foreach ($operations as $key => $operation) {
67+
foreach ($this->operationMutators->get($key) as $mutator) {
68+
$operation = $mutator($operation);
69+
}
70+
71+
$newOperations->add($key, $operation);
72+
}
73+
74+
return $newOperations;
75+
}
76+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the API Platform project.
5+
*
6+
* (c) Kévin Dunglas <dunglas@gmail.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
declare(strict_types=1);
13+
14+
namespace ApiPlatform\Metadata;
15+
16+
interface ResourceMutatorInterface
17+
{
18+
public function __invoke(ApiResource $resource): ApiResource;
19+
}

0 commit comments

Comments
 (0)