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

[Twig-Bridge] [RFC] Allow to declare twig extensions via config ? #53403

Open
VincentLanglet opened this issue Jan 4, 2024 · 3 comments
Open
Labels
RFC RFC = Request For Comments (proposals about features that you want to be discussed) TwigBridge TwigBundle

Comments

@VincentLanglet
Copy link
Contributor

VincentLanglet commented Jan 4, 2024

Description

Maybe I misunderstood some things about TwigRuntime but when I create one I have to do:

  • One runtime, with some services injections and a method doThings.
  • One twigExtension with the code:
new TwigFunction('doThings', [MyRuntime::class, 'doThings']),

This create duplicate classes.

Eventually, one thing I can do is to have multiple runtimes, but one single twigExtension calling all of them.

new TwigFunction('doThings', [MyRuntime::class, 'doThings']),
new TwigFunction('doOtherThings', [MyOtherRuntime::class, 'doOtherThings']),

But I was wondering the purpose of this twigExtension in such case and if this couldn't be generated by some config directly:

framework:
    twig:
        functions:
        filters:
        tests:

What do you think about such feature ?

@carsonbot carsonbot added the RFC RFC = Request For Comments (proposals about features that you want to be discussed) label Jan 4, 2024
@stof
Copy link
Member

stof commented Jan 4, 2024

See twigphp/Twig#3916 where this is in progress (we will need a configuration layer in TwigBundle leveraging this new code, once the foundation is merged in Twig)

@stof
Copy link
Member

stof commented Jan 4, 2024

Actually, the TwigBundle PR already exist at #52748

@94noni
Copy link
Contributor

94noni commented Jan 5, 2024

It would indeed simplify twig custom registration logic (perhaps not usefull when attributes are in place)

At work we do have an internal sort of such thing:

# service.yaml
FrontBundle\Component\CMS\Twig\ConfigurableExtension:
        $globals: []
        $filters:
            app_format_price: ['@CoreBundle\Twig\Runtime\MoneyFormatterRuntime', 'formatPrice']
            app_format_html_price:
                callable: ['@CoreBundle\Twig\Runtime\MoneyFormatterRuntime', 'htmlPrice']
                options:
                    is_safe: ['html']
        $functions:
            app_get_product: ['@FrontBundle\Twig\Runtime\ProductHelperRuntime', 'getProduct']
            app_image_url_for_path: ['@CoreBundle\Twig\Runtime\ImageProviderRuntime', 'getImageUrlForPath']
            app_render_offer_discount:
                callable: ['@CoreBundle\Twig\Runtime\UtilsRuntime', 'renderDiscount']
                options:
                    needs_environment: true

with class as service extending the twig abstract extension

Code

<?php

declare(strict_types=1);

namespace FrontBundle\Component\CMS\Twig;

use Twig\Extension\AbstractExtension;
use Twig\TwigFilter;
use Twig\TwigFunction;

class ConfigurableExtension extends AbstractExtension
{
    /**
     * @var string[]
     */
    private $globals;

    /**
     * @var callable[]
     */
    private $filters;

    /**
     * @var callable[]
     */
    private $functions;

    public function __construct(array $globals, iterable $filters, iterable $functions)
    {
        $this->globals = $globals;
        $this->filters = $filters;
        $this->functions = $functions;
    }

    public function getGlobals()
    {
        return $this->globals;
    }

    public function getFilters(): array
    {
        $arr = [];
        foreach ($this->filters as $name => $callable) {
            if (isset($callable['callable'])) {
                $arr[] = new TwigFilter($name, $callable['callable'], $callable['options'] ?? []);
            } else {
                $arr[] = new TwigFilter($name, $callable);
            }
        }

        return $arr;
    }

    public function getFunctions(): array
    {
        $arr = [];
        foreach ($this->functions as $name => $callable) {
            if (isset($callable['callable'])) {
                $arr[] = new TwigFunction($name, $callable['callable'], $callable['options'] ?? []);
            } else {
                $arr[] = new TwigFunction($name, $callable);
            }
        }

        return $arr;
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
RFC RFC = Request For Comments (proposals about features that you want to be discussed) TwigBridge TwigBundle
Projects
None yet
Development

No branches or pull requests

5 participants