Make twig sandboxed again, and empower themers by injecting services

Created on 8 March 2023, over 1 year ago
Updated 19 April 2023, about 1 year ago

Problem/Motivation

Coming from ✨ Have a way to implement the a preprocess function per each SDC component (ideally in the same folder) Active . Although this is currently not actionable for SDC in core, i hope it can help with other decisions right now.

My gut feeling is that the current preprocess logic comes from a procedural and arrays mindset, and that more modern paradigms can help us in theming.
Currently, everything is (and has to be) prepared in render arrays, and the template can only assemble that pre-rendered items.

Sometimes this is not enough, and then some twig_extensions module adds some global function.
Using object methods in twig is strongly limited, and can only be extended via settings.php.

What if we inject services into templates like we do in the service container?
There are many possible services, but in the first round think: formatters.
While themes should not contain too much logic, this would be a nice way to hand over logic to themes (and power to themers).

Other issues this would solve

- Some modules like twig_tweak add global functions to each and every twig template. => By handing over that functions as service methods we can empower some themes while keeping sandboxing in place for others.
- Themes currently can construct and render arbitrary render arrays, which kills sandboxing and opens information disclosure security issues (e.g.: render an arbitrary view). => By handing over render array builder and renderer services we can solve that problem.
- Services can be altered. E.g. a URL or Date renderer may get improved markup.
- Sometimes theming depends on some data value, but the template only gets the data converted to render arrays, which leads to all kinds of kiten-killer solutions. => Here, the template gets the raw data, plus formatters or formatter factories.

In the end, this makes twig safer (via sandboxing), empower themers, and allow to alter services.

Proposed resolution

- Find and implement a way to whitelist object methods via an extension (i.e. without touching settings.php)
- Implement a way for a component template to require injected services (e.g. via frontmatter)
- Have some early adaptors work with that, add useful twig services, and document best practices
- Maybe deprecate other mechanisms, like global twig functions and maybe preprocess

Example

I doubt this is the best example, but the first that comes to my mind.

entity-component.twig

# FrontMatter yaml contains the analog of a service argument definition.
# Assume that twig.* services are whitelisted.
injected-services:
  entity_display_reposirory: twig.entity_display_reposirory
  formatter_factory: twig.date_formatter_factory
---
{# Render the entity like defined, but override the date formatter. #}
{% for field in entity %}
  {% if field.name == 'field_data' %}
    {{ formatter_factory.get('data', {'format': 'costum:Y-M-D'}).render(field) }}
  {% else %}
    {{ entity_display_reposirory.getFormatterForField(field).render(field) }}
  {% endif %}
{% endfor %}
🌱 Plan
Status

Closed: won't fix

Version

2.0

Component

Code

Created by

πŸ‡©πŸ‡ͺGermany geek-merlin Freiburg, Germany

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

Not all content is available!

It's likely this issue predates Contrib.social: some issue and comment data are missing.

  • Issue created by @geek-merlin
  • πŸ‡©πŸ‡ͺGermany geek-merlin Freiburg, Germany
  • e0ipso Can Picafort

    Ohh! This is a cool idea. I need to think more about it. It is likely something better fit for contrib, but this could indeed alleviate the need for pre-processors.

    Do you think they need to be services? Or could they be some other type of simpler patterns more approachable to front-end devs new to Drupal?

  • πŸ‡©πŸ‡ͺGermany geek-merlin Freiburg, Germany

    Great you resonate with it! And yes, it should mature in contrib, like cl / sdc.

    > Do you think they need to be services? Or could they be some other type of simpler patterns more approachable to front-end devs new to Drupal?

    I use the term service injection because it is a concept well-known to php devs. But i have no strong feelings how to name it.

    In the end it's about injecting helpful pieces of logic, and i can't think of a good alternative to object methods.

  • πŸ‡ΊπŸ‡ΈUnited States Dave Reid Nebraska πŸ‡ΊπŸ‡Έ
  • Status changed to Closed: won't fix about 1 year ago
  • e0ipso Can Picafort

    Although this is currently not actionable for SDC in core, i hope it can help with other decisions right now.

    Since this project a mirror of Drupal core's version, I think we should close this one. Maybe a separate contrib can address this.

Production build 0.69.0 2024