Problem/Motivation

Sometimes it can be useful to use an object with a custom __invoke() method as a #pre_render callback.
Currently such a callback is rejected in DoTrustedCallbackTrait::doTrustedCallback().

Steps to reproduce

The below example is a bit pointless, and will cause issues with serialization, but it's ok to reproduce the problem.

$element['#pre_render'][] = new class {
  function __invoke(array $element): array {
    return $element;
  }
};

Proposed resolution

We have two options:

  1. Support _any_ object with __invoke() method as #pre_render callback.
  2. Support object with __invoke() method, _if_ that object implements a specific interface, or the class or __invoke() method has a '#[TrustedCallback]' attribute.

The second option is required if:

  • There is a vector that would allow to inject an instance of an arbitrary class with __invoke() method into #pre_render, AND
  • There is or could be a class with __invoke() method that would cause security-relevant trouble if used in #pre_render.

Remaining tasks

User interface changes

Introduced terminology

API changes

Data model changes

Release notes snippet

Issue fork drupal-3498999

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

donquixote created an issue. See original summary.

quietone’s picture

Version: 11.1.x-dev » 11.x-dev
donquixote’s picture

An alternative would be to put #[TrustedCallback] on the class itself. Which means we would have to change the #[Attribute] attribute on that attribute class.
But I think it is simpler and less "special" to just have the attribute on the __invoke() method.

Version: 11.x-dev » main

Drupal core is now using the main branch as the primary development branch. New developments and disruptive changes should now be targeted to the main branch.

Read more in the announcement.