Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 14 additions & 35 deletions Classes/ContentObject/WebcomponentContentObject.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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);
Expand All @@ -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;
}

Expand Down
13 changes: 4 additions & 9 deletions Classes/DataProviding/Traits/Image.php
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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);
}
}
4 changes: 0 additions & 4 deletions Classes/DataProviding/Traits/RenderSubComponent.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
18 changes: 18 additions & 0 deletions Classes/Dto/Events/ComponentFolderIsApplied.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

declare(strict_types=1);

namespace Sinso\Webcomponents\Dto\Events;

use Sinso\Webcomponents\Dto\ComponentRenderingData;
use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;

readonly class ComponentFolderIsApplied
{
public function __construct(
public ComponentRenderingData $componentRenderingData,
public ContentObjectRenderer $contentObjectRenderer,
public string $componentFolder,
) {
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<?php

declare(strict_types=1);

namespace Sinso\Webcomponents\EventListener\ComponentFolderIsApplied;

use Praetorius\ViteAssetCollector\Service\ViteService;
use Sinso\Webcomponents\Dto\Events\ComponentFolderIsApplied;
use TYPO3\CMS\Core\Attribute\AsEventListener;
use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;

#[AsEventListener(identifier: 'webcomponents/addEntryPointToAssetCollector')]
class AddEntryPointToAssetCollector
{
protected const SUPPORTED_ENTRY_POINT_FILE_NAMES = [
'entry.ts',
'entry.js',
];

public function __construct(
private readonly ViteService $viteService
) {
}

public function __invoke(ComponentFolderIsApplied $event): void
{
foreach (self::SUPPORTED_ENTRY_POINT_FILE_NAMES as $fileName) {
$this->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,
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php

declare(strict_types=1);

namespace Sinso\Webcomponents\EventListener\ComponentFolderIsApplied;

use Sinso\Webcomponents\Dto\Events\ComponentFolderIsApplied;
use TYPO3\CMS\Core\Attribute\AsEventListener;

#[AsEventListener(identifier: 'webcomponents/deriveTagNameFromComponentFolder')]
class DeriveTagNameFromComponentFolder
{
public function __invoke(ComponentFolderIsApplied $event): void
{
$componentFolderPath = rtrim($event->componentFolder, '/');
$lastFolderName = basename($componentFolderPath);
$event->componentRenderingData->setTagName($lastFolderName);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

declare(strict_types=1);

namespace Sinso\Webcomponents\EventListener\ComponentFolderIsApplied;

use Sinso\Webcomponents\DataProviding\ComponentInterface;
use Sinso\Webcomponents\Dto\Events\ComponentFolderIsApplied;
use TYPO3\CMS\Core\Attribute\AsEventListener;
use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;

#[AsEventListener(identifier: 'webcomponents/executeProviderFile')]
class ExecuteProviderFile
{
public function __invoke(ComponentFolderIsApplied $event): void
{
$absoluteComponentFolder = ExtensionManagementUtility::resolvePackagePath($event->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);
}
}
59 changes: 59 additions & 0 deletions Classes/ServiceProvider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
<?php

declare(strict_types=1);

namespace Sinso\Webcomponents;

use Psr\Container\ContainerInterface;
use TYPO3\CMS\ContentBlocks\Definition\ContentType\ContentType;
use TYPO3\CMS\ContentBlocks\Definition\TableDefinitionCollection;
use TYPO3\CMS\ContentBlocks\Registry\ContentBlockRegistry;
use TYPO3\CMS\Core\Package\AbstractServiceProvider;

class ServiceProvider extends AbstractServiceProvider
{

protected static function getPackagePath(): string
{
return __DIR__ . '/../';
}

protected static function getPackageName(): string
{
return 'sinso/webcomponents';
}

public function getFactories(): array
{
return [];
}

public function getExtensions(): array
{
return [
'content-blocks.typoscript' => 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 = <<<HEREDOC
tt_content.{$typeDefinition->getTypeName()} >
tt_content.{$typeDefinition->getTypeName()} = WEBCOMPONENT
tt_content.{$typeDefinition->getTypeName()}.componentFolder = $contentBlockExtPath
HEREDOC;
$typoScriptArrayObject->append($typoScript);
}
}

return $typoScriptArrayObject;
}
}
11 changes: 3 additions & 8 deletions Classes/ViewHelpers/RenderViewHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
3 changes: 3 additions & 0 deletions Configuration/Services.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ services:
autoconfigure: true
public: false

Sinso\Webcomponents\:
resource: '../Classes/*'

Sinso\Webcomponents\ContentObject\WebcomponentContentObject:
tags:
- name: frontend.contentobject
Expand Down
5 changes: 4 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@
"description": "Render Web Components",
"extra": {
"typo3/cms": {
"extension-key": "webcomponents"
"extension-key": "webcomponents",
"Package": {
"serviceProvider": "Sinso\\Webcomponents\\ServiceProvider"
}
}
},
"autoload": {
Expand Down