Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/refactor component data #144

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
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
89 changes: 89 additions & 0 deletions Classes/Domain/Model/Component.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
<?php

declare(strict_types=1);

namespace SMS\FluidComponents\Domain\Model;

class Component
{
protected string $namespace;
protected string $package;
protected string $name;
protected string $file;

protected array $data = [];
protected ?string $class = null;
protected ?string $prefix = null;

public function __construct(
string $fullNamespace,
string $package,
string $name,
string $file
) {
$this->namespace = $fullNamespace;
$this->package = $package;
$this->name = $name;
$this->file = $file;
}

public function getNamespace(): string
{
return $this->namespace;
}

public function getPackage(): string
{
return $this->package;
}

public function getName(): string
{
return $this->name;
}

public function getPath(): string
{
return dirname($this->file);
}

public function getFile(): string
{
return $this->file;
}

public function getData(): array
{
return $this->data;
}

public function setData(array $data): void
{
$this->data = $data;
}

public function getClass(): ?string
{
return $this->class;
}

public function setClass(string $class): void
{
$this->class = $class;
}

public function getPrefix(): ?string
{
return $this->prefix;
}

public function setPrefix(string $prefix): void
{
$this->prefix = $prefix;
}

public function __toString(): string
{
return $this->file;
}
}
117 changes: 28 additions & 89 deletions Classes/Fluid/ViewHelper/ComponentRenderer.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@

use Psr\Container\ContainerInterface;
use SMS\FluidComponents\Domain\Model\RequiredSlotPlaceholder;
use SMS\FluidComponents\Domain\Model\Component;
use SMS\FluidComponents\Domain\Model\Slot;
use SMS\FluidComponents\Interfaces\ComponentAware;
use SMS\FluidComponents\Interfaces\EscapedParameter;
use SMS\FluidComponents\Interfaces\RenderingContextAware;
use SMS\FluidComponents\Utility\ComponentArgumentConverter;
use SMS\FluidComponents\Service\ComponentDataLoader;
use SMS\FluidComponents\Utility\ComponentLoader;
use SMS\FluidComponents\Utility\ComponentPrefixer\ComponentPrefixerInterface;
use SMS\FluidComponents\Utility\ComponentPrefixer\GenericComponentPrefixer;
use SMS\FluidComponents\Utility\ComponentSettings;
use SMS\FluidComponents\ViewHelpers\ComponentViewHelper;
use SMS\FluidComponents\ViewHelpers\ContentViewHelper;
Expand Down Expand Up @@ -49,6 +49,13 @@ class ComponentRenderer extends AbstractViewHelper
*/
protected $componentNamespace;

/**
* Object containing information about the current component
*
* @var Component
*/
protected Component $component;

/**
* Cache for component template instance used for rendering
*
Expand All @@ -66,13 +73,6 @@ class ComponentRenderer extends AbstractViewHelper
*/
protected static $componentArgumentDefinitionCache = [];

/**
* Cache of component prefixer objects
*
* @var array
*/
protected static $componentPrefixerCache = [];

/**
* Components are HTML markup which should not be escaped
*
Expand All @@ -97,6 +97,11 @@ class ComponentRenderer extends AbstractViewHelper
*/
protected ComponentSettings $componentSettings;

/**
* @var ComponentDataLoader
*/
protected ComponentDataLoader $componentDataLoader;

/**
* @var ComponentArgumentConverter
*/
Expand All @@ -116,11 +121,13 @@ class ComponentRenderer extends AbstractViewHelper
public function __construct(
ComponentLoader $componentLoader,
ComponentSettings $componentSettings,
ComponentDataLoader $componentDataLoader,
ComponentArgumentConverter $componentArgumentConverter,
ContainerInterface $container
) {
$this->componentLoader = $componentLoader;
$this->componentSettings = $componentSettings;
$this->componentDataLoader = $componentDataLoader;
$this->componentArgumentConverter = $componentArgumentConverter;
$this->container = $container;
}
Expand All @@ -134,39 +141,20 @@ public function __construct(
public function setComponentNamespace($componentNamespace)
{
$this->componentNamespace = $componentNamespace;
$this->component = $this->componentLoader->findComponent($this->componentNamespace);
return $this;
}

/**
* Returns the namespace of the component the viewhelper renders
*
* @return void
* @return string
*/
public function getComponentNamespace()
{
return $this->componentNamespace;
}

/**
* Returns the component prefix
*
* @return string
*/
public function getComponentClass()
{
return $this->getComponentPrefixer()->prefix($this->componentNamespace);
}

/**
* Returns the component prefix
*
* @return string
*/
public function getComponentPrefix()
{
return $this->getComponentClass() . $this->getComponentPrefixer()->getSeparator();
}

/**
* Renders the component the viewhelper is responsible for
* TODO this can probably be improved by using renderComponent() directly
Expand All @@ -193,12 +181,11 @@ public function render()
}
$variableContainer = $renderingContext->getVariableProvider();

// Load additional data for component
$this->componentDataLoader->loadData($this->component);

// Provide information about component to renderer
$variableContainer->add('component', [
'namespace' => $this->componentNamespace,
'class' => $this->getComponentClass(),
'prefix' => $this->getComponentPrefix(),
]);
$variableContainer->add('component', $this->component);
$variableContainer->add('settings', $this->componentSettings);

// Provide supplied arguments from component call to renderer
Expand Down Expand Up @@ -228,12 +215,10 @@ public function render()

// Initialize component rendering template
if (!isset($this->parsedTemplate)) {
$componentFile = $this->componentLoader->findComponent($this->componentNamespace);

$this->parsedTemplate = $renderingContext->getTemplateParser()->getOrParseAndStoreTemplate(
$this->getTemplateIdentifier($componentFile),
function () use ($componentFile) {
return file_get_contents($componentFile);
$this->getTemplateIdentifier($this->component->getFile()),
function () {
return file_get_contents($this->component->getFile());
}
);
}
Expand Down Expand Up @@ -459,12 +444,10 @@ protected function initializeComponentParams()
{
$renderingContext = $this->getRenderingContext();

$componentFile = $this->componentLoader->findComponent($this->componentNamespace);

// Parse component template without using the cache
$parsedTemplate = $renderingContext->getTemplateParser()->parse(
file_get_contents($componentFile),
$this->getTemplateIdentifier($componentFile)
file_get_contents($this->component->getFile()),
$this->getTemplateIdentifier($this->component->getFile())
);

// Extract all component viewhelpers
Expand All @@ -476,7 +459,7 @@ protected function initializeComponentParams()
if (count($componentNodes) > 1) {
throw new Exception(sprintf(
'Only one component per file allowed in: %s',
$componentFile
$this->component->getFile()
), 1527779393);
}

Expand Down Expand Up @@ -607,50 +590,6 @@ protected function getTemplateIdentifier(string $pathAndFilename, string $prefix
);
}

/**
* Returns the prefixer object responsible for the current component namespaces
*
* @return ComponentPrefixerInterface
*/
protected function getComponentPrefixer()
{
if (!isset(self::$componentPrefixerCache[$this->componentNamespace])) {
if (isset($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['fluid_components']['prefixer']) &&
is_array($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['fluid_components']['prefixer'])
) {
arsort($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['fluid_components']['prefixer']);
foreach ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['fluid_components']['prefixer'] as $namespace => $prefixer) {
$namespace = ltrim($namespace, '\\');
if (strpos($this->componentNamespace, $namespace) === 0) {
$componentPrefixerClass = $prefixer;
break;
}
}
}

if (empty($componentPrefixerClass)) {
$componentPrefixerClass = GenericComponentPrefixer::class;
}

if ($this->container->has($componentPrefixerClass)) {
$componentPrefixer = $this->container->get($componentPrefixerClass);
} else {
$componentPrefixer = GeneralUtility::makeInstance($componentPrefixerClass);
}

if (!($componentPrefixer instanceof ComponentPrefixerInterface)) {
throw new Exception(sprintf(
'Invalid component prefixer: %s',
$componentPrefixerClass
), 1530608357);
}

self::$componentPrefixerCache[$this->componentNamespace] = $componentPrefixer;
}

return self::$componentPrefixerCache[$this->componentNamespace];
}

/**
* @return RenderingContext
*/
Expand Down
10 changes: 10 additions & 0 deletions Classes/Interfaces/ComponentDataProvider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

namespace SMS\FluidComponents\Interfaces;

use SMS\FluidComponents\Domain\Model\Component;

interface ComponentDataProvider
{
public function applyData(Component $component);
}
36 changes: 36 additions & 0 deletions Classes/Service/ComponentDataLoader.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?php

declare(strict_types=1);

namespace SMS\FluidComponents\Service;

use SMS\FluidComponents\Domain\Model\Component;
use TYPO3\CMS\Core\SingletonInterface;

class ComponentDataLoader implements SingletonInterface
{
private array $loadedComponents = [];
private iterable $dataProviders;

public function __construct(iterable $dataProviders)
{
$this->dataProviders = $dataProviders;
}

public function reset(): void
{
$this->loadedComponents = [];
}

public function loadData(Component $component): void
{
if (isset($this->loadedComponents[$component->getNamespace()])) {
return;
}

foreach ($this->dataProviders as $dataProvider) {
$dataProvider->applyData($component);
}
$this->loadedComponents[$component->getNamespace()] = true;
}
}
25 changes: 25 additions & 0 deletions Classes/Service/DataProvider/ComponentPrefixer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

declare(strict_types=1);

namespace SMS\FluidComponents\Service\DataProvider;

use SMS\FluidComponents\Domain\Model\Component;
use SMS\FluidComponents\Interfaces\ComponentDataProvider;

class ComponentPrefixer implements ComponentDataProvider
{
public function applyData(Component $component): void
{
if ($component->getPrefix() !== null) {
return;
}

$vendorName = substr($component->getPackage(), 0, strpos($component->getPackage(), '\\'));
$componentName = str_replace('\\', '', $component->getName());
$prefix = strtolower($vendorName) . $componentName;

$component->setClass($prefix);
$component->setPrefix($prefix . '_');
}
}
Loading