diff -u b/core/includes/common.inc b/core/includes/common.inc --- b/core/includes/common.inc +++ b/core/includes/common.inc @@ -3603,32 +3603,6 @@ } /** - * @needsdoc - */ -function drupal_pre_render($elements) { - // If the default values for this element have not been loaded yet, populate - // them. - if (isset($elements['#type']) && empty($elements['#defaults_loaded'])) { - $elements += element_info($elements['#type']); - } - - if (isset($elements['#pre_render'])) { - foreach ($elements['#pre_render'] as $callable) { - $elements = call_user_func($callable, $elements); - } - // Once the item is built, the callback is no longer needed. - unset($elements['#pre_render']); - } - // Build the child elements as well. - if ($children = element_children($elements)) { - foreach ($children as $child) { - $elements[$child] = drupal_pre_render($elements[$child]); - } - } - return $elements; -} - -/** * Renders the page, including all theming. * * @param string|array $page @@ -3809,11 +3783,19 @@ } } + // If the default values for this element have not been loaded yet, populate + // them. + if (isset($elements['#type']) && empty($elements['#defaults_loaded'])) { + $elements += element_info($elements['#type']); + } + // Make any final changes to the element before it is rendered. This means // that the $element or the children can be altered or corrected before the // element is rendered into the final text. - if (!$is_recursive_call) { - $elements = drupal_pre_render($elements); + if (isset($elements['#pre_render'])) { + foreach ($elements['#pre_render'] as $callable) { + $elements = call_user_func($callable, $elements); + } } // Allow #pre_render to abort rendering. @@ -3821,16 +3803,6 @@ return ''; } - // Collect all #post_render_cache callbacks associated with this element when: - // - about to store this element in the render cache, or when; - // - about to apply #post_render_cache callbacks. - if (isset($elements['#cache']) || !$is_recursive_call) { - $post_render_cache = drupal_render_collect_post_render_cache($elements); - if ($post_render_cache) { - $elements['#post_render_cache'] = $post_render_cache; - } - } - // Add any JavaScript state information associated with the element. if (!empty($elements['#states'])) { drupal_process_states($elements); @@ -3934,6 +3906,12 @@ $suffix = isset($elements['#suffix']) ? $elements['#suffix'] : ''; $elements['#markup'] = $prefix . $elements['#children'] . $suffix; + if (!$is_recursive_call || isset($elements['#cache'])) { + $post_render_cache = drupal_render_collect_post_render_cache($elements); + if ($post_render_cache) { + $elements['#post_render_cache'] = $post_render_cache; + } + } // Collect all cache tags. This allows the caller of drupal_render() to also // access the complete list of cache tags. if (!$is_recursive_call || isset($elements['#cache'])) { @@ -3954,7 +3932,7 @@ // - they run when #cache is enabled and there is a cache miss. // Only the case of a cache hit when #cache is enabled, is not handled here, // that is handled earlier in drupal_render(). - if (!$is_recursive_call) { + if (!$is_recursive_call || isset($elements['#cache'])) { _drupal_render_process_post_render_cache($elements); } @@ -4239,42 +4217,11 @@ // and if keyed by a number, no token is passed, otherwise, the token string // is passed to the callback as well. This token is used to uniquely // identify the placeholder in the markup. - $modified_elements = $elements; foreach ($elements['#post_render_cache'] as $callback => $options) { foreach ($elements['#post_render_cache'][$callback] as $token => $context) { - // The advanced option, when setting #post_render_cache directly. - if (is_numeric($token)) { - $modified_elements = call_user_func_array($callback, array($modified_elements, $context)); - } - // The simple option, when using the standard placeholders, and hence - // also when using #type => render_cache_placeholder. - else { - // Call #post_render_cache callback to generate the element that will - // fill in the placeholder. - $generated_element = call_user_func_array($callback, array($context)); - - // Update #attached based on the generated element. - if (isset($generated_element['#attached'])) { - if (!isset($modified_elements['#attached'])) { - $modified_elements['#attached'] = array(); - } - $modified_elements['#attached'] = drupal_merge_attached($modified_elements['#attached'], drupal_render_collect_attached($generated_element, TRUE)); - } - - // Replace the placeholder with the rendered markup of the generated - // element. - $placeholder = drupal_render_cache_generate_placeholder($callback, $context, $token); - $modified_elements['#markup'] = str_replace($placeholder, drupal_render($generated_element), $modified_elements['#markup']); - } + $elements = call_user_func_array($callback, array($elements, $context)); } } - // Only retain changes to the #markup and #attached properties, as would be - // the case when the render cache was actually being used. - $elements['#markup'] = $modified_elements['#markup']; - if (isset($modified_elements['#attached'])) { - $elements['#attached'] = $modified_elements['#attached']; - } - // Make sure that any attachments added in #post_render_cache callbacks are // also executed. if (isset($elements['#attached'])) { @@ -4331,13 +4278,6 @@ } } - // If this is a render cache placeholder that hasn't been rendered yet, then - // render it now, because we must be able to collect its #post_render_cache - // callback. - if (!isset($elements['#post_render_cache']) && isset($elements['#type']) && $elements['#type'] === 'render_cache_placeholder') { - $elements = drupal_pre_render_render_cache_placeholder($elements); - } - // Collect all #post_render_cache callbacks for this element. if (isset($elements['#post_render_cache'])) { $callbacks = NestedArray::mergeDeep($callbacks, $elements['#post_render_cache']); diff -u b/core/lib/Drupal/Core/Entity/EntityViewBuilder.php b/core/lib/Drupal/Core/Entity/EntityViewBuilder.php --- b/core/lib/Drupal/Core/Entity/EntityViewBuilder.php +++ b/core/lib/Drupal/Core/Entity/EntityViewBuilder.php @@ -147,7 +147,7 @@ $return = array( '#theme' => $this->entityTypeId, - '#build' => array(array($this, 'entityViewBuilderBuildView')), + '#pre_render' => array(array($this, 'entityViewBuilderBuildView')), "#{$this->entityTypeId}" => $entity, '#view_mode' => $view_mode, '#langcode' => $langcode, diff -u b/core/modules/node/lib/Drupal/node/NodeViewBuilder.php b/core/modules/node/lib/Drupal/node/NodeViewBuilder.php --- b/core/modules/node/lib/Drupal/node/NodeViewBuilder.php +++ b/core/modules/node/lib/Drupal/node/NodeViewBuilder.php @@ -34,16 +34,25 @@ $bundle = $entity->bundle(); $display = $displays[$bundle]; + $callback = '\Drupal\node\NodeViewBuilder::renderLinks'; + $token = \Drupal\Component\Utility\Crypt::randomBytesBase64(55); + $context = array( + 'node_entity_id' => $entity->id(), + 'view_mode' => $view_mode, + 'langcode' => $langcode, + 'in_preview' => !empty($entity->in_preview), + 'token' => $token, + ); + $entity->content['links'] = array( - '#type' => 'render_cache_placeholder', - '#callback' => '\Drupal\node\NodeViewBuilder::renderLinks', - '#context' => array( - 'node_entity_id' => $entity->id(), - 'view_mode' => $view_mode, - 'langcode' => $langcode, - 'in_preview' => !empty($entity->in_preview), + '#post_render_cache' => array( + $callback => array( + $context, + ), ), - ); + '#markup' => drupal_render_cache_generate_placeholder($callback, $context, $context['token']), + ); + // Add Language field text element to node render array. if ($display->getComponent('langcode')) { @@ -92,7 +101,10 @@ * @return array * A renderable array representing the node links. */ - public static function renderLinks(array $context) { + public static function renderLinks(array $element, array $context) { + $callback = '\Drupal\node\NodeViewBuilder::renderLinks'; + $placeholder = drupal_render_cache_generate_placeholder($callback, $context, $context['token']); + $links = array( '#theme' => 'links__node', '#pre_render' => array('drupal_pre_render_links'), @@ -110,8 +122,10 @@ ); \Drupal::moduleHandler()->alter('node_links', $links, $entity, $hook_context); } + $replace = drupal_render($links); + $element['#markup'] = str_replace($placeholder, $replace, $element['#markup']); - return $links; + return $element; } /** only in patch2: unchanged: --- a/core/modules/comment/lib/Drupal/comment/CommentViewBuilder.php +++ b/core/modules/comment/lib/Drupal/comment/CommentViewBuilder.php @@ -123,17 +123,24 @@ public function buildContent(array $entities, array $displays, $view_mode, $lang } $entity->content['#entity'] = $entity; $entity->content['#theme'] = 'comment__' . $entity->getFieldId() . '__' . $commented_entity->bundle(); + $callback = '\Drupal\comment\CommentViewBuilder::renderLinks'; + $token = \Drupal\Component\Utility\Crypt::randomBytesBase64(55); + $context = array( + 'comment_entity_id' => $entity->id(), + 'view_mode' => $view_mode, + 'langcode' => $langcode, + 'commented_entity_type' => $commented_entity->getEntityTypeId(), + 'commented_entity_id' => $commented_entity->id(), + 'in_preview' => !empty($entity->in_preview), + 'token' => $token, + ); $entity->content['links'] = array( - '#type' => 'render_cache_placeholder', - '#callback' => '\Drupal\comment\CommentViewBuilder::renderLinks', - '#context' => array( - 'comment_entity_id' => $entity->id(), - 'view_mode' => $view_mode, - 'langcode' => $langcode, - 'commented_entity_type' => $commented_entity->getEntityTypeId(), - 'commented_entity_id' => $commented_entity->id(), - 'in_preview' => !empty($entity->in_preview), + '#post_render_cache' => array( + $callback => array( + $context, + ), ), + '#markup' => drupal_render_cache_generate_placeholder($callback, $context, $context['token']), ); if (!isset($entity->content['#attached'])) { @@ -168,7 +175,9 @@ public function buildContent(array $entities, array $displays, $view_mode, $lang * @return array * A renderable array representing the comment links. */ - public static function renderLinks(array $context) { + public static function renderLinks(array $element, array $context) { + $callback = '\Drupal\comment\CommentViewBuilder::renderLinks'; + $placeholder = drupal_render_cache_generate_placeholder($callback, $context, $context['token']); $links = array( '#theme' => 'links__comment', '#pre_render' => array('drupal_pre_render_links'), @@ -189,8 +198,10 @@ public static function renderLinks(array $context) { ); \Drupal::moduleHandler()->alter('comment_links', $links, $entity, $hook_context); } + $replace = drupal_render($links); + $element['#markup'] = str_replace($placeholder, $replace, $element['#markup']); - return $links; + return $element; } /** only in patch2: unchanged: --- a/core/modules/comment/lib/Drupal/comment/Plugin/Field/FieldFormatter/CommentDefaultFormatter.php +++ b/core/modules/comment/lib/Drupal/comment/Plugin/Field/FieldFormatter/CommentDefaultFormatter.php @@ -162,14 +162,20 @@ public function viewElements(FieldItemListInterface $items) { // All other users need a user-specific form, which would break the // render cache: hence use a #post_render_cache callback. else { + $callback = '\Drupal\comment\Plugin\Field\FieldFormatter\CommentDefaultFormatter::renderForm'; + $context = array( + 'entity_type' => $entity->getEntityTypeId(), + 'entity_id' => $entity->id(), + 'field_name' => $field_name, + 'token' => \Drupal\Component\Utility\Crypt::randomBytesBase64(55), + ); $output['comment_form'] = array( - '#type' => 'render_cache_placeholder', - '#callback' => '\Drupal\comment\Plugin\Field\FieldFormatter\CommentDefaultFormatter::renderForm', - '#context' => array( - 'entity_type' => $entity->getEntityTypeId(), - 'entity_id' => $entity->id(), - 'field_name' => $field_name, + '#post_render_cache' => array( + $callback => array( + $context, + ), ), + '#markup' => drupal_render_cache_generate_placeholder($callback, $context, $context['token']), ); } } @@ -199,9 +205,16 @@ public function viewElements(FieldItemListInterface $items) { * @return array * A renderable array containing the comment form. */ - public static function renderForm(array $context) { + public static function renderForm(array $element, array $context) { + $callback = '\Drupal\comment\Plugin\Field\FieldFormatter\CommentDefaultFormatter::renderForm'; + $placeholder = drupal_render_cache_generate_placeholder($callback, $context, $context['token']); $entity = entity_load($context['entity_type'], $context['entity_id']); - return comment_add($entity, $context['field_name']); + $form = comment_add($entity, $context['field_name']); + // @todo: #attached. + $replace = drupal_render($form); + $element['#markup'] = str_replace($placeholder, $replace, $element['#markup']); + + return $element; } /** @@ -231,5 +244,4 @@ public function settingsSummary() { } return array(); } - }