diff --git a/Classes/ContentObject/WebcomponentContentObject.php b/Classes/ContentObject/WebcomponentContentObject.php index 477cf1c..5b6f8c7 100644 --- a/Classes/ContentObject/WebcomponentContentObject.php +++ b/Classes/ContentObject/WebcomponentContentObject.php @@ -6,6 +6,7 @@ use Sinso\Webcomponents\DataProviding\AssertionFailedException; use Sinso\Webcomponents\DataProviding\Traits\RenderComponent; +use Sinso\Webcomponents\Dto\Events\ComponentFolderIsApplied; use Sinso\Webcomponents\Dto\Events\ComponentWillBeRendered; use Sinso\Webcomponents\Dto\ComponentRenderingData; use TYPO3\CMS\Core\EventDispatcher\EventDispatcher; @@ -16,39 +17,26 @@ class WebcomponentContentObject extends AbstractContentObject { use RenderComponent; + public function __construct( + private readonly EventDispatcher $eventDispatcher, + ) { + } + public function render($conf = []): string { $componentRenderingData = GeneralUtility::makeInstance(ComponentRenderingData::class); if ($this->cObj->getCurrentTable() === 'tt_content') { $componentRenderingData->setContentRecord($this->cObj->data); } - if (isset($conf['additionalInputData.'])) { - // apply stdWrap to all additionalInputData properties - foreach ($conf['additionalInputData.'] as $key => $value) { - $key = (string) $key; - if (!str_ends_with($key, '.')) { - continue; - } - $keyWithoutDot = substr($key, 0, -1); - $conf['additionalInputData.'][$keyWithoutDot] = $this->cObj->stdWrapValue($keyWithoutDot, $conf['additionalInputData.']); - unset($conf['additionalInputData.'][$key]); - } - $componentRenderingData->setAdditionalInputData($conf['additionalInputData.']); - } + + $componentFolder = $this->cObj->stdWrapValue('componentFolder', $conf); try { - $componentRenderingData = self::evaluateComponent($componentRenderingData, $conf['component'] ?? '', $this->cObj); + $componentRenderingData = $this->applyComponentFolder($componentRenderingData, $componentFolder); + $event = GeneralUtility::makeInstance(ComponentWillBeRendered::class, $this->cObj, $componentRenderingData); + $this->eventDispatcher->dispatch($event); } catch (AssertionFailedException $e) { return $e->getRenderingPlaceholder(); } - $componentRenderingData = $this->evaluateTypoScriptConfiguration($componentRenderingData, $conf); - - $event = GeneralUtility::makeInstance(ComponentWillBeRendered::class, $this->cObj, $componentRenderingData); - $eventDispatcher = GeneralUtility::makeInstance(EventDispatcher::class); - $eventDispatcher->dispatch($event); - - if (!$componentRenderingData->isRenderable()) { - return ''; - } // render with tag builder $markup = $this->renderMarkup($componentRenderingData); @@ -59,19 +47,10 @@ public function render($conf = []): string return $markup; } - private function evaluateTypoScriptConfiguration(ComponentRenderingData $componentRenderingData, array $conf): ComponentRenderingData + private function applyComponentFolder(ComponentRenderingData $componentRenderingData, string $componentFolder): ComponentRenderingData { - if (isset($conf['properties.'])) { - foreach ($conf['properties.'] as $key => $value) { - if (is_array($value)) { - continue; - } - $componentRenderingData->setTagProperty($key, $this->cObj->cObjGetSingle($value, $conf['properties.'][$key . '.'])); - } - } - if (($conf['tagName'] ?? '') || ($conf['tagName.'] ?? [])) { - $componentRenderingData->setTagName($this->cObj->stdWrap($conf['tagName'] ?? '', $conf['tagName.'] ?? []) ?: null); - } + $event = GeneralUtility::makeInstance(ComponentFolderIsApplied::class, $componentRenderingData, $this->cObj, $componentFolder); + $this->eventDispatcher->dispatch($event); return $componentRenderingData; } diff --git a/Classes/DataProviding/Traits/Image.php b/Classes/DataProviding/Traits/Image.php index 0f816f0..d312e9c 100644 --- a/Classes/DataProviding/Traits/Image.php +++ b/Classes/DataProviding/Traits/Image.php @@ -6,18 +6,12 @@ use TYPO3\CMS\Core\Imaging\ImageManipulation\CropVariantCollection; use TYPO3\CMS\Core\Resource\FileReference; +use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Extbase\Domain\Model\FileReference as ExtbaseFileReference; use TYPO3\CMS\Extbase\Service\ImageService; trait Image { - private ImageService $imageService; - - public function injectImageService(ImageService $imageService): void - { - $this->imageService = $imageService; - } - public function getImageUri($image, $width, $height, string $cropVariant = 'default', bool $absolute = false): string { if ($image instanceof ExtbaseFileReference) { @@ -41,7 +35,8 @@ public function getImageUri($image, $width, $height, string $cropVariant = 'defa $processingInstructions['fileExtension'] = $arguments['fileExtension']; } - $processedImage = $this->imageService->applyProcessingInstructions($image, $processingInstructions); - return $this->imageService->getImageUri($processedImage, $absolute); + $imageService = GeneralUtility::makeInstance(ImageService::class); + $processedImage = $imageService->applyProcessingInstructions($image, $processingInstructions); + return $imageService->getImageUri($processedImage, $absolute); } } diff --git a/Classes/DataProviding/Traits/RenderSubComponent.php b/Classes/DataProviding/Traits/RenderSubComponent.php index 71d7f48..ad62f16 100644 --- a/Classes/DataProviding/Traits/RenderSubComponent.php +++ b/Classes/DataProviding/Traits/RenderSubComponent.php @@ -29,10 +29,6 @@ protected function renderSubComponent(string $componentClassName, $additionalInp return null; } - if (!$componentRenderingData->isRenderable()) { - return null; - } - $properties = $componentRenderingData->getTagProperties(); if ($slot !== null) { $properties['slot'] = $slot; diff --git a/Classes/Dto/Events/ComponentFolderIsApplied.php b/Classes/Dto/Events/ComponentFolderIsApplied.php new file mode 100644 index 0000000..b548300 --- /dev/null +++ b/Classes/Dto/Events/ComponentFolderIsApplied.php @@ -0,0 +1,18 @@ +findAndAddEntryPoint($event->componentFolder . '/Source/' . $fileName); + } + } + + protected function findAndAddEntryPoint(string $entryPointPath): void + { + $absoluteEntryPointFile = ExtensionManagementUtility::resolvePackagePath($entryPointPath); + if (!file_exists($absoluteEntryPointFile)) { + return; + } + + $this->viteService->addAssetsFromManifest( + $this->viteService->getDefaultManifestFile(), + $entryPointPath, + ); + } +} \ No newline at end of file diff --git a/Classes/EventListener/ComponentFolderIsApplied/DeriveTagNameFromComponentFolder.php b/Classes/EventListener/ComponentFolderIsApplied/DeriveTagNameFromComponentFolder.php new file mode 100644 index 0000000..e4ad56a --- /dev/null +++ b/Classes/EventListener/ComponentFolderIsApplied/DeriveTagNameFromComponentFolder.php @@ -0,0 +1,19 @@ +componentFolder, '/'); + $lastFolderName = basename($componentFolderPath); + $event->componentRenderingData->setTagName($lastFolderName); + } +} \ No newline at end of file diff --git a/Classes/EventListener/ComponentFolderIsApplied/ExecuteProviderFile.php b/Classes/EventListener/ComponentFolderIsApplied/ExecuteProviderFile.php new file mode 100644 index 0000000..4c575a7 --- /dev/null +++ b/Classes/EventListener/ComponentFolderIsApplied/ExecuteProviderFile.php @@ -0,0 +1,32 @@ +componentFolder); + $providerFile = $absoluteComponentFolder . '/Source/provide.php'; + if (!file_exists($providerFile)) { + return; + } + + $class = require $providerFile; + $provider = new $class(); + if (!$provider instanceof ComponentInterface) { + throw new \Exception('Provider must implement ComponentInterface', 1722526311); + } + $provider->setContentObjectRenderer($event->contentObjectRenderer); + + $provider->provide($event->componentRenderingData); + } +} \ No newline at end of file diff --git a/Classes/ServiceProvider.php b/Classes/ServiceProvider.php new file mode 100644 index 0000000..b49f8e7 --- /dev/null +++ b/Classes/ServiceProvider.php @@ -0,0 +1,59 @@ + static::overwriteContentBlocksTypoScript(...), + ] + parent::getExtensions(); + } + + public static function overwriteContentBlocksTypoScript(ContainerInterface $container, \ArrayObject $typoScriptArrayObject): \ArrayObject + { + $contentBlockRegistry = $container->get(ContentBlockRegistry::class); + $tableDefinitionCollection = $container->get(TableDefinitionCollection::class); + foreach ($tableDefinitionCollection as $tableDefinition) { + foreach ($tableDefinition->getContentTypeDefinitionCollection() ?? [] as $typeDefinition) { + if ($tableDefinition->getContentType() !== ContentType::CONTENT_ELEMENT) { + continue; + } + $contentBlockExtPath = $contentBlockRegistry->getContentBlockExtPath($typeDefinition->getName()); + $typoScript = <<getTypeName()} > +tt_content.{$typeDefinition->getTypeName()} = WEBCOMPONENT +tt_content.{$typeDefinition->getTypeName()}.componentFolder = $contentBlockExtPath +HEREDOC; + $typoScriptArrayObject->append($typoScript); + } + } + + return $typoScriptArrayObject; + } +} \ No newline at end of file diff --git a/Classes/ViewHelpers/RenderViewHelper.php b/Classes/ViewHelpers/RenderViewHelper.php index bc12eb3..7e07055 100644 --- a/Classes/ViewHelpers/RenderViewHelper.php +++ b/Classes/ViewHelpers/RenderViewHelper.php @@ -42,18 +42,13 @@ public static function renderStatic(array $arguments, \Closure $renderChildrenCl $componentRenderingData->setContentRecord($contentObjectRenderer->data); try { $componentRenderingData = self::evaluateComponent($componentRenderingData, $arguments['component'], $contentObjectRenderer); + $event = GeneralUtility::makeInstance(ComponentWillBeRendered::class, $contentObjectRenderer, $componentRenderingData); + $eventDispatcher = GeneralUtility::makeInstance(EventDispatcher::class); + $eventDispatcher->dispatch($event); } catch (AssertionFailedException $e) { return $e->getRenderingPlaceholder(); } - $event = GeneralUtility::makeInstance(ComponentWillBeRendered::class, $contentObjectRenderer, $componentRenderingData); - $eventDispatcher = GeneralUtility::makeInstance(EventDispatcher::class); - $eventDispatcher->dispatch($event); - - if (!$componentRenderingData->isRenderable()) { - return ''; - } - $tagName = $componentRenderingData->getTagName(); $content = $componentRenderingData->getTagContent(); $properties = $componentRenderingData->getTagProperties(); diff --git a/Configuration/Services.yaml b/Configuration/Services.yaml index cdb67d5..bfa70df 100644 --- a/Configuration/Services.yaml +++ b/Configuration/Services.yaml @@ -4,6 +4,9 @@ services: autoconfigure: true public: false + Sinso\Webcomponents\: + resource: '../Classes/*' + Sinso\Webcomponents\ContentObject\WebcomponentContentObject: tags: - name: frontend.contentobject diff --git a/composer.json b/composer.json index 53952f7..5fdc39e 100644 --- a/composer.json +++ b/composer.json @@ -5,7 +5,10 @@ "description": "Render Web Components", "extra": { "typo3/cms": { - "extension-key": "webcomponents" + "extension-key": "webcomponents", + "Package": { + "serviceProvider": "Sinso\\Webcomponents\\ServiceProvider" + } } }, "autoload": {