<?php
namespace App\Twig;
use App\Twig\Components\ComponentsMiddleware;
use Twig\Extension\AbstractExtension;
use Twig\TwigFunction;
/**
* Twig extension with adapt_attribute twig function.
*
* adapt_attribute can be used for any attribute of any markups in twig layer. This function is responsible for passing
* input and output thanks to lazy loading of proper handler.
* adapt_attribute has 2 parameters:
* - concatenation of key of handler (name of microfrontend component) and name of method (name of attribute) to which
* data have to be passed written in snake case and separated with "." (eg. download_files.items)
* - data which have to be handled.
*
* There are a lot of handlers. Single handler responses to single microfrontend component. Methods which are
* responsible for data handling must be suffixed with "Attribute" for better readability.
* Handling of common data eg. images, is encapsulated in traits which can be used in handlers eg. ImageTrait is used
* in many handlers because many components needs images.
*
* @example Breadcrumbs microfrontend components has some data to handle for its attribute social-media. So there is
* need to call adapt_attribute('breadcrumbs.social_media', data). Data will be passed to Breadcrumbs handler to
* socialMediaAttribute method.
*
* @author Michał Wiązek <michal.wiazek@makolab.com>
*/
class ComponentDataAdapterExtension extends AbstractExtension
{
private ComponentsMiddleware $componentMiddleware;
/**
* Constructor.
*/
public function __construct(ComponentsMiddleware $componentMiddleware)
{
$this->componentMiddleware = $componentMiddleware;
}
/**
* {@inheritDoc}
*/
public function getFunctions(): array
{
return [
new TwigFunction('adapt_attribute', [$this, 'adaptAttribute']),
];
}
/**
* Return structure and data fitting to frontend components.
*
* @param array $data
*
* @return mixed
*/
public function adaptAttribute(string $componentAttribute, array $data = null)
{
list($componentKey, $attribute) = explode('.', $componentAttribute);
$method = $this->snakeToCamel($attribute).'Attribute';
$preparedData = $this->componentMiddleware->getServiceLocator()->get($componentKey)->$method($data);
return $preparedData;
}
/**
* Convert snakeCase to camelCase.
*
* @param $snakeCase
*/
private function snakeToCamel($snakeCase): string
{
return lcfirst(str_replace(' ', '', ucwords(str_replace('_', ' ', $snakeCase))));
}
}