diff --git a/core/modules/node/src/Tests/Views/FrontPageTest.php b/core/modules/node/src/Tests/Views/FrontPageTest.php index 83e54b00fea4b86fb6e5b7104e203a87ca4c63e5..04414dcb10047d43cdfbc8f7fedb3e3e856cb787 100644 --- a/core/modules/node/src/Tests/Views/FrontPageTest.php +++ b/core/modules/node/src/Tests/Views/FrontPageTest.php @@ -250,6 +250,7 @@ protected function assertFrontPageViewCacheTags($do_assert_views_caches) { 'user.permissions', // Default cache contexts of the renderer. 'theme', + 'url.query_args.pagers:0', ]; // Test before there are any nodes. diff --git a/core/modules/views/src/Plugin/views/cache/CachePluginBase.php b/core/modules/views/src/Plugin/views/cache/CachePluginBase.php index bf5eb2a89936457830e759bfd258b0d190dcf780..23c917a55aa2a81a58c9081710228bf33f535ff5 100644 --- a/core/modules/views/src/Plugin/views/cache/CachePluginBase.php +++ b/core/modules/views/src/Plugin/views/cache/CachePluginBase.php @@ -229,7 +229,7 @@ public function cacheGet($type) { // Load entities for each result. $this->view->query->loadEntities($this->view->result); $this->view->total_rows = $cache->data['total_rows']; - $this->view->setCurrentPage($cache->data['current_page']); + $this->view->setCurrentPage($cache->data['current_page'], TRUE); $this->view->execute_time = 0; return TRUE; } diff --git a/core/modules/views/src/Plugin/views/pager/SqlBase.php b/core/modules/views/src/Plugin/views/pager/SqlBase.php index b4edcd1ab4e737aff725dc854b0c4d41a89075d4..24e8bab000d2ab9e0bfd838f272022310491249c 100644 --- a/core/modules/views/src/Plugin/views/pager/SqlBase.php +++ b/core/modules/views/src/Plugin/views/pager/SqlBase.php @@ -388,7 +388,7 @@ public function isCacheable() { * {@inheritdoc} */ public function getCacheContexts() { - $contexts = []; + $contexts = ['url.query_args.pagers:' . $this->options['id']]; if ($this->options['expose']['items_per_page']) { $contexts[] = 'url.query_args:items_per_page'; } diff --git a/core/modules/views/src/Tests/Handler/FieldWebTest.php b/core/modules/views/src/Tests/Handler/FieldWebTest.php index e8a2de96763ea54ba6f1cfe4865e0ace323f0e07..f333403735b71b81ea0b5c8cc28bdd8704fdb1ec 100644 --- a/core/modules/views/src/Tests/Handler/FieldWebTest.php +++ b/core/modules/views/src/Tests/Handler/FieldWebTest.php @@ -75,6 +75,7 @@ public function testClickSorting() { $expected_contexts = [ 'languages:language_interface', 'theme', + 'url.query_args.pagers:0', 'url.query_args:order', 'url.query_args:sort', ]; diff --git a/core/modules/views/src/Tests/Plugin/ExposedFormTest.php b/core/modules/views/src/Tests/Plugin/ExposedFormTest.php index 97de723445ad8a626ee459c271b6a31123952127..7e58113fe834533e2eb4b3a44278fe8650711264 100644 --- a/core/modules/views/src/Tests/Plugin/ExposedFormTest.php +++ b/core/modules/views/src/Tests/Plugin/ExposedFormTest.php @@ -206,6 +206,7 @@ public function testExposedSortAndItemsPerPage() { 'languages:language_interface', 'entity_test_view_grants', 'theme', + 'url.query_args.pagers:0', 'url.query_args:items_per_page', 'url.query_args:offset', 'url.query_args:sort_order', diff --git a/core/modules/views/src/Tests/Plugin/PagerKernelTest.php b/core/modules/views/src/Tests/Plugin/PagerKernelTest.php new file mode 100644 index 0000000000000000000000000000000000000000..de1817180b3c1d05a12e0a391e5463ec034737f2 --- /dev/null +++ b/core/modules/views/src/Tests/Plugin/PagerKernelTest.php @@ -0,0 +1,77 @@ +<?php + +/** + * @file + * Contains \Drupal\views\Tests\Plugin\PagerKernelTest. + */ + +namespace Drupal\views\Tests\Plugin; + +use Drupal\Core\Cache\CacheBackendInterface; +use Drupal\views\Tests\ViewUnitTestBase; +use Drupal\views\Views; + +/** + * Tests pager related APIs. + * + * @group views + */ +class PagerKernelTest extends ViewUnitTestBase { + + /** + * {@inheritdoc} + */ + public static $testViews = ['test_pager_full']; + + /** + * {@inheritdoc} + */ + public static $modules = ['user', 'node']; + + /** + * {@inheritdoc} + */ + protected function setUp($import_test_views = TRUE) { + parent::setUp($import_test_views); + + $this->installEntitySchema('node'); + $this->installEntitySchema('user'); + } + + /** + * Tests pager related setter methods on ViewExecutable. + * + * @see \Drupal\views\ViewExecutable::setItemsPerPage + * @see \Drupal\views\ViewExecutable::setOffset + * @see \Drupal\views\ViewExecutable::setCurrentPage + */ + public function testSetPagerMethods() { + $view = Views::getView('test_pager_full'); + $output = $view->preview(); + + \Drupal::service('renderer')->renderPlain($output); + $this->assertIdentical(CacheBackendInterface::CACHE_PERMANENT, $output['#cache']['max-age']); + + foreach (['setItemsPerPage', 'setOffset', 'setCurrentPage'] as $method) { + // Without $keep_cacheablity. + $view = Views::getView('test_pager_full'); + $view->setDisplay('default'); + $view->{$method}(1); + $output = $view->preview(); + + \Drupal::service('renderer')->renderPlain($output); + $this->assertIdentical(0, $output['#cache']['max-age'], 'Max age set to 0 without $keep_cacheablity.'); + + // With $keep_cacheablity. + $view = Views::getView('test_pager_full'); + $view->setDisplay('default'); + $view->{$method}(1, TRUE); + $output = $view->preview(); + + \Drupal::service('renderer')->renderPlain($output); + $this->assertIdentical(CacheBackendInterface::CACHE_PERMANENT, $output['#cache']['max-age'], 'Max age kept on -1 with $keep_cacheablity.'); + } + + } + +} diff --git a/core/modules/views/src/Tests/Plugin/PagerTest.php b/core/modules/views/src/Tests/Plugin/PagerTest.php index af4555d62e5860721d05bfa47443ae2b2ee1a152..15384c1dcd6457ec2f4d783b4a09ad0fd0830dd4 100644 --- a/core/modules/views/src/Tests/Plugin/PagerTest.php +++ b/core/modules/views/src/Tests/Plugin/PagerTest.php @@ -7,6 +7,7 @@ namespace Drupal\views\Tests\Plugin; +use Drupal\system\Tests\Cache\AssertPageCacheContextsAndTagsTrait; use Drupal\views\Views; use Drupal\language\Entity\ConfigurableLanguage; @@ -17,6 +18,8 @@ */ class PagerTest extends PluginTestBase { + use AssertPageCacheContextsAndTagsTrait; + /** * Views used by this test. * @@ -255,6 +258,10 @@ public function testNormalPager() { $this->executeView($view); $this->assertEqual($view->pager->getItemsPerPage(), 0); $this->assertEqual(count($view->result), 11); + + // Test pager cache contexts. + $this->drupalGet('test_pager_full'); + $this->assertCacheContexts(['languages:language_interface', 'theme', 'timezone', 'url.query_args.pagers:0', 'user.node_grants:view']); } /** diff --git a/core/modules/views/src/Tests/RenderCacheIntegrationTest.php b/core/modules/views/src/Tests/RenderCacheIntegrationTest.php index 183e3956ee5e383f6d63ca7fe6703eb520072419..4ec2c41f2c88cbda4b12f47b5c1b4e0ac4986975 100644 --- a/core/modules/views/src/Tests/RenderCacheIntegrationTest.php +++ b/core/modules/views/src/Tests/RenderCacheIntegrationTest.php @@ -222,7 +222,7 @@ public function testViewAddCacheMetadata() { $view = View::load('test_display'); $view->save(); - $this->assertEqual(['languages:' . LanguageInterface::TYPE_CONTENT, 'languages:' . LanguageInterface::TYPE_INTERFACE, 'user.node_grants:view'], $view->getDisplay('default')['cache_metadata']['contexts']); + $this->assertEqual(['languages:' . LanguageInterface::TYPE_CONTENT, 'languages:' . LanguageInterface::TYPE_INTERFACE, 'url.query_args.pagers:0', 'user.node_grants:view'], $view->getDisplay('default')['cache_metadata']['contexts']); } } diff --git a/core/modules/views/src/ViewExecutable.php b/core/modules/views/src/ViewExecutable.php index d44f477ec031bd990dfc90ae2c93f9a18c69f9d2..7fd389b653a263cae86735c7de5d9f34fd362be7 100644 --- a/core/modules/views/src/ViewExecutable.php +++ b/core/modules/views/src/ViewExecutable.php @@ -491,10 +491,22 @@ public function setArguments(array $args) { /** * Change/Set the current page for the pager. + * + * @param int $page + * The current page. + * @param bool $keep_cacheability + * (optional) Keep the cacheability. By default we mark the view as not + * cacheable. The reason for this parameter is that we do not know what the + * passed in value varies by. For example, it could be per role. Defaults to + * FALSE. */ - public function setCurrentPage($page) { + public function setCurrentPage($page, $keep_cacheability = FALSE) { $this->current_page = $page; + if (!$keep_cacheability) { + $this->element['#cache']['max-age'] = 0; + } + // If the pager is already initialized, pass it through to the pager. if (!empty($this->pager)) { return $this->pager->setCurrentPage($page); @@ -531,14 +543,26 @@ public function getItemsPerPage() { /** * Set the items per page on the pager. + * + * @param int $items_per_page + * The items per page. + * @param bool $keep_cacheability + * (optional) Keep the cacheability. By default we mark the view as not + * cacheable. The reason for this parameter is that we do not know what the + * passed in value varies by. For example, it could be per role. Defaults to + * FALSE. */ - public function setItemsPerPage($items_per_page) { + public function setItemsPerPage($items_per_page, $keep_cacheability = FALSE) { $this->items_per_page = $items_per_page; // If the pager is already initialized, pass it through to the pager. if (!empty($this->pager)) { $this->pager->setItemsPerPage($items_per_page); } + + if (!$keep_cacheability) { + $this->element['#cache']['max-age'] = 0; + } } /** @@ -557,14 +581,26 @@ public function getOffset() { /** * Set the offset on the pager. + * + * @param int $offset + * The pager offset. + * @param bool $keep_cacheability + * (optional) Keep the cacheability. By default we mark the view as not + * cacheable. The reason for this parameter is that we do not know what the + * passed in value varies by. For example, it could be per role. Defaults to + * FALSE. */ - public function setOffset($offset) { + public function setOffset($offset, $keep_cacheability = FALSE) { $this->offset = $offset; // If the pager is already initialized, pass it through to the pager. if (!empty($this->pager)) { $this->pager->setOffset($offset); } + + if (!$keep_cacheability) { + $this->element['#cache']['max-age'] = 0; + } } /** @@ -2363,7 +2399,7 @@ public function unserialize($serialized) { $this->setDisplay($current_display); $this->setArguments($args); - $this->setCurrentPage($current_page); + $this->setCurrentPage($current_page, TRUE); $this->setExposedInput($exposed_input); $this->exposed_data = $exposed_data; $this->exposed_raw_input = $exposed_raw_input;