1

We are upgrading our sites one at a time from Drupal 8 to Drupal 9 and there is one line of code in our custom theme that is the last of our problems.

We get the following error on View that uses an exposed filter:

Drupal\Core\Security\UntrustedCallbackException: Render #pre_render callbacks must be methods of a class that implements \Drupal\Core\Security\TrustedCallbackInterface or be an anonymous function. The callback was MYSITE_form_alter_views_exposed_form_MYVIEW_pre_render. See https://www.drupal.org/node/2966725 in Drupal\Core\Render\Renderer->doTrustedCallback() (line 96 of core/lib/Drupal/Core/Security/DoTrustedCallbackTrait.php).

In the OURTHEME.theme file, we have this function:

/**
 * Custom form alter for events.
 */
function OURTHEME_form_alter_views_exposed_form_events_pre_render($form) {
  $fields = [
    'field_start_date_value',
    'field_end_date_value',
    'field_address_locality',
  ];
  foreach ($fields as $field) {
    $form[$field]['#title_display'] = 'after';
  }
  $form['field_date_range_end_value']['#prefix'] = '<div class="event-exposed-form">';
  $form['field_event_address_locality']['#suffix'] = '</div>';
  return $form;
}

And the function is called here (just a snippet of the code in this function):

/**
 * These are the alterations to forms variables before they are rendered.
 */
function OURTHEME_form_alter(&$form, &$form_state, $form_id) {
  if ($form_id == 'views_exposed_form' && strpos($form['#id'], 'views-exposed-form-events-') === 0) {
    $form['#pre_render'][] = 'OURTHEME_form_alter_views_exposed_form_events_pre_render';
  }
  return $form;
}

From what I could divine from the research I've done so far, it seems that normally whatever class these kinds of functions are utilized in have implemented Drupal's TrustedCallbackInterface. Unfortunately, the only information I have found has been throughout the various patches being applied to projects throughout Drupal.org, so I'm trying to cobble together a methodology from random applications of it.

Of course, there's the Drupal API page, but that's not especially helpful when it comes to actually putting the pieces together into a useful methodology without knowing the rest of the API like the back of your hand.

Does anyone know if there's any documentation on how to apply the TrustedCallbackInterface to a function that previously used $form['#pre_render'][], especially in THEME.theme which is not set up the same as any old custom class in a Module?

6
  • 1
    The error is right there - you are adding a function to pre_render that is not approved to be called. drupal.org/node/2966725
    – Kevin
    Jun 29, 2021 at 15:28
  • So, the answer is just "Don't try altering the form pre-render. Do what you need to do another way." ?
    – Loopy
    Jun 29, 2021 at 16:33
  • Look at the linked change record
    – Kevin
    Jun 29, 2021 at 16:33
  • The .theme file isn't a class. So I should create an src folder in my theme and move the code from my .theme file to a new class declaration?
    – Loopy
    Jun 29, 2021 at 16:36
  • 2
    Yes, see for example drupal.stackexchange.com/a/300204/47547. For a different callback type, but it shows a class implementing RenderCallbackInterface in a theme.
    – 4uk4
    Jun 29, 2021 at 19:35

1 Answer 1

3

You can do something like this:

in your new module my_prerenders in my_prerenders/src/ add a new class:

namespace Drupal\my_prerenders;

use Drupal\Core\Security\TrustedCallbackInterface;


class MyPreRenders implements TrustedCallbackInterface {

  /**
   * @inheritDoc
   */
  public static function trustedCallbacks() {
    return ['formAlterViewsExposedFormEventsPreRender'];
  }

  public function formAlterViewsExposedFormEventsPreRender($form) {
    $fields = [
    'field_start_date_value',
    'field_end_date_value',
    'field_address_locality',
    ];
    foreach ($fields as $field) {
      $form[$field]['#title_display'] = 'after';
    }
    $form['field_date_range_end_value']['#prefix'] = '<div class="event-exposed-form">';
    $form['field_event_address_locality']['#suffix'] = '</div>';
    return $form;
  }

}

In OURTHEME.theme you just have to use:

use Drupal\my_prerenders\MyPreRenders;

...
...

$form['#pre_render'][] = [MyPreRenders::class, 'formAlterViewsExposedFormEventsPreRender'];

instead of

$form['#pre_render'][] = 'OURTHEME_form_alter_views_exposed_form_events_pre_render';

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.