diff --git a/core/includes/common.inc b/core/includes/common.inc index be97724..4bdc258 100644 --- a/core/includes/common.inc +++ b/core/includes/common.inc @@ -4139,7 +4139,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); cache($bin)->set($cid, $data, $expire, $tags); } @@ -4187,6 +4187,50 @@ function drupal_render_collect_attached($elements, $return = FALSE) { } /** + * Collects cache tags for an element and its children into a single array. + * + * The cache tags array is returned in a format that is valid for + * \Drupal\Core\Cache\CacheBackendInterface::set(). + * + * 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 $element + * The element to collect cache tags from. + * @param array $tags + * (optional) An array of already collected cache tags (i.e. from a parent + * element). Defaults to an empty array. + * + * @return array + * The cache tags array for this element and its descendants. + */ +function drupal_render_collect_cache_tags($element, $tags = array()) { + if (isset($element['#cache']['tags'])) { + foreach ($element['#cache']['tags'] as $namespace => $values) { + if (is_array($values)) { + foreach ($values as $value) { + $tags[$namespace][$value] = $value; + } + } + else { + if (!isset($tags[$namespace])) { + $tags[$namespace] = $values; + } + } + } + } + if ($children = element_children($element)) { + foreach ($children as $child) { + $tags = drupal_render_collect_cache_tags($element[$child], $tags); + } + } + + return $tags; +} + +/** * 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 b6b92b0..aadf346 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 @@ -609,14 +621,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->id())); + } + return $render_controller->view($entity, $view_mode, $langcode); } /** @@ -629,15 +646,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(array_keys($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 0bf08f0..016767d 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/Entity.php b/core/lib/Drupal/Core/Entity/Entity.php index 958996c..f74a044 100644 --- a/core/lib/Drupal/Core/Entity/Entity.php +++ b/core/lib/Drupal/Core/Entity/Entity.php @@ -8,6 +8,7 @@ namespace Drupal\Core\Entity; use Drupal\Component\Uuid\Uuid; +use Drupal\Core\Entity\Plugin\DataType\EntityReferenceItem; use Drupal\Core\Language\Language; use Drupal\Core\TypedData\TranslatableInterface; use Drupal\Core\TypedData\TypedDataInterface; @@ -538,6 +539,7 @@ public function preSave(EntityStorageControllerInterface $storage_controller) { * {@inheritdoc} */ public function postSave(EntityStorageControllerInterface $storage_controller, $update = TRUE) { + $this->changed(); } /** @@ -562,6 +564,9 @@ public static function preDelete(EntityStorageControllerInterface $storage_contr * {@inheritdoc} */ public static function postDelete(EntityStorageControllerInterface $storage_controller, array $entities) { + foreach ($entities as $entity) { + $entity->changed(); + } } /** @@ -625,4 +630,48 @@ public static function baseFieldDefinitions($entity_type) { return array(); } + /** + * {@inheritdoc} + */ + public function referencedEntities() { + $referenced_entities = array(); + + // @todo Remove when all entities are converted to EntityNG. + // https://drupal.org/node/1818580 + if (!$this->getPropertyDefinitions()) { + return $referenced_entities; + } + + // Gather a list of referenced entities. + foreach ($this->getProperties() as $name => $definition) { + $field_items = $this->get($name); + foreach ($field_items as $field_item) { + if ($field_item instanceof EntityReferenceItem && $entity = $field_item->entity) { + $referenced_entities[] = $entity; + } + } + } + + return $referenced_entities; + } + + /** + * {@inheritdoc} + */ + public function changed() { + $referenced_entity_ids = array( + $this->entityType() => array($this->id() => TRUE), + ); + + foreach ($this->referencedEntities() as $referenced_entity) { + $referenced_entity_ids[$referenced_entity->entityType()][$referenced_entity->id()] = TRUE; + } + + foreach ($referenced_entity_ids as $entity_type => $entity_ids) { + if (\Drupal::entityManager()->hasController($entity_type, 'render')) { + \Drupal::entityManager()->getRenderController($entity_type)->resetCache(array_keys($entity_ids)); + } + } + } + } diff --git a/core/lib/Drupal/Core/Entity/EntityInterface.php b/core/lib/Drupal/Core/Entity/EntityInterface.php index 7d0056c..c0949f7 100644 --- a/core/lib/Drupal/Core/Entity/EntityInterface.php +++ b/core/lib/Drupal/Core/Entity/EntityInterface.php @@ -325,4 +325,17 @@ public function initTranslation($langcode); */ public static function baseFieldDefinitions($entity_type); + /** + * Returns a list of entities referenced by this entity. + * + * @return array + * An array of entities. + */ + public function referencedEntities(); + + /** + * Acts on an entity after it was saved or deleted. + */ + public function changed(); + } diff --git a/core/lib/Drupal/Core/Entity/EntityRenderController.php b/core/lib/Drupal/Core/Entity/EntityRenderController.php index 860c044..9b5bd3f 100644 --- a/core/lib/Drupal/Core/Entity/EntityRenderController.php +++ b/core/lib/Drupal/Core/Entity/EntityRenderController.php @@ -6,8 +6,8 @@ */ namespace Drupal\Core\Entity; -use Drupal\entity\Entity\EntityDisplay; +use Drupal\entity\Entity\EntityDisplay; use Drupal\Core\Language\Language; /** @@ -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,23 @@ protected function getBuildDefaults(EntityInterface $entity, $view_mode, $langco '#view_mode' => $view_mode, '#langcode' => $langcode, ); + + // Cache the rendered output if permitted by the view mode and global entity + // type configuration. The isset() checks below are necessary because + // 'default' is not an actual view mode. + $view_mode_is_cacheable = !isset($this->viewModesInfo[$view_mode]) || (isset($this->viewModesInfo[$view_mode]) && $this->viewModesInfo[$view_mode]['cache']); + if ($view_mode_is_cacheable && !$entity->isNew() && !isset($entity->in_preview) && $this->entityInfo['render_cache']) { + $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 +210,20 @@ public function viewMultiple(array $entities = array(), $view_mode = 'full', $la return $build; } + + /** + * {@inheritdoc} + */ + public function resetCache(array $ids = NULL) { + if (isset($ids)) { + $tags = array(); + foreach ($ids as $entity_id) { + $tags[$this->entityType][$entity_id] = $entity_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..a112fc2 100644 --- a/core/lib/Drupal/Core/Entity/EntityRenderControllerInterface.php +++ b/core/lib/Drupal/Core/Entity/EntityRenderControllerInterface.php @@ -75,4 +75,14 @@ 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 $ids + * (optional) If specified, the cache is reset for the given entity IDs + * only. + */ + public function resetCache(array $ids = NULL); + } diff --git a/core/modules/aggregator/lib/Drupal/aggregator/Tests/Views/IntegrationTest.php b/core/modules/aggregator/lib/Drupal/aggregator/Tests/Views/IntegrationTest.php index 53621cf..77393d6 100644 --- a/core/modules/aggregator/lib/Drupal/aggregator/Tests/Views/IntegrationTest.php +++ b/core/modules/aggregator/lib/Drupal/aggregator/Tests/Views/IntegrationTest.php @@ -20,7 +20,7 @@ class IntegrationTest extends ViewUnitTestBase { * * @var array */ - public static $modules = array('aggregator', 'aggregator_test_views', 'system', 'field'); + public static $modules = array('aggregator', 'aggregator_test_views', 'system', 'entity', 'field'); /** * Views used by this test. 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/lib/Drupal/block/BlockRenderController.php b/core/modules/block/lib/Drupal/block/BlockRenderController.php index 57a5d62..68599a5 100644 --- a/core/modules/block/lib/Drupal/block/BlockRenderController.php +++ b/core/modules/block/lib/Drupal/block/BlockRenderController.php @@ -62,4 +62,9 @@ public function viewMultiple(array $entities = array(), $view_mode = 'full', $la return $build; } + /** + * {@inheritdoc} + */ + public function resetCache(array $ids = NULL) { } + } 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/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/Controller/CommentController.php b/core/modules/comment/lib/Drupal/comment/Controller/CommentController.php index 48a23cd..275a27b 100644 --- a/core/modules/comment/lib/Drupal/comment/Controller/CommentController.php +++ b/core/modules/comment/lib/Drupal/comment/Controller/CommentController.php @@ -219,6 +219,7 @@ public function getReplyForm(Request $request, NodeInterface $node, $pid = NULL) elseif ($account->hasPermission('access content')) { // Display the node. $build['comment_node'] = $this->entityManager()->getRenderController('node')->view($node); + unset($build['comment_node']['#cache']); } } else { diff --git a/core/modules/comment/lib/Drupal/comment/Entity/Comment.php b/core/modules/comment/lib/Drupal/comment/Entity/Comment.php index dfe08c1..c30d380 100644 --- a/core/modules/comment/lib/Drupal/comment/Entity/Comment.php +++ b/core/modules/comment/lib/Drupal/comment/Entity/Comment.php @@ -36,6 +36,7 @@ * uri_callback = "comment_uri", * fieldable = TRUE, * translatable = TRUE, + * render_cache = FALSE, * route_base_path = "admin/structure/types/manage/{bundle}/comment", * bundle_prefix = "comment_node_", * entity_keys = { diff --git a/core/modules/editor/lib/Drupal/editor/Tests/EditorFileUsageTest.php b/core/modules/editor/lib/Drupal/editor/Tests/EditorFileUsageTest.php index 80384ae..97715b5 100644 --- a/core/modules/editor/lib/Drupal/editor/Tests/EditorFileUsageTest.php +++ b/core/modules/editor/lib/Drupal/editor/Tests/EditorFileUsageTest.php @@ -7,19 +7,19 @@ namespace Drupal\editor\Tests; -use Drupal\simpletest\DrupalUnitTestBase; +use Drupal\system\Tests\Entity\EntityUnitTestBase; /** * Unit tests for editor.module's entity hooks to track file usage. */ -class EditorFileUsageTest extends DrupalUnitTestBase { +class EditorFileUsageTest extends EntityUnitTestBase { /** * Modules to enable. * * @var array */ - public static $modules = array('system', 'editor', 'editor_test', 'filter', 'node', 'entity', 'field', 'text', 'field_sql_storage', 'file'); + public static $modules = array('editor', 'editor_test', 'node', 'file'); public static function getInfo() { return array( @@ -31,13 +31,8 @@ public static function getInfo() { function setUp() { parent::setUp(); - $this->installSchema('system', 'url_alias'); - $this->installSchema('node', 'node'); - $this->installSchema('node', 'node_access'); - $this->installSchema('node', 'node_field_data'); - $this->installSchema('node', 'node_field_revision'); - $this->installSchema('file', 'file_managed'); - $this->installSchema('file', 'file_usage'); + $this->installSchema('node', array('node', 'node_access', 'node_field_data', 'node_field_revision')); + $this->installSchema('file', array('file_managed', 'file_usage')); // Add text formats. $filtered_html_format = entity_create('filter_format', array( @@ -71,13 +66,15 @@ function testEditorEntityHooks() { $this->assertIdentical(array(), file_usage()->listUsage($image), 'The image has zero usages.'); // Test editor_entity_insert(): increment. + $this->createUser(); $node = entity_create('node', array( 'type' => 'page', 'title' => 'test', 'body' => array( 'value' => '

Hello, world!

', 'format' => 'filtered_html', - ) + ), + 'uid' => 1, )); $node->save(); $this->assertIdentical(array('editor' => array('node' => array(1 => '1'))), file_usage()->listUsage($image), 'The image has 1 usage.'); diff --git a/core/modules/entity/lib/Drupal/entity/EntityDisplayBase.php b/core/modules/entity/lib/Drupal/entity/EntityDisplayBase.php index 128bc7c..eabce25 100644 --- a/core/modules/entity/lib/Drupal/entity/EntityDisplayBase.php +++ b/core/modules/entity/lib/Drupal/entity/EntityDisplayBase.php @@ -121,6 +121,20 @@ public function id() { /** * {@inheritdoc} */ + public function 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; + } + + /** + * {@inheritdoc} + */ public function getExportProperties() { $names = array( 'id', diff --git a/core/modules/entity/lib/Drupal/entity/EntityDisplayModeBase.php b/core/modules/entity/lib/Drupal/entity/EntityDisplayModeBase.php index 8fe73cb..1541143 100644 --- a/core/modules/entity/lib/Drupal/entity/EntityDisplayModeBase.php +++ b/core/modules/entity/lib/Drupal/entity/EntityDisplayModeBase.php @@ -58,6 +58,13 @@ public $status = TRUE; /** + * Whether or not the rendered output of this view mode is cached by default. + * + * @var bool + */ + public $cache = TRUE; + + /** * {@inheritdoc} */ public static function sort($a, $b) { 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 bb9edd3..34cadae 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 @@ -96,8 +96,21 @@ public function view(FieldInterface $items) { '#object' => $entity, '#items' => $items->getValue(TRUE), '#formatter' => $this->getPluginId(), + '#cache' => array('tags' => array()) ); + // Gather cache tags from reference fields. + foreach ($items as $item) { + if (isset($item->format)) { + $info['#cache']['tags']['filter_format'] = $item->format; + } + + 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/lib/Drupal/field/Tests/FieldUnitTestBase.php b/core/modules/field/lib/Drupal/field/Tests/FieldUnitTestBase.php index b619aa2..cd809a6 100644 --- a/core/modules/field/lib/Drupal/field/Tests/FieldUnitTestBase.php +++ b/core/modules/field/lib/Drupal/field/Tests/FieldUnitTestBase.php @@ -35,8 +35,9 @@ */ function setUp() { parent::setUp(); - $this->installSchema('system', array('sequences', 'variable', 'config_snapshot')); $this->installSchema('entity_test', 'entity_test'); + $this->installSchema('system', array('sequences', 'variable', 'config_snapshot')); + $this->installSchema('user', array('users', 'users_roles')); // Set default storage backend and configure the theme system. $this->installConfig(array('field', 'system')); diff --git a/core/modules/filter/lib/Drupal/filter/Tests/FilterAPITest.php b/core/modules/filter/lib/Drupal/filter/Tests/FilterAPITest.php index 0efcb30..945e30b 100644 --- a/core/modules/filter/lib/Drupal/filter/Tests/FilterAPITest.php +++ b/core/modules/filter/lib/Drupal/filter/Tests/FilterAPITest.php @@ -31,7 +31,6 @@ function setUp() { parent::setUp(); $this->installConfig(array('system', 'filter')); - $this->installSchema('user', array('users_roles')); // Create Filtered HTML format. $filtered_html_format = entity_create('filter_format', array( 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/Entity/Node.php b/core/modules/node/lib/Drupal/node/Entity/Node.php index 5105d29..8367e16 100644 --- a/core/modules/node/lib/Drupal/node/Entity/Node.php +++ b/core/modules/node/lib/Drupal/node/Entity/Node.php @@ -40,6 +40,7 @@ * uri_callback = "node_uri", * fieldable = TRUE, * translatable = TRUE, + * render_cache = FALSE, * entity_keys = { * "id" = "nid", * "revision" = "vid", diff --git a/core/modules/node/lib/Drupal/node/NodeRenderController.php b/core/modules/node/lib/Drupal/node/NodeRenderController.php index 6da0b29..433adb3 100644 --- a/core/modules/node/lib/Drupal/node/NodeRenderController.php +++ b/core/modules/node/lib/Drupal/node/NodeRenderController.php @@ -85,6 +85,10 @@ protected function alterBuild(array &$build, EntityInterface $entity, EntityDisp if ($entity->id()) { $build['#contextual_links']['node'] = array('node', array($entity->id())); } + + // 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/Condition/NodeConditionTest.php b/core/modules/node/lib/Drupal/node/Tests/Condition/NodeConditionTest.php index 31d515f..4718c85 100644 --- a/core/modules/node/lib/Drupal/node/Tests/Condition/NodeConditionTest.php +++ b/core/modules/node/lib/Drupal/node/Tests/Condition/NodeConditionTest.php @@ -7,14 +7,14 @@ namespace Drupal\node\Tests\Condition; -use Drupal\simpletest\DrupalUnitTestBase; +use Drupal\system\Tests\Entity\EntityUnitTestBase; /** * Tests the node conditions. */ -class NodeConditionTest extends DrupalUnitTestBase { +class NodeConditionTest extends EntityUnitTestBase { - public static $modules = array('system', 'node', 'field'); + public static $modules = array('node'); public static function getInfo() { return array( @@ -24,11 +24,9 @@ public static function getInfo() { ); } - protected function setUp() { + public function setUp() { parent::setUp(); - $this->installSchema('node', 'node'); - $this->installSchema('node', 'node_field_data'); - $this->installSchema('node', 'node_field_revision'); + $this->installSchema('node', array('node', 'node_field_data', 'node_field_revision')); } /** @@ -36,13 +34,14 @@ protected function setUp() { */ function testConditions() { $manager = $this->container->get('plugin.manager.condition', $this->container->get('container.namespaces')); + $this->createUser(); // Get some nodes of various types to check against. - $page = entity_create('node', array('type' => 'page', 'title' => $this->randomName())); + $page = entity_create('node', array('type' => 'page', 'title' => $this->randomName(), 'uid' => 1)); $page->save(); - $article = entity_create('node', array('type' => 'article', 'title' => $this->randomName())); + $article = entity_create('node', array('type' => 'article', 'title' => $this->randomName(), 'uid' => 1)); $article->save(); - $test = entity_create('node', array('type' => 'test', 'title' => $this->randomName())); + $test = entity_create('node', array('type' => 'test', 'title' => $this->randomName(), 'uid' => 1)); $test->save(); // Grab the node type condition and configure it to check against node type diff --git a/core/modules/node/lib/Drupal/node/Tests/NodeValidationTest.php b/core/modules/node/lib/Drupal/node/Tests/NodeValidationTest.php index e5ecd7d..2d3efe8 100644 --- a/core/modules/node/lib/Drupal/node/Tests/NodeValidationTest.php +++ b/core/modules/node/lib/Drupal/node/Tests/NodeValidationTest.php @@ -7,19 +7,19 @@ namespace Drupal\node\Tests; -use Drupal\simpletest\DrupalUnitTestBase; +use Drupal\system\Tests\Entity\EntityUnitTestBase; /** * Tests node validation constraints. */ -class NodeValidationTest extends DrupalUnitTestBase { +class NodeValidationTest extends EntityUnitTestBase { /** * Modules to enable. * * @var array */ - public static $modules = array('node', 'entity', 'field', 'text', 'field_sql_storage', 'filter'); + public static $modules = array('node'); public static function getInfo() { return array( @@ -34,9 +34,7 @@ public static function getInfo() { */ public function setUp() { parent::setUp(); - $this->installSchema('node', 'node'); - $this->installSchema('node', 'node_field_data'); - $this->installSchema('node', 'node_field_revision'); + $this->installSchema('node', array('node', 'node_field_data', 'node_field_revision')); // Create a node type for testing. $type = entity_create('node_type', array('type' => 'page', 'name' => 'page')); @@ -47,7 +45,8 @@ public function setUp() { * Tests the node validation constraints. */ public function testValidation() { - $node = entity_create('node', array('type' => 'page', 'title' => 'test')); + $this->createUser(); + $node = entity_create('node', array('type' => 'page', 'title' => 'test', 'uid' => 1)); $violations = $node->validate(); $this->assertEqual(count($violations), 0, 'No violations when validating a default node.'); diff --git a/core/modules/node/node.module b/core/modules/node/node.module index 67bfcec..60bbe8f 100644 --- a/core/modules/node/node.module +++ b/core/modules/node/node.module @@ -577,13 +577,15 @@ 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(). + $page = 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->getRevisionCreationTime()))), PASS_THROUGH); + // Don't use the render cache when a revision is displayed. + unset($page['nodes'][$node->id()]['#cache']); } - // For markup consistency with other pages, use node_view_multiple() rather than node_view(). - $page = array('nodes' => node_view_multiple(array($node->id() => $node), 'full')); - // Update the history table, stating that this user viewed this node. global $user; if (\Drupal::moduleHandler()->moduleExists('history') && $user->isAuthenticated()) { 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/serialization/lib/Drupal/serialization/Tests/NormalizerTestBase.php b/core/modules/serialization/lib/Drupal/serialization/Tests/NormalizerTestBase.php index 1966e3a..977437b 100644 --- a/core/modules/serialization/lib/Drupal/serialization/Tests/NormalizerTestBase.php +++ b/core/modules/serialization/lib/Drupal/serialization/Tests/NormalizerTestBase.php @@ -16,12 +16,13 @@ * * @var array */ - public static $modules = array('serialization', 'system', 'entity', 'field', 'entity_test', 'text', 'filter'); + public static $modules = array('serialization', 'system', 'entity', 'field', 'entity_test', 'text', 'filter', 'user'); protected function setUp() { parent::setUp(); $this->installSchema('entity_test', array('entity_test_mulrev', 'entity_test_mulrev_property_revision', 'entity_test_mulrev_property_data')); + $this->installSchema('user', array('users', 'users_roles')); $this->installSchema('system', array('url_alias')); $this->installConfig(array('field')); diff --git a/core/modules/statistics/statistics.module b/core/modules/statistics/statistics.module index 34fd8d3..09b17a6 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 bb313c5..e1e5e8b 100644 --- a/core/modules/system/lib/Drupal/system/Form/DateFormatLocalizeResetForm.php +++ b/core/modules/system/lib/Drupal/system/Form/DateFormatLocalizeResetForm.php @@ -109,6 +109,7 @@ public function submitForm(array &$form, array &$form_state) { foreach (config_get_storage_names_with_prefix('locale.config.' . $this->language->id . '.system.date_format.') as $config_id) { $this->configFactory->get($config_id)->delete(); } + entity_render_cache_clear(); $form_state['redirect'] = 'admin/config/regional/date-time/locale'; } diff --git a/core/modules/system/lib/Drupal/system/Tests/Action/ActionUnitTest.php b/core/modules/system/lib/Drupal/system/Tests/Action/ActionUnitTest.php index 03cc551..96f2d73 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Action/ActionUnitTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Action/ActionUnitTest.php @@ -18,7 +18,7 @@ class ActionUnitTest extends DrupalUnitTestBase { /** * {@inheritdoc} */ - public static $modules = array('system', 'field', 'user', 'action_test'); + public static $modules = array('system','entity' , 'field', 'user', 'action_test'); /** * The action manager. diff --git a/core/modules/system/lib/Drupal/system/Tests/Common/RenderTest.php b/core/modules/system/lib/Drupal/system/Tests/Common/RenderTest.php index be4d7e5..b76786c 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Common/RenderTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Common/RenderTest.php @@ -553,8 +553,16 @@ function testDrupalRenderCache() { $test_element = array( '#cache' => array( 'cid' => 'render_cache_test', + 'tags' => array('render_cache_tag' => TRUE) ), '#markup' => '', + 'child' => array( + '#cache' => array( + 'cid' => 'render_cache_test_child', + 'tags' => array('render_cache_tag_child' => array(1, 2)) + ), + '#markup' => '', + ), ); // Render the element and confirm that it goes through the rendering @@ -569,6 +577,15 @@ function testDrupalRenderCache() { drupal_render($element); $this->assertFalse(isset($element['#printed']), 'Cache hit'); + // Test that cache tags are correctly collected from the render element, + // including the ones from its subchild. + $expected_tags = array( + 'render_cache_tag' => TRUE, + 'render_cache_tag_child' => array(1 => 1, 2 => 2), + ); + $actual_tags = drupal_render_collect_cache_tags($test_element); + $this->assertEqual($expected_tags, $actual_tags, 'Cache tags were collected from the element and its subchild.'); + // Restore the previous request method. $_SERVER['REQUEST_METHOD'] = $request_method; } diff --git a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityAccessTest.php b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityAccessTest.php index be02e7f..440d2d0 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityAccessTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityAccessTest.php @@ -29,7 +29,6 @@ public static function getInfo() { function setUp() { parent::setUp(); - $this->installSchema('user', array('users_roles')); $this->installSchema('system', array('variable', 'url_alias')); $this->installConfig(array('language')); diff --git a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityCrudHookTest.php b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityCrudHookTest.php index 2c452d4..84231d3 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityCrudHookTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityCrudHookTest.php @@ -43,7 +43,7 @@ public static function getInfo() { public function setUp() { parent::setUp(); - $this->installSchema('user', array('users_roles', 'users_data')); + $this->installSchema('user', array('users_data')); $this->installSchema('node', array('node', 'node_field_data', 'node_field_revision', 'node_access')); $this->installSchema('comment', array('comment', 'node_comment_statistics')); } diff --git a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityFieldTest.php b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityFieldTest.php index ebc328d..9bf20e2 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityFieldTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityFieldTest.php @@ -36,7 +36,7 @@ public static function getInfo() { public function setUp() { parent::setUp(); - $this->installSchema('user', array('users_roles', 'users_data')); + $this->installSchema('user', array('users_data')); $this->installSchema('node', array('node', 'node_field_data', 'node_field_revision', 'node_access')); $this->installSchema('entity_test', array( 'entity_test_mul', diff --git a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityRenderTest.php b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityRenderTest.php new file mode 100644 index 0000000..9836c7d --- /dev/null +++ b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityRenderTest.php @@ -0,0 +1,177 @@ + 'Entity rendering', + 'description' => 'Tests the entity render controller.', + 'group' => 'Entity API', + ); + } + + /** + * {@inheritdoc} + */ + public function setUp() { + parent::setUp(); + $this->installConfig(array('entity_test')); + } + + /** + * Tests entity render cache handling. + */ + public function testEntityRenderCache() { + // Force a request via GET so we can get drupal_render() cache working. + $request_method = $_SERVER['REQUEST_METHOD']; + $this->container->get('request')->setMethod('GET'); + + $entity_test = $this->createTestEntity('entity_test_render'); + + // Test that new entities (before they are saved for the first time) do not + // generate a cache entry. + $build = $this->container->get('entity.manager')->getRenderController('entity_test_render')->view($entity_test, 'full'); + $this->assertFalse(isset($build['#cache']), 'The render array element of new (unsaved) entities is not cached.'); + + // Get a fully built entity view render array. + $entity_test->save(); + $build = $this->container->get('entity.manager')->getRenderController('entity_test_render')->view($entity_test, 'full'); + $cid = drupal_render_cid_create($build); + $bin = $build['#cache']['bin']; + + // Mock the build array to not require the theme registry. + unset($build['#theme']); + $build['#markup'] = 'entity_render_test'; + + // Test that a cache entry is created. + drupal_render($build); + $this->assertTrue($this->container->get('cache.' . $bin)->get($cid), 'The entity render element has been cached.'); + + // Re-save the entity and check that the cache entry has been deleted. + $entity_test->save(); + $this->assertFalse($this->container->get('cache.' . $bin)->get($cid), 'The entity render cache has been cleared when the entity was saved.'); + + // Rebuild the render array (creating a new cache entry in the process) and + // delete the entity to check the cache entry is deleted. + unset($build['#printed']); + drupal_render($build); + $this->assertTrue($this->container->get('cache.' . $bin)->get($cid), 'The entity render element has been cached.'); + $entity_test->delete(); + $this->assertFalse($this->container->get('cache.' . $bin)->get($cid), 'The entity render cache has been cleared when the entity was deleted.'); + + // Restore the previous request method. + $this->container->get('request')->setMethod($request_method); + } + + /** + * Tests entity render cache with references. + */ + public function testEntityRenderCacheWithReferences() { + // Force a request via GET so we can get drupal_render() cache working. + $request_method = $_SERVER['REQUEST_METHOD']; + $this->container->get('request')->setMethod('GET'); + + // Create an entity reference field and an entity that will be referenced. + entity_reference_create_instance('entity_test_render', 'entity_test_render', 'reference_field', 'Reference', 'entity_test_render'); + entity_get_display('entity_test_render', 'entity_test_render', 'full')->setComponent('reference_field')->save(); + $entity_test_reference = $this->createTestEntity('entity_test_render'); + $entity_test_reference->save(); + + // Get a fully built entity view render array for the referenced entity. + $build = $this->container->get('entity.manager')->getRenderController('entity_test_render')->view($entity_test_reference, 'full'); + $cid_reference = drupal_render_cid_create($build); + $bin_reference = $build['#cache']['bin']; + + // Mock the build array to not require the theme registry. + unset($build['#theme']); + $build['#markup'] = 'entity_render_test'; + drupal_render($build); + + // Test that a cache entry was created for the referenced entity. + $this->assertTrue($this->container->get('cache.' . $bin_reference)->get($cid_reference), 'The entity render element for the referenced entity has been cached.'); + + // Create another entity that references the first one. + $entity_test = $this->createTestEntity('entity_test_render'); + $entity_test->reference_field->entity = $entity_test_reference; + $entity_test->save(); + + // Get a fully built entity view render array. + $build = $this->container->get('entity.manager')->getRenderController('entity_test_render')->view($entity_test, 'full'); + $cid = drupal_render_cid_create($build); + $bin = $build['#cache']['bin']; + + // Mock the build array to not require the theme registry. + unset($build['#theme']); + $build['#markup'] = 'entity_render_test'; + drupal_render($build); + + // Test that a cache entry is created. + $this->assertTrue($this->container->get('cache.' . $bin)->get($cid), 'The entity render element has been cached.'); + + // Save the entity and verify that both cache entries have been deleted. + $entity_test->save(); + $this->assertFalse($this->container->get('cache.' . $bin)->get($cid), 'The entity render cache has been cleared when the entity was deleted.'); + $this->assertFalse($this->container->get('cache.' . $bin_reference)->get($cid_reference), 'The entity render cache for the referenced entity has been cleared when the entity was deleted.'); + + // Restore the previous request method. + $this->container->get('request')->setMethod($request_method); + } + + /** + * Tests entity render cache toggling. + */ + public function testEntityRenderCacheToggling() { + $entity_test = $this->createTestEntity('entity_test_render'); + $entity_test->save(); + + // Test a view mode in default conditions: render caching is enabled for + // the entity type and the view mode. + $build = $this->container->get('entity.manager')->getRenderController('entity_test_render')->view($entity_test, 'full'); + $this->assertTrue(isset($build['#cache']), 'A view mode with render cache enabled has the correct output.'); + + // Test that a view mode can opt out of render caching. + $build = $this->container->get('entity.manager')->getRenderController('entity_test_render')->view($entity_test, 'test'); + $this->assertFalse(isset($build['#cache']), 'A view mode with render cache disabled has the correct output.'); + + // Test that an entity type can opt out of render caching completely. + $entity_test_no_cache = $this->createTestEntity('entity_test_label'); + $entity_test_no_cache->save(); + $build = $this->container->get('entity.manager')->getRenderController('entity_test_label')->view($entity_test_no_cache, 'full'); + $this->assertFalse(isset($build['#cache']), 'An entity type can opt out of render caching regardless of view mode configuration.'); + } + + /** + * Creates an entity for testing. + * + * @param string $entity_type + * The entity type. + * + * @return \Drupal\Core\Entity\EntityInterface + * The created entity. + */ + protected function createTestEntity($entity_type) { + $data = array( + 'bundle' => $entity_type, + 'name' => $this->randomName(), + ); + return $this->container->get('entity.manager')->getStorageController($entity_type)->create($data); + } + +} diff --git a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityUnitTestBase.php b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityUnitTestBase.php index d3225b3..657cd0a 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityUnitTestBase.php +++ b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityUnitTestBase.php @@ -42,7 +42,7 @@ public function setUp() { $this->entityManager = $this->container->get('entity.manager'); $this->state = $this->container->get('state'); - $this->installSchema('user', 'users'); + $this->installSchema('user', array('users', 'users_roles')); $this->installSchema('system', 'sequences'); $this->installSchema('entity_test', 'entity_test'); $this->installConfig(array('field')); diff --git a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityValidationTest.php b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityValidationTest.php index eab31a8c..b17a700 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityValidationTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityValidationTest.php @@ -37,7 +37,7 @@ public static function getInfo() { */ public function setUp() { parent::setUp(); - $this->installSchema('user', array('users_roles', 'users_data')); + $this->installSchema('user', array('users_data')); $this->installSchema('entity_test', array( 'entity_test_mul', 'entity_test_mul_property_data', diff --git a/core/modules/system/lib/Drupal/system/Tests/TypedData/TypedDataTest.php b/core/modules/system/lib/Drupal/system/Tests/TypedData/TypedDataTest.php index a0e4eb3..6415f27 100644 --- a/core/modules/system/lib/Drupal/system/Tests/TypedData/TypedDataTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/TypedData/TypedDataTest.php @@ -28,7 +28,7 @@ class TypedDataTest extends DrupalUnitTestBase { * * @var array */ - public static $modules = array('system', 'field', 'file'); + public static $modules = array('system', 'entity', 'field', 'file'); public static function getInfo() { return array( diff --git a/core/modules/system/tests/modules/entity_test/config/entity.view_mode.entity_test_label.full.yml b/core/modules/system/tests/modules/entity_test/config/entity.view_mode.entity_test_label.full.yml new file mode 100644 index 0000000..004246f --- /dev/null +++ b/core/modules/system/tests/modules/entity_test/config/entity.view_mode.entity_test_label.full.yml @@ -0,0 +1,5 @@ +id: entity_test_label.full +label: Full +status: '0' +cache: '1' +targetEntityType: entity_test_label 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..8593b8c 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: '0' targetEntityType: entity_test_render diff --git a/core/modules/system/tests/modules/entity_test/entity_test.module b/core/modules/system/tests/modules/entity_test/entity_test.module index 88fc46e..03f73bb 100644 --- a/core/modules/system/tests/modules/entity_test/entity_test.module +++ b/core/modules/system/tests/modules/entity_test/entity_test.module @@ -143,15 +143,17 @@ function entity_test_entity_bundle_info() { function entity_test_entity_view_mode_info_alter(&$view_modes) { $entity_info = entity_get_info(); foreach ($entity_info as $entity_type => $info) { - if ($entity_info[$entity_type]['module'] == 'entity_test') { + if ($entity_info[$entity_type]['module'] == 'entity_test' && !isset($view_modes[$entity_type])) { $view_modes[$entity_type] = array( 'full' => array( 'label' => t('Full object'), 'status' => TRUE, + 'cache' => TRUE, ), 'teaser' => array( 'label' => t('Teaser'), 'status' => TRUE, + 'cache' => TRUE, ), ); } diff --git a/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTestLabel.php b/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTestLabel.php index 224da5a..fc969c3 100644 --- a/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTestLabel.php +++ b/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTestLabel.php @@ -18,9 +18,11 @@ * label = @Translation("Entity Test label"), * module = "entity_test", * controllers = { - * "storage" = "Drupal\entity_test\EntityTestStorageController" + * "storage" = "Drupal\entity_test\EntityTestStorageController", + * "render" = "Drupal\entity_test\EntityTestRenderController" * }, * base_table = "entity_test", + * render_cache = FALSE, * entity_keys = { * "id" = "id", * "label" = "name", 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/lib/Drupal/taxonomy/Entity/Term.php b/core/modules/taxonomy/lib/Drupal/taxonomy/Entity/Term.php index 08b11f8..03ddfe2 100644 --- a/core/modules/taxonomy/lib/Drupal/taxonomy/Entity/Term.php +++ b/core/modules/taxonomy/lib/Drupal/taxonomy/Entity/Term.php @@ -189,7 +189,7 @@ public function preSave(EntityStorageControllerInterface $storage_controller) { * {@inheritdoc} */ public function postSave(EntityStorageControllerInterface $storage_controller, $update = TRUE) { - parent::preSave($storage_controller, $update); + parent::postSave($storage_controller, $update); // Only change the parents if a value is set, keep the existing values if // not. 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/Tests/Views/UserUnitTestBase.php b/core/modules/user/lib/Drupal/user/Tests/Views/UserUnitTestBase.php index 02265f9..9446f66 100644 --- a/core/modules/user/lib/Drupal/user/Tests/Views/UserUnitTestBase.php +++ b/core/modules/user/lib/Drupal/user/Tests/Views/UserUnitTestBase.php @@ -20,7 +20,7 @@ * * @var array */ - public static $modules = array('user_test_views', 'user', 'system', 'field'); + public static $modules = array('user_test_views', 'user', 'system', 'entity', 'field'); /** * Users to use during this test. diff --git a/core/modules/views/lib/Drupal/views/Tests/Plugin/RelationshipJoinTestBase.php b/core/modules/views/lib/Drupal/views/Tests/Plugin/RelationshipJoinTestBase.php index d0bd49c..fae3515 100644 --- a/core/modules/views/lib/Drupal/views/Tests/Plugin/RelationshipJoinTestBase.php +++ b/core/modules/views/lib/Drupal/views/Tests/Plugin/RelationshipJoinTestBase.php @@ -20,7 +20,7 @@ * * @var array */ - public static $modules = array('system', 'user', 'field'); + public static $modules = array('system', 'user', 'entity', 'field'); /** * Overrides \Drupal\views\Tests\ViewUnitTestBase::setUpFixtures(). diff --git a/core/modules/views_ui/lib/Drupal/views_ui/ViewUI.php b/core/modules/views_ui/lib/Drupal/views_ui/ViewUI.php index aa78fb9..7d88791 100644 --- a/core/modules/views_ui/lib/Drupal/views_ui/ViewUI.php +++ b/core/modules/views_ui/lib/Drupal/views_ui/ViewUI.php @@ -1232,4 +1232,19 @@ public static function baseFieldDefinitions($entity_type) { // https://drupal.org/node/2004244. return array(); } + + /** + * {@inheritdoc} + */ + public function referencedEntities() { + return $this->storage->referencedEntities(); + } + + /** + * {@inheritdoc} + */ + public function changed() { + return $this->storage->changed(); + } + }