public function testAvailableContextLabels()
 {
     $container = $this->getMockContainer();
     $container->expects($this->once())->method("get")->with("cache_context.foo")->will($this->returnValue(new FooCacheContext()));
     $cache_contexts = new CacheContexts($container, $this->getContextsFixture());
     $labels = $cache_contexts->getLabels();
     $expected = array("cache_context.foo" => "Foo");
     $this->assertEquals($expected, $labels);
 }
예제 #2
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;
 }
예제 #3
0
 /**
  * Creates the cache ID for a renderable element.
  *
  * This creates the cache ID string, either by returning the #cache['cid']
  * property if present or by building the cache ID out of the #cache['keys'] +
  * #cache['contexts'].
  *
  * @param array $elements
  *   A renderable array.
  *
  * @return string
  *   The cache ID string, or FALSE if the element may not be cached.
  */
 protected function createCacheID(array $elements)
 {
     // If the maximum age is zero, then caching is effectively prohibited.
     if (isset($elements['#cache']['max-age']) && $elements['#cache']['max-age'] === 0) {
         return FALSE;
     }
     if (isset($elements['#cache']['cid'])) {
         return $elements['#cache']['cid'];
     } elseif (isset($elements['#cache']['keys'])) {
         $cid_parts = $elements['#cache']['keys'];
         if (isset($elements['#cache']['contexts'])) {
             $contexts = $this->cacheContexts->convertTokensToKeys($elements['#cache']['contexts']);
             $cid_parts = array_merge($cid_parts, $contexts);
         }
         return implode(':', $cid_parts);
     }
     return FALSE;
 }
예제 #4
0
 public function testAvailableContextLabels()
 {
     $container = $this->getMockContainer();
     $cache_contexts = new CacheContexts($container, $this->getContextsFixture());
     $labels = $cache_contexts->getLabels();
     $expected = array("foo" => "Foo");
     $this->assertEquals($expected, $labels);
 }
예제 #5
0
 /**
  * {@inheritdoc}
  *
  * Creates a generic configuration form for all block types. Individual
  * block plugins can add elements to this form by overriding
  * BlockBase::blockForm(). Most block plugins should not override this
  * method unless they need to alter the generic form elements.
  *
  * @see \Drupal\Core\Block\BlockBase::blockForm()
  */
 public function buildConfigurationForm(array $form, FormStateInterface $form_state)
 {
     $definition = $this->getPluginDefinition();
     $form['provider'] = array('#type' => 'value', '#value' => $definition['provider']);
     $form['admin_label'] = array('#type' => 'item', '#title' => $this->t('Block description'), '#markup' => String::checkPlain($definition['admin_label']));
     $form['label'] = array('#type' => 'textfield', '#title' => $this->t('Title'), '#maxlength' => 255, '#default_value' => $this->label(), '#required' => TRUE);
     $form['label_display'] = array('#type' => 'checkbox', '#title' => $this->t('Display title'), '#default_value' => $this->configuration['label_display'] === BlockInterface::BLOCK_LABEL_VISIBLE, '#return_value' => BlockInterface::BLOCK_LABEL_VISIBLE);
     // Identical options to the ones for page caching.
     // @see \Drupal\system\Form\PerformanceForm::buildForm()
     $period = array(0, 60, 180, 300, 600, 900, 1800, 2700, 3600, 10800, 21600, 32400, 43200, 86400);
     $period = array_map(array(\Drupal::service('date.formatter'), 'formatInterval'), array_combine($period, $period));
     $period[0] = '<' . $this->t('no caching') . '>';
     $period[\Drupal\Core\Cache\Cache::PERMANENT] = $this->t('Forever');
     $form['cache'] = array('#type' => 'details', '#title' => $this->t('Cache settings'));
     $form['cache']['max_age'] = array('#type' => 'select', '#title' => $this->t('Maximum age'), '#description' => $this->t('The maximum time this block may be cached.'), '#default_value' => $this->configuration['cache']['max_age'], '#options' => $period);
     $contexts = \Drupal::service("cache_contexts")->getLabels();
     // Blocks are always rendered in the "per language" and "per theme" cache
     // contexts. No need to show those options to the end user.
     unset($contexts['languages']);
     unset($contexts['theme']);
     $form['cache']['contexts'] = array('#type' => 'checkboxes', '#title' => $this->t('Vary by context'), '#description' => $this->t('The contexts this cached block must be varied by. <em>All</em> blocks are varied by language and theme.'), '#default_value' => $this->configuration['cache']['contexts'], '#options' => $contexts, '#states' => array('disabled' => array(':input[name="settings[cache][max_age]"]' => array('value' => (string) 0))));
     if (count($this->getRequiredCacheContexts()) > 0) {
         // Remove the required cache contexts from the list of contexts a user can
         // choose to modify by: they must always be applied.
         $context_labels = array();
         $all_contexts = \Drupal::service("cache_contexts")->getLabels(TRUE);
         foreach (CacheContexts::parseTokens($this->getRequiredCacheContexts()) as $context) {
             $context_id = $context[0];
             $context_labels[] = $all_contexts[$context_id];
             unset($form['cache']['contexts']['#options'][$context_id]);
         }
         $required_context_list = implode(', ', $context_labels);
         $form['cache']['contexts']['#description'] .= ' ' . $this->t('This block is <em>always</em> varied by the following contexts: %required-context-list.', array('%required-context-list' => $required_context_list));
     }
     // Add plugin-specific settings for this block type.
     $form += $this->blockForm($form, $form_state);
     return $form;
 }