コード例 #1
0
 /**
  * {@inheritdoc}
  *
  * @see ::prepareView()
  * @see ::getEntitiestoView()
  */
 public function view(FieldItemListInterface $items, $langcode = NULL)
 {
     $elements = parent::view($items, $langcode);
     $field_level_access_cacheability = new CacheableMetadata();
     // Try to map the cacheability of the access result that was set at
     // _accessCacheability in getEntitiesToView() to the corresponding render
     // subtree. If no such subtree is found, then merge it with the field-level
     // access cacheability.
     foreach ($items as $delta => $item) {
         // Ignore items for which access cacheability could not be determined in
         // prepareView().
         if (!empty($item->_accessCacheability)) {
             if (isset($elements[$delta])) {
                 CacheableMetadata::createFromRenderArray($elements[$delta])->merge($item->_accessCacheability)->applyTo($elements[$delta]);
             } else {
                 $field_level_access_cacheability = $field_level_access_cacheability->merge($item->_accessCacheability);
             }
         }
     }
     // Apply the cacheability metadata for the inaccessible entities and the
     // entities for which the corresponding render subtree could not be found.
     // This causes the field to be rendered (and cached) according to the cache
     // contexts by which the access results vary, to ensure only users with
     // access to this field can view it. It also tags this field with the cache
     // tags on which the access results depend, to ensure users that cannot view
     // this field at the moment will gain access once any of those cache tags
     // are invalidated.
     $field_level_access_cacheability->applyTo($elements);
     return $elements;
 }
コード例 #2
0
 /**
  * Creates a bubbleable metadata object with values taken from a render array.
  *
  * @param array $build
  *   A render array.
  *
  * @return static
  */
 public static function createFromRenderArray(array $build)
 {
     $meta = parent::createFromRenderArray($build);
     $meta->attached = isset($build['#attached']) ? $build['#attached'] : [];
     $meta->postRenderCache = isset($build['#post_render_cache']) ? $build['#post_render_cache'] : [];
     return $meta;
 }
コード例 #3
0
 /**
  * {@inheritdoc}
  */
 public function setContent($content)
 {
     // A render array can automatically be converted to a string and set the
     // necessary metadata.
     if (is_array($content) && isset($content['#markup'])) {
         $this->addCacheableDependency(CacheableMetadata::createFromRenderArray($content));
         $this->setAttachments($content['#attached']);
         $content = $content['#markup'];
     }
     parent::setContent($content);
 }
コード例 #4
0
ファイル: HtmlResponse.php プロジェクト: aWEBoLabs/taxi
 /**
  * {@inheritdoc}
  */
 public function setContent($content)
 {
     // A render array can automatically be converted to a string and set the
     // necessary metadata.
     if (is_array($content) && isset($content['#markup'])) {
         $content += ['#attached' => ['html_response_attachment_placeholders' => [], 'placeholders' => []]];
         $this->addCacheableDependency(CacheableMetadata::createFromRenderArray($content));
         $this->setAttachments($content['#attached']);
         $content = $content['#markup'];
     }
     return parent::setContent($content);
 }
コード例 #5
0
ファイル: JsonRenderer.php プロジェクト: sarahwillem/OD8
 /**
  * {@inheritdoc}
  */
 public function renderResponse(array $main_content, Request $request, RouteMatchInterface $route_match)
 {
     $json = [];
     $json['content'] = (string) $this->renderer->renderRoot($main_content);
     if (!empty($main_content['#title'])) {
         $json['title'] = (string) $main_content['#title'];
     } else {
         $json['title'] = (string) $this->titleResolver->getTitle($request, $route_match->getRouteObject());
     }
     $response = new CacheableJsonResponse($json, 200);
     $response->addCacheableDependency(CacheableMetadata::createFromRenderArray($main_content));
     return $response;
 }
コード例 #6
0
 /**
  * {@inheritdoc}
  */
 public function buildSelectorForm(array $form, FormStateInterface $form_state)
 {
     $form = parent::buildSelectorForm($form, $form_state);
     $available_plugins = [];
     $cacheability_metadata = CacheableMetadata::createFromRenderArray($form);
     foreach (array_keys($this->selectablePluginDiscovery->getDefinitions()) as $plugin_id) {
         $available_plugin = $this->selectablePluginFactory->createInstance($plugin_id);
         $available_plugins[] = $available_plugin;
         $cacheability_metadata = $cacheability_metadata->merge(CacheableMetadata::createFromObject($available_plugin));
     }
     $cacheability_metadata->applyTo($form);
     $plugin_selector_form_state_key = static::setPluginSelector($form_state, $this);
     $form['container'] = array('#attributes' => array('class' => array('plugin-selector-' . Html::getClass($this->getPluginId()))), '#available_plugins' => $available_plugins, '#plugin_selector_form_state_key' => $plugin_selector_form_state_key, '#process' => [[get_class(), 'processBuildSelectorForm']], '#tree' => TRUE, '#type' => 'container');
     return $form;
 }
コード例 #7
0
ファイル: Feed.php プロジェクト: ddrozdik/dmaps
 /**
  * {@inheritdoc}
  */
 public static function buildResponse($view_id, $display_id, array $args = [])
 {
     $build = static::buildBasicRenderable($view_id, $display_id, $args);
     // Set up an empty response, so for example RSS can set the proper
     // Content-Type header.
     $response = new CacheableResponse('', 200);
     $build['#response'] = $response;
     /** @var \Drupal\Core\Render\RendererInterface $renderer */
     $renderer = \Drupal::service('renderer');
     $output = (string) $renderer->renderRoot($build);
     if (empty($output)) {
         throw new NotFoundHttpException();
     }
     $response->setContent($output);
     $cache_metadata = CacheableMetadata::createFromRenderArray($build);
     $response->addCacheableDependency($cache_metadata);
     return $response;
 }
コード例 #8
0
ファイル: Link.php プロジェクト: nstielau/drops-8
 /**
  * Pre-render callback: Renders a link into #markup.
  *
  * Doing so during pre_render gives modules a chance to alter the link parts.
  *
  * @param array $element
  *   A structured array whose keys form the arguments to _l():
  *   - #title: The link text to pass as argument to _l().
  *   - #url: The URL info either pointing to a route or a non routed path.
  *   - #options: (optional) An array of options to pass to _l() or the link
  *     generator.
  *
  * @return array
  *   The passed-in element containing a rendered link in '#markup'.
  */
 public static function preRenderLink($element)
 {
     // By default, link options to pass to _l() are normally set in #options.
     $element += array('#options' => array());
     // However, within the scope of renderable elements, #attributes is a valid
     // way to specify attributes, too. Take them into account, but do not override
     // attributes from #options.
     if (isset($element['#attributes'])) {
         $element['#options'] += array('attributes' => array());
         $element['#options']['attributes'] += $element['#attributes'];
     }
     // This #pre_render callback can be invoked from inside or outside of a Form
     // API context, and depending on that, a HTML ID may be already set in
     // different locations. #options should have precedence over Form API's #id.
     // #attributes have been taken over into #options above already.
     if (isset($element['#options']['attributes']['id'])) {
         $element['#id'] = $element['#options']['attributes']['id'];
     } elseif (isset($element['#id'])) {
         $element['#options']['attributes']['id'] = $element['#id'];
     }
     // Conditionally invoke self::preRenderAjaxForm(), if #ajax is set.
     if (isset($element['#ajax']) && !isset($element['#ajax_processed'])) {
         // If no HTML ID was found above, automatically create one.
         if (!isset($element['#id'])) {
             $element['#id'] = $element['#options']['attributes']['id'] = HtmlUtility::getUniqueId('ajax-link');
         }
         $element = static::preRenderAjaxForm($element);
     }
     if (!empty($element['#url']) && $element['#url'] instanceof CoreUrl) {
         $options = NestedArray::mergeDeep($element['#url']->getOptions(), $element['#options']);
         /** @var \Drupal\Core\Utility\LinkGenerator $link_generator */
         $link_generator = \Drupal::service('link_generator');
         $generated_link = $link_generator->generate($element['#title'], $element['#url']->setOptions($options), TRUE);
         $element['#markup'] = $generated_link->getGeneratedLink();
         $generated_link->merge(CacheableMetadata::createFromRenderArray($element))->applyTo($element);
     }
     return $element;
 }
コード例 #9
0
 /**
  * Embeds a Response object in a render array so that RenderCache can cache it.
  *
  * @param \Drupal\Core\Cache\CacheableResponseInterface $response
  *   A cacheable response.
  *
  * @return array
  *   A render array that embeds the given cacheable response object, with the
  *   cacheability metadata of the response object present in the #cache
  *   property of the render array.
  *
  * @see renderArrayToResponse()
  *
  * @todo Refactor/remove once https://www.drupal.org/node/2551419 lands.
  */
 protected function responseToRenderArray(CacheableResponseInterface $response)
 {
     $response_as_render_array = $this->dynamicPageCacheRedirectRenderArray + ['#response' => $response, '#cache_properties' => ['#response'], '#markup' => '', '#attached' => ''];
     // Merge the response's cacheability metadata, so that RenderCache can take
     // care of cache redirects for us.
     CacheableMetadata::createFromObject($response->getCacheableMetadata())->merge(CacheableMetadata::createFromRenderArray($response_as_render_array))->applyTo($response_as_render_array);
     return $response_as_render_array;
 }
コード例 #10
0
ファイル: RestExport.php プロジェクト: eigentor/tommiblog
 /**
  * {@inheritdoc}
  */
 public static function buildResponse($view_id, $display_id, array $args = [])
 {
     $build = static::buildBasicRenderable($view_id, $display_id, $args);
     // Setup an empty response so headers can be added as needed during views
     // rendering and processing.
     $response = new CacheableResponse('', 200);
     $build['#response'] = $response;
     /** @var \Drupal\Core\Render\RendererInterface $renderer */
     $renderer = \Drupal::service('renderer');
     $output = (string) $renderer->renderRoot($build);
     $response->setContent($output);
     $cache_metadata = CacheableMetadata::createFromRenderArray($build);
     $response->addCacheableDependency($cache_metadata);
     $response->headers->set('Content-type', $build['#content_type']);
     return $response;
 }
コード例 #11
0
 /**
  * Prior to set the response it check if we can redirect.
  *
  * @param \Symfony\Component\HttpKernel\Event\GetResponseEvent $event
  *   The event object.
  * @param \Drupal\Core\Url $url
  *   The Url where we want to redirect.
  */
 protected function setResponse(GetResponseEvent $event, Url $url)
 {
     $request = $event->getRequest();
     $this->context->fromRequest($request);
     parse_str($request->getQueryString(), $query);
     $url->setOption('query', $query);
     $url->setAbsolute(TRUE);
     // We can only check access for routed URLs.
     if (!$url->isRouted() || $this->checker->canRedirect($request, $url->getRouteName())) {
         // Add the 'rendered' cache tag, so that we can invalidate all responses
         // when settings are changed.
         $response = new TrustedRedirectResponse($url->toString(), 301);
         $response->addCacheableDependency(CacheableMetadata::createFromRenderArray([])->addCacheTags(['rendered']));
         $event->setResponse($response);
     }
 }
コード例 #12
0
 /**
  * Prepares search results for rendering.
  *
  * @param \Drupal\Core\Database\StatementInterface $found
  *   Results found from a successful search query execute() method.
  *
  * @return array
  *   Array of search result item render arrays (empty array if no results).
  */
 protected function prepareResults(StatementInterface $found)
 {
     $results = array();
     $node_storage = $this->entityManager->getStorage('node');
     $node_render = $this->entityManager->getViewBuilder('node');
     $keys = $this->keywords;
     foreach ($found as $item) {
         // Render the node.
         /** @var \Drupal\node\NodeInterface $node */
         $node = $node_storage->load($item->sid)->getTranslation($item->langcode);
         $build = $node_render->view($node, 'search_result', $item->langcode);
         /** @var \Drupal\node\NodeTypeInterface $type*/
         $type = $this->entityManager->getStorage('node_type')->load($node->bundle());
         unset($build['#theme']);
         $build['#pre_render'][] = array($this, 'removeSubmittedInfo');
         // Fetch comments for snippet.
         $rendered = $this->renderer->renderPlain($build);
         $this->addCacheableDependency(CacheableMetadata::createFromRenderArray($build));
         $rendered .= ' ' . $this->moduleHandler->invoke('comment', 'node_update_index', [$node]);
         $extra = $this->moduleHandler->invokeAll('node_search_result', [$node]);
         $language = $this->languageManager->getLanguage($item->langcode);
         $username = array('#theme' => 'username', '#account' => $node->getOwner());
         $result = array('link' => $node->url('canonical', array('absolute' => TRUE, 'language' => $language)), 'type' => $type->label(), 'title' => $node->label(), 'node' => $node, 'extra' => $extra, 'score' => $item->calculated_score, 'snippet' => search_excerpt($keys, $rendered, $item->langcode), 'langcode' => $node->language()->getId());
         $this->addCacheableDependency($node);
         // We have to separately add the node owner's cache tags because search
         // module doesn't use the rendering system, it does its own rendering
         // without taking cacheability metadata into account. So we have to do it
         // explicitly here.
         $this->addCacheableDependency($node->getOwner());
         if ($type->displaySubmitted()) {
             $result += array('user' => $this->renderer->renderPlain($username), 'date' => $node->getChangedTime());
         }
         $results[] = $result;
     }
     return $results;
 }
コード例 #13
0
ファイル: HtmlRenderer.php プロジェクト: nstielau/drops-8
 /**
  * {@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];
     // 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);
     // Set the generator in the HTTP header.
     list($version) = explode('.', \Drupal::VERSION, 2);
     $response = new CacheableResponse($content, 200, ['Content-Type' => 'text/html; charset=UTF-8', 'X-Generator' => 'Drupal ' . $version . ' (https://www.drupal.org)']);
     // Bubble the cacheability metadata associated with the rendered render
     // arrays to the response.
     foreach (['page_top', 'page', 'page_bottom'] as $region) {
         if (isset($html[$region])) {
             $response->addCacheableDependency(CacheableMetadata::createFromRenderArray($html[$region]));
         }
     }
     // Also associate the "rendered" cache tag. This allows us to invalidate the
     // entire render cache, regardless of the cache bin.
     $default = new CacheableMetadata();
     $default->setCacheTags(['rendered']);
     $response->addCacheableDependency($default);
     return $response;
 }
コード例 #14
0
 /**
  * @covers ::createFromRenderArray
  * @dataProvider providerTestCreateFromRenderArray
  */
 public function testCreateFromRenderArray(array $render_array, CacheableMetadata $expected)
 {
     $this->assertEquals($expected, CacheableMetadata::createFromRenderArray($render_array));
 }
コード例 #15
0
ファイル: Renderer.php プロジェクト: nstielau/drops-8
 /**
  * {@inheritdoc}
  */
 public function addCacheableDependency(array &$elements, $dependency)
 {
     $meta_a = CacheableMetadata::createFromRenderArray($elements);
     $meta_b = CacheableMetadata::createFromObject($dependency);
     $meta_a->merge($meta_b)->applyTo($elements);
 }
コード例 #16
0
ファイル: Field.php プロジェクト: brstde/gap1
 /**
  * Gets an array of items for the field.
  *
  * @param \Drupal\views\ResultRow $values
  *   The result row object containing the values.
  *
  * @return array
  *   An array of items for the field.
  */
 public function getItems(ResultRow $values)
 {
     $original_entity = $this->getEntity($values);
     if (!$original_entity) {
         return array();
     }
     $entity = $this->process_entity($values, $original_entity);
     if (!$entity) {
         return array();
     }
     $display = array('type' => $this->options['type'], 'settings' => $this->options['settings'], 'label' => 'hidden');
     $render_array = $entity->get($this->definition['field_name'])->view($display);
     if ($this->options['field_api_classes']) {
         return array(array('rendered' => $this->renderer->render($render_array)));
     }
     $items = array();
     foreach (Element::children($render_array) as $delta) {
         $items[$delta]['rendered'] = $render_array[$delta];
         // Merge the cacheability metadata of the top-level render array into
         // each child because they will most likely be rendered individually.
         if (isset($render_array['#cache'])) {
             CacheableMetadata::createFromRenderArray($render_array)->merge(CacheableMetadata::createFromRenderArray($items[$delta]['rendered']))->applyTo($items[$delta]['rendered']);
         }
         // Add the raw field items (for use in tokens).
         $items[$delta]['raw'] = $render_array['#items'][$delta];
     }
     return $items;
 }
コード例 #17
0
 /**
  * {@inheritdoc}
  */
 public static function buildResponse($view_id, $display_id, array $args = [])
 {
     $build = static::buildBasicRenderable($view_id, $display_id, $args);
     $build['#cache']['contexts'][] = "url.query_args:callback";
     /** @var \Drupal\Core\Render\RendererInterface $renderer */
     $renderer = \Drupal::service('renderer');
     $output = $renderer->renderRoot($build);
     if (isset($build['#jsonp_callback'])) {
         $response = new CacheableJsonResponse($output, 200);
         $response->setCallback($build['#jsonp_callback']);
     } else {
         $response = new CacheableResponse($output, 200);
     }
     $cache_metadata = CacheableMetadata::createFromRenderArray($build);
     $response->addCacheableDependency($cache_metadata);
     $response->headers->set('Content-type', $build['#content_type']);
     return $response;
 }
コード例 #18
0
ファイル: RestExport.php プロジェクト: aWEBoLabs/taxi
 /**
  * {@inheritdoc}
  */
 public static function buildResponse($view_id, $display_id, array $args = [])
 {
     $build = static::buildBasicRenderable($view_id, $display_id, $args);
     /** @var \Drupal\Core\Render\RendererInterface $renderer */
     $renderer = \Drupal::service('renderer');
     $output = $renderer->renderRoot($build);
     $response = new CacheableResponse($output, 200);
     $cache_metadata = CacheableMetadata::createFromRenderArray($build);
     $response->addCacheableDependency($cache_metadata);
     $response->headers->set('Content-type', $build['#content_type']);
     return $response;
 }
コード例 #19
0
ファイル: BubbleableMetadata.php プロジェクト: aWEBoLabs/taxi
 /**
  * Creates a bubbleable metadata object with values taken from a render array.
  *
  * @param array $build
  *   A render array.
  *
  * @return static
  */
 public static function createFromRenderArray(array $build)
 {
     $meta = parent::createFromRenderArray($build);
     $meta->attachments = isset($build['#attached']) ? $build['#attached'] : [];
     return $meta;
 }
コード例 #20
0
 /**
  * Tests the label formatter.
  */
 public function testLabelFormatter()
 {
     /** @var \Drupal\Core\Render\RendererInterface $renderer */
     $renderer = $this->container->get('renderer');
     $formatter = 'entity_reference_label';
     // The 'link' settings is TRUE by default.
     $build = $this->buildRenderArray([$this->referencedEntity, $this->unsavedReferencedEntity], $formatter);
     $expected_field_cacheability = ['contexts' => [], 'tags' => [], 'max-age' => Cache::PERMANENT];
     $this->assertEqual($build['#cache'], $expected_field_cacheability, 'The field render array contains the entity access cacheability metadata');
     $expected_item_1 = array('#type' => 'link', '#title' => $this->referencedEntity->label(), '#url' => $this->referencedEntity->urlInfo(), '#options' => $this->referencedEntity->urlInfo()->getOptions(), '#cache' => array('contexts' => ['user.permissions'], 'tags' => $this->referencedEntity->getCacheTags()));
     $this->assertEqual($renderer->renderRoot($build[0]), $renderer->renderRoot($expected_item_1), sprintf('The markup returned by the %s formatter is correct for an item with a saved entity.', $formatter));
     $this->assertEqual(CacheableMetadata::createFromRenderArray($build[0]), CacheableMetadata::createFromRenderArray($expected_item_1));
     // The second referenced entity is "autocreated", therefore not saved and
     // lacking any URL info.
     $expected_item_2 = array('#plain_text' => $this->unsavedReferencedEntity->label(), '#cache' => array('contexts' => ['user.permissions'], 'tags' => $this->unsavedReferencedEntity->getCacheTags(), 'max-age' => Cache::PERMANENT));
     $this->assertEqual($build[1], $expected_item_2, sprintf('The render array returned by the %s formatter is correct for an item with a unsaved entity.', $formatter));
     // Test with the 'link' setting set to FALSE.
     $build = $this->buildRenderArray([$this->referencedEntity, $this->unsavedReferencedEntity], $formatter, array('link' => FALSE));
     $this->assertEqual($build[0]['#plain_text'], $this->referencedEntity->label(), sprintf('The markup returned by the %s formatter is correct for an item with a saved entity.', $formatter));
     $this->assertEqual($build[1]['#plain_text'], $this->unsavedReferencedEntity->label(), sprintf('The markup returned by the %s formatter is correct for an item with a unsaved entity.', $formatter));
     // Test an entity type that doesn't have any link templates, which means
     // \Drupal\Core\Entity\EntityInterface::urlInfo() will throw an exception
     // and the label formatter will output only the label instead of a link.
     $field_storage_config = FieldStorageConfig::loadByName($this->entityType, $this->fieldName);
     $field_storage_config->setSetting('target_type', 'entity_test_label');
     $field_storage_config->save();
     $referenced_entity_with_no_link_template = EntityTestLabel::create(array('name' => $this->randomMachineName()));
     $referenced_entity_with_no_link_template->save();
     $build = $this->buildRenderArray([$referenced_entity_with_no_link_template], $formatter, array('link' => TRUE));
     $this->assertEqual($build[0]['#plain_text'], $referenced_entity_with_no_link_template->label(), sprintf('The markup returned by the %s formatter is correct for an entity type with no valid link template.', $formatter));
 }
コード例 #21
0
ファイル: RestExport.php プロジェクト: nstielau/drops-8
 /**
  * {@inheritdoc}
  */
 public function execute()
 {
     parent::execute();
     $output = $this->view->render();
     $header = [];
     $header['Content-type'] = $this->getMimeType();
     $response = new CacheableResponse($this->renderer->renderRoot($output), 200);
     $cache_metadata = CacheableMetadata::createFromRenderArray($output);
     $response->addCacheableDependency($cache_metadata);
     return $response;
 }
コード例 #22
0
ファイル: BlockViewBuilder.php プロジェクト: 318io/318-io
 /**
  * #pre_render callback for building a block.
  *
  * Renders the content using the provided block plugin, and then:
  * - if there is no content, aborts rendering, and makes sure the block won't
  *   be rendered.
  * - if there is content, moves the contextual links from the block content to
  *   the block itself.
  */
 public static function preRender($build)
 {
     $content = $build['#block']->getPlugin()->build();
     // Remove the block entity from the render array, to ensure that blocks
     // can be rendered without the block config entity.
     unset($build['#block']);
     if ($content !== NULL && !Element::isEmpty($content)) {
         // Place the $content returned by the block plugin into a 'content' child
         // element, as a way to allow the plugin to have complete control of its
         // properties and rendering (for instance, its own #theme) without
         // conflicting with the properties used above, or alternate ones used by
         // alternate block rendering approaches in contrib (for instance, Panels).
         // However, the use of a child element is an implementation detail of this
         // particular block rendering approach. Semantically, the content returned
         // by the plugin "is the" block, and in particular, #attributes and
         // #contextual_links is information about the *entire* block. Therefore,
         // we must move these properties from $content and merge them into the
         // top-level element.
         foreach (array('#attributes', '#contextual_links') as $property) {
             if (isset($content[$property])) {
                 $build[$property] += $content[$property];
                 unset($content[$property]);
             }
         }
         $build['content'] = $content;
     } else {
         // Abort rendering: render as the empty string and ensure this block is
         // render cached, so we can avoid the work of having to repeatedly
         // determine whether the block is empty. For instance, modifying or adding
         // entities could cause the block to no longer be empty.
         $build = array('#markup' => '', '#cache' => $build['#cache']);
         // If $content is not empty, then it contains cacheability metadata, and
         // we must merge it with the existing cacheability metadata. This allows
         // blocks to be empty, yet still bubble cacheability metadata, to indicate
         // why they are empty.
         if (!empty($content)) {
             CacheableMetadata::createFromRenderArray($build)->merge(CacheableMetadata::createFromRenderArray($content))->applyTo($build);
         }
     }
     return $build;
 }
コード例 #23
0
ファイル: BlockPageVariant.php プロジェクト: nsp15/Drupal8
 /**
  * {@inheritdoc}
  */
 public function build()
 {
     // Track whether blocks showing the main content and messages are displayed.
     $main_content_block_displayed = FALSE;
     $messages_block_displayed = FALSE;
     $build = ['#cache' => ['tags' => $this->blockListCacheTags]];
     // Load all region content assigned via blocks.
     $cacheable_metadata_list = [];
     foreach ($this->blockRepository->getVisibleBlocksPerRegion($cacheable_metadata_list) as $region => $blocks) {
         /** @var $blocks \Drupal\block\BlockInterface[] */
         foreach ($blocks as $key => $block) {
             $block_plugin = $block->getPlugin();
             if ($block_plugin instanceof MainContentBlockPluginInterface) {
                 $block_plugin->setMainContent($this->mainContent);
                 $main_content_block_displayed = TRUE;
             } elseif ($block_plugin instanceof MessagesBlockPluginInterface) {
                 $messages_block_displayed = TRUE;
             }
             $build[$region][$key] = $this->blockViewBuilder->view($block);
             // The main content block cannot be cached: it is a placeholder for the
             // render array returned by the controller. It should be rendered as-is,
             // with other placed blocks "decorating" it.
             if ($block_plugin instanceof MainContentBlockPluginInterface) {
                 unset($build[$region][$key]['#cache']['keys']);
             }
         }
         if (!empty($build[$region])) {
             // \Drupal\block\BlockRepositoryInterface::getVisibleBlocksPerRegion()
             // returns the blocks in sorted order.
             $build[$region]['#sorted'] = TRUE;
         }
     }
     // If no block that shows the main content is displayed, still show the main
     // content. Otherwise the end user will see all displayed blocks, but not
     // the main content they came for.
     if (!$main_content_block_displayed) {
         $build['content']['system_main'] = $this->mainContent;
     }
     // If no block displays status messages, still render them.
     if (!$messages_block_displayed) {
         $build['content']['messages'] = ['#weight' => -1000, '#type' => 'status_messages'];
     }
     // The access results' cacheability is currently added to the top level of the
     // render array. This is done to prevent issues with empty regions being
     // displayed.
     // This would need to be changed to allow caching of block regions, as each
     // region must then have the relevant cacheable metadata.
     $merged_cacheable_metadata = CacheableMetadata::createFromRenderArray($build);
     foreach ($cacheable_metadata_list as $cacheable_metadata) {
         $merged_cacheable_metadata = $merged_cacheable_metadata->merge($cacheable_metadata);
     }
     $merged_cacheable_metadata->applyTo($build);
     return $build;
 }
コード例 #24
0
ファイル: MenuForm.php プロジェクト: komejo/article-test
 /**
  * Recursive helper function for buildOverviewForm().
  *
  * @param \Drupal\Core\Menu\MenuLinkTreeElement[] $tree
  *   The tree retrieved by \Drupal\Core\Menu\MenuLinkTreeInterface::load().
  * @param int $delta
  *   The default number of menu items used in the menu weight selector is 50.
  *
  * @return array
  *   The overview tree form.
  */
 protected function buildOverviewTreeForm($tree, $delta)
 {
     $form =& $this->overviewTreeForm;
     $tree_access_cacheability = new CacheableMetadata();
     foreach ($tree as $element) {
         $tree_access_cacheability = $tree_access_cacheability->merge(CacheableMetadata::createFromObject($element->access));
         // Only render accessible links.
         if (!$element->access->isAllowed()) {
             continue;
         }
         /** @var \Drupal\Core\Menu\MenuLinkInterface $link */
         $link = $element->link;
         if ($link) {
             $id = 'menu_plugin_id:' . $link->getPluginId();
             $form[$id]['#item'] = $element;
             $form[$id]['#attributes'] = $link->isEnabled() ? array('class' => array('menu-enabled')) : array('class' => array('menu-disabled'));
             $form[$id]['title'] = Link::fromTextAndUrl($link->getTitle(), $link->getUrlObject())->toRenderable();
             if (!$link->isEnabled()) {
                 $form[$id]['title']['#suffix'] = ' (' . $this->t('disabled') . ')';
             } elseif (($url = $link->getUrlObject()) && $url->isRouted() && $url->getRouteName() == 'user.page') {
                 $form[$id]['title']['#suffix'] = ' (' . $this->t('logged in users only') . ')';
             }
             $form[$id]['enabled'] = array('#type' => 'checkbox', '#title' => $this->t('Enable @title menu link', array('@title' => $link->getTitle())), '#title_display' => 'invisible', '#default_value' => $link->isEnabled());
             $form[$id]['weight'] = array('#type' => 'weight', '#delta' => $delta, '#default_value' => $link->getWeight(), '#title' => $this->t('Weight for @title', array('@title' => $link->getTitle())), '#title_display' => 'invisible');
             $form[$id]['id'] = array('#type' => 'hidden', '#value' => $link->getPluginId());
             $form[$id]['parent'] = array('#type' => 'hidden', '#default_value' => $link->getParent());
             // Build a list of operations.
             $operations = array();
             $operations['edit'] = array('title' => $this->t('Edit'));
             // Allow for a custom edit link per plugin.
             $edit_route = $link->getEditRoute();
             if ($edit_route) {
                 $operations['edit']['url'] = $edit_route;
                 // Bring the user back to the menu overview.
                 $operations['edit']['query'] = $this->getDestinationArray();
             } else {
                 // Fall back to the standard edit link.
                 $operations['edit'] += array('url' => Url::fromRoute('menu_ui.link_edit', ['menu_link_plugin' => $link->getPluginId()]));
             }
             // Links can either be reset or deleted, not both.
             if ($link->isResettable()) {
                 $operations['reset'] = array('title' => $this->t('Reset'), 'url' => Url::fromRoute('menu_ui.link_reset', ['menu_link_plugin' => $link->getPluginId()]));
             } elseif ($delete_link = $link->getDeleteRoute()) {
                 $operations['delete']['url'] = $delete_link;
                 $operations['delete']['query'] = $this->getDestinationArray();
                 $operations['delete']['title'] = $this->t('Delete');
             }
             if ($link->isTranslatable()) {
                 $operations['translate'] = array('title' => $this->t('Translate'), 'url' => $link->getTranslateRoute());
             }
             $form[$id]['operations'] = array('#type' => 'operations', '#links' => $operations);
         }
         if ($element->subtree) {
             $this->buildOverviewTreeForm($element->subtree, $delta);
         }
     }
     $tree_access_cacheability->merge(CacheableMetadata::createFromRenderArray($form))->applyTo($form);
     return $form;
 }
コード例 #25
0
 /**
  * #pre_render callback for building a block.
  *
  * Renders the content using the provided block plugin, if there is no
  * content, aborts rendering, and makes sure the block won't be rendered.
  */
 public function buildBlock($build)
 {
     $content = $build['#block_plugin']->build();
     // Remove the block plugin from the render array.
     unset($build['#block_plugin']);
     if ($content !== NULL && !Element::isEmpty($content)) {
         $build['content'] = $content;
     } else {
         // Abort rendering: render as the empty string and ensure this block is
         // render cached, so we can avoid the work of having to repeatedly
         // determine whether the block is empty. E.g. modifying or adding entities
         // could cause the block to no longer be empty.
         $build = ['#markup' => '', '#cache' => $build['#cache']];
     }
     // If $content is not empty, then it contains cacheability metadata, and
     // we must merge it with the existing cacheability metadata. This allows
     // blocks to be empty, yet still bubble cacheability metadata, to indicate
     // why they are empty.
     if (!empty($content)) {
         CacheableMetadata::createFromRenderArray($build)->merge(CacheableMetadata::createFromRenderArray($content))->applyTo($build);
     }
     return $build;
 }
コード例 #26
0
ファイル: DisplayPluginBase.php プロジェクト: 318io/318-io
 /**
  * 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);
 }
コード例 #27
0
 /**
  * Tests bubbling of menu links' outbound route/path processing cacheability.
  */
 public function testOutboundPathAndRouteProcessing()
 {
     \Drupal::service('router.builder')->rebuild();
     $request_stack = \Drupal::requestStack();
     /** @var \Symfony\Component\Routing\RequestContext $request_context */
     $request_context = \Drupal::service('router.request_context');
     $request = Request::create('/');
     $request->attributes->set(RouteObjectInterface::ROUTE_NAME, '<front>');
     $request->attributes->set(RouteObjectInterface::ROUTE_OBJECT, new Route('/'));
     $request_stack->push($request);
     $request_context->fromRequest($request);
     $menu_tree = \Drupal::menuTree();
     $renderer = \Drupal::service('renderer');
     $default_menu_cacheability = (new CacheableMetadata())->setCacheMaxAge(Cache::PERMANENT)->setCacheTags(['config:system.menu.tools'])->setCacheContexts(['languages:' . LanguageInterface::TYPE_INTERFACE, 'theme']);
     User::create(['uid' => 1, 'name' => $this->randomString()])->save();
     User::create(['uid' => 2, 'name' => $this->randomString()])->save();
     // Five test cases, four asserting one outbound path/route processor, and
     // together covering one of each:
     // - no cacheability metadata,
     // - a cache context,
     // - a cache tag,
     // - a cache max-age.
     // Plus an additional test case to verify that multiple links adding
     // cacheability metadata of the same type is working (two links with cache
     // tags).
     $test_cases = [['uri' => 'route:<current>', 'cacheability' => (new CacheableMetadata())->setCacheContexts(['route'])], ['uri' => 'route:outbound_processing_test.route.csrf', 'cacheability' => (new CacheableMetadata())->setCacheMaxAge(0)], ['uri' => 'internal:/', 'cacheability' => new CacheableMetadata()], ['uri' => 'internal:/user/1', 'cacheability' => (new CacheableMetadata())->setCacheTags(User::load(1)->getCacheTags())], ['uri' => 'internal:/user/2', 'cacheability' => (new CacheableMetadata())->setCacheTags(User::load(2)->getCacheTags())]];
     // Test each expectation individually.
     foreach ($test_cases as $expectation) {
         $menu_link_content = MenuLinkContent::create(['link' => ['uri' => $expectation['uri']], 'menu_name' => 'tools']);
         $menu_link_content->save();
         $tree = $menu_tree->load('tools', new MenuTreeParameters());
         $build = $menu_tree->build($tree);
         $renderer->renderRoot($build);
         $expected_cacheability = $default_menu_cacheability->merge($expectation['cacheability']);
         $this->assertEqual($expected_cacheability, CacheableMetadata::createFromRenderArray($build));
         $menu_link_content->delete();
     }
     // Now test them all together in one menu: the rendered menu's cacheability
     // metadata should be the combination of the cacheability of all links, and
     // thus of all tested outbound path & route processors.
     $expected_cacheability = new CacheableMetadata();
     foreach ($test_cases as $expectation) {
         $menu_link_content = MenuLinkContent::create(['link' => ['uri' => $expectation['uri']], 'menu_name' => 'tools']);
         $menu_link_content->save();
         $expected_cacheability = $expected_cacheability->merge($expectation['cacheability']);
     }
     $tree = $menu_tree->load('tools', new MenuTreeParameters());
     $build = $menu_tree->build($tree);
     $renderer->renderRoot($build);
     $expected_cacheability = $expected_cacheability->merge($default_menu_cacheability);
     $this->assertEqual($expected_cacheability, CacheableMetadata::createFromRenderArray($build));
 }
コード例 #28
0
 /**
  * Creates the cache ID for a renderable element.
  *
  * Creates the cache ID string based on #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']['keys'])) {
         $cid_parts = $elements['#cache']['keys'];
         if (!empty($elements['#cache']['contexts'])) {
             $context_cache_keys = $this->cacheContextsManager->convertTokensToKeys($elements['#cache']['contexts']);
             $cid_parts = array_merge($cid_parts, $context_cache_keys->getKeys());
             CacheableMetadata::createFromRenderArray($elements)->merge($context_cache_keys)->applyTo($elements);
         }
         return implode(':', $cid_parts);
     }
     return FALSE;
 }
コード例 #29
0
ファイル: Field.php プロジェクト: nstielau/drops-8
 /**
  * Gets an array of items for the field.
  *
  * @param \Drupal\views\ResultRow $values
  *   The result row object containing the values.
  *
  * @return array
  *   An array of items for the field.
  */
 public function getItems(ResultRow $values)
 {
     if (!$this->displayHandler->useGroupBy()) {
         $build_list = $this->getEntityFieldRenderer()->render($values, $this);
     } else {
         // For grouped results we need to retrieve a massaged entity having
         // grouped field values to ensure that "grouped by" values, especially
         // those with multiple cardinality work properly. See
         // \Drupal\views\Tests\QueryGroupByTest::testGroupByFieldWithCardinality.
         $display = ['type' => $this->options['type'], 'settings' => $this->options['settings'], 'label' => 'hidden'];
         $build_list = $this->createEntityForGroupBy($this->getEntity($values), $values)->{$this->definition['field_name']}->view($display);
     }
     if (!$build_list) {
         return [];
     }
     if ($this->options['field_api_classes']) {
         return [['rendered' => $this->renderer->render($build_list)]];
     }
     // Render using the formatted data itself.
     $items = [];
     foreach (Element::children($build_list) as $delta) {
         $items[$delta]['rendered'] = $build_list[$delta];
         // Merge the cacheability metadata of the top-level render array into
         // each child because they will most likely be rendered individually.
         if (isset($build_list['#cache'])) {
             CacheableMetadata::createFromRenderArray($build_list)->merge(CacheableMetadata::createFromRenderArray($items[$delta]['rendered']))->applyTo($items[$delta]['rendered']);
         }
         // Add the raw field items (for use in tokens).
         $items[$delta]['raw'] = $build_list['#items'][$delta];
     }
     return $items;
 }