diff --git a/src/Metadata/Extractor/AbstractPropertyExtractor.php b/src/Metadata/Extractor/AbstractPropertyExtractor.php index 2f011bf64d9..ba429e6838f 100644 --- a/src/Metadata/Extractor/AbstractPropertyExtractor.php +++ b/src/Metadata/Extractor/AbstractPropertyExtractor.php @@ -15,13 +15,14 @@ use Psr\Container\ContainerInterface; use Symfony\Component\DependencyInjection\ContainerInterface as SymfonyContainerInterface; +use Symfony\Contracts\Service\ResetInterface; /** * Base file extractor. * * @author Vincent Chalamon */ -abstract class AbstractPropertyExtractor implements PropertyExtractorInterface +abstract class AbstractPropertyExtractor implements PropertyExtractorInterface, ResetInterface { protected ?array $properties = null; private array $collectedParameters = []; @@ -55,6 +56,15 @@ public function getProperties(): array */ abstract protected function extractPath(string $path): void; + /** + * {@inheritdoc} + */ + public function reset(): void + { + $this->properties = null; + $this->collectedParameters = []; + } + /** * Recursively replaces placeholders with the service container parameters. * diff --git a/src/Metadata/Extractor/AbstractResourceExtractor.php b/src/Metadata/Extractor/AbstractResourceExtractor.php index d9bd3eac43d..353a7266b34 100644 --- a/src/Metadata/Extractor/AbstractResourceExtractor.php +++ b/src/Metadata/Extractor/AbstractResourceExtractor.php @@ -15,13 +15,14 @@ use Psr\Container\ContainerInterface; use Symfony\Component\DependencyInjection\ContainerInterface as SymfonyContainerInterface; +use Symfony\Contracts\Service\ResetInterface; /** * Base file extractor. * * @author Kévin Dunglas */ -abstract class AbstractResourceExtractor implements ResourceExtractorInterface +abstract class AbstractResourceExtractor implements ResourceExtractorInterface, ResetInterface { protected ?array $resources = null; private array $collectedParameters = []; @@ -55,6 +56,15 @@ public function getResources(): array */ abstract protected function extractPath(string $path): void; + /** + * {@inheritdoc} + */ + public function reset(): void + { + $this->resources = null; + $this->collectedParameters = []; + } + /** * Recursively replaces placeholders with the service container parameters. * diff --git a/src/Metadata/ResourceClassResolver.php b/src/Metadata/ResourceClassResolver.php index c7d7fc8e4ff..181eb288c51 100644 --- a/src/Metadata/ResourceClassResolver.php +++ b/src/Metadata/ResourceClassResolver.php @@ -16,6 +16,7 @@ use ApiPlatform\Metadata\Exception\InvalidArgumentException; use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; use ApiPlatform\Metadata\Util\ClassInfoTrait; +use Symfony\Contracts\Service\ResetInterface; /** * {@inheritdoc} @@ -23,7 +24,7 @@ * @author Kévin Dunglas * @author Samuel ROZE */ -final class ResourceClassResolver implements ResourceClassResolverInterface +final class ResourceClassResolver implements ResourceClassResolverInterface, ResetInterface { use ClassInfoTrait; private array $localIsResourceClassCache = []; @@ -105,4 +106,13 @@ public function isResourceClass(string $type): bool return $this->localIsResourceClassCache[$type] = false; } + + /** + * {@inheritdoc} + */ + public function reset(): void + { + $this->localIsResourceClassCache = []; + $this->localMostSpecificResourceClassCache = []; + } } diff --git a/src/Metadata/Tests/Extractor/YamlPropertyExtractorResetTest.php b/src/Metadata/Tests/Extractor/YamlPropertyExtractorResetTest.php new file mode 100644 index 00000000000..459384e2e10 --- /dev/null +++ b/src/Metadata/Tests/Extractor/YamlPropertyExtractorResetTest.php @@ -0,0 +1,43 @@ + + * + * 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\Metadata\Tests\Extractor; + +use ApiPlatform\Metadata\Extractor\AbstractPropertyExtractor; +use ApiPlatform\Metadata\Extractor\YamlPropertyExtractor; +use PHPUnit\Framework\TestCase; + +class YamlPropertyExtractorResetTest extends TestCase +{ + public function testReset(): void + { + $extractor = new YamlPropertyExtractor([]); + + $refl = new \ReflectionClass($extractor); + $properties = $refl->getProperty('properties'); + $properties->setAccessible(true); + $properties->setValue($extractor, ['foo' => 'bar']); + + $collectedParameters = new \ReflectionProperty(AbstractPropertyExtractor::class, 'collectedParameters'); + $collectedParameters->setAccessible(true); + $collectedParameters->setValue($extractor, ['param' => 'value']); + + $this->assertNotEmpty($properties->getValue($extractor)); + $this->assertNotEmpty($collectedParameters->getValue($extractor)); + + $extractor->reset(); + + $this->assertNull($properties->getValue($extractor)); + $this->assertEmpty($collectedParameters->getValue($extractor)); + } +} diff --git a/src/Metadata/Tests/Extractor/YamlResourceExtractorResetTest.php b/src/Metadata/Tests/Extractor/YamlResourceExtractorResetTest.php new file mode 100644 index 00000000000..02d60033b90 --- /dev/null +++ b/src/Metadata/Tests/Extractor/YamlResourceExtractorResetTest.php @@ -0,0 +1,43 @@ + + * + * 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\Metadata\Tests\Extractor; + +use ApiPlatform\Metadata\Extractor\AbstractResourceExtractor; +use ApiPlatform\Metadata\Extractor\YamlResourceExtractor; +use PHPUnit\Framework\TestCase; + +class YamlResourceExtractorResetTest extends TestCase +{ + public function testReset(): void + { + $extractor = new YamlResourceExtractor([]); + + $refl = new \ReflectionClass($extractor); + $resources = $refl->getProperty('resources'); + $resources->setAccessible(true); + $resources->setValue($extractor, ['foo' => 'bar']); + + $collectedParameters = new \ReflectionProperty(AbstractResourceExtractor::class, 'collectedParameters'); + $collectedParameters->setAccessible(true); + $collectedParameters->setValue($extractor, ['param' => 'value']); + + $this->assertNotEmpty($resources->getValue($extractor)); + $this->assertNotEmpty($collectedParameters->getValue($extractor)); + + $extractor->reset(); + + $this->assertNull($resources->getValue($extractor)); + $this->assertEmpty($collectedParameters->getValue($extractor)); + } +} diff --git a/src/Metadata/Tests/ResourceClassResolverTest.php b/src/Metadata/Tests/ResourceClassResolverTest.php new file mode 100644 index 00000000000..0751b11b20f --- /dev/null +++ b/src/Metadata/Tests/ResourceClassResolverTest.php @@ -0,0 +1,43 @@ + + * + * 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\Metadata\Tests; + +use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; +use ApiPlatform\Metadata\Resource\ResourceNameCollection; +use ApiPlatform\Metadata\ResourceClassResolver; +use PHPUnit\Framework\TestCase; + +class ResourceClassResolverTest extends TestCase +{ + public function testReset(): void + { + $resourceNameCollectionFactoryProphecy = $this->createMock(ResourceNameCollectionFactoryInterface::class); + $resourceNameCollectionFactoryProphecy->method('create')->willReturn(new ResourceNameCollection([ \stdClass::class ])); + + $resolver = new ResourceClassResolver($resourceNameCollectionFactoryProphecy); + + $this->assertTrue($resolver->isResourceClass(\stdClass::class)); + + $resolver->reset(); + + $refl = new \ReflectionClass($resolver); + $localIsResourceClassCache = $refl->getProperty('localIsResourceClassCache'); + $localIsResourceClassCache->setAccessible(true); + $localMostSpecificResourceClassCache = $refl->getProperty('localMostSpecificResourceClassCache'); + $localMostSpecificResourceClassCache->setAccessible(true); + + $this->assertEmpty($localIsResourceClassCache->getValue($resolver)); + $this->assertEmpty($localMostSpecificResourceClassCache->getValue($resolver)); + } +}