diff --git a/core/modules/views/tests/modules/views_test_cacheable_metadata_calculation/config/install/views.view.test_cacheable_metadata_calculation.yml b/core/modules/views/tests/modules/views_test_cacheable_metadata_calculation/config/install/views.view.test_cacheable_metadata_calculation.yml new file mode 100644 index 0000000000..10015bd237 --- /dev/null +++ b/core/modules/views/tests/modules/views_test_cacheable_metadata_calculation/config/install/views.view.test_cacheable_metadata_calculation.yml @@ -0,0 +1,39 @@ +langcode: en +status: true +dependencies: + module: + - user +id: test_cacheable_metadata_calculation +label: '' +module: views +description: '' +tag: '' +base_table: users_field_data +base_field: uid +core: '8' +display: + default: + display_options: + access: + type: test_cacheable_metadata_access + cache: + type: tag + exposed_form: + type: basic + pager: + type: full + style: + type: default + row: + type: fields + display_plugin: default + display_title: Master + id: default + position: 0 + cache_metadata: + max-age: -1 + contexts: + - 'languages:language_content' + - 'languages:language_interface' + - 'user.node_grants:view' + tags: { } diff --git a/core/modules/views/tests/modules/views_test_cacheable_metadata_calculation/src/Plugin/views/access/CachableMetadataCalculationTest.php b/core/modules/views/tests/modules/views_test_cacheable_metadata_calculation/src/Plugin/views/access/CachableMetadataCalculationTest.php new file mode 100644 index 0000000000..379dfec702 --- /dev/null +++ b/core/modules/views/tests/modules/views_test_cacheable_metadata_calculation/src/Plugin/views/access/CachableMetadataCalculationTest.php @@ -0,0 +1,104 @@ +state = $state; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { + return new static( + $configuration, + $plugin_id, + $plugin_definition, + $container->get('state') + ); + } + + /** + * {@inheritdoc} + */ + public function access(AccountInterface $account) { + return TRUE; + } + + /** + * {@inheritdoc} + */ + public function alterRouteDefinition(Route $route) { + } + + /** + * {@inheritdoc} + */ + public function getCacheContexts() { + $this->cacheableMetadataHasBeenAccessed(); + return []; + } + + /** + * {@inheritdoc} + */ + public function getCacheTags() { + $this->cacheableMetadataHasBeenAccessed(); + return []; + } + + /** + * {@inheritdoc} + */ + public function getCacheMaxAge() { + $this->cacheableMetadataHasBeenAccessed(); + return Cache::PERMANENT; + } + + /** + * Sets a flag to inform tests that cacheable metadata has been accessed. + */ + protected function cacheableMetadataHasBeenAccessed() { + $this->state->set('views_test_cacheable_metadata_has_been_accessed', TRUE); + } + +} diff --git a/core/modules/views/tests/modules/views_test_cacheable_metadata_calculation/views_test_cacheable_metadata_calculation.info.yml b/core/modules/views/tests/modules/views_test_cacheable_metadata_calculation/views_test_cacheable_metadata_calculation.info.yml new file mode 100644 index 0000000000..e8c1664b91 --- /dev/null +++ b/core/modules/views/tests/modules/views_test_cacheable_metadata_calculation/views_test_cacheable_metadata_calculation.info.yml @@ -0,0 +1,8 @@ +name: 'Views test cacheable metadata calculation' +type: module +description: 'Module to test cacheable metadata calculation in Views.' +package: Testing +version: VERSION +core: 8.x +dependencies: + - drupal:views diff --git a/core/modules/views/tests/src/Kernel/CachableMetadataCalculationTest.php b/core/modules/views/tests/src/Kernel/CachableMetadataCalculationTest.php new file mode 100644 index 0000000000..1befb03bd4 --- /dev/null +++ b/core/modules/views/tests/src/Kernel/CachableMetadataCalculationTest.php @@ -0,0 +1,111 @@ +installConfig(['views']); + $this->installEntitySchema('user'); + + $this->state = $this->container->get('state'); + $this->entityTypeManager = $this->container->get('entity_type.manager'); + } + + /** + * Tests that cacheability metadata is only calculated when needed. + * + * Determining the cacheability of a view is an expensive operation since it + * requires all Views plugins and handlers to be initialized. For efficiency + * reasons this should only be done if a view is being saved (either through + * the UI or the API). The cacheability metadata is then stored in the view + * config and is ready to use at runtime. + * + * It should not be calculated when a view is enabled through installing a + * module, or by syncing configuration. + * + * @see \Drupal\views\Entity\View::addCacheMetadata() + */ + public function testCacheableMetadataCalculation() { + // Enabling a module that contains a view should not cause the cacheability + // metadata to be recalculated. + $this->enableModules([self::TEST_MODULE]); + $this->installConfig([self::TEST_MODULE]); + $this->assertCachebleMetadataHasBeenCalculated(FALSE); + + // When a view is saved normally we have to recalculate the cacheability + // metadata, since it is possible changes have been made to the view that + // affect cacheability. + $view = $this->entityTypeManager->getStorage('view')->load(self::TEST_VIEW_ID); + $view->save(); + $this->assertCachebleMetadataHasBeenCalculated(TRUE); + $this->resetState(); + + // When a view is being saved due to config being synchronized, the + // cacheability metadata doesn't change so it should not be recalculated. + $view->setSyncing(TRUE); + $view->save(); + $this->assertCachebleMetadataHasBeenCalculated(FALSE); + } + + /** + * Checks whether the view has calculated its cacheability metadata. + * + * @param bool $expected_result + * TRUE if it is expected that the cacheability metadata has been + * calculated. FALSE otherwise. + */ + protected function assertCachebleMetadataHasBeenCalculated($expected_result) { + $this->state->resetCache(); + $this->assertEquals($expected_result, $this->state->get('views_test_cacheable_metadata_has_been_accessed')); + } + + /** + * Resets the state so we are ready for a new test. + */ + protected function resetState() { + $this->state->set('views_test_cacheable_metadata_has_been_accessed', FALSE); + } + +}