cache_review-1.0.x-dev/src/Render/RenderCacheReview.php

src/Render/RenderCacheReview.php
<?php

namespace Drupal\cache_review\Render;

use Drupal\cache_review\Form\CacheReviewConfigForm;
use Drupal\Core\Cache\CacheableMetadata;
use Drupal\Core\Cache\Context\CacheContextsManager;
use Drupal\Core\Cache\VariationCacheFactoryInterface;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Render\Markup;
use Drupal\Core\Render\PlaceholderGeneratorInterface;
use Drupal\Core\Render\PlaceholderingRenderCache;
use Drupal\Core\Routing\CurrentRouteMatch;
use Symfony\Component\HttpFoundation\RequestStack;

/**
 * Decorate RenderCache service.
 *
 * Adding mark for cached and non-cached elements.
 */
class RenderCacheReview extends PlaceholderingRenderCache {
  /**
   * Original PlaceholderingRenderCache.
   *
   * @var \Drupal\Core\Render\PlaceholderingRenderCache
   */
  protected $placeholderingRenderCache;

  /**
   * The current route match service.
   *
   * @var \Drupal\Core\Routing\CurrentRouteMatch
   */
  protected $currentRouteMatch;

  /**
   * The config factory service.
   *
   * @var \Drupal\Core\Config\ConfigFactoryInterface
   */
  protected $configFactory;

  /**
   * The renderer configuration array.
   *
   * @var array
   */
  protected array $rendererConfig;

  /**
   * Construct RenderCacheReview object.
   *
   * @param \Drupal\Core\Render\PlaceholderingRenderCache $original_placeholdering_render_cache
   *   The original placeholdering_render_cache.
   * @param array $renderer_config
   *   The renderer configuration array.
   * @param \Drupal\Core\Routing\CurrentRouteMatch $current_route_match
   *   The current route match service.
   * @param \Symfony\Component\HttpFoundation\RequestStack $request_stack
   *   The request stack.
   * @param \Drupal\Core\Cache\Context\CacheContextsManager $cache_contexts_manager
   *   The cache contexts manager.
   * @param \Drupal\Core\Render\PlaceholderGeneratorInterface $placeholder_generator
   *   The placeholder generator.
   * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
   *   The config factory for retrieving required config objects.
   * @param \Drupal\Core\Cache\VariationCacheFactoryInterface $cache_factory
   *   The variation cache factory.
   */
  public function __construct(PlaceholderingRenderCache $original_placeholdering_render_cache, array $renderer_config, CurrentRouteMatch $current_route_match, RequestStack $request_stack, CacheContextsManager $cache_contexts_manager, PlaceholderGeneratorInterface $placeholder_generator, ConfigFactoryInterface $config_factory, VariationCacheFactoryInterface $cache_factory) {
    $this->placeholderingRenderCache = $original_placeholdering_render_cache;
    $this->rendererConfig = $renderer_config;
    $this->currentRouteMatch = $current_route_match;
    $this->configFactory = $config_factory;

    parent::__construct($request_stack, $cache_factory, $cache_contexts_manager, $placeholder_generator);
  }

  /**
   * {@inheritdoc}
   */
  public function get(array $elements) {
    // Part from original PlaceholderingRenderCache->get().
    // @todo remove this check when https://www.drupal.org/node/2367555 lands.
    if (!$this->requestStack->getCurrentRequest()->isMethodCacheable()) {
      return FALSE;
    }
    if (isset($elements['#create_placeholder']) && $elements['#create_placeholder'] === FALSE) {
      $cached_placeholder_result = $this->getFromPlaceholderResultsCache($elements);
      if ($cached_placeholder_result !== FALSE) {
        return $cached_placeholder_result;
      }
    }

    // Call overridden RenderCache->get().
    $cached_element = $this->parentGet($elements);

    if ($cached_element === FALSE) {
      return FALSE;
    }
    else {
      if ($this->placeholderGenerator->canCreatePlaceholder($elements) && $this->placeholderGenerator->shouldAutomaticallyPlaceholder($cached_element)) {
        return $this->createPlaceholderAndRemember($cached_element, $elements);
      }
      return $cached_element;
    }

  }

  /**
   * Overridden Part from RenderCache->get().
   */
  private function parentGet(array $elements) {
    $check_cache_item = !$this->isElementCacheable($elements);

    if (!$this->requestStack->getCurrentRequest()->isMethodCacheable() || $check_cache_item) {
      return FALSE;
    }
    $bin = $elements['#cache']['bin'] ?? 'render';

    if ($this->isElementCacheable($elements) &&
      ($cache_bin = $this->cacheFactory->get($bin)) &&
      ($cache = $cache_bin->get($elements['#cache']['keys'], CacheableMetadata::createFromRenderArray($elements)))) {

      $cached_element = $cache->data;

      if (isset($cached_element['#cache_redirect'])) {
        return $this->parentGet($cached_element);
      }

      // Ignore html_tags from cache_review configuration.
      $cache_review_config = $this->configFactory->get(CacheReviewConfigForm::CACHE_REVIEW_CONF);
      $framing = $cache_review_config->get('framing');
      // Check html id tags if framing is set to disable.
      $analyze_by_id = FALSE;
      if ($framing === 'no_frame') {
        $html_tags_values = $cache_review_config->get('html_tags');
        $html_tags = array_filter(explode("\r\n", trim($html_tags_values)));
        foreach ($html_tags as $html_tag) {
          if (str_contains($cached_element['#markup'], 'id="' . $html_tag . '"')) {
            $analyze_by_id = TRUE;
          }
        }
      }

      // Check if it needs to show cache info on admin routes.
      $check_admin_routes = $cache_review_config->get('check_admin_routes');
      $is_admin = (bool) $this->currentRouteMatch->getRouteObject()->getOption('_admin_route');

      // Add cache info for non-admin routes only.
      // Check framing settings.
      if (!$is_admin || $check_admin_routes) {
        if (($framing !== 'frame_lazy' && $framing !== 'no_frame') ||
          ($framing === 'no_frame' && $analyze_by_id)) {
          // Add mark to cached element.
          $markup_string = (string) $cached_element['#markup'];
          $caught_condition = '';
          if (!empty($markup_string)) {

            $apc = $this->rendererConfig['auto_placeholder_conditions'];
            if ($cached_element['#cache']['max-age'] == $apc['max-age'] ||
              array_intersect($cached_element['#cache']['contexts'], $apc['contexts']) ||
              array_intersect($cached_element['#cache']['tags'], $apc['tags'])) {
              $caught_condition = ' cache_caught';
            }

            $prefix = '<div class="cached-wrapper">';
            $suffix = '</div>';
            $options_data = 'contexts: ' . json_encode(array_values($cached_element['#cache']['contexts'])) . '<br>' .
              'max-age: ' . json_encode($cached_element['#cache']['max-age']) . '<br>' .
              'tags: ' . json_encode(array_values($cached_element['#cache']['tags']));
            $options = '<span class="cache_tooltip_text">' . $options_data . '</span>';
            $cache_mark = '<div class="cached-item cache_tooltip' . $caught_condition . '">C' . $options . '</div>';
            $cached_element['#markup'] = Markup::create($prefix . $cache_mark . $markup_string . $suffix);
          }
        }
      }

      return $cached_element;
    }
    return FALSE;
  }

  /**
   * Checks whether a renderable array can be cached.
   *
   * This allows us to not even have to instantiate the cache backend if a
   * renderable array does not have any cache keys or specifies a zero cache
   * max age.
   * Added for compatibility with previous versions of RenderCache.
   *
   * @param array $element
   *   A renderable array.
   *
   * @return bool
   *   Whether the renderable array is cacheable.
   */
  protected function isElementCacheable(array $element) {
    // If the maximum age is zero, then caching is effectively prohibited.
    if (isset($element['#cache']['max-age']) && $element['#cache']['max-age'] === 0) {
      return FALSE;
    }
    return isset($element['#cache']['keys']);
  }

}

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc