diff --git a/Classes/Core/AdditionalPropertiesInterface.php b/Classes/Core/AdditionalPropertiesInterface.php new file mode 100644 index 00000000..bfcc6985 --- /dev/null +++ b/Classes/Core/AdditionalPropertiesInterface.php @@ -0,0 +1,28 @@ + + */ + public function getAdditionalProperties(): array; +} diff --git a/Classes/Core/Model/AbstractType.php b/Classes/Core/Model/AbstractType.php index 42797cf7..ce2790ad 100644 --- a/Classes/Core/Model/AbstractType.php +++ b/Classes/Core/Model/AbstractType.php @@ -14,6 +14,7 @@ use Brotkrueml\Schema\Attributes\Type; use Brotkrueml\Schema\Event\RegisterAdditionalTypePropertiesEvent; use Brotkrueml\Schema\Extension; +use Brotkrueml\Schema\Type\AdditionalPropertiesProvider; use Psr\EventDispatcher\EventDispatcherInterface; use TYPO3\CMS\Core\Cache\CacheManager; use TYPO3\CMS\Core\Utility\GeneralUtility; @@ -58,6 +59,12 @@ protected function addAdditionalProperties(): void $cache = GeneralUtility::makeInstance(CacheManager::class)->getCache(Extension::CACHE_IDENTIFIER); $additionalProperties = $cache->get($cacheEntryIdentifier); if ($additionalProperties === false) { + $additionalPropertiesProvider = GeneralUtility::makeInstance(AdditionalPropertiesProvider::class); + $additionalProperties = []; + foreach ($additionalPropertiesProvider->get($this->getType()) as $class) { + $additionalProperties = [...$additionalProperties, ...(new $class())->getAdditionalProperties()]; + } + $event = new RegisterAdditionalTypePropertiesEvent(static::class); /** @var EventDispatcherInterface $eventDispatcher */ @@ -65,7 +72,7 @@ protected function addAdditionalProperties(): void /** @var RegisterAdditionalTypePropertiesEvent $event */ $event = $eventDispatcher->dispatch($event); - $additionalProperties = $event->getAdditionalProperties(); + $additionalProperties = [...$additionalProperties, ...$event->getAdditionalProperties()]; $cache->set($cacheEntryIdentifier, $additionalProperties, [], 0); } diff --git a/Classes/DependencyInjection/AdditionalPropertiesPass.php b/Classes/DependencyInjection/AdditionalPropertiesPass.php new file mode 100644 index 00000000..14609f02 --- /dev/null +++ b/Classes/DependencyInjection/AdditionalPropertiesPass.php @@ -0,0 +1,38 @@ +hasDefinition(AdditionalPropertiesProvider::class)) { + return; + } + + $providerDefinition = $container->getDefinition(AdditionalPropertiesProvider::class)->setPublic(true); + foreach (\array_keys($container->findTaggedServiceIds($this->tagName)) as $id) { + $providerDefinition->addMethodCall('add', [$id]); + } + } +} diff --git a/Classes/Type/AdditionalPropertiesProvider.php b/Classes/Type/AdditionalPropertiesProvider.php new file mode 100644 index 00000000..ba8eee48 --- /dev/null +++ b/Classes/Type/AdditionalPropertiesProvider.php @@ -0,0 +1,45 @@ +>> + */ + private array $additionalProperties = []; + + /** + * @param class-string $class + */ + public function add(string $class): void + { + $type = (new $class())->getType(); + if (! isset($this->additionalProperties[$type])) { + $this->additionalProperties[$type] = []; + } + $this->additionalProperties[$type][] = $class; + } + + /** + * @return list> + */ + public function get(string $type): array + { + return $this->additionalProperties[$type] ?? []; + } +} diff --git a/Configuration/Services.php b/Configuration/Services.php index 54a4cd1a..17d5921c 100644 --- a/Configuration/Services.php +++ b/Configuration/Services.php @@ -14,7 +14,9 @@ use Brotkrueml\Schema\Cache\PagesCacheService; use Brotkrueml\Schema\Configuration\Configuration; use Brotkrueml\Schema\Configuration\ConfigurationProvider; +use Brotkrueml\Schema\Core\AdditionalPropertiesInterface; use Brotkrueml\Schema\Core\Model\TypeInterface; +use Brotkrueml\Schema\DependencyInjection\AdditionalPropertiesPass; use Brotkrueml\Schema\DependencyInjection\TypeProviderPass; use Brotkrueml\Schema\EventListener\AddBreadcrumbList; use Brotkrueml\Schema\EventListener\AddWebPageType; @@ -33,6 +35,9 @@ $builder->registerForAutoconfiguration(TypeInterface::class)->addTag('tx_schema.type'); $builder->addCompilerPass(new TypeProviderPass('tx_schema.type')); + $builder->registerForAutoconfiguration(AdditionalPropertiesInterface::class)->addTag('tx_schema.additional_properties'); + $builder->addCompilerPass(new AdditionalPropertiesPass('tx_schema.additional_properties')); + $services = $configurator->services(); $services->defaults() ->autowire() diff --git a/Tests/Fixtures/Model/AdditionalProperties/Event.php b/Tests/Fixtures/Model/AdditionalProperties/Event.php new file mode 100644 index 00000000..185d5cad --- /dev/null +++ b/Tests/Fixtures/Model/AdditionalProperties/Event.php @@ -0,0 +1,29 @@ +subject = new AdditionalPropertiesProvider(); + } + + #[Test] + public function getReturnsEmptyArrayIfTypeIsNotAvailable(): void + { + $actual = $this->subject->get('NonExisting'); + + self::assertSame([], $actual); + } + + #[Test] + public function getReturnsPreviouslyAddedClassesCorrectly(): void + { + $this->subject->add(Person1::class); + $this->subject->add(Person2::class); + $this->subject->add(Event::class); + + $actual = $this->subject->get('Person'); + + self::assertCount(2, $actual); + self::assertContains(Person1::class, $actual); + self::assertContains(Person2::class, $actual); + } +}