Skip to content

Instantly share code, notes, and snippets.

@dsasser
Last active April 22, 2022 18:05
Show Gist options
  • Save dsasser/2e5d0ae10cc190d9f17240c425b76d11 to your computer and use it in GitHub Desktop.
Save dsasser/2e5d0ae10cc190d9f17240c425b76d11 to your computer and use it in GitHub Desktop.
<?php
namespace Drupal\module\Plugin\Preprocess;
use Drupal\Core\Cache\CacheableMetadata;
use Drupal\Core\Render\Element;
use Drupal\preprocess\PreprocessPluginBase;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
/**
* Base class for preprocess plugins.
*
* Define any helper functions needed in plugins within this class.
*/
class PreprocessBase extends PreprocessPluginBase implements ContainerFactoryPluginInterface {
/**
* Whether to bubble descendant cache metadata to the top level.
*
* @var bool
*/
public $bubbleCache = FALSE;
/**
* Constructs a new PreprocessBase object.
*
* @param array $configuration
* A configuration array containing information about the plugin instance.
* @param string $plugin_id
* The plugin_id for the plugin instance.
* @param mixed $plugin_definition
* The plugin implementation definition.
* @param \Symfony\Component\DependencyInjection\ContainerInterface $container
* The dependency injection container.
*/
public function __construct(array $configuration, $plugin_id, $plugin_definition, ContainerInterface $container) {
parent::__construct($configuration, $plugin_id, $plugin_definition);
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
return new static(
$configuration,
$plugin_id,
$plugin_definition,
$container,
);
}
/**
* {@inheritdoc}
*/
public function preprocess(array $variables): array {
// Bubble cache metadata if configured to do so.
if ($this->bubbleCache) {
$cache = $this->bubbleCache($variables, CacheableMetadata::createFromRenderArray($variables));
$cache->applyTo($variables);
}
return $variables;
}
/**
* Ensures that all cache metadata for nested elements bubble to response.
*
* Some templates do not print the content render array choosing to instead
* print variables created during preprocessing. When this happens, cache
* metadata is lost causing improper cache behavior. This method does the work
* of grabbing cache metadata from a render array regardless of the depth of
* the #cache key in the array.
*
* @param array $variables
* Elements to pull cache metadata from.
* @param \Drupal\Core\Cache\CacheableMetadata $cache
* Cache metadata for the current element.
*
* @return \Drupal\Core\Cache\CacheableMetadata
* Updated cache metadata.
*/
public function bubbleCache(array $variables, CacheableMetadata $cache) {
foreach (@Element::children($variables) as $key) {
if (!empty($variables[$key])) {
$cache = $this->bubbleCache($variables[$key], $cache);
}
}
return $cache->merge(CacheableMetadata::createFromRenderArray($variables));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment