From 56325a65466a3f4e8353f859b9e29b9ffb76d111 Mon Sep 17 00:00:00 2001 From: Daniel Subiabre Date: Tue, 13 May 2025 11:23:54 +0200 Subject: [PATCH 1/2] Update versioned resource naming logic --- src/ApiResource/Version.php | 5 +- .../Compiler/VersionedResourcePass.php | 47 ++++++++++++++----- src/Filter/ResourceVersionResourceFilter.php | 2 +- src/Service/ApiService.php | 24 ---------- src/Service/VersionedResourceService.php | 36 ++++++++++++-- src/State/ResourceVersionStateProvider.php | 13 +++-- 6 files changed, 77 insertions(+), 50 deletions(-) delete mode 100644 src/Service/ApiService.php diff --git a/src/ApiResource/Version.php b/src/ApiResource/Version.php index a04432f..e585b14 100644 --- a/src/ApiResource/Version.php +++ b/src/ApiResource/Version.php @@ -5,7 +5,6 @@ namespace App\ApiResource; use ApiPlatform\Metadata as API; use App\Filter\ResourceVersionResourceFilter; use App\Filter\ResourceVersionResourceIdFilter; -use App\Service\ApiService; use App\State\ResourceVersionStateProvider; use Gedmo\Loggable\Entity\LogEntry; @@ -23,7 +22,7 @@ class Version { public function __construct( private readonly LogEntry $log, - private readonly object $entity, + private readonly string $shortName, ) {} /** @@ -55,7 +54,7 @@ class Version */ public function getResource(): string { - return ApiService::toResource($this->log->getObjectClass()); + return $this->shortName; } /** diff --git a/src/DependencyInjection/Compiler/VersionedResourcePass.php b/src/DependencyInjection/Compiler/VersionedResourcePass.php index 5f8e9c2..231baef 100644 --- a/src/DependencyInjection/Compiler/VersionedResourcePass.php +++ b/src/DependencyInjection/Compiler/VersionedResourcePass.php @@ -2,9 +2,9 @@ namespace App\DependencyInjection\Compiler; -use App\Service\ApiService; +use ApiPlatform\Metadata\ApiResource; use App\Service\VersionedResourceService; -use Gedmo\Mapping\Annotation as Gedmo; +use Gedmo\Mapping\Annotation\Loggable; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; use Symfony\Component\DependencyInjection\ContainerBuilder; @@ -13,27 +13,48 @@ class VersionedResourcePass implements CompilerPassInterface public function process(ContainerBuilder $container): void { $allClasses = \get_declared_classes(); - $entityClasses = \array_filter($allClasses, function (string $className) { - return \str_starts_with($className, 'App\\Entity\\'); + $resourceClasses = \array_filter($allClasses, function (string $className) { + return \str_starts_with($className, 'App\\ApiResource\\'); }); - $versionedResourceNames = []; - foreach ($entityClasses as $entityClass) { - $reflectionClass = new \ReflectionClass($entityClass); - $attributes = $reflectionClass->getAttributes(Gedmo\Loggable::class); + $versionedResources = []; + foreach ($resourceClasses as $resourceClass) { + $resourceReflection = new \ReflectionClass($resourceClass); + $resourceAttributes = $resourceReflection->getAttributes(ApiResource::class); - if (empty($attributes)) { + if (empty($resourceAttributes)) { continue; } - $versionedResourceNames = [ - ...$versionedResourceNames, - ApiService::toResource($entityClass), + $resourceAttribute = $resourceAttributes[0]; + $resourceAttributeArgs = $resourceAttribute->getArguments(); + + if (!\array_key_exists('stateOptions', $resourceAttributeArgs)) { + continue; + } + + if (!\array_key_exists('shortName', $resourceAttributeArgs)) { + continue; + } + + /** @var string */ + $resourceEntityClass = $resourceAttributeArgs['stateOptions']->getEntityClass(); + + $entityReflection = new \ReflectionClass($resourceEntityClass); + $entityLoggable = $entityReflection->getAttributes(Loggable::class); + + if (empty($entityLoggable)) { + continue; + } + + $versionedResources = [ + ...$versionedResources, + $resourceAttributeArgs['shortName'] => $resourceEntityClass, ]; } /** @var VersionedResourceService */ $versionedResourceService = $container->get(VersionedResourceService::class); - $versionedResourceService->compileNames($versionedResourceNames); + $versionedResourceService->compileNames($versionedResources); } } diff --git a/src/Filter/ResourceVersionResourceFilter.php b/src/Filter/ResourceVersionResourceFilter.php index 24ab0ad..95573bf 100644 --- a/src/Filter/ResourceVersionResourceFilter.php +++ b/src/Filter/ResourceVersionResourceFilter.php @@ -47,7 +47,7 @@ final class ResourceVersionResourceFilter extends AbstractFilter 'description' => 'The name of the resource.', 'schema' => [ 'type' => Type::BUILTIN_TYPE_STRING, - 'enum' => $this->versionedResourceService->getNames(), + 'enum' => \array_keys($this->versionedResourceService->getNames()), ], 'openapi' => [ 'allowEmptyValue' => false, diff --git a/src/Service/ApiService.php b/src/Service/ApiService.php deleted file mode 100644 index 3ac8503..0000000 --- a/src/Service/ApiService.php +++ /dev/null @@ -1,24 +0,0 @@ - $names */ public function compileNames(array $names) { @@ -51,17 +51,45 @@ class VersionedResourceService \file_put_contents( self::getNamesLockFile(), - implode(PHP_EOL, $names) + json_encode($names) ); } /** - * @return array List of the versioned resource names + * @return array List of the versioned resource names * * @see compileNames() */ public static function getNames(): array { - return explode(PHP_EOL, \file_get_contents(self::getNamesLockFile())); + return json_decode(\file_get_contents(self::getNamesLockFile()), true); + } + + public static function getEntityFromResource(string $resourceShortName): string + { + $names = self::getNames(); + + if (\array_key_exists($resourceShortName, $names)) { + return $names[$resourceShortName]; + } + + throw new \Exception(\sprintf( + "The resource shortName '%s' does not match to a known versioned resource", + $resourceShortName + )); + } + + public static function getResourceFromEntity(string $entityClass): string + { + foreach (self::getNames() as $shortName => $entityFqcl) { + if ($entityFqcl === $entityClass) { + return $shortName; + } + } + + throw new \Exception(\sprintf( + "The entity class name '%s' does not match to a known versioned resource", + $entityClass + )); } } diff --git a/src/State/ResourceVersionStateProvider.php b/src/State/ResourceVersionStateProvider.php index 3698d73..9a475d9 100644 --- a/src/State/ResourceVersionStateProvider.php +++ b/src/State/ResourceVersionStateProvider.php @@ -6,7 +6,7 @@ use ApiPlatform\Metadata as API; use ApiPlatform\Metadata\Operation; use ApiPlatform\State\ProviderInterface; use App\ApiResource\Version; -use App\Service\ApiResourceNormalizer; +use App\Service\VersionedResourceService; use Doctrine\ORM\EntityManagerInterface; use Doctrine\Persistence\Mapping\MappingException; use Gedmo\Loggable\Entity\LogEntry; @@ -33,6 +33,8 @@ class ResourceVersionStateProvider implements ProviderInterface $context['request']->query->get('resource'), $context['request']->query->get('resourceId') ); + default: + throw new \Exception('Operation not supported for Version resource', 1); } } @@ -48,8 +50,9 @@ class ResourceVersionStateProvider implements ProviderInterface } $entity = $this->entityManager->find($log->getObjectClass(), $log->getObjectId()); + $resourceName = VersionedResourceService::getResourceFromEntity($entity::class); - return new Version($log, $entity); + return new Version($log, $resourceName); } /** @@ -57,10 +60,10 @@ class ResourceVersionStateProvider implements ProviderInterface */ private function getVersions(string $resourceName, int $resourceId): array { - $resourceClass = ApiResourceNormalizer::toEntity($resourceName); + $entityClass = VersionedResourceService::getEntityFromResource($resourceName); try { - $entity = $this->entityManager->find($resourceClass, $resourceId); + $entity = $this->entityManager->find($entityClass, $resourceId); } catch (MappingException $e) { throw new NotFoundHttpException(sprintf("Resource '%s' does not exist", $resourceName)); } @@ -73,7 +76,7 @@ class ResourceVersionStateProvider implements ProviderInterface $versions = []; foreach ($logs as $log) { - $versions[] = new Version($log, $entity); + $versions[] = new Version($log, $resourceName); } return $versions; From a6b60dc2b7bbcdf6b5b3561c32389f92e5566fce Mon Sep 17 00:00:00 2001 From: Daniel Subiabre Date: Tue, 13 May 2025 11:28:32 +0200 Subject: [PATCH 2/2] Update resource version number display property --- src/ApiResource/Version.php | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/ApiResource/Version.php b/src/ApiResource/Version.php index e585b14..36b4d57 100644 --- a/src/ApiResource/Version.php +++ b/src/ApiResource/Version.php @@ -33,14 +33,6 @@ class Version return $this->log->getId(); } - /** - * The ID of the version for this specific resource. - */ - public function getVersion(): ?int - { - return $this->log->getVersion(); - } - /** * The type of action that performed the recorded changes. */ @@ -65,6 +57,14 @@ class Version return $this->log->getObjectId(); } + /** + * The version number for this specific resource. + */ + public function getResourceVersion(): ?int + { + return $this->log->getVersion(); + } + /** * The changed resource data, i.e the new values of the changed properties. */