Refactor Twig extensions to use attributes for declaring functions and filters, remove AbstractExtension inheritance, and clean up related service definitions.

This commit is contained in:
2025-12-19 12:23:20 +01:00
parent 0d42ed9262
commit 741f655cfc
19 changed files with 72 additions and 244 deletions

View File

@@ -22,7 +22,7 @@ use Twig\TwigFunction;
* * chill_custom_field_widget : to render the value of the custom field,
* * chill_custom_field_label : to render the label of the custom field,.
*/
class CustomFieldRenderingTwig extends AbstractExtension
class CustomFieldRenderingTwig
{
/**
* @var array<string, string> The default parameters
@@ -33,29 +33,6 @@ class CustomFieldRenderingTwig extends AbstractExtension
public function __construct(private readonly CustomFieldsHelper $customFieldsHelper) {}
/**
* (non-PHPdoc).
*
* @see Twig_Extension::getFunctions()
*/
#[\Override]
public function getFunctions()
{
return [
new TwigFunction('chill_custom_field_widget', $this->renderWidget(...), [
'is_safe' => [
'html',
],
]),
new TwigFunction('chill_custom_field_label', $this->renderLabel(...), [
'is_safe' => [
'html',
],
'needs_environment' => true,
]),
];
}
/** (non-PHPdoc).
* @see Twig_ExtensionInterface::getName()
*/
@@ -79,6 +56,9 @@ class CustomFieldRenderingTwig extends AbstractExtension
*
* @return string HTML representation of the custom field label
*/
#[\Twig\Attribute\AsTwigFunction('chill_custom_field_label', isSafe: [
'html',
], needsEnvironment: true)]
public function renderLabel(Environment $env, CustomField $customField, array $params = []): string
{
$resolvedParams = array_merge($this->defaultParams, $params);
@@ -97,6 +77,9 @@ class CustomFieldRenderingTwig extends AbstractExtension
*
* @return string HTML representation of the custom field value, as described in the CustomFieldInterface. Is HTML safe
*/
#[\Twig\Attribute\AsTwigFunction('chill_custom_field_widget', isSafe: [
'html',
])]
public function renderWidget(array $fields, CustomField $customField, $documentType = 'html')
{
return $this->customFieldsHelper

View File

@@ -20,7 +20,7 @@ use Twig\TwigFunction;
* * chill_custom_fields_group_widget : to render the value of a custom field
* * group.
*/
final class CustomFieldsGroupRenderingTwig extends AbstractExtension
final class CustomFieldsGroupRenderingTwig
{
/**
* @var array<string, string|bool> The default parameters
@@ -38,24 +38,6 @@ final class CustomFieldsGroupRenderingTwig extends AbstractExtension
$this->defaultParams['show_empty'] = $showEmptyValues;
}
/**
* (non-PHPdoc).
*
* @see Twig_Extension::getFunctions()
*/
#[\Override]
public function getFunctions()
{
return [
new TwigFunction('chill_custom_fields_group_widget', $this->renderWidget(...), [
'is_safe' => [
'html',
],
'needs_environment' => true,
]),
];
}
/** (non-PHPdoc).
* @see Twig_ExtensionInterface::getName()
*/
@@ -81,6 +63,9 @@ final class CustomFieldsGroupRenderingTwig extends AbstractExtension
* @return string HTML representation of the custom field group value, as described in
* the CustomFieldInterface. Is HTML safe
*/
#[\Twig\Attribute\AsTwigFunction('chill_custom_fields_group_widget', isSafe: [
'html',
], needsEnvironment: true)]
public function renderWidget(Environment $env, array $fields, $customFielsGroup, $documentType = 'html', array $params = []): string
{
$resolvedParams = array_merge($this->defaultParams, $params);

View File

@@ -102,15 +102,11 @@ services:
class: Chill\CustomFieldsBundle\Templating\Twig\CustomFieldRenderingTwig
arguments:
- "@chill.custom_field.helper"
tags:
- { name: twig.extension }
chill.custom_field.twig.custom_fields_group_rendering:
class: Chill\CustomFieldsBundle\Templating\Twig\CustomFieldsGroupRenderingTwig
arguments:
- "%chill_custom_fields.show_empty_values%"
tags:
- { name: twig.extension }
chill.custom_field.custom_field_long_choice:
class: Chill\CustomFieldsBundle\CustomFields\CustomFieldLongChoice

View File

@@ -19,7 +19,7 @@ use Twig\TwigFunction;
* Class TwigCRUDResolver
* Twig filters to display data in crud template.
*/
class TwigCRUDResolver extends AbstractExtension
class TwigCRUDResolver
{
/**
* @var Resolver
@@ -39,31 +39,13 @@ class TwigCRUDResolver extends AbstractExtension
*
* @return string
*/
#[\Twig\Attribute\AsTwigFunction('chill_crud_config', isSafe: ['html'])]
public function getConfig($configKey, $crudName, $action = null)
{
return $this->resolver->getConfigValue($configKey, $crudName, $action);
}
/**
* @return array|TwigFunction[]
*/
#[\Override]
public function getFunctions()
{
return [
new TwigFunction(
'chill_crud_config',
$this->getConfig(...),
['is_safe' => 'html']
),
new TwigFunction(
'chill_crud_action_exists',
$this->hasAction(...),
[]
),
];
}
#[\Twig\Attribute\AsTwigFunction('chill_crud_action_exists')]
public function hasAction($crudName, $action): bool
{
return $this->resolver->hasAction($crudName, $action);

View File

@@ -18,28 +18,14 @@ use Twig\TwigFunction;
/**
* add twig function to render pagination.
*/
class ChillItemsPerPageTwig extends AbstractExtension
class ChillItemsPerPageTwig
{
#[\Override]
public function getFunctions()
{
return [
new TwigFunction(
'chill_items_per_page',
$this->paginationRender(...),
[
'needs_environment' => true,
'is_safe' => ['html'],
]
),
];
}
public function getName()
{
return 'chill_items_per_page';
}
#[\Twig\Attribute\AsTwigFunction('chill_items_per_page', needsEnvironment: true, isSafe: ['html'])]
public function paginationRender(
Environment $env,
PaginatorInterface $paginator,

View File

@@ -18,32 +18,18 @@ use Twig\TwigFunction;
/**
* add twig function to render pagination.
*/
class ChillPaginationTwig extends AbstractExtension
class ChillPaginationTwig
{
final public const string LONG_TEMPLATE = '@ChillMain/Pagination/long.html.twig';
final public const string SHORT_TEMPLATE = '@ChillMain/Pagination/short.html.twig';
#[\Override]
public function getFunctions()
{
return [
new TwigFunction(
'chill_pagination',
$this->paginationRender(...),
[
'needs_environment' => true,
'is_safe' => ['html'],
]
),
];
}
public function getName()
{
return 'chill_pagination';
}
#[\Twig\Attribute\AsTwigFunction('chill_pagination', needsEnvironment: true, isSafe: ['html'])]
public function paginationRender(
Environment $env,
PaginatorInterface $paginator,

View File

@@ -18,7 +18,7 @@ use Twig\TwigFunction;
/**
* Add the filter 'chill_menu'.
*/
class MenuTwig extends AbstractExtension
class MenuTwig
{
/**
* the default parameters for chillMenu.
@@ -45,6 +45,7 @@ class MenuTwig extends AbstractExtension
* @param mixed[] $params
*/
#[\Deprecated(message: 'link: see https://redmine.champs-libres.coop/issues/179 for more informations')]
#[\Twig\Attribute\AsTwigFunction('chill_menu', isSafe: ['html'], needsEnvironment: true)]
public function chillMenu(Environment $env, $menuId, array $params = []): string
{
$resolvedParams = array_merge($this->defaultParams, $params);
@@ -62,20 +63,6 @@ class MenuTwig extends AbstractExtension
return $env->render($layout, $resolvedParams);
}
#[\Override]
public function getFunctions()
{
return [new TwigFunction(
'chill_menu',
$this->chillMenu(...),
[
'is_safe' => ['html'],
'needs_environment' => true,
]
),
];
}
public function getName()
{
return 'chill_menu';

View File

@@ -20,7 +20,7 @@ use Twig\TwigFilter;
*
* This filter replace the char " by ""
*/
class CSVCellTwig extends AbstractExtension
class CSVCellTwig
{
/**
* Replace into a string the char " by "".
@@ -29,30 +29,12 @@ class CSVCellTwig extends AbstractExtension
*
* @return string the safe string
*/
#[\Twig\Attribute\AsTwigFilter('csv_cell', isSafe: ['html'])]
public function csvCellFilter($content): string|array
{
return str_replace('"', '""', $content);
}
/**
* Returns a list of filters to add to the existing list.
*
* (non-PHPdoc)
*
* @see Twig_Extension::getFilters()
*/
#[\Override]
public function getFilters()
{
return [
new TwigFilter(
'csv_cell',
$this->csvCellFilter(...),
['is_safe' => ['html']]
),
];
}
/**
* Returns the name of the extension.
*

View File

@@ -17,7 +17,7 @@ use Twig\TwigFilter;
/**
* Render markdown.
*/
final class ChillMarkdownRenderExtension extends AbstractExtension
final class ChillMarkdownRenderExtension
{
/**
* @var \Parsedown
@@ -30,16 +30,7 @@ final class ChillMarkdownRenderExtension extends AbstractExtension
$this->parsedown->setSafeMode(true);
}
#[\Override]
public function getFilters(): array
{
return [
new TwigFilter('chill_markdown_to_html', $this->renderMarkdownToHtml(...), [
'is_safe' => ['html'],
]),
];
}
#[\Twig\Attribute\AsTwigFilter('chill_markdown_to_html', isSafe: ['html'])]
public function renderMarkdownToHtml(?string $var): string
{
return $this->parsedown->parse((string) $var);

View File

@@ -16,19 +16,8 @@ use Twig\Environment;
use Twig\Extension\AbstractExtension;
use Twig\TwigFilter;
class ChillTwigHelper extends AbstractExtension
class ChillTwigHelper
{
#[\Override]
public function getFilters()
{
return [
new TwigFilter('chill_print_or_message', $this->printOrMessage(...), [
'needs_environment' => true,
'is_safe' => ['html', 'html_attrs'],
]),
];
}
/**
* Print `value` inside a template, or, if $value is empty,
* print $message.
@@ -49,6 +38,7 @@ class ChillTwigHelper extends AbstractExtension
* @param string $message
* @param string $template
*/
#[\Twig\Attribute\AsTwigFilter('chill_print_or_message', needsEnvironment: true, isSafe: ['html', 'html_attrs'])]
public function printOrMessage(
Environment $twig,
$value,

View File

@@ -13,9 +13,7 @@ namespace Chill\MainBundle\Templating;
use Symfony\Bridge\Twig\Extension\RoutingExtension;
use Symfony\Component\HttpFoundation\RequestStack;
use Twig\Extension\AbstractExtension;
use Twig\Node\Node;
use Twig\TwigFilter;
use Twig\TwigFunction;
/**
@@ -23,25 +21,12 @@ use Twig\TwigFunction;
*
* The logic of the function is based on the original routing extension.
*/
class ChillTwigRoutingHelper extends AbstractExtension
final readonly class ChillTwigRoutingHelper
{
/**
* @var RoutingExtension
*/
protected $originalExtension;
/**
* @var RequestStack
*/
protected $requestStack;
public function __construct(
RequestStack $requestStack,
RoutingExtension $originalExtension,
) {
$this->requestStack = $requestStack;
$this->originalExtension = $originalExtension;
}
private RequestStack $requestStack,
private RoutingExtension $originalExtension,
) {}
public function getFunctions(): array
{
@@ -75,20 +60,6 @@ class ChillTwigRoutingHelper extends AbstractExtension
return $this->originalExtension->getPath($name, $params, $relative);
}
public function getFilters(): array
{
return [
new TwigFilter('chill_return_path_label', $this->getLabelReturnPath(...)),
];
}
public function getLabelReturnPath($default)
{
$request = $this->requestStack->getCurrentRequest();
return $request->query->get('returnPathLabel', null) ?? $default;
}
/**
* Build an url with a returnPath parameter to current page.
*

View File

@@ -0,0 +1,29 @@
<?php
declare(strict_types=1);
/*
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\MainBundle\Templating;
use Symfony\Component\HttpFoundation\RequestStack;
final readonly class ChillTwigRoutingHelperLabel
{
public function __construct(
private RequestStack $requestStack,
) {}
#[\Twig\Attribute\AsTwigFilter('chill_return_path_label')]
public function getLabelReturnPath($default): string
{
$request = $this->requestStack->getCurrentRequest();
return $request->query->get('returnPathLabel', null) ?? $default;
}
}

View File

@@ -17,31 +17,17 @@ use Twig\TwigFilter;
/**
* Class ChillEntityRenderExtension.
*/
class ChillEntityRenderExtension extends AbstractExtension
class ChillEntityRenderExtension
{
public function __construct(private readonly ChillEntityRenderManagerInterface $renderManager) {}
/**
* @return array|TwigFilter[]
*/
#[\Override]
public function getFilters()
{
return [
new TwigFilter('chill_entity_render_string', $this->renderString(...), [
'is_safe' => ['html'],
]),
new TwigFilter('chill_entity_render_box', $this->renderBox(...), [
'is_safe' => ['html'],
]),
];
}
#[\Twig\Attribute\AsTwigFilter('chill_entity_render_box', isSafe: ['html'])]
public function renderBox(?object $entity, array $options = []): string
{
return $this->renderManager->renderBox($entity, $options);
}
#[\Twig\Attribute\AsTwigFilter('chill_entity_render_string', isSafe: ['html'])]
public function renderString(?object $entity, array $options = []): string
{
return $this->renderManager->renderString($entity, $options);

View File

@@ -20,28 +20,19 @@ use Twig\Error\SyntaxError;
use Twig\Extension\AbstractExtension;
use Twig\TwigFilter;
class Templating extends AbstractExtension
class Templating
{
public function __construct(
private readonly RequestStack $requestStack,
private readonly FilterOrderGetActiveFilterHelper $filterOrderGetActiveFilterHelper,
) {}
#[\Override]
public function getFilters(): array
{
return [
new TwigFilter('chill_render_filter_order_helper', $this->renderFilterOrderHelper(...), [
'needs_environment' => true, 'is_safe' => ['html'],
]),
];
}
/**
* @throws SyntaxError
* @throws RuntimeError
* @throws LoaderError
*/
#[\Twig\Attribute\AsTwigFilter('chill_render_filter_order_helper', needsEnvironment: true, isSafe: ['html'])]
public function renderFilterOrderHelper(
Environment $environment,
FilterOrderHelper $helper,

View File

@@ -13,8 +13,8 @@ namespace Chill\MainBundle\Templating\Widget;
use Chill\MainBundle\Templating\Events\DelegatedBlockRenderingEvent;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Twig\DeprecatedCallableInfo;
use Twig\Environment;
use Twig\Extension\AbstractExtension;
use Twig\TwigFunction;
/**
@@ -40,7 +40,7 @@ use Twig\TwigFunction;
* `Chill\MainBundle\Templating\Events\DelegatedBlockRenderingEvent`
* for usage of this event class
*/
class WidgetRenderingTwig extends AbstractExtension
class WidgetRenderingTwig
{
/**
* @var EventDispatcherInterface
@@ -83,8 +83,7 @@ class WidgetRenderingTwig extends AbstractExtension
$this->widget[$place][$ordering] = [$widget, $config];
}
#[\Override]
public function getFunctions()
public function getFunctions(): array
{
return [
new TwigFunction(
@@ -96,11 +95,6 @@ class WidgetRenderingTwig extends AbstractExtension
'deprecated' => true, 'alternative' => 'chill_widget',
]
),
new TwigFunction(
'chill_widget',
$this->renderingWidget(...),
['is_safe' => ['html'], 'needs_environment' => true]
),
];
}
@@ -109,7 +103,8 @@ class WidgetRenderingTwig extends AbstractExtension
return 'chill_main_widget';
}
public function renderingWidget(Environment $env, $block, array $context = [])
#[\Twig\Attribute\AsTwigFunction('chill_widget', needsEnvironment: true, isSafe: ['html'], deprecationInfo: new DeprecatedCallableInfo('chill-project/chill-bundles', '3.0'))]
public function renderingWidget(Environment $env, $block, array $context = []): string
{
// get the content of widgets
$content = '';

View File

@@ -17,5 +17,3 @@ services:
Chill\MainBundle\CRUD\Templating\TwigCRUDResolver:
arguments:
$resolver: '@Chill\MainBundle\CRUD\Resolver\Resolver'
tags:
- { name: twig.extension }

View File

@@ -16,10 +16,6 @@ services:
chill_main.paginator.twig_extensions:
class: Chill\MainBundle\Pagination\ChillPaginationTwig
tags:
- { name: twig.extension }
chill_main.paginator.items_per_page.twig_extensions:
class: Chill\MainBundle\Pagination\ChillItemsPerPageTwig
tags:
- { name: twig.extension }

View File

@@ -20,8 +20,6 @@ services:
chill.main.twig.chill_menu:
class: Chill\MainBundle\Routing\MenuTwig
tags:
- { name: twig.extension }
Chill\MainBundle\Routing\ChillUrlGenerator: ~

View File

@@ -20,17 +20,13 @@ services:
# tags:
# - { name: twig.extension }
Chill\MainBundle\Templating\ChillTwigHelper:
tags:
- { name: twig.extension }
Chill\MainBundle\Templating\ChillTwigHelper: ~
Chill\MainBundle\Templating\ChillTwigRoutingHelper:
arguments:
$originalExtension: '@twig.extension.routing'
autoconfigure: true
autowire: true
tags:
- { name: twig.extension }
Chill\MainBundle\Templating\ChillTwigRoutingHelperLabel: ~
Chill\MainBundle\Templating\Entity\ChillEntityRenderExtension:
autoconfigure: true