/**
  * Merges the values of another bubbleable metadata object with this one.
  *
  * @param \Drupal\Core\Render\BubbleableMetadata $other
  *   The other bubbleable metadata object.
  * @return static
  *   A new bubbleable metadata object, with the merged data.
  *
  * @todo Add unit test for this in
  *       \Drupal\Tests\Core\Render\BubbleableMetadataTest when
  *       drupal_merge_attached() no longer is a procedural function and remove
  *       the '@codeCoverageIgnore' annotation.
  */
 public function merge(BubbleableMetadata $other)
 {
     $result = new BubbleableMetadata();
     $result->contexts = Cache::mergeContexts($this->contexts, $other->contexts);
     $result->tags = Cache::mergeTags($this->tags, $other->tags);
     $result->maxAge = Cache::mergeMaxAges($this->maxAge, $other->maxAge);
     $result->attached = Renderer::mergeAttachments($this->attached, $other->attached);
     $result->postRenderCache = NestedArray::mergeDeep($this->postRenderCache, $other->postRenderCache);
     return $result;
 }
 /**
  * Merges cacheable metadata from conditions onto the access result object.
  *
  * @param \Drupal\Core\Access\AccessResult $access
  *   The access result object.
  * @param \Drupal\Core\Condition\ConditionInterface[] $conditions
  *   List of visibility conditions.
  */
 protected function mergeCacheabilityFromConditions(AccessResult $access, array $conditions)
 {
     foreach ($conditions as $condition) {
         if ($condition instanceof CacheableDependencyInterface) {
             $access->addCacheTags($condition->getCacheTags());
             $access->addCacheContexts($condition->getCacheContexts());
             $access->setCacheMaxAge(Cache::mergeMaxAges($access->getCacheMaxAge(), $condition->getCacheMaxAge()));
         }
     }
 }
Example #3
0
 /**
  * Applies the cacheability of the current display to the given render array.
  *
  * @param array $element
  *   The render array with updated cacheability metadata.
  */
 protected function applyDisplayCachablityMetadata(array &$element)
 {
     /** @var \Drupal\views\Plugin\views\cache\CachePluginBase $cache */
     $cache = $this->getPlugin('cache');
     (new CacheableMetadata())->setCacheTags(Cache::mergeTags($this->view->getCacheTags(), isset($this->display['cache_metadata']['tags']) ? $this->display['cache_metadata']['tags'] : []))->setCacheContexts(isset($this->display['cache_metadata']['contexts']) ? $this->display['cache_metadata']['contexts'] : [])->setCacheMaxAge(Cache::mergeMaxAges($cache->getCacheMaxAge(), isset($this->display['cache_metadata']['max-age']) ? $this->display['cache_metadata']['max-age'] : Cache::PERMANENT))->merge(CacheableMetadata::createFromRenderArray($element))->applyTo($element);
 }
Example #4
0
  /**
   * {@inheritdoc}
   */
  public function getCacheMaxAge() {
    $max_age = parent::getCacheMaxAge();
    foreach ($this->getAllEntities() as $entity) {
      $max_age = Cache::mergeMaxAges($max_age, $entity->getCacheMaxAge());
    }

    return $max_age;
  }
Example #5
0
 /**
  * Gets the max age for the current view.
  *
  * @return int
  */
 public function getCacheMaxAge()
 {
     $max_age = $this->getDefaultCacheMaxAge();
     $max_age = Cache::mergeMaxAges($max_age, $this->view->getQuery()->getCacheMaxAge());
     return $max_age;
 }
Example #6
0
 /**
  * Inherits the cacheability of the other access result, if any.
  *
  * inheritCacheability() differs from addCacheableDependency() in how it
  * handles max-age, because it is designed to inherit the cacheability of the
  * second operand in the andIf() and orIf() operations. There, the situation
  * "allowed, max-age=0 OR allowed, max-age=1000" needs to yield max-age 1000
  * as the end result.
  *
  * @param \Drupal\Core\Access\AccessResultInterface $other
  *   The other access result, whose cacheability (if any) to inherit.
  *
  * @return $this
  */
 public function inheritCacheability(AccessResultInterface $other)
 {
     $this->addCacheableDependency($other);
     if ($other instanceof CacheableDependencyInterface) {
         if ($this->getCacheMaxAge() !== 0 && $other->getCacheMaxAge() !== 0) {
             $this->setCacheMaxAge(Cache::mergeMaxAges($this->getCacheMaxAge(), $other->getCacheMaxAge()));
         } else {
             $this->setCacheMaxAge($other->getCacheMaxAge());
         }
     }
     return $this;
 }
 /**
  * {@inheritdoc}
  */
 public function getCacheMaxAge()
 {
     $max_age = Cache::PERMANENT;
     // Asks all subplugins (argument defaults, argument validator and styles).
     if (($plugin = $this->getPlugin('argument_default')) && $plugin instanceof CacheableDependencyInterface) {
         $max_age = Cache::mergeMaxAges($max_age, $plugin->getCacheMaxAge());
     }
     if (($plugin = $this->getPlugin('argument_validator')) && $plugin instanceof CacheableDependencyInterface) {
         $max_age = Cache::mergeMaxAges($max_age, $plugin->getCacheMaxAge());
     }
     // Summaries use style plugins.
     if (($plugin = $this->getPlugin('style')) && $plugin instanceof CacheableDependencyInterface) {
         $max_age = Cache::mergeMaxAges($max_age, $plugin->getCacheMaxAge());
     }
     return $max_age;
 }
Example #8
0
 /**
  * @covers ::mergeMaxAges
  *
  * @dataProvider mergeMaxAgesProvider
  */
 public function testMergeMaxAges($a, $b, $expected)
 {
     $this->assertSame($expected, Cache::mergeMaxAges($a, $b));
 }
Example #9
0
 /**
  * {@inheritdoc}
  */
 public function render()
 {
     $build = array();
     $build['#markup'] = $this->view->style_plugin->render();
     // Wrap the output in a pre tag if this is for a live preview.
     if (!empty($this->view->live_preview)) {
         $build['#prefix'] = '<pre>';
         $build['#markup'] = SafeMarkup::checkPlain($build['#markup']);
         $build['#suffix'] = '</pre>';
     }
     // Defaults for bubbleable rendering metadata.
     $build['#cache']['tags'] = isset($build['#cache']['tags']) ? $build['#cache']['tags'] : array();
     $build['#cache']['max-age'] = isset($build['#cache']['max-age']) ? $build['#cache']['max-age'] : Cache::PERMANENT;
     /** @var \Drupal\views\Plugin\views\cache\CachePluginBase $cache */
     $cache = $this->getPlugin('cache');
     $build['#cache']['tags'] = Cache::mergeTags($build['#cache']['tags'], $cache->getCacheTags());
     $build['#cache']['max-age'] = Cache::mergeMaxAges($build['#cache']['max-age'], $cache->getCacheMaxAge());
     return $build;
 }
Example #10
0
 /**
  * {@inheritdoc}
  */
 public function build()
 {
     $build = [];
     // Default the max page age to permanent.
     $max_page_age = Cache::PERMANENT;
     $page = $this->executable->getPage();
     // Set default page cache keys that include the page and display.
     $page_cache_keys = ['page_manager_page', $page->id(), $this->configuration['uuid']];
     $page_cache_contexts = [];
     $contexts = $this->getContexts();
     foreach ($this->getRegionAssignments() as $region => $blocks) {
         if (!$blocks) {
             continue;
         }
         $region_name = Html::getClass("block-region-{$region}");
         $build['regions'][$region]['#prefix'] = '<div class="' . $region_name . '">';
         $build['regions'][$region]['#suffix'] = '</div>';
         /** @var $blocks \Drupal\Core\Block\BlockPluginInterface[] */
         $weight = 0;
         foreach ($blocks as $block_id => $block) {
             if ($block instanceof ContextAwarePluginInterface) {
                 $this->contextHandler()->applyContextMapping($block, $contexts);
             }
             if (!$block->access($this->account)) {
                 continue;
             }
             $max_age = $block->getCacheMaxAge();
             $block_build = ['#theme' => 'block', '#attributes' => [], '#weight' => $weight++, '#configuration' => $block->getConfiguration(), '#plugin_id' => $block->getPluginId(), '#base_plugin_id' => $block->getBaseId(), '#derivative_plugin_id' => $block->getDerivativeId(), '#block_plugin' => $block, '#pre_render' => [[$this, 'buildBlock']], '#cache' => ['keys' => ['page_manager_page', $page->id(), 'block', $block_id], 'tags' => Cache::mergeTags($page->getCacheTags(), $block->getCacheTags()), 'contexts' => $block->getCacheContexts(), 'max-age' => $max_age]];
             // Build the cache key and a list of all contexts for the whole page.
             $page_cache_keys[] = $block_id;
             $page_cache_contexts = Cache::mergeContexts($page_cache_contexts, $block_build['#cache']['contexts']);
             if (!empty($block_build['#configuration']['label'])) {
                 $block_build['#configuration']['label'] = SafeMarkup::checkPlain($block_build['#configuration']['label']);
             }
             // Update the page max age, set it to the lowest max age of all blocks.
             $max_page_age = Cache::mergeMaxAges($max_age, $max_page_age);
             $build['regions'][$region][$block_id] = $block_build;
         }
     }
     $build['#title'] = $this->renderPageTitle($this->configuration['page_title']);
     if ($max_page_age !== 0) {
         // If all blocks of this page can be cached, then the max page age is not
         // 0. In this case, we additionally cache the whole page, so we need
         // to fetch fewer caches. Also explicitly provide the cache contexts,
         // additional contexts might still bubble up from the block content, but
         // if not, then we save a cache redirection.
         // We don't have to set those values in case we can't cache all blocks,
         // as they will bubble up from the blocks.
         $build['regions']['#cache'] = ['keys' => $page_cache_keys, 'contexts' => $page_cache_contexts, 'max-age' => $max_page_age];
     }
     return $build;
 }
Example #11
0
 /**
  * {@inheritdoc}
  */
 public function getCacheMaxAge()
 {
     $max_age = parent::getCacheMaxAge();
     // @todo Configurability of this will be removed in
     //   https://www.drupal.org/node/2458763.
     return Cache::mergeMaxAges($max_age, (int) $this->configuration['cache']['max_age']);
 }
 /**
  * {@inheritdoc}
  */
 public function getCacheMaxAge()
 {
     $max_age = Cache::PERMANENT;
     // Applied contexts can affect the cache max age when this plugin is
     // involved in caching, collect and return them.
     foreach ($this->getContexts() as $context) {
         /** @var $context \Drupal\Core\Cache\CacheableDependencyInterface */
         if ($context instanceof CacheableDependencyInterface) {
             $max_age = Cache::mergeMaxAges($max_age, $context->getCacheMaxAge());
         }
     }
     return $max_age;
 }
Example #13
0
  /**
   * {@inheritdoc}
   */
  public function getCacheMaxAge() {
    $cache_max_age = Cache::mergeMaxAges(parent::getCacheMaxAge(), $this->view->storage->getCacheMaxAge());

    return $cache_max_age;
  }
Example #14
0
 /**
  * {@inheritdoc}
  *
  * The entire HTML: takes a #type 'page' and wraps it in a #type 'html'.
  */
 public function renderResponse(array $main_content, Request $request, RouteMatchInterface $route_match)
 {
     list($page, $title) = $this->prepare($main_content, $request, $route_match);
     if (!isset($page['#type']) || $page['#type'] !== 'page') {
         throw new \LogicException('Must be #type page');
     }
     $page['#title'] = $title;
     // Now render the rendered page.html.twig template inside the html.html.twig
     // template, and use the bubbled #attached metadata from $page to ensure we
     // load all attached assets.
     $html = ['#type' => 'html', 'page' => $page];
     $html += element_info('html');
     // The special page regions will appear directly in html.html.twig, not in
     // page.html.twig, hence add them here, just before rendering html.html.twig.
     $this->buildPageTopAndBottom($html);
     // The three parts of rendered markup in html.html.twig (page_top, page and
     // page_bottom) must be rendered with drupal_render_root(), so that their
     // #post_render_cache callbacks are executed (which may attach additional
     // assets).
     // html.html.twig must be able to render the final list of attached assets,
     // and hence may not execute any #post_render_cache_callbacks (because they
     // might add yet more assets to be attached), and therefore it must be
     // rendered with drupal_render(), not drupal_render_root().
     $this->renderer->render($html['page'], TRUE);
     if (isset($html['page_top'])) {
         $this->renderer->render($html['page_top'], TRUE);
     }
     if (isset($html['page_bottom'])) {
         $this->renderer->render($html['page_bottom'], TRUE);
     }
     $content = $this->renderer->render($html);
     // Expose the cache contexts and cache tags associated with this page in a
     // X-Drupal-Cache-Contexts and X-Drupal-Cache-Tags header respectively. Also
     // associate the "rendered" cache tag. This allows us to invalidate the
     // entire render cache, regardless of the cache bin.
     $cache_contexts = [];
     $cache_tags = ['rendered'];
     $cache_max_age = Cache::PERMANENT;
     foreach (['page_top', 'page', 'page_bottom'] as $region) {
         if (isset($html[$region])) {
             $cache_contexts = Cache::mergeContexts($cache_contexts, $html[$region]['#cache']['contexts']);
             $cache_tags = Cache::mergeTags($cache_tags, $html[$region]['#cache']['tags']);
             $cache_max_age = Cache::mergeMaxAges($cache_max_age, $html[$region]['#cache']['max-age']);
         }
     }
     // Set the generator in the HTTP header.
     list($version) = explode('.', \Drupal::VERSION, 2);
     $response = new Response($content, 200, ['X-Drupal-Cache-Tags' => implode(' ', $cache_tags), 'X-Drupal-Cache-Contexts' => implode(' ', $this->cacheContexts->optimizeTokens($cache_contexts)), 'X-Generator' => 'Drupal ' . $version . ' (https://www.drupal.org)']);
     // If an explicit non-infinite max-age is specified by a part of the page,
     // respect that by applying it to the response's headers.
     if ($cache_max_age !== Cache::PERMANENT) {
         $response->setMaxAge($cache_max_age);
     }
     return $response;
 }
Example #15
0
 /**
  * Inherits the cacheability of the other access result, if any.
  *
  * @param \Drupal\Core\Access\AccessResultInterface $other
  *   The other access result, whose cacheability (if any) to inherit.
  *
  * @return $this
  */
 public function inheritCacheability(AccessResultInterface $other)
 {
     if ($other instanceof CacheableInterface) {
         $this->setCacheable($other->isCacheable());
         $this->addCacheContexts($other->getCacheContexts());
         $this->addCacheTags($other->getCacheTags());
         $this->setCacheMaxAge(Cache::mergeMaxAges($this->getCacheMaxAge(), $other->getCacheMaxAge()));
     } else {
         $this->setCacheable(FALSE);
     }
     return $this;
 }