0

Background information for this question can be found here: How to have a different hero image per node?

I have written a custom block that takes the data from this "hero" paragraph and renders it within the region I want using custom templates that I've defined in the module file in hook_theme. I am using the node context definition to get the data within the "hero" paragraph that is on the node but when I go to the revisions listing and click through them, the wrong paragraph revision is not loaded in some cases.

Example:

  • Create new basic page with image 1 and save as draft
  • Edit, update with image 2 and save as published
  • Edit, update with image 3 and save as draft

In this scenario, if I go to the revisions listings for the node, revision 1 (that should have image 1) is showing image 2. Revisions 2 and 3 have the correct images though.

Relevant code for custom block plugin:

<?php

use Drupal\Core\Access\AccessResult;
use Drupal\Core\Block\BlockBase;
use Drupal\Core\Cache\Cache;
use Drupal\Core\Cache\CacheableMetadata;
use Drupal\Core\Entity\EntityTypeManager;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\Session\AccountInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Provides an 'Hero Block' block.
 *
 * @Block(
 *   id = "hero_block",
 *   admin_label = @Translation("Hero Block"),
 *   category = @Translation("Custom"),
 *   context_definitions = {
 *    "node" = @ContextDefinition("entity:node", label = @Translation("Node"))
 *   }
 * )
 */
class HeroBlock extends BlockBase implements ContainerFactoryPluginInterface {

  /**
   * The entity manager.
   *
   * @var \Drupal\Core\Entity\EntityTypeManager
   */
  private $entityTypeManager;

  /**
   * @param array $configuration
   * @param string $plugin_id
   * @param mixed $plugin_definition
   * @param \Drupal\Core\Routing\RouteMatchInterface
   * @param \Drupal\Core\Entity\EntityTypeManager
   */
  public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityTypeManager $entity_type_manager) {
    parent::__construct($configuration, $plugin_id, $plugin_definition);
    $this->entityTypeManager = $entity_type_manager;
  }

  /**
   * @param \Symfony\Component\DependencyInjection\ContainerInterface $container
   * @param array $configuration
   * @param string $plugin_id
   * @param mixed $plugin_definition
   *
   * @return static
   */
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
    return new static(
      $configuration,
      $plugin_id,
      $plugin_definition,
      $container->get('entity_type.manager')
    );
  }

  /**
   * {@inheritdoc}
   */
  public function defaultConfiguration() {
    return ['label_display' => FALSE];
  }

  /**
   * {@inheritDoc}
   */
  public function build() {

    $node = $this->getContextValue('node');

    if (!isset($node)
        || !isset($node->field_hero)
        || $node->field_hero->isEmpty()) {
      return [];
    }

    $heroParagraph = $node->field_hero->entity;

    if (!isset($heroParagraph)
        || $heroParagraph->field_layout->isEmpty()
        || $heroParagraph->field_hero->isEmpty()) {
      return [];
    }

    $build = [];
    
    $cacheable_metadata = CacheableMetadata::createFromRenderArray($build);
    $cacheable_metadata->addCacheableDependency($node);
    $cacheable_metadata->addCacheableDependency($heroParagraph);

    $media = $heroParagraph->field_hero->entity;

    if (isset($media)) {
      $cacheable_metadata->addCacheableDependency($media);

      if ($media->bundle() === 'image') {
        $this->setImageVars($build, $media);
      } else {
        $this->setVideoVars($build, $media);
      }

      if (isset($build['#media']) || isset($build['#is_video'])) {
        $build['#theme'] = $heroParagraph->field_layout->value;

        $this->setTemplateVars($build, $heroParagraph);
      }
    }

    $cacheable_metadata->applyTo($build);

    return $build;
  }

Obviously based on my problem, I'm assuming I'm either not loading the paragraph revisions correctly, not loading the node revisions correctly, or the context value is not correct for some reason. I'm not sure which one and I've tried a few different ways of loading the paragraph or node using \Drupal::routeMatch()->getParameter('node_revision') if its there instead of using $this->getContextValue('node') or checking the node to see if its the latest revision, default revision, or something else but can't seem to get all of the revisions to display as expected whichever way I try.

5
  • A few things to clarify. Did you place the block after adding the context definition? This is important because the context definition is added to the block config when placing the block. Does your block plugin receive the correct node revision? Output the node title and change the title in each revision. Then get the paragraph via $node->field_paragraph->entity and check the revision again. The if-else is not necessary.
    – 4uk4
    Sep 19, 2023 at 15:52
  • Yes, I placed the block after adding the context definition. Yes, it seems as though the block plugin is getting the correct node revision. I just made a basic page, revision 1 I created a draft with node title "title 1", edited and updated the title to "title 2" saved as draft again, edited and updated the title to "title 3" saved as published, and lastly edited and updated the title to "title 4" and saved as draft. All of these showed up correctly and the title was updated as expected.
    – Jordan
    Sep 19, 2023 at 16:05
  • The weird behavior still is happening when I go to the revisions listing and click through the links there. I added a heading to the hero paragraph field for each of these at the same time and updated them when I updated the title. For the first revision the heading is showing up as "heading 2" (not "heading 1"), the second is showing as "heading 3" (not "heading 2"), and the last two revisions are showing up with the correct headings ("heading 3" and "heading 4" respectively). I'll get the paragraph with $node-field_hero->entity and try again now.
    – Jordan
    Sep 19, 2023 at 16:07
  • I removed the if else and got the paragraph with $node->field_hero->entity; and everything shows up correctly on save but when I go to the revisions and click through them again, revision 1 has "title 1" but "heading 2", revision 2 has "title 2" but "heading 3", and then again revisions 3 and 4 have the correct title and heading.
    – Jordan
    Sep 19, 2023 at 16:13
  • I updated the code in my question to what I've updated based on our discussion so far.
    – Jordan
    Sep 19, 2023 at 16:28

1 Answer 1

0

Make sure you apply cacheable metadata of all entities before returning $build:

use Drupal\Core\Cache\CacheableMetadata;

...

  $cacheable_metadata = CacheableMetadata::createFromRenderArray($build);

  if ($node) { 
    $cacheable_metadata->addCacheableDependency($node);
  }
  if ($paragraph) { 
    $cacheable_metadata->addCacheableDependency($paragraph);
  }
  if ($media) { 
    $cacheable_metadata->addCacheableDependency($media);
  }

  $cacheable_metadata->applyTo($build);

  return $build;
}
5
  • I've added this and updated my code in this question to reflect the changes but something still must be wrong, seems like the behavior is that if I make a draft and then switch the image and publish the page, when I go to the revisions list, the draft and the published revisions have the same image. If I make a page publish it and then edit it and save as a draft, the /latest shows the draft page with the correct image and the /node/node-id shows the published version correctly but the clicking the revisions links still are not the correct behavior.
    – Jordan
    Sep 19, 2023 at 20:07
  • I did the same steps and recorded the heading field and revision ids of the paragraph and the image field within the paragraph. I can't figure it out. I'll post them here in the form (heading - paragraph rev id - media rev id). When saving the pages: heading 1 - 10777118 - 4621, heading 2 - 10777119 - 7411, heading 3 - 10777120 - 10186, heading 4 - 10777121 - 7666, heading 5 - 10777122 - 9716 but then when looking at revisions urls: heading 2 - 10777118 - 7411, heading 3 - 10777119 - 10186, heading 4 - 10777120 - 7666, heading 5 - 10777121 - 9716, heading 5 - 10777122 - 9716.
    – Jordan
    Sep 19, 2023 at 21:20
  • Yeah so it looks like if I create a draft and then the next revision is a published page, the paragraph in the draft gets the published revisions paragraph data. If there are two draft revisions then a published revision, the first draft is correct but the second one (the draft just before the published revision) now has the same paragraph data as the published revision.
    – Jordan
    Sep 19, 2023 at 21:37
  • So the problem is already in the database? My answer is to keep the rendered output in sync with the database, but if this is already inconsistent the block plugin can't produce the correct output.
    – 4uk4
    Sep 19, 2023 at 21:52
  • That was a new basic page I created and just updated it multiple times with different info so they were new values being inserted not existing ones. Here's something strange I found though. I updated the widget for the entity_reference_revisions field that is referencing the "hero" paragraph from "Inline entity form - simple" to "Paragraphs (stable)" and it now works as expected even using the links in the revisions listing. So it seems something is different between the two widgets other than the styling/formatting of the fields on the form add/edit pages.
    – Jordan
    Sep 19, 2023 at 22:04

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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