diff --git a/core/includes/common.inc b/core/includes/common.inc index 35056de..9e71d4a 100644 --- a/core/includes/common.inc +++ b/core/includes/common.inc @@ -5811,7 +5811,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); } @@ -5859,6 +5859,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 708706e..ac00daa 100644 --- a/core/includes/entity.inc +++ b/core/includes/entity.inc @@ -46,6 +46,18 @@ function entity_info_cache_clear() { } /** + * Clears the entity render cache for all entity types. + */ +function entity_render_cache_clear() { + $entity_manager = drupal_container()->get('plugin.manager.entity'); + foreach ($entity_manager->getDefinitions() as $entity_type => $info) { + if (isset($info['render_controller_class'])) { + $entity_manager->getRenderController($entity_type)->resetCache(); + } + } +} + +/** * Returns the entity bundle info. * * @param string|null $entity_type @@ -108,6 +120,7 @@ function entity_get_view_modes($entity_type = NULL) { foreach ($entity_info as $view_mode => $view_mode_info) { $view_modes[$type][$view_mode] += array( 'custom_settings' => FALSE, + 'cache' => TRUE, ); } } @@ -587,14 +600,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_container()->get('plugin.manager.entity') - ->getRenderController($entity->entityType()) - ->view($entity, $view_mode, $langcode); +function entity_view(EntityInterface $entity, $view_mode, $langcode = NULL, $reset = FALSE) { + $render_controller = drupal_container()->get('plugin.manager.entity')->getRenderController($entity->entityType()); + if ($reset) { + $render_controller->resetCache(array($entity)); + } + return $render_controller->view($entity, $view_mode, $langcode); } /** @@ -607,15 +625,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_container()->get('plugin.manager.entity') - ->getRenderController(reset($entities)->entityType()) - ->viewMultiple($entities, $view_mode, $langcode); +function entity_view_multiple(array $entities, $view_mode, $langcode = NULL, $reset = FALSE) { + $render_controller = drupal_container()->get('plugin.manager.entity')->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/DatabaseStorageController.php b/core/lib/Drupal/Core/Entity/DatabaseStorageController.php index e57f4bb..a07a9d8 100644 --- a/core/lib/Drupal/Core/Entity/DatabaseStorageController.php +++ b/core/lib/Drupal/Core/Entity/DatabaseStorageController.php @@ -537,6 +537,7 @@ public function save(EntityInterface $entity) { $this->saveRevision($entity); } $this->resetCache(array($entity->id())); + $this->postSave($entity, TRUE); $this->invokeHook('update', $entity); } diff --git a/core/lib/Drupal/Core/Entity/DatabaseStorageControllerNG.php b/core/lib/Drupal/Core/Entity/DatabaseStorageControllerNG.php index e18edbd..9098d15 100644 --- a/core/lib/Drupal/Core/Entity/DatabaseStorageControllerNG.php +++ b/core/lib/Drupal/Core/Entity/DatabaseStorageControllerNG.php @@ -308,6 +308,7 @@ public function save(EntityInterface $entity) { $this->savePropertyData($entity); } $this->resetCache(array($entity->id())); + $this->postSave($entity, TRUE); $this->invokeHook('update', $entity); } diff --git a/core/lib/Drupal/Core/Entity/EntityFormController.php b/core/lib/Drupal/Core/Entity/EntityFormController.php index 4a03975..3279cad 100644 --- a/core/lib/Drupal/Core/Entity/EntityFormController.php +++ b/core/lib/Drupal/Core/Entity/EntityFormController.php @@ -203,7 +203,14 @@ 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. + $entity = $this->getEntity($form_state); + try { + \Drupal::service('plugin.manager.entity')->getRenderController($entity->entityType())->resetCache(array($entity)); + } + catch (\Exception $e) { + // Nothing to do if the entity type doesn't have a render controller. + } } /** diff --git a/core/lib/Drupal/Core/Entity/EntityManager.php b/core/lib/Drupal/Core/Entity/EntityManager.php index 43d0497..6d4dea6 100644 --- a/core/lib/Drupal/Core/Entity/EntityManager.php +++ b/core/lib/Drupal/Core/Entity/EntityManager.php @@ -75,6 +75,8 @@ * - static_cache: (optional) Boolean indicating whether entities should be * statically cached during a page request. Used by * Drupal\Core\Entity\DatabaseStorageController. Defaults to TRUE. + * - render_cache: (optional) Boolean indicating whether the rendered output of + * entities should be cached during a page request. Defaults to TRUE. * - translatable: (optional) Boolean indicating whether entities of this type * have mutlilingual support. Defaults to FALSE. * - entity_keys: An array describing how the Field API can extract certain @@ -159,6 +161,7 @@ class EntityManager extends PluginManagerBase { 'list_controller_class' => 'Drupal\Core\Entity\EntityListController', 'access_controller_class' => 'Drupal\Core\Entity\EntityAccessController', 'static_cache' => TRUE, + 'render_cache' => TRUE, 'translation' => array(), 'permission_granularity' => 'entity_type', ); diff --git a/core/lib/Drupal/Core/Entity/EntityRenderController.php b/core/lib/Drupal/Core/Entity/EntityRenderController.php index 53457aa..b544c02 100644 --- a/core/lib/Drupal/Core/Entity/EntityRenderController.php +++ b/core/lib/Drupal/Core/Entity/EntityRenderController.php @@ -20,8 +20,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); } /** @@ -60,6 +89,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 ($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; } @@ -162,4 +206,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 97fb698..add59d8 100644 --- a/core/modules/aggregator/lib/Drupal/aggregator/FeedFormController.php +++ b/core/modules/aggregator/lib/Drupal/aggregator/FeedFormController.php @@ -111,6 +111,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->getEntity($form_state); $insert = (bool) $feed->id(); if (!empty($form_state['values']['category'])) { 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 0094c42..d14fd27 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 @@ -158,6 +158,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->getEntity($form_state); $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 77664e9..4c5fa78 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, EntityInterface $block_typ * Overrides \Drupal\Core\Entity\EntityFormController::save(). */ public function save(array $form, array &$form_state) { + parent::save($form, $form_state); + $block_type = $this->getEntity($form_state); $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 e1c560e..4715f66 100644 --- a/core/modules/block/lib/Drupal/block/BlockRenderController.php +++ b/core/modules/block/lib/Drupal/block/BlockRenderController.php @@ -87,4 +87,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/comment/lib/Drupal/comment/CommentFormController.php b/core/modules/comment/lib/Drupal/comment/CommentFormController.php index a5e5f15..cfbf84d 100644 --- a/core/modules/comment/lib/Drupal/comment/CommentFormController.php +++ b/core/modules/comment/lib/Drupal/comment/CommentFormController.php @@ -309,6 +309,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->getEntity($form_state); diff --git a/core/modules/comment/lib/Drupal/comment/CommentRenderController.php b/core/modules/comment/lib/Drupal/comment/CommentRenderController.php index dab8dc4..0e1ce5e 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/config/tests/config_test/lib/Drupal/config_test/ConfigTestFormController.php b/core/modules/config/tests/config_test/lib/Drupal/config_test/ConfigTestFormController.php index 7e54e1c..ebfe3ff 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 @@ -64,6 +64,8 @@ public function form(array $form, array &$form_state, EntityInterface $entity) { * Overrides Drupal\Core\Entity\EntityFormController::save(). */ public function save(array $form, array &$form_state) { + parent::save($form, $form_state); + $entity = $this->getEntity($form_state); $status = $entity->save(); diff --git a/core/modules/contact/lib/Drupal/contact/CategoryFormController.php b/core/modules/contact/lib/Drupal/contact/CategoryFormController.php index d60308f..e0e2217 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->getEntity($form_state); $status = $category->save(); diff --git a/core/modules/contact/lib/Drupal/contact/MessageFormController.php b/core/modules/contact/lib/Drupal/contact/MessageFormController.php index c4352cf..4950dc3 100644 --- a/core/modules/contact/lib/Drupal/contact/MessageFormController.php +++ b/core/modules/contact/lib/Drupal/contact/MessageFormController.php @@ -137,6 +137,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); + global $user; $language_interface = language(LANGUAGE_TYPE_INTERFACE); diff --git a/core/modules/entity/lib/Drupal/entity/Plugin/Core/Entity/EntityDisplay.php b/core/modules/entity/lib/Drupal/entity/Plugin/Core/Entity/EntityDisplay.php index d88967f..5e30e5a 100644 --- a/core/modules/entity/lib/Drupal/entity/Plugin/Core/Entity/EntityDisplay.php +++ b/core/modules/entity/lib/Drupal/entity/Plugin/Core/Entity/EntityDisplay.php @@ -117,7 +117,17 @@ 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. + try { + \Drupal::service('plugin.manager.entity')->getRenderController($this->targetEntityType)->resetCache(); + } + catch (\Exception $e) { + // Nothing to do if the entity type doesn't have a render controller. + } + + return $return; } /** 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 93ef2aa..8e768a2 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 @@ -36,6 +36,8 @@ public function form(array $form, array &$form_state, EntityInterface $entity) { * Overrides Drupal\Core\Entity\EntityFormController::save(). */ public function save(array $form, array &$form_state) { + parent::save($form, $form_state); + $entity = $this->getEntity($form_state); $is_new = $entity->isNew(); $entity->save(); diff --git a/core/modules/menu/lib/Drupal/menu/MenuFormController.php b/core/modules/menu/lib/Drupal/menu/MenuFormController.php index ff42a20..da487eb 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->getEntity($form_state); $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 9506602..a76512e 100644 --- a/core/modules/menu_link/lib/Drupal/menu_link/MenuLinkFormController.php +++ b/core/modules/menu_link/lib/Drupal/menu_link/MenuLinkFormController.php @@ -202,8 +202,9 @@ public function submit(array $form, array &$form_state) { * Overrides EntityFormController::save(). */ public function save(array $form, array &$form_state) { - $menu_link = $this->getEntity($form_state); + parent::save($form, $form_state); + $menu_link = $this->getEntity($form_state); $saved = $menu_link->save(); if ($saved) { diff --git a/core/modules/node/lib/Drupal/node/NodeFormController.php b/core/modules/node/lib/Drupal/node/NodeFormController.php index 63b4189..fa4e0b7 100644 --- a/core/modules/node/lib/Drupal/node/NodeFormController.php +++ b/core/modules/node/lib/Drupal/node/NodeFormController.php @@ -426,6 +426,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->getEntity($form_state); $insert = empty($node->nid); $node->save(); diff --git a/core/modules/picture/lib/Drupal/picture/PictureMappingFormController.php b/core/modules/picture/lib/Drupal/picture/PictureMappingFormController.php index 466e14c..a16e84c 100644 --- a/core/modules/picture/lib/Drupal/picture/PictureMappingFormController.php +++ b/core/modules/picture/lib/Drupal/picture/PictureMappingFormController.php @@ -126,6 +126,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->getEntity($form_state); $picture_mapping->save(); diff --git a/core/modules/shortcut/lib/Drupal/shortcut/ShortcutFormController.php b/core/modules/shortcut/lib/Drupal/shortcut/ShortcutFormController.php index 059de38..fffd359 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->getEntity($form_state); $is_new = !$entity->getOriginalID(); $entity->save(); 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 c08e3b3..d23dd08 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 @@ -57,6 +57,8 @@ public function form(array $form, array &$form_state, EntityInterface $entity) { * Overrides Drupal\Core\Entity\EntityFormController::save(). */ public function save(array $form, array &$form_state) { + parent::save($form, $form_state); + $entity = $this->getEntity($form_state); $is_new = $entity->isNew(); $entity->save(); diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/TermFormController.php b/core/modules/taxonomy/lib/Drupal/taxonomy/TermFormController.php index 3735ad6..eab6b17 100644 --- a/core/modules/taxonomy/lib/Drupal/taxonomy/TermFormController.php +++ b/core/modules/taxonomy/lib/Drupal/taxonomy/TermFormController.php @@ -150,6 +150,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); + $term = $this->getEntity($form_state); $status = taxonomy_term_save($term); diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/VocabularyFormController.php b/core/modules/taxonomy/lib/Drupal/taxonomy/VocabularyFormController.php index 6785335..16ed460 100644 --- a/core/modules/taxonomy/lib/Drupal/taxonomy/VocabularyFormController.php +++ b/core/modules/taxonomy/lib/Drupal/taxonomy/VocabularyFormController.php @@ -164,6 +164,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->getEntity($form_state); // Prevent leading and trailing spaces in vocabulary names. diff --git a/core/modules/user/lib/Drupal/user/ProfileFormController.php b/core/modules/user/lib/Drupal/user/ProfileFormController.php index c2b139d..6068f6d 100644 --- a/core/modules/user/lib/Drupal/user/ProfileFormController.php +++ b/core/modules/user/lib/Drupal/user/ProfileFormController.php @@ -43,6 +43,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->getEntity($form_state); $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 2a84412..9a7f0e1 100644 --- a/core/modules/user/lib/Drupal/user/RegisterFormController.php +++ b/core/modules/user/lib/Drupal/user/RegisterFormController.php @@ -94,6 +94,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->getEntity($form_state); $pass = $account->pass; $admin = $form_state['values']['administer_users']; diff --git a/core/modules/user/user.module b/core/modules/user/user.module index bdf5862..5031e14 100644 --- a/core/modules/user/user.module +++ b/core/modules/user/user.module @@ -1955,6 +1955,8 @@ function user_role_grant_permissions($rid, array $permissions = array()) { // Clear the user access cache. drupal_static_reset('user_access'); drupal_static_reset('user_role_permissions'); + // Entity render cache is based on user roles, so we need to clear it as well. + entity_render_cache_clear(); } /** @@ -1978,6 +1980,8 @@ function user_role_revoke_permissions($rid, array $permissions = array()) { // Clear the user access cache. drupal_static_reset('user_access'); drupal_static_reset('user_role_permissions'); + // Entity render cache is based on user roles, so we need to clear it as well. + entity_render_cache_clear(); } /**