diff --git a/core/includes/common.inc b/core/includes/common.inc index 667807a..d536478 100644 --- a/core/includes/common.inc +++ b/core/includes/common.inc @@ -5016,7 +5016,7 @@ function drupal_render_cache_set(&$markup, $elements) { } $bin = isset($elements['#cache']['bin']) ? $elements['#cache']['bin'] : 'cache'; $expire = isset($elements['#cache']['expire']) ? $elements['#cache']['expire'] : CacheBackendInterface::CACHE_PERMANENT; - $tags = isset($elements['#cache']['tags']) ? $elements['#cache']['tags'] : array(); + $tags = drupal_render_collect_cache_tags($elements, TRUE); cache($bin)->set($cid, $data, $expire, $tags); } @@ -5064,6 +5064,57 @@ function drupal_render_collect_attached($elements, $return = FALSE) { } /** + * Collects cache tags for an element and its children into a single array. + * + * When caching elements, it is necessary to collect all cache tags into a + * single array, from both the element itself and all child elements. This + * allows items to be invalidated based on all tags attached to the content + * they're constituted from. + * + * @param array $elements + * The element to collect cache tags from. + * @param bool $return + * Whether to return the attached elements and reset the internal static. + * + * @return array + * The cache tags array for this element and its descendants. + */ +function drupal_render_collect_cache_tags($elements, $return = FALSE) { + $tags = &drupal_static(__FUNCTION__, array()); + + // Collect all cache tags for this element. + if (isset($elements['#cache']['tags'])) { + foreach ($elements['#cache']['tags'] as $namespace => $values) { + if (is_array($values)) { + foreach ($values as $value) { + if (!isset($tags[$namespace][$value])) { + $tags[$namespace][$value] = $value; + } + } + } + else { + if (!isset($tags[$namespace])) { + $tags[$namespace] = $values; + } + } + } + } + if ($children = element_children($elements)) { + foreach ($children as $child) { + drupal_render_collect_cache_tags($elements[$child]); + } + } + + // If this was the first call to the function, return all attached elements + // and reset the static cache. + if ($return) { + $return = $tags; + $tags = array(); + return $return; + } +} + +/** * Prepares an element for caching based on a query. * * This smart caching strategy saves Drupal from querying and rendering to HTML diff --git a/core/includes/entity.inc b/core/includes/entity.inc index 702a56e..948106c 100644 --- a/core/includes/entity.inc +++ b/core/includes/entity.inc @@ -47,6 +47,18 @@ function entity_info_cache_clear() { } /** + * Clears the entity render cache for all entity types. + */ +function entity_render_cache_clear() { + $entity_manager = Drupal::entityManager(); + foreach ($entity_manager->getDefinitions() as $entity_type => $info) { + if ($entity_manager->hasController($entity_type, 'render')) { + $entity_manager->getRenderController($entity_type)->resetCache(); + } + } +} + +/** * Returns the entity bundle info. * * @param string|null $entity_type @@ -580,14 +592,19 @@ function entity_render_controller($entity_type) { * @param string $langcode * (optional) For which language the entity should be rendered, defaults to * the current content language. + * @param bool $reset + * (optional) Whether to reset the render cache for the requested entity. + * Defaults to FALSE. * * @return array * A render array for the entity. */ -function entity_view(EntityInterface $entity, $view_mode, $langcode = NULL) { - return Drupal::entityManager() - ->getRenderController($entity->entityType()) - ->view($entity, $view_mode, $langcode); +function entity_view(EntityInterface $entity, $view_mode, $langcode = NULL, $reset = FALSE) { + $render_controller = Drupal::entityManager()->getRenderController($entity->entityType()); + if ($reset) { + $render_controller->resetCache(array($entity)); + } + return $render_controller->view($entity, $view_mode, $langcode); } /** @@ -600,15 +617,20 @@ function entity_view(EntityInterface $entity, $view_mode, $langcode = NULL) { * @param string $langcode * (optional) For which language the entity should be rendered, defaults to * the current content language. + * @param bool $reset + * (optional) Whether to reset the render cache for the requested entities. + * Defaults to FALSE. * * @return array * A render array for the entities, indexed by the same keys as the * entities array passed in $entities. */ -function entity_view_multiple(array $entities, $view_mode, $langcode = NULL) { - return Drupal::entityManager() - ->getRenderController(reset($entities)->entityType()) - ->viewMultiple($entities, $view_mode, $langcode); +function entity_view_multiple(array $entities, $view_mode, $langcode = NULL, $reset = FALSE) { + $render_controller = Drupal::entityManager()->getRenderController(reset($entities)->entityType()); + if ($reset) { + $render_controller->resetCache($entities); + } + return $render_controller->viewMultiple($entities, $view_mode, $langcode); } /** diff --git a/core/lib/Drupal/Core/Entity/Annotation/EntityType.php b/core/lib/Drupal/Core/Entity/Annotation/EntityType.php index beaa4e3..735f5e0 100644 --- a/core/lib/Drupal/Core/Entity/Annotation/EntityType.php +++ b/core/lib/Drupal/Core/Entity/Annotation/EntityType.php @@ -138,6 +138,14 @@ class EntityType extends Plugin { public $static_cache = TRUE; /** + * Boolean indicating whether the rendered output of entities should be + * cached. + * + * @var bool (optional) + */ + public $render_cache = TRUE; + + /** * Boolean indicating whether entities of this type have multilingual support. * * At an entity level, this indicates language support and at a bundle level diff --git a/core/lib/Drupal/Core/Entity/EntityFormController.php b/core/lib/Drupal/Core/Entity/EntityFormController.php index 7c5f7ed..69644e2 100644 --- a/core/lib/Drupal/Core/Entity/EntityFormController.php +++ b/core/lib/Drupal/Core/Entity/EntityFormController.php @@ -289,7 +289,10 @@ public function submit(array $form, array &$form_state) { * A reference to a keyed array containing the current state of the form. */ public function save(array $form, array &$form_state) { - // @todo Perform common save operations. + // Clear the render cache. + if (\Drupal::entityManager()->hasController($this->entity->entityType(), 'render')) { + \Drupal::entityManager()->getRenderController($this->entity->entityType())->resetCache(); + } } /** diff --git a/core/lib/Drupal/Core/Entity/EntityRenderController.php b/core/lib/Drupal/Core/Entity/EntityRenderController.php index d202636..5fc1fa8 100644 --- a/core/lib/Drupal/Core/Entity/EntityRenderController.php +++ b/core/lib/Drupal/Core/Entity/EntityRenderController.php @@ -22,8 +22,37 @@ class EntityRenderController implements EntityRenderControllerInterface { */ protected $entityType; + /** + * The entity info array. + * + * @var array + * + * @see entity_get_info() + */ + protected $entityInfo; + + /** + * An array of view mode info for the type of entities for which this + * controller is instantiated. + * + * @var array + */ + protected $viewModesInfo; + + /** + * The cache bin used to store the render cache. + * + * @todo Defaults to 'cache' for now, until http://drupal.org/node/1194136 is + * fixed. + * + * @var string + */ + protected $cacheBin = 'cache'; + public function __construct($entity_type) { $this->entityType = $entity_type; + $this->entityInfo = entity_get_info($entity_type); + $this->viewModesInfo = entity_get_view_modes($entity_type); } /** @@ -62,6 +91,21 @@ protected function getBuildDefaults(EntityInterface $entity, $view_mode, $langco '#view_mode' => $view_mode, '#langcode' => $langcode, ); + + // Cache the rendered output if permitted by the view mode settings. + $view_mode_is_cacheable = !isset($this->viewModesInfo[$view_mode]) || (isset($this->viewModesInfo[$view_mode]) && $this->viewModesInfo[$view_mode]['cache']); + if (!isset($entity->in_preview) && $this->entityInfo['render_cache'] && $view_mode_is_cacheable) { + $return['#cache'] = array( + 'keys' => array('entity_view', $this->entityType ,$entity->id(), $view_mode), + 'granularity' => DRUPAL_CACHE_PER_ROLE, + 'bin' => $this->cacheBin, + 'tags' => array( + $this->entityType . '_view' => TRUE, + $this->entityType => array($entity->id()), + ), + ); + } + return $return; } @@ -164,4 +208,35 @@ public function viewMultiple(array $entities = array(), $view_mode = 'full', $la return $build; } + + /** + * Implements \Drupal\Core\Entity\EntityRenderControllerInterface::resetCache(). + */ + public function resetCache(array $entities = NULL) { + if (isset($entities)) { + $tags = array(); + foreach ($entities as $entity) { + $tags[$this->entityType][$entity->id()] = $entity->id(); + + // @todo Remove when all entities are converted to EntityNG. + if ($entity->getPropertyDefinitions() === NULL) { + continue; + } + + // Add all the referenced entity types and IDs to the tags that will be + // cleared. + foreach ($entity->getPropertyDefinitions() as $name => $definition) { + if ($definition['type'] == 'entity_reference_field' && $field_values = $entity->get($name)->getValue()) { + foreach ($field_values as $value) { + $tags[$definition['settings']['target_type']][$value['target_id']] = $value['target_id']; + } + } + } + } + \Drupal::cache($this->cacheBin)->deleteTags($tags); + } + else { + \Drupal::cache($this->cacheBin)->deleteTags(array($this->entityType . '_view' => TRUE)); + } + } } diff --git a/core/lib/Drupal/Core/Entity/EntityRenderControllerInterface.php b/core/lib/Drupal/Core/Entity/EntityRenderControllerInterface.php index 03ba014..88e1461 100644 --- a/core/lib/Drupal/Core/Entity/EntityRenderControllerInterface.php +++ b/core/lib/Drupal/Core/Entity/EntityRenderControllerInterface.php @@ -75,4 +75,12 @@ public function view(EntityInterface $entity, $view_mode = 'full', $langcode = N * be available for loading. */ public function viewMultiple(array $entities = array(), $view_mode = 'full', $langcode = NULL); + + /** + * Resets the entity render cache. + * + * @param array|null $entities + * (optional) If specified, the cache is reset for the given entities only. + */ + public function resetCache(array $entities = NULL); } diff --git a/core/modules/aggregator/lib/Drupal/aggregator/FeedFormController.php b/core/modules/aggregator/lib/Drupal/aggregator/FeedFormController.php index 1e77d7c..e769281 100644 --- a/core/modules/aggregator/lib/Drupal/aggregator/FeedFormController.php +++ b/core/modules/aggregator/lib/Drupal/aggregator/FeedFormController.php @@ -112,6 +112,8 @@ public function validate(array $form, array &$form_state) { * Overrides Drupal\Core\Entity\EntityFormController::save(). */ public function save(array $form, array &$form_state) { + parent::save($form, $form_state); + $feed = $this->entity; $insert = (bool) $feed->id(); if (!empty($form_state['values']['category'])) { diff --git a/core/modules/block/custom_block/config/entity.view_mode.custom_block.full.yml b/core/modules/block/custom_block/config/entity.view_mode.custom_block.full.yml index ebacec5..6c2a3d1 100644 --- a/core/modules/block/custom_block/config/entity.view_mode.custom_block.full.yml +++ b/core/modules/block/custom_block/config/entity.view_mode.custom_block.full.yml @@ -1,4 +1,5 @@ id: custom_block.full label: Full status: '0' +cache: '1' targetEntityType: custom_block diff --git a/core/modules/block/custom_block/lib/Drupal/custom_block/CustomBlockFormController.php b/core/modules/block/custom_block/lib/Drupal/custom_block/CustomBlockFormController.php index 2457d97..7ec62ee 100644 --- a/core/modules/block/custom_block/lib/Drupal/custom_block/CustomBlockFormController.php +++ b/core/modules/block/custom_block/lib/Drupal/custom_block/CustomBlockFormController.php @@ -160,6 +160,8 @@ public function submit(array $form, array &$form_state) { * Overrides \Drupal\Core\Entity\EntityFormController::save(). */ public function save(array $form, array &$form_state) { + parent::save($form, $form_state); + $block = $this->entity; $insert = empty($block->id->value); $block->save(); diff --git a/core/modules/block/custom_block/lib/Drupal/custom_block/CustomBlockTypeFormController.php b/core/modules/block/custom_block/lib/Drupal/custom_block/CustomBlockTypeFormController.php index 6e5de33..bb9159a 100644 --- a/core/modules/block/custom_block/lib/Drupal/custom_block/CustomBlockTypeFormController.php +++ b/core/modules/block/custom_block/lib/Drupal/custom_block/CustomBlockTypeFormController.php @@ -87,6 +87,8 @@ public function form(array $form, array &$form_state) { * Overrides \Drupal\Core\Entity\EntityFormController::save(). */ public function save(array $form, array &$form_state) { + parent::save($form, $form_state); + $block_type = $this->entity; $status = $block_type->save(); diff --git a/core/modules/block/lib/Drupal/block/BlockRenderController.php b/core/modules/block/lib/Drupal/block/BlockRenderController.php index 45a85d9..fb7edfb 100644 --- a/core/modules/block/lib/Drupal/block/BlockRenderController.php +++ b/core/modules/block/lib/Drupal/block/BlockRenderController.php @@ -62,4 +62,10 @@ public function viewMultiple(array $entities = array(), $view_mode = 'full', $la return $build; } + /** + * Implements \Drupal\Core\Entity\EntityRenderControllerInterface::resetCache(). + */ + public function resetCache(array $entities = NULL) { + // @todo Move block render caching logic to this controller? + } } diff --git a/core/modules/book/config/entity.view_mode.node.print.yml b/core/modules/book/config/entity.view_mode.node.print.yml index fe45f50..6f7333f 100644 --- a/core/modules/book/config/entity.view_mode.node.print.yml +++ b/core/modules/book/config/entity.view_mode.node.print.yml @@ -1,4 +1,5 @@ id: node.print label: Print status: '0' +cache: '1' targetEntityType: node diff --git a/core/modules/comment/comment.admin.inc b/core/modules/comment/comment.admin.inc index 3890a1a..3d1bef2 100644 --- a/core/modules/comment/comment.admin.inc +++ b/core/modules/comment/comment.admin.inc @@ -206,6 +206,7 @@ function comment_admin_overview_submit($form, &$form_state) { } drupal_set_message(t('The update has been performed.')); $form_state['redirect'] = 'admin/content/comment'; + Drupal::entityManager()->getRenderController('comment')->resetCache(array($comment)); cache_invalidate_tags(array('content' => TRUE)); } @@ -253,7 +254,13 @@ function comment_multiple_delete_confirm($form, &$form_state) { */ function comment_multiple_delete_confirm_submit($form, &$form_state) { if ($form_state['values']['confirm']) { - entity_delete_multiple('comment', array_keys($form_state['values']['comments'])); + $entity_manager = Drupal::entityManager(); + + $controller = $entity_manager->getStorageController('comment'); + $entities = $controller->load(array_keys($form_state['values']['comments'])); + $controller->delete($entities); + + $entity_manager->getRenderController('comment')->resetCache($entities); cache_invalidate_tags(array('content' => TRUE)); $count = count($form_state['values']['comments']); watchdog('content', 'Deleted @count comments.', array('@count' => $count)); @@ -310,6 +317,7 @@ function comment_confirm_delete_submit($form, &$form_state) { drupal_set_message(t('The comment and all its replies have been deleted.')); watchdog('content', 'Deleted comment @cid and its replies.', array('@cid' => $comment->id())); // Clear the cache so an anonymous user sees that his comment was deleted. + Drupal::entityManager()->getRenderController('comment')->resetCache(array($comment)); cache_invalidate_tags(array('content' => TRUE)); $form_state['redirect'] = "node/{$comment->nid->target_id}"; diff --git a/core/modules/comment/comment.pages.inc b/core/modules/comment/comment.pages.inc index 5e1b190..371da22 100644 --- a/core/modules/comment/comment.pages.inc +++ b/core/modules/comment/comment.pages.inc @@ -80,6 +80,7 @@ function comment_reply(EntityInterface $node, $pid = NULL) { // This is the case where the comment is in response to a node. Display the node. elseif (user_access('access content')) { $build['comment_node'] = node_view($node); + unset($build['comment_node']['#cache']); } // Should we show the reply box? @@ -118,6 +119,7 @@ function comment_approve(Comment $comment) { $comment->status->value = COMMENT_PUBLISHED; $comment->save(); + Drupal::entityManager()->getRenderController('comment')->resetCache(array($comment)); drupal_set_message(t('Comment approved.')); drupal_goto('node/' . $comment->nid->target_id); diff --git a/core/modules/comment/config/entity.view_mode.comment.full.yml b/core/modules/comment/config/entity.view_mode.comment.full.yml index e48fbd7..abfc646 100644 --- a/core/modules/comment/config/entity.view_mode.comment.full.yml +++ b/core/modules/comment/config/entity.view_mode.comment.full.yml @@ -1,4 +1,5 @@ id: comment.full label: Full comment status: '0' +cache: '1' targetEntityType: comment diff --git a/core/modules/comment/lib/Drupal/comment/CommentFormController.php b/core/modules/comment/lib/Drupal/comment/CommentFormController.php index e2040d5..6c5f86d 100644 --- a/core/modules/comment/lib/Drupal/comment/CommentFormController.php +++ b/core/modules/comment/lib/Drupal/comment/CommentFormController.php @@ -310,6 +310,8 @@ public function preview(array $form, array &$form_state) { * Overrides Drupal\Core\Entity\EntityFormController::save(). */ public function save(array $form, array &$form_state) { + parent::save($form, $form_state); + $node = node_load($form_state['values']['nid']); $comment = $this->entity; diff --git a/core/modules/comment/lib/Drupal/comment/CommentRenderController.php b/core/modules/comment/lib/Drupal/comment/CommentRenderController.php index c6b21f0..14585d6 100644 --- a/core/modules/comment/lib/Drupal/comment/CommentRenderController.php +++ b/core/modules/comment/lib/Drupal/comment/CommentRenderController.php @@ -79,9 +79,10 @@ protected function alterBuild(array &$build, EntityInterface $comment, EntityDis $is_threaded = isset($comment->divs) && variable_get('comment_default_mode_' . $comment->bundle(), COMMENT_MODE_THREADED) == COMMENT_MODE_THREADED; - // Add 'new' anchor if needed. + // Add 'new' anchor and disable render cache if needed. if (!empty($comment->first_new)) { $prefix .= "\n"; + unset($build['#cache']); } // Add indentation div or close open divs as needed. diff --git a/core/modules/comment/lib/Drupal/comment/Plugin/Action/SaveComment.php b/core/modules/comment/lib/Drupal/comment/Plugin/Action/SaveComment.php index 6127c8d..5ca8f25 100644 --- a/core/modules/comment/lib/Drupal/comment/Plugin/Action/SaveComment.php +++ b/core/modules/comment/lib/Drupal/comment/Plugin/Action/SaveComment.php @@ -28,6 +28,7 @@ class SaveComment extends ActionBase { */ public function execute($comment = NULL) { $comment->save(); + \Drupal::entityManager()->getRenderController('comment')->resetCache(array($comment)); Cache::invalidateTags(array('content' => TRUE)); } diff --git a/core/modules/comment/lib/Drupal/comment/Tests/CommentAnonymousTest.php b/core/modules/comment/lib/Drupal/comment/Tests/CommentAnonymousTest.php index f4ef8cf..f6d595c 100644 --- a/core/modules/comment/lib/Drupal/comment/Tests/CommentAnonymousTest.php +++ b/core/modules/comment/lib/Drupal/comment/Tests/CommentAnonymousTest.php @@ -148,6 +148,8 @@ function testAnonymous() { 'post comments' => FALSE, 'skip comment approval' => FALSE, )); + \Drupal::entityManager()->getRenderController('node')->resetCache(); + \Drupal::entityManager()->getRenderController('comment')->resetCache(); $this->drupalGet('node/' . $this->node->nid); $this->assertPattern('@]*>Comments@', 'Comments were displayed.'); $this->assertLink('Log in', 1, 'Link to log in was found.'); @@ -158,6 +160,8 @@ function testAnonymous() { 'post comments' => TRUE, 'skip comment approval' => TRUE, )); + \Drupal::entityManager()->getRenderController('node')->resetCache(); + \Drupal::entityManager()->getRenderController('comment')->resetCache(); $this->drupalGet('node/' . $this->node->nid); $this->assertNoPattern('@]*>Comments@', 'Comments were not displayed.'); $this->assertFieldByName('subject', '', 'Subject field found.'); diff --git a/core/modules/comment/lib/Drupal/comment/Tests/CommentLinksTest.php b/core/modules/comment/lib/Drupal/comment/Tests/CommentLinksTest.php index a0f0cdc..082b746 100644 --- a/core/modules/comment/lib/Drupal/comment/Tests/CommentLinksTest.php +++ b/core/modules/comment/lib/Drupal/comment/Tests/CommentLinksTest.php @@ -210,6 +210,9 @@ function setEnvironment(array $info) { // Update current environment. $current = $info; + // Clear the render cache. + entity_render_cache_clear(); + return $info; } diff --git a/core/modules/comment/lib/Drupal/comment/Tests/CommentTestBase.php b/core/modules/comment/lib/Drupal/comment/Tests/CommentTestBase.php index 22132c1..8573f95 100644 --- a/core/modules/comment/lib/Drupal/comment/Tests/CommentTestBase.php +++ b/core/modules/comment/lib/Drupal/comment/Tests/CommentTestBase.php @@ -268,6 +268,7 @@ function setCommentsPerPage($number) { */ function setCommentSettings($name, $value, $message) { variable_set($name . '_article', $value); + \Drupal::entityManager()->getRenderController('comment')->resetCache(); // Display status message. $this->pass($message); } diff --git a/core/modules/config/tests/config_test/lib/Drupal/config_test/ConfigTestFormController.php b/core/modules/config/tests/config_test/lib/Drupal/config_test/ConfigTestFormController.php index 119774b..ebc6596 100644 --- a/core/modules/config/tests/config_test/lib/Drupal/config_test/ConfigTestFormController.php +++ b/core/modules/config/tests/config_test/lib/Drupal/config_test/ConfigTestFormController.php @@ -69,6 +69,8 @@ public function form(array $form, array &$form_state) { * Overrides Drupal\Core\Entity\EntityFormController::save(). */ public function save(array $form, array &$form_state) { + parent::save($form, $form_state); + $entity = $this->entity; $status = $entity->save(); diff --git a/core/modules/contact/lib/Drupal/contact/CategoryFormController.php b/core/modules/contact/lib/Drupal/contact/CategoryFormController.php index 5f2e78c..2ec70d7 100644 --- a/core/modules/contact/lib/Drupal/contact/CategoryFormController.php +++ b/core/modules/contact/lib/Drupal/contact/CategoryFormController.php @@ -94,6 +94,8 @@ public function validate(array $form, array &$form_state) { * Overrides Drupal\Core\Entity\EntityFormController::save(). */ public function save(array $form, array &$form_state) { + parent::save($form, $form_state); + $category = $this->entity; $status = $category->save(); diff --git a/core/modules/contact/lib/Drupal/contact/MessageFormController.php b/core/modules/contact/lib/Drupal/contact/MessageFormController.php index 723b8ca..276ed9f 100644 --- a/core/modules/contact/lib/Drupal/contact/MessageFormController.php +++ b/core/modules/contact/lib/Drupal/contact/MessageFormController.php @@ -138,6 +138,7 @@ public function preview(array $form, array &$form_state) { */ public function save(array $form, array &$form_state) { global $user; + parent::save($form, $form_state); $language_interface = language(Language::TYPE_INTERFACE); $message = $this->entity; diff --git a/core/modules/entity/lib/Drupal/entity/EntityDisplayBase.php b/core/modules/entity/lib/Drupal/entity/EntityDisplayBase.php index 0a7ff40..a41b57f 100644 --- a/core/modules/entity/lib/Drupal/entity/EntityDisplayBase.php +++ b/core/modules/entity/lib/Drupal/entity/EntityDisplayBase.php @@ -126,7 +126,14 @@ public function save() { if (empty($this->id)) { $this->id = $this->id(); } - return parent::save(); + $return = parent::save(); + + // Reset the render cache for the target entity type. + if (\Drupal::entityManager()->hasController($this->targetEntityType, 'render')) { + \Drupal::entityManager()->getRenderController($this->targetEntityType)->resetCache(); + } + + return $return; } /** diff --git a/core/modules/entity/lib/Drupal/entity/Plugin/Core/Entity/EntityViewMode.php b/core/modules/entity/lib/Drupal/entity/Plugin/Core/Entity/EntityViewMode.php index c2c54dd..a29bb82 100644 --- a/core/modules/entity/lib/Drupal/entity/Plugin/Core/Entity/EntityViewMode.php +++ b/core/modules/entity/lib/Drupal/entity/Plugin/Core/Entity/EntityViewMode.php @@ -91,4 +91,11 @@ class EntityViewMode extends ConfigEntityBase implements EntityViewModeInterface */ public $status = FALSE; + /** + * Whether or not the rendered output of this view mode is cached by default. + * + * @var bool + */ + public $cache = TRUE; + } diff --git a/core/modules/field/lib/Drupal/field/Plugin/Type/Formatter/FormatterBase.php b/core/modules/field/lib/Drupal/field/Plugin/Type/Formatter/FormatterBase.php index fa780a5..686d040 100644 --- a/core/modules/field/lib/Drupal/field/Plugin/Type/Formatter/FormatterBase.php +++ b/core/modules/field/lib/Drupal/field/Plugin/Type/Formatter/FormatterBase.php @@ -97,6 +97,14 @@ public function view(EntityInterface $entity, $langcode, array $items) { '#formatter' => $this->getPluginId(), ); + // Gather cache tags from reference fields. + foreach ($items as $item) { + if (isset($item['entity'])) { + $info['#cache']['tags'][$item['entity']->entityType()][] = $item['entity']->id(); + $info['#cache']['tags'][$item['entity']->entityType() . '_view'] = TRUE; + } + } + $addition[$field_name] = array_merge($info, $elements); } diff --git a/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/TestEntityFormController.php b/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/TestEntityFormController.php index d5a4508..7d48c0d 100644 --- a/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/TestEntityFormController.php +++ b/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/TestEntityFormController.php @@ -37,6 +37,8 @@ public function form(array $form, array &$form_state) { * Overrides Drupal\Core\Entity\EntityFormController::save(). */ public function save(array $form, array &$form_state) { + parent::save($form, $form_state); + $entity = $this->entity; $is_new = $entity->isNew(); $entity->save(); diff --git a/core/modules/field_ui/lib/Drupal/field_ui/DisplayOverview.php b/core/modules/field_ui/lib/Drupal/field_ui/DisplayOverview.php index e77dfee..3d9e94a 100644 --- a/core/modules/field_ui/lib/Drupal/field_ui/DisplayOverview.php +++ b/core/modules/field_ui/lib/Drupal/field_ui/DisplayOverview.php @@ -531,6 +531,9 @@ public function submitForm(array &$form, array &$form_state) { field_bundle_settings($this->entity_type, $this->bundle, $bundle_settings); } + // Clear the render cache for this entity type. + \Drupal::entityManager()->getRenderController($this->entity_type)->resetCache(); + drupal_set_message(t('Your settings have been saved.')); } diff --git a/core/modules/field_ui/lib/Drupal/field_ui/Tests/ManageDisplayTest.php b/core/modules/field_ui/lib/Drupal/field_ui/Tests/ManageDisplayTest.php index 55028d1..c26b2cf 100644 --- a/core/modules/field_ui/lib/Drupal/field_ui/Tests/ManageDisplayTest.php +++ b/core/modules/field_ui/lib/Drupal/field_ui/Tests/ManageDisplayTest.php @@ -280,7 +280,7 @@ function assertNodeViewTextHelper(EntityInterface $node, $view_mode, $text, $mes // Render a cloned node, so that we do not alter the original. $clone = clone $node; - $element = node_view($clone, $view_mode); + $element = entity_view($clone, $view_mode, NULL, TRUE); $output = drupal_render($element); $this->verbose(t('Rendered node - view mode: @view_mode', array('@view_mode' => $view_mode)) . '
'. $output); diff --git a/core/modules/file/config/entity.view_mode.file.full.yml b/core/modules/file/config/entity.view_mode.file.full.yml index 60808f9..4d4ed1f 100644 --- a/core/modules/file/config/entity.view_mode.file.full.yml +++ b/core/modules/file/config/entity.view_mode.file.full.yml @@ -1,4 +1,5 @@ id: file.full label: File default status: '0' +cache: '1' targetEntityType: file diff --git a/core/modules/filter/filter.admin.inc b/core/modules/filter/filter.admin.inc index a4493a9..911612a 100644 --- a/core/modules/filter/filter.admin.inc +++ b/core/modules/filter/filter.admin.inc @@ -344,5 +344,6 @@ function filter_admin_format_form_submit($form, &$form_state) { break; } + entity_render_cache_clear(); $form_state['redirect'] = 'admin/config/content/formats'; } diff --git a/core/modules/image/lib/Drupal/image/Tests/ImageFieldDisplayTest.php b/core/modules/image/lib/Drupal/image/Tests/ImageFieldDisplayTest.php index ccc39bd..e2127e1 100644 --- a/core/modules/image/lib/Drupal/image/Tests/ImageFieldDisplayTest.php +++ b/core/modules/image/lib/Drupal/image/Tests/ImageFieldDisplayTest.php @@ -231,6 +231,7 @@ function testImageFieldDefaultImage() { $this->drupalPost("admin/structure/types/manage/article/fields/node.article.$field_name/field", $edit, t('Save field settings')); // Clear field info cache so the new default image is detected. field_info_cache_clear(); + \Drupal::entityManager()->getRenderController('node')->resetCache(array($node)); $field = field_info_field($field_name); $image = file_load($field['settings']['default_image']); $this->assertTrue($image->isPermanent(), 'The default image status is permanent.'); diff --git a/core/modules/menu/lib/Drupal/menu/MenuFormController.php b/core/modules/menu/lib/Drupal/menu/MenuFormController.php index 4eeab27..7aeac04 100644 --- a/core/modules/menu/lib/Drupal/menu/MenuFormController.php +++ b/core/modules/menu/lib/Drupal/menu/MenuFormController.php @@ -83,6 +83,8 @@ protected function actions(array $form, array &$form_state) { * Overrides Drupal\Core\Entity\EntityFormController::save(). */ public function save(array $form, array &$form_state) { + parent::save($form, $form_state); + $menu = $this->entity; $system_menus = menu_list_system_menus(); diff --git a/core/modules/menu_link/lib/Drupal/menu_link/MenuLinkFormController.php b/core/modules/menu_link/lib/Drupal/menu_link/MenuLinkFormController.php index 9aa76d4..728f659 100644 --- a/core/modules/menu_link/lib/Drupal/menu_link/MenuLinkFormController.php +++ b/core/modules/menu_link/lib/Drupal/menu_link/MenuLinkFormController.php @@ -237,8 +237,9 @@ public function submit(array $form, array &$form_state) { * Overrides EntityFormController::save(). */ public function save(array $form, array &$form_state) { - $menu_link = $this->entity; + parent::save($form, $form_state); + $menu_link = $this->entity; $saved = $menu_link->save(); if ($saved) { diff --git a/core/modules/node/config/entity.view_mode.node.full.yml b/core/modules/node/config/entity.view_mode.node.full.yml index af6d938..e4d8bd0 100644 --- a/core/modules/node/config/entity.view_mode.node.full.yml +++ b/core/modules/node/config/entity.view_mode.node.full.yml @@ -1,4 +1,5 @@ id: node.full label: Full content status: '0' +cache: '1' targetEntityType: node diff --git a/core/modules/node/config/entity.view_mode.node.rss.yml b/core/modules/node/config/entity.view_mode.node.rss.yml index 984b05f..0dbf7c1 100644 --- a/core/modules/node/config/entity.view_mode.node.rss.yml +++ b/core/modules/node/config/entity.view_mode.node.rss.yml @@ -1,4 +1,5 @@ id: node.rss label: RSS status: '0' +cache: '1' targetEntityType: node diff --git a/core/modules/node/config/entity.view_mode.node.teaser.yml b/core/modules/node/config/entity.view_mode.node.teaser.yml index 2089b94..636de15 100644 --- a/core/modules/node/config/entity.view_mode.node.teaser.yml +++ b/core/modules/node/config/entity.view_mode.node.teaser.yml @@ -1,4 +1,5 @@ id: node.teaser label: Teaser status: '1' +cache: '1' targetEntityType: node diff --git a/core/modules/node/lib/Drupal/node/NodeFormController.php b/core/modules/node/lib/Drupal/node/NodeFormController.php index bdd5801..a95583f 100644 --- a/core/modules/node/lib/Drupal/node/NodeFormController.php +++ b/core/modules/node/lib/Drupal/node/NodeFormController.php @@ -433,6 +433,8 @@ public function unpublish(array $form, array &$form_state) { * Overrides Drupal\Core\Entity\EntityFormController::save(). */ public function save(array $form, array &$form_state) { + parent::save($form, $form_state); + $node = $this->entity; $insert = empty($node->nid); $node->save(); diff --git a/core/modules/node/lib/Drupal/node/NodeRenderController.php b/core/modules/node/lib/Drupal/node/NodeRenderController.php index 6a6608a..5973fbd 100644 --- a/core/modules/node/lib/Drupal/node/NodeRenderController.php +++ b/core/modules/node/lib/Drupal/node/NodeRenderController.php @@ -91,6 +91,10 @@ protected function alterBuild(array &$build, EntityInterface $entity, EntityDisp if (!empty($entity->nid)) { $build['#contextual_links']['node'] = array('node', array($entity->nid)); } + + // The node 'submitted' info is not rendered in a standard way (renderable + // array) so we have to add a cache tag manually. + $build['#cache']['tags']['user'][] = $entity->uid; } } diff --git a/core/modules/node/lib/Drupal/node/Tests/NodeRevisionsTest.php b/core/modules/node/lib/Drupal/node/Tests/NodeRevisionsTest.php index 640175a..60d53e1 100644 --- a/core/modules/node/lib/Drupal/node/Tests/NodeRevisionsTest.php +++ b/core/modules/node/lib/Drupal/node/Tests/NodeRevisionsTest.php @@ -141,6 +141,7 @@ function testRevisions() { $new_node_revision->setNewRevision(); $new_node_revision->isDefaultRevision = FALSE; $new_node_revision->save(); + \Drupal::entityManager()->getRenderController('node')->resetCache(array($node)); $this->drupalGet("node/$node->nid"); $this->assertNoText($new_body, 'Revision body text is not present on default version of node.'); diff --git a/core/modules/node/lib/Drupal/node/Tests/Views/RowPluginTest.php b/core/modules/node/lib/Drupal/node/Tests/Views/RowPluginTest.php index 4924f56..b43fc3c 100644 --- a/core/modules/node/lib/Drupal/node/Tests/Views/RowPluginTest.php +++ b/core/modules/node/lib/Drupal/node/Tests/Views/RowPluginTest.php @@ -137,6 +137,7 @@ public function testRowPlugin() { // Test with links disabled. $view->rowPlugin->options['links'] = FALSE; + \Drupal::entityManager()->getRenderController('node')->resetCache(); $output = $view->preview(); $output = drupal_render($output); $this->drupalSetContent($output); @@ -146,6 +147,7 @@ public function testRowPlugin() { // Test with links enabled. $view->rowPlugin->options['links'] = TRUE; + \Drupal::entityManager()->getRenderController('node')->resetCache(); $output = $view->preview(); $output = drupal_render($output); $this->drupalSetContent($output); @@ -155,6 +157,7 @@ public function testRowPlugin() { // Test with comments enabled. $view->rowPlugin->options['comments'] = TRUE; + \Drupal::entityManager()->getRenderController('node')->resetCache(); $output = $view->preview(); $output = drupal_render($output); foreach ($this->nodes as $node) { @@ -165,6 +168,7 @@ public function testRowPlugin() { // Test with comments disabled. $view->rowPlugin->options['comments'] = FALSE; + \Drupal::entityManager()->getRenderController('node')->resetCache(); $output = $view->preview(); $output = drupal_render($output); foreach ($this->nodes as $node) { diff --git a/core/modules/node/node.module b/core/modules/node/node.module index 3245f24..f09831c 100644 --- a/core/modules/node/node.module +++ b/core/modules/node/node.module @@ -1012,16 +1012,18 @@ function node_revision_delete($revision_id) { * @see node_menu() */ function node_show(EntityInterface $node, $message = FALSE) { + // For markup consistency with other pages, use node_view_multiple() rather than node_view(). + $nodes = array('nodes' => node_view_multiple(array($node->id() => $node), 'full')); + if ($message) { drupal_set_title(t('Revision of %title from %date', array('%title' => $node->label(), '%date' => format_date($node->revision_timestamp))), PASS_THROUGH); + // Don't use the render cache when a revision is displayed. + unset($nodes['nodes'][$node->id()]['#cache']); } - // For markup consistency with other pages, use node_view_multiple() rather than node_view(). - $nodes = array('nodes' => node_view_multiple(array($node->nid => $node), 'full')); - // Update the history table, stating that this user viewed this node. if (module_exists('history')) { - history_write($node->nid); + history_write($node->id()); } return $nodes; @@ -2220,7 +2222,7 @@ function _node_index_node(EntityInterface $node) { foreach ($languages as $language) { // Render the node. - $build = node_view($node, 'search_index', $language->langcode); + $build = entity_view($node, 'search_index', $language->langcode, TRUE); unset($build['#theme']); $node->rendered = drupal_render($build); diff --git a/core/modules/picture/lib/Drupal/picture/PictureMappingFormController.php b/core/modules/picture/lib/Drupal/picture/PictureMappingFormController.php index 4b93dc5..55f969b 100644 --- a/core/modules/picture/lib/Drupal/picture/PictureMappingFormController.php +++ b/core/modules/picture/lib/Drupal/picture/PictureMappingFormController.php @@ -134,6 +134,8 @@ public function validate(array $form, array &$form_state) { * Overrides Drupal\Core\Entity\EntityFormController::save(). */ public function save(array $form, array &$form_state) { + parent::save($form, $form_state); + $picture_mapping = $this->entity; $picture_mapping->save(); diff --git a/core/modules/rdf/lib/Drupal/rdf/Tests/CommentAttributesTest.php b/core/modules/rdf/lib/Drupal/rdf/Tests/CommentAttributesTest.php index 87a4e10..6c0e001 100644 --- a/core/modules/rdf/lib/Drupal/rdf/Tests/CommentAttributesTest.php +++ b/core/modules/rdf/lib/Drupal/rdf/Tests/CommentAttributesTest.php @@ -291,6 +291,7 @@ function saveComment($nid, $uid, $contact = NULL, $pid = 0) { $comment = entity_create('comment', $values); $comment->save(); + \Drupal::entityManager()->getRenderController('comment')->resetCache(array($comment)); return $comment; } } diff --git a/core/modules/search/config/entity.view_mode.node.search_index.yml b/core/modules/search/config/entity.view_mode.node.search_index.yml index ed22c30..e12156d 100644 --- a/core/modules/search/config/entity.view_mode.node.search_index.yml +++ b/core/modules/search/config/entity.view_mode.node.search_index.yml @@ -1,4 +1,5 @@ id: node.search_index label: Search index status: '0' +cache: '1' targetEntityType: node diff --git a/core/modules/search/config/entity.view_mode.node.search_result.yml b/core/modules/search/config/entity.view_mode.node.search_result.yml index 1608657..776ada9 100644 --- a/core/modules/search/config/entity.view_mode.node.search_result.yml +++ b/core/modules/search/config/entity.view_mode.node.search_result.yml @@ -1,4 +1,5 @@ id: node.search_result label: Search result status: '0' +cache: '1' targetEntityType: node diff --git a/core/modules/shortcut/lib/Drupal/shortcut/ShortcutFormController.php b/core/modules/shortcut/lib/Drupal/shortcut/ShortcutFormController.php index 1e25679..0eed29e 100644 --- a/core/modules/shortcut/lib/Drupal/shortcut/ShortcutFormController.php +++ b/core/modules/shortcut/lib/Drupal/shortcut/ShortcutFormController.php @@ -73,6 +73,8 @@ public function validate(array $form, array &$form_state) { * Overrides \Drupal\Core\Entity\EntityFormController::save(). */ public function save(array $form, array &$form_state) { + parent::save($form, $form_state); + $entity = $this->entity; $is_new = !$entity->getOriginalID(); $entity->save(); diff --git a/core/modules/statistics/statistics.module b/core/modules/statistics/statistics.module index 0c4580c..dbe529f 100644 --- a/core/modules/statistics/statistics.module +++ b/core/modules/statistics/statistics.module @@ -73,6 +73,17 @@ function statistics_node_view(EntityInterface $node, EntityDisplay $display, $vi } /** + * Implements hook_node_view_alter(). + */ +function statistics_node_view_alter(&$build, EntityInterface $node, EntityDisplay $display) { + // If statistics were added to the node render array, we can't use the render + // cache. + if (isset($build['links']['statistics'])) { + unset($build['#cache']); + } +} + +/** * Implements hook_menu(). */ function statistics_menu() { diff --git a/core/modules/system/lib/Drupal/system/Form/DateFormatLocalizeResetForm.php b/core/modules/system/lib/Drupal/system/Form/DateFormatLocalizeResetForm.php index 3392b76..cbfd6e3 100644 --- a/core/modules/system/lib/Drupal/system/Form/DateFormatLocalizeResetForm.php +++ b/core/modules/system/lib/Drupal/system/Form/DateFormatLocalizeResetForm.php @@ -102,6 +102,7 @@ public function buildForm(array $form, array &$form_state, $langcode = NULL) { */ public function submitForm(array &$form, array &$form_state) { $this->configFactory->get('locale.config.' . $this->language->langcode . '.system.date')->delete(); + entity_render_cache_clear(); $form_state['redirect'] = 'admin/config/regional/date-time/locale'; } diff --git a/core/modules/system/lib/Drupal/system/Tests/System/DateTimeTest.php b/core/modules/system/lib/Drupal/system/Tests/System/DateTimeTest.php index c867581..f2afd30 100644 --- a/core/modules/system/lib/Drupal/system/Tests/System/DateTimeTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/System/DateTimeTest.php @@ -65,6 +65,7 @@ function testTimeZoneHandling() { // Set time zone to Los Angeles time. $config->set('default', 'America/Los_Angeles')->save(); + \Drupal::entityManager()->getRenderController('node')->resetCache(array($node1, $node2)); // Confirm date format and time zone. $this->drupalGet("node/$node1->nid"); diff --git a/core/modules/system/tests/modules/entity_test/config/entity.view_mode.entity_test_render.full.yml b/core/modules/system/tests/modules/entity_test/config/entity.view_mode.entity_test_render.full.yml index 8902bc3..4ce40f1 100644 --- a/core/modules/system/tests/modules/entity_test/config/entity.view_mode.entity_test_render.full.yml +++ b/core/modules/system/tests/modules/entity_test/config/entity.view_mode.entity_test_render.full.yml @@ -1,4 +1,5 @@ id: entity_test_render.full label: Full status: '0' +cache: '1' targetEntityType: entity_test_render diff --git a/core/modules/system/tests/modules/entity_test/config/entity.view_mode.entity_test_render.test.yml b/core/modules/system/tests/modules/entity_test/config/entity.view_mode.entity_test_render.test.yml index a0d108b..310bceb 100644 --- a/core/modules/system/tests/modules/entity_test/config/entity.view_mode.entity_test_render.test.yml +++ b/core/modules/system/tests/modules/entity_test/config/entity.view_mode.entity_test_render.test.yml @@ -1,4 +1,5 @@ id: entity_test_render.test label: Test status: '0' +cache: '1' targetEntityType: entity_test_render diff --git a/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/EntityTestFormController.php b/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/EntityTestFormController.php index 0ad1da0..1a1d9a0 100644 --- a/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/EntityTestFormController.php +++ b/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/EntityTestFormController.php @@ -83,6 +83,8 @@ public function submit(array $form, array &$form_state) { * Overrides Drupal\Core\Entity\EntityFormController::save(). */ public function save(array $form, array &$form_state) { + parent::save($form, $form_state); + $entity = $this->entity; $is_new = $entity->isNew(); $entity->save(); diff --git a/core/modules/taxonomy/config/entity.view_mode.taxonomy_term.full.yml b/core/modules/taxonomy/config/entity.view_mode.taxonomy_term.full.yml index 100547e..2666012 100644 --- a/core/modules/taxonomy/config/entity.view_mode.taxonomy_term.full.yml +++ b/core/modules/taxonomy/config/entity.view_mode.taxonomy_term.full.yml @@ -1,4 +1,5 @@ id: taxonomy_term.full label: Taxonomy term page status: '0' +cache: '1' targetEntityType: taxonomy_term diff --git a/core/modules/taxonomy/config/entity.view_mode.taxonomy_vocabulary.full.yml b/core/modules/taxonomy/config/entity.view_mode.taxonomy_vocabulary.full.yml index bb47091..8961a6f 100644 --- a/core/modules/taxonomy/config/entity.view_mode.taxonomy_vocabulary.full.yml +++ b/core/modules/taxonomy/config/entity.view_mode.taxonomy_vocabulary.full.yml @@ -1,4 +1,5 @@ id: vocabulary.full label: Taxonomy vocabulary status: '0' +cache: '1' targetEntityType: taxonomy_vocabulary diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/TermFormController.php b/core/modules/taxonomy/lib/Drupal/taxonomy/TermFormController.php index 832a0cf..8c95fb2 100644 --- a/core/modules/taxonomy/lib/Drupal/taxonomy/TermFormController.php +++ b/core/modules/taxonomy/lib/Drupal/taxonomy/TermFormController.php @@ -155,6 +155,8 @@ public function buildEntity(array $form, array &$form_state) { * Overrides Drupal\Core\Entity\EntityFormController::save(). */ public function save(array $form, array &$form_state) { + parent::save($form, $form_state); + $term = $this->entity; switch ($term->save()) { diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TermTest.php b/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TermTest.php index 2a0907d..dc6a662 100644 --- a/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TermTest.php +++ b/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TermTest.php @@ -342,6 +342,7 @@ function testTermInterface() { // Check that it does NOT show a description when description is blank. $term->description = ''; $term->save(); + \Drupal::entityManager()->getRenderController('taxonomy_term')->resetCache(array($term)); $this->drupalGet('taxonomy/term/' . $term->id()); $this->assertNoPattern('|class="taxonomy-term-description"|', 'Term page did not display the term description when description was blank.'); diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/VocabularyFormController.php b/core/modules/taxonomy/lib/Drupal/taxonomy/VocabularyFormController.php index f6d7f42..5314460 100644 --- a/core/modules/taxonomy/lib/Drupal/taxonomy/VocabularyFormController.php +++ b/core/modules/taxonomy/lib/Drupal/taxonomy/VocabularyFormController.php @@ -145,6 +145,8 @@ public function submit(array $form, array &$form_state) { * Overrides Drupal\Core\Entity\EntityFormController::save(). */ public function save(array $form, array &$form_state) { + parent::save($form, $form_state); + $vocabulary = $this->entity; // Prevent leading and trailing spaces in vocabulary names. diff --git a/core/modules/taxonomy/taxonomy.admin.inc b/core/modules/taxonomy/taxonomy.admin.inc index e2d6841..e72c306 100644 --- a/core/modules/taxonomy/taxonomy.admin.inc +++ b/core/modules/taxonomy/taxonomy.admin.inc @@ -431,13 +431,15 @@ function taxonomy_term_confirm_delete($form, &$form_state, Term $term) { * @see taxonomy_term_confirm_delete() */ function taxonomy_term_confirm_delete_submit($form, &$form_state) { - entity_delete_multiple('taxonomy_term', array($form_state['values']['tid'])); + $entity = taxonomy_term_load($form_state['values']['tid']); + $entity->delete(); taxonomy_check_vocabulary_hierarchy($form_state['taxonomy']['vocabulary'], $form_state['values']); drupal_set_message(t('Deleted term %name.', array('%name' => $form_state['values']['name']))); watchdog('taxonomy', 'Deleted term %name.', array('%name' => $form_state['values']['name']), WATCHDOG_NOTICE); if (!isset($_GET['destination'])) { $form_state['redirect'] = 'admin/structure/taxonomy'; } + Drupal::entityManager()->getRenderController('taxonomy_term')->resetCache(array($entity)); cache_invalidate_tags(array('content' => TRUE)); return; } diff --git a/core/modules/user/config/entity.view_mode.user.compact.yml b/core/modules/user/config/entity.view_mode.user.compact.yml index c27265b..c211e99 100644 --- a/core/modules/user/config/entity.view_mode.user.compact.yml +++ b/core/modules/user/config/entity.view_mode.user.compact.yml @@ -1,4 +1,5 @@ id: user.compact label: Compact status: '1' +cache: '1' targetEntityType: user diff --git a/core/modules/user/config/entity.view_mode.user.full.yml b/core/modules/user/config/entity.view_mode.user.full.yml index ac1ca20..343e909 100644 --- a/core/modules/user/config/entity.view_mode.user.full.yml +++ b/core/modules/user/config/entity.view_mode.user.full.yml @@ -1,4 +1,5 @@ id: user.full label: User account status: '0' +cache: '1' targetEntityType: user diff --git a/core/modules/user/lib/Drupal/user/ProfileFormController.php b/core/modules/user/lib/Drupal/user/ProfileFormController.php index 484a4af..8e72e76 100644 --- a/core/modules/user/lib/Drupal/user/ProfileFormController.php +++ b/core/modules/user/lib/Drupal/user/ProfileFormController.php @@ -41,6 +41,8 @@ public function submit(array $form, array &$form_state) { * Overrides Drupal\Core\Entity\EntityFormController::save(). */ public function save(array $form, array &$form_state) { + parent::save($form, $form_state); + $account = $this->entity; $account->save(); $form_state['values']['uid'] = $account->id(); diff --git a/core/modules/user/lib/Drupal/user/RegisterFormController.php b/core/modules/user/lib/Drupal/user/RegisterFormController.php index ceecd65..3c0bdbd 100644 --- a/core/modules/user/lib/Drupal/user/RegisterFormController.php +++ b/core/modules/user/lib/Drupal/user/RegisterFormController.php @@ -93,6 +93,8 @@ public function submit(array $form, array &$form_state) { * Overrides Drupal\Core\Entity\EntityFormController::submit(). */ public function save(array $form, array &$form_state) { + parent::save($form, $form_state); + $account = $this->entity; $pass = $account->pass; $admin = $form_state['values']['administer_users']; diff --git a/core/modules/user/lib/Drupal/user/Tests/UserPictureTest.php b/core/modules/user/lib/Drupal/user/Tests/UserPictureTest.php index 633e0cf..41a8a76 100644 --- a/core/modules/user/lib/Drupal/user/Tests/UserPictureTest.php +++ b/core/modules/user/lib/Drupal/user/Tests/UserPictureTest.php @@ -121,6 +121,8 @@ function testPictureOnNodeComment() { ->set('features.node_user_picture', FALSE) ->set('features.comment_user_picture', FALSE) ->save(); + \Drupal::entityManager()->getStorageController('node')->resetCache(array($node)); + \Drupal::entityManager()->getStorageController('comment')->resetCache(); $this->drupalGet('node/' . $node->nid); $this->assertNoRaw(file_uri_target($file->getFileUri()), 'User picture not found on node and comment.'); diff --git a/core/modules/user/user.admin.inc b/core/modules/user/user.admin.inc index 95a0382..cf242c7 100644 --- a/core/modules/user/user.admin.inc +++ b/core/modules/user/user.admin.inc @@ -183,8 +183,9 @@ function user_admin_permissions_submit($form, &$form_state) { drupal_set_message(t('The changes have been saved.')); - // Clear the cached pages and blocks. + // Clear cached pages, blocks and rendered entities. cache_invalidate_tags(array('content' => TRUE)); + entity_render_cache_clear(); } /**