Score:0

Altering paragraph field within revision using preprocess hook

dk flag

I'm using a hook_preprocess function (hook_preprocess_entity_print) to alter the content within a paragraph field prior to rendering (replacing some strings based on a regex). This works great when I'm working on the node, but not when I'm trying to do the same on a revision of the node.

This works for the node:

/**
 * Implements hook_preprocess_entity_print().
 */
function mymodule_preprocess_entity_print(&$variables) {
  $route = \Drupal::routeMatch();
  $entity_id = $route->getParameter('entity_id');
  $node = \Drupal::entityTypeManager()->getStorage('node')->load($entity_id);
  $type = $node->getType();
  if ($type === 'product_child') {
    foreach ($node->get('field_submittal_wysiwyg') as $paragraph) {
      $type = $paragraph->entity->getType();
      switch ($type) {
        case 'submittal_2_col':
          $field_submittal_text = $paragraph->entity->field_submittal_text_1->value;
          $field_submittal_text = mymodule_token_replace($field_submittal_text, $variables);
          $paragraph->entity->field_submittal_text_1->value = $field_submittal_text;
          break;
      }
    }
  }
}

When I decided to make these same replacements work when rendering a revision of the node, I tried this first:

/**
 * Implements hook_preprocess_entity_print().
 */
function mymodule_preprocess_entity_print(&$variables) {
  $route = \Drupal::routeMatch();
  $entity_id = $route->getParameter('entity_id');
  $revision_id = $route->getParameter('revision_id');
  $node_revision = \Drupal::entityTypeManager()->getStorage('node')->loadRevision($revision_id);
  $type = $node_revision->getType();
  if ($type === 'product_child') {
    foreach ($node_revision->get('field_submittal_wysiwyg') as $paragraph) {
      $type = $paragraph->entity->getType();
      switch ($type) {
        case 'submittal_2_col':
          $field_submittal_text = $paragraph->entity->field_submittal_text_1->value;
          $field_submittal_text = mymodule_token_replace($field_submittal_text, $variables);
          $paragraph->entity->field_submittal_text_1->value = $field_submittal_text;
          break;
      }
    }

  }
}

I can confirm that I'm getting the correct values for the draft revision in $field_submittal_text. But when I try to set the value of the paragraph, it works only for the published node.

I figured I must not be loading the paragraph revisions referenced within the node revisions. So I then tried to address that:

/**
 * Implements hook_preprocess_entity_print().
 */
function mymodule_preprocess_entity_print(&$variables) {
  $route = \Drupal::routeMatch();
  $entity_id = $route->getParameter('entity_id');
  $revision_id = $route->getParameter('revision_id');
  $node_revision = \Drupal::entityTypeManager()->getStorage('node')->loadRevision($revision_id);
  $type = $node_revision->getType();
  if ($type === 'product_child') {
    $field_submittal_wysiwyg = $node_revision->field_submittal_wysiwyg->referencedEntities();
    foreach ($field_submittal_wysiwyg as $paragraph) {
      $paragraph_type = $paragraph->getType();
      switch ($paragraph_type) {
        case 'submittal_2_col':
          $field_submittal_text = $paragraph->field_submittal_text_1->value;
          $field_submittal_text = mymodule_token_replace($field_submittal_text, $variables);
          $paragraph->field_submittal_text_1->value = $field_submittal_text;
          break;
      }
    }
  }
}

Again, I can confirm that I'm getting the correct values for $field_submittal_text based on the revision that I'm trying to load. But the last line before the break isn't changing what is rendered.

What do I need to do to set the value of the paragraph field for a revision before rendering?

ETA: I'm attempting to replace some product attribute values in several paragraph WYSIWYG fields with values from another field, based on a product_id sent in through the route parameters. So I need access to multiple fields in order to do these replacements.

leymannx avatar
ne flag
Doesn't the `$variables` already contain the entity and by that also the parent entity? That means there's no need to get the node from the route. Getting the parent entity from the `$variables` also means your code would work even when you are not viewing a node on its canonical URL (in views for example).
dk flag
It's not surprising that I made it more complicated than it needs to be. For some reason, accessing entities programmatically has confused me. Thanks for the advice; I'll look into stripping it down to changing $variables directly.
dk flag
So far, in `$variables`, I'm able to find only the published versions of the paragraph fields I'm seeking to alter. I can't locate the draft version. This is the case regardless of whether I'm viewing the published revision or a draft. This is why I went to the extra step of loading the node_revision.
dk flag
(I do wonder if I might be missing the values I'm seeking due to a max_depth for my `dump()` statement.)
Score:1
cn flag

The purpose of a preprocess hook is to prepare the variables printed in the template. Check the {{...}} statements in the Twig template.

Some other options:

  • Look for a different template that prints the variable you want to change.
  • Create a custom text filter and add it to the text format.
  • Add a #post_render callback, see How to alter page content?
dk flag
I added a little more context to my question. I'm trying to change some text strings (essentially token strings) in a few paragraph wysiwyg fields with values from another field (product data text field) based on a product_id sent in the route parameters. So I need access to multiple fields at once. All this needs to occur prior to handing over to entity_print to render the PDF. I handled this for the published revision of the node using this preprocess hook; now just trying to make the same thing work for a draft revision.
4uk4 avatar
cn flag
Instead of the futile attempt to change objects out of scope in a preprocess hook, you might consider storing the computed data in a new field. The simplest Drupal way for a computed field is an extra field, if you don't want to define a custom field plugin. See https://www.webomelette.com/creating-pseudo-fields-drupal-8. You can also consider putting the extra field inside the paragraph type, it's easier to access the different fields (read-only!) from there.
dk flag
I was able to accomplish what I needed with `hook_ENTITY_TYPE_view()`. Thanks!
I sit in a Tesla and translated this thread with Ai:

mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.