Chris@0
|
1 <?php
|
Chris@0
|
2
|
Chris@0
|
3 namespace Drupal\Tests\views\Kernel;
|
Chris@0
|
4
|
Chris@0
|
5 use Drupal\Core\Cache\Cache;
|
Chris@0
|
6 use Drupal\Core\Entity\EntityInterface;
|
Chris@0
|
7 use Drupal\Core\Language\LanguageInterface;
|
Chris@0
|
8 use Drupal\entity_test\Entity\EntityTest;
|
Chris@0
|
9 use Drupal\views\Tests\AssertViewsCacheTagsTrait;
|
Chris@0
|
10 use Drupal\views\Views;
|
Chris@0
|
11 use Drupal\views\Entity\View;
|
Chris@0
|
12
|
Chris@0
|
13 /**
|
Chris@0
|
14 * Tests the general integration between views and the render cache.
|
Chris@0
|
15 *
|
Chris@0
|
16 * @group views
|
Chris@0
|
17 */
|
Chris@0
|
18 class RenderCacheIntegrationTest extends ViewsKernelTestBase {
|
Chris@0
|
19
|
Chris@0
|
20 use AssertViewsCacheTagsTrait;
|
Chris@0
|
21
|
Chris@0
|
22 /**
|
Chris@0
|
23 * {@inheritdoc}
|
Chris@0
|
24 */
|
Chris@0
|
25 public static $testViews = ['test_view', 'test_display', 'entity_test_fields', 'entity_test_row'];
|
Chris@0
|
26
|
Chris@0
|
27 /**
|
Chris@0
|
28 * {@inheritdoc}
|
Chris@0
|
29 */
|
Chris@0
|
30 public static $modules = ['entity_test', 'user', 'node'];
|
Chris@0
|
31
|
Chris@0
|
32 /**
|
Chris@0
|
33 * {@inheritdoc}
|
Chris@0
|
34 */
|
Chris@0
|
35 protected function setUp($import_test_views = TRUE) {
|
Chris@0
|
36 parent::setUp();
|
Chris@0
|
37
|
Chris@0
|
38 $this->installEntitySchema('entity_test');
|
Chris@0
|
39 $this->installEntitySchema('user');
|
Chris@0
|
40 }
|
Chris@0
|
41
|
Chris@0
|
42 /**
|
Chris@0
|
43 * Tests a field-based view's cache tags when using the "none" cache plugin.
|
Chris@0
|
44 */
|
Chris@0
|
45 public function testFieldBasedViewCacheTagsWithCachePluginNone() {
|
Chris@0
|
46 $view = Views::getview('entity_test_fields');
|
Chris@0
|
47 $view->getDisplay()->overrideOption('cache', [
|
Chris@0
|
48 'type' => 'none',
|
Chris@0
|
49 ]);
|
Chris@0
|
50 $view->save();
|
Chris@0
|
51
|
Chris@0
|
52 $this->assertCacheTagsForFieldBasedView(FALSE);
|
Chris@0
|
53 }
|
Chris@0
|
54
|
Chris@0
|
55 /**
|
Chris@0
|
56 * Tests a field-based view's cache tags when using the "tag" cache plugin.
|
Chris@0
|
57 */
|
Chris@0
|
58 public function testFieldBasedViewCacheTagsWithCachePluginTag() {
|
Chris@0
|
59 $view = Views::getview('entity_test_fields');
|
Chris@0
|
60 $view->getDisplay()->overrideOption('cache', [
|
Chris@0
|
61 'type' => 'tag',
|
Chris@0
|
62 ]);
|
Chris@0
|
63 $view->save();
|
Chris@0
|
64
|
Chris@0
|
65 $this->assertCacheTagsForFieldBasedView(TRUE);
|
Chris@0
|
66 }
|
Chris@0
|
67
|
Chris@0
|
68 /**
|
Chris@0
|
69 * Tests a field-based view's cache tags when using the "time" cache plugin.
|
Chris@0
|
70 */
|
Chris@0
|
71 public function testFieldBasedViewCacheTagsWithCachePluginTime() {
|
Chris@0
|
72 $view = Views::getview('entity_test_fields');
|
Chris@0
|
73 $view->getDisplay()->overrideOption('cache', [
|
Chris@0
|
74 'type' => 'time',
|
Chris@0
|
75 'options' => [
|
Chris@0
|
76 'results_lifespan' => 3600,
|
Chris@0
|
77 'output_lifespan' => 3600,
|
Chris@0
|
78 ],
|
Chris@0
|
79 ]);
|
Chris@0
|
80 $view->save();
|
Chris@0
|
81
|
Chris@0
|
82 $this->assertCacheTagsForFieldBasedView(TRUE);
|
Chris@0
|
83 }
|
Chris@0
|
84
|
Chris@0
|
85 /**
|
Chris@0
|
86 * Tests cache tags on output & result cache items for a field-based view.
|
Chris@0
|
87 *
|
Chris@0
|
88 * @param bool $do_assert_views_caches
|
Chris@0
|
89 * Whether to check Views' result & output caches.
|
Chris@0
|
90 */
|
Chris@0
|
91 protected function assertCacheTagsForFieldBasedView($do_assert_views_caches) {
|
Chris@0
|
92 $this->pass('Checking cache tags for field-based view.');
|
Chris@0
|
93 $view = Views::getview('entity_test_fields');
|
Chris@0
|
94
|
Chris@0
|
95 // Empty result (no entities yet).
|
Chris@0
|
96 $this->pass('Test without entities');
|
Chris@0
|
97 $base_tags = ['config:views.view.entity_test_fields', 'entity_test_list'];
|
Chris@0
|
98 $this->assertViewsCacheTags($view, $base_tags, $do_assert_views_caches, $base_tags);
|
Chris@0
|
99 $this->assertViewsCacheTagsFromStaticRenderArray($view, $base_tags, $do_assert_views_caches);
|
Chris@0
|
100
|
Chris@0
|
101 // Non-empty result (1 entity).
|
Chris@0
|
102 /** @var \Drupal\Core\Entity\EntityInterface[] $entities */
|
Chris@0
|
103 $entities[] = $entity = EntityTest::create();
|
Chris@0
|
104 $entity->save();
|
Chris@0
|
105
|
Chris@0
|
106 $this->pass('Test with entities');
|
Chris@0
|
107 $tags_with_entity = Cache::mergeTags($base_tags, $entities[0]->getCacheTags());
|
Chris@0
|
108 $this->assertViewsCacheTags($view, $tags_with_entity, $do_assert_views_caches, $tags_with_entity);
|
Chris@0
|
109 $this->assertViewsCacheTagsFromStaticRenderArray($view, $tags_with_entity, $do_assert_views_caches);
|
Chris@0
|
110
|
Chris@0
|
111 // Paged result (more entities than the items-per-page limit).
|
Chris@0
|
112 for ($i = 0; $i < 5; $i++) {
|
Chris@0
|
113 $entities[] = $entity = EntityTest::create();
|
Chris@0
|
114 $entity->save();
|
Chris@0
|
115 }
|
Chris@0
|
116
|
Chris@0
|
117 // Page 1.
|
Chris@0
|
118 $this->pass('Test pager');
|
Chris@0
|
119 $this->pass('Page 1');
|
Chris@0
|
120 \Drupal::request()->query->set('page', 0);
|
Chris@0
|
121 $tags_page_1 = Cache::mergeTags($base_tags, $entities[1]->getCacheTags());
|
Chris@0
|
122 $tags_page_1 = Cache::mergeTags($tags_page_1, $entities[2]->getCacheTags());
|
Chris@0
|
123 $tags_page_1 = Cache::mergeTags($tags_page_1, $entities[3]->getCacheTags());
|
Chris@0
|
124 $tags_page_1 = Cache::mergeTags($tags_page_1, $entities[4]->getCacheTags());
|
Chris@0
|
125 $tags_page_1 = Cache::mergeTags($tags_page_1, $entities[5]->getCacheTags());
|
Chris@0
|
126 $this->assertViewsCacheTags($view, $tags_page_1, $do_assert_views_caches, $tags_page_1);
|
Chris@0
|
127 $this->assertViewsCacheTagsFromStaticRenderArray($view, $tags_page_1, $do_assert_views_caches);
|
Chris@0
|
128 $view->destroy();
|
Chris@0
|
129 // Page 2.
|
Chris@0
|
130 $this->pass('Page 2');
|
Chris@0
|
131 $view->setCurrentPage(1);
|
Chris@0
|
132 \Drupal::request()->query->set('page', 1);
|
Chris@0
|
133 $tags_page_2 = Cache::mergeTags($base_tags, $entities[0]->getCacheTags());
|
Chris@0
|
134 $this->assertViewsCacheTags($view, $tags_page_2, $do_assert_views_caches, $tags_page_2);
|
Chris@0
|
135 $view->destroy();
|
Chris@0
|
136
|
Chris@0
|
137 // Ensure that invalidation works on both pages.
|
Chris@0
|
138 $this->pass('Page invalidations');
|
Chris@0
|
139 $this->pass('Page 2');
|
Chris@0
|
140 $view->setCurrentPage(1);
|
Chris@0
|
141 \Drupal::request()->query->set('page', 1);
|
Chris@0
|
142 $entities[0]->name->value = $random_name = $this->randomMachineName();
|
Chris@0
|
143 $entities[0]->save();
|
Chris@0
|
144 $build = $this->assertViewsCacheTags($view, $tags_page_2, $do_assert_views_caches, $tags_page_2);
|
Chris@0
|
145 // @todo Static render arrays don't support different pages yet, see
|
Chris@0
|
146 // https://www.drupal.org/node/2500701.
|
Chris@0
|
147 // $this->assertViewsCacheTagsFromStaticRenderArray($view, $tags_page_2, $do_assert_views_caches);
|
Chris@0
|
148 $this->assertTrue(strpos($build['#markup'], $random_name) !== FALSE);
|
Chris@0
|
149 $view->destroy();
|
Chris@0
|
150
|
Chris@0
|
151 $this->pass('Page 1');
|
Chris@0
|
152 $view->setCurrentPage(0);
|
Chris@0
|
153 \Drupal::request()->query->set('page', 0);
|
Chris@0
|
154 $entities[1]->name->value = $random_name = $this->randomMachineName();
|
Chris@0
|
155 $entities[1]->save();
|
Chris@0
|
156 $build = $this->assertViewsCacheTags($view, $tags_page_1, $do_assert_views_caches, $tags_page_1);
|
Chris@0
|
157 $this->assertViewsCacheTagsFromStaticRenderArray($view, $tags_page_1, $do_assert_views_caches);
|
Chris@0
|
158 $this->assertTrue(strpos($build['#markup'], $random_name) !== FALSE);
|
Chris@0
|
159 $view->destroy();
|
Chris@0
|
160
|
Chris@0
|
161 // Setup arguments to ensure that render caching also varies by them.
|
Chris@0
|
162 $this->pass('Test arguments');
|
Chris@0
|
163
|
Chris@0
|
164 // Custom assert for a single result row.
|
Chris@0
|
165 $single_entity_assertions = function (array $build, EntityInterface $entity) {
|
Chris@0
|
166 $this->setRawContent($build['#markup']);
|
Chris@0
|
167
|
Chris@0
|
168 $result = $this->cssSelect('div.views-row');
|
Chris@0
|
169 $count = count($result);
|
Chris@0
|
170 $this->assertEqual($count, 1);
|
Chris@0
|
171
|
Chris@0
|
172 $this->assertEqual((string) $result[0]->div->span, (string) $entity->id());
|
Chris@0
|
173 };
|
Chris@0
|
174
|
Chris@0
|
175 // Execute the view once with a static renderable and one with a full
|
Chris@0
|
176 // prepared render array.
|
Chris@0
|
177 $tags_argument = Cache::mergeTags($base_tags, $entities[0]->getCacheTags());
|
Chris@0
|
178 $view->setArguments([$entities[0]->id()]);
|
Chris@0
|
179 $build = $this->assertViewsCacheTags($view, $tags_argument, $do_assert_views_caches, $tags_argument);
|
Chris@0
|
180 $single_entity_assertions($build, $entities[0]);
|
Chris@0
|
181
|
Chris@0
|
182 $view->setArguments([$entities[0]->id()]);
|
Chris@0
|
183 $build = $this->assertViewsCacheTagsFromStaticRenderArray($view, $tags_argument, $do_assert_views_caches);
|
Chris@0
|
184 $single_entity_assertions($build, $entities[0]);
|
Chris@0
|
185
|
Chris@0
|
186 // Set a different argument and ensure that the result is different.
|
Chris@0
|
187 $tags2_argument = Cache::mergeTags($base_tags, $entities[1]->getCacheTags());
|
Chris@0
|
188 $view->setArguments([$entities[1]->id()]);
|
Chris@0
|
189 $build = $this->assertViewsCacheTagsFromStaticRenderArray($view, $tags2_argument, $do_assert_views_caches);
|
Chris@0
|
190 $single_entity_assertions($build, $entities[1]);
|
Chris@0
|
191
|
Chris@0
|
192 $view->destroy();
|
Chris@0
|
193 }
|
Chris@0
|
194
|
Chris@0
|
195 /**
|
Chris@0
|
196 * Tests a entity-based view's cache tags when using the "none" cache plugin.
|
Chris@0
|
197 */
|
Chris@0
|
198 public function testEntityBasedViewCacheTagsWithCachePluginNone() {
|
Chris@0
|
199 $view = Views::getview('entity_test_row');
|
Chris@0
|
200 $view->getDisplay()->overrideOption('cache', [
|
Chris@0
|
201 'type' => 'none',
|
Chris@0
|
202 ]);
|
Chris@0
|
203 $view->save();
|
Chris@0
|
204
|
Chris@0
|
205 $this->assertCacheTagsForEntityBasedView(FALSE);
|
Chris@0
|
206 }
|
Chris@0
|
207
|
Chris@0
|
208 /**
|
Chris@0
|
209 * Tests a entity-based view's cache tags when using the "tag" cache plugin.
|
Chris@0
|
210 */
|
Chris@0
|
211 public function testEntityBasedViewCacheTagsWithCachePluginTag() {
|
Chris@0
|
212 $view = Views::getview('entity_test_row');
|
Chris@0
|
213 $view->getDisplay()->overrideOption('cache', [
|
Chris@0
|
214 'type' => 'tag',
|
Chris@0
|
215 ]);
|
Chris@0
|
216 $view->save();
|
Chris@0
|
217
|
Chris@0
|
218 $this->assertCacheTagsForEntityBasedView(TRUE);
|
Chris@0
|
219 }
|
Chris@0
|
220
|
Chris@0
|
221 /**
|
Chris@0
|
222 * Tests a entity-based view's cache tags when using the "time" cache plugin.
|
Chris@0
|
223 */
|
Chris@0
|
224 public function testEntityBasedViewCacheTagsWithCachePluginTime() {
|
Chris@0
|
225 $view = Views::getview('entity_test_row');
|
Chris@0
|
226 $view->getDisplay()->overrideOption('cache', [
|
Chris@0
|
227 'type' => 'time',
|
Chris@0
|
228 'options' => [
|
Chris@0
|
229 'results_lifespan' => 3600,
|
Chris@0
|
230 'output_lifespan' => 3600,
|
Chris@0
|
231 ],
|
Chris@0
|
232 ]);
|
Chris@0
|
233 $view->save();
|
Chris@0
|
234
|
Chris@0
|
235 $this->assertCacheTagsForEntityBasedView(TRUE);
|
Chris@0
|
236 }
|
Chris@0
|
237
|
Chris@0
|
238 /**
|
Chris@0
|
239 * Tests cache tags on output & result cache items for an entity-based view.
|
Chris@0
|
240 */
|
Chris@0
|
241 protected function assertCacheTagsForEntityBasedView($do_assert_views_caches) {
|
Chris@0
|
242 $this->pass('Checking cache tags for entity-based view.');
|
Chris@0
|
243 $view = Views::getview('entity_test_row');
|
Chris@0
|
244
|
Chris@0
|
245 // Empty result (no entities yet).
|
Chris@0
|
246 $base_tags = $base_render_tags = ['config:views.view.entity_test_row', 'entity_test_list'];
|
Chris@0
|
247 $this->assertViewsCacheTags($view, $base_tags, $do_assert_views_caches, $base_tags);
|
Chris@0
|
248 $this->assertViewsCacheTagsFromStaticRenderArray($view, $base_tags, $do_assert_views_caches);
|
Chris@0
|
249
|
Chris@0
|
250 // Non-empty result (1 entity).
|
Chris@0
|
251 $entities[] = $entity = EntityTest::create();
|
Chris@0
|
252 $entity->save();
|
Chris@0
|
253
|
Chris@0
|
254 $result_tags_with_entity = Cache::mergeTags($base_tags, $entities[0]->getCacheTags());
|
Chris@0
|
255 $render_tags_with_entity = Cache::mergeTags($base_render_tags, $entities[0]->getCacheTags());
|
Chris@0
|
256 $render_tags_with_entity = Cache::mergeTags($render_tags_with_entity, ['entity_test_view']);
|
Chris@0
|
257 $this->assertViewsCacheTags($view, $result_tags_with_entity, $do_assert_views_caches, $render_tags_with_entity);
|
Chris@0
|
258 $this->assertViewsCacheTagsFromStaticRenderArray($view, $render_tags_with_entity, $do_assert_views_caches);
|
Chris@0
|
259
|
Chris@0
|
260 // Paged result (more entities than the items-per-page limit).
|
Chris@0
|
261 for ($i = 0; $i < 5; $i++) {
|
Chris@0
|
262 $entities[] = $entity = EntityTest::create();
|
Chris@0
|
263 $entity->save();
|
Chris@0
|
264 }
|
Chris@0
|
265
|
Chris@0
|
266 $new_entities_cache_tags = Cache::mergeTags($entities[1]->getCacheTags(), $entities[2]->getCacheTags());
|
Chris@0
|
267 $new_entities_cache_tags = Cache::mergeTags($new_entities_cache_tags, $entities[3]->getCacheTags());
|
Chris@0
|
268 $new_entities_cache_tags = Cache::mergeTags($new_entities_cache_tags, $entities[4]->getCacheTags());
|
Chris@0
|
269 $new_entities_cache_tags = Cache::mergeTags($new_entities_cache_tags, $entities[5]->getCacheTags());
|
Chris@0
|
270 $result_tags_page_1 = Cache::mergeTags($base_tags, $new_entities_cache_tags);
|
Chris@0
|
271 $render_tags_page_1 = Cache::mergeTags($base_render_tags, $new_entities_cache_tags);
|
Chris@0
|
272 $render_tags_page_1 = Cache::mergeTags($render_tags_page_1, ['entity_test_view']);
|
Chris@0
|
273 $this->assertViewsCacheTags($view, $result_tags_page_1, $do_assert_views_caches, $render_tags_page_1);
|
Chris@0
|
274 $this->assertViewsCacheTagsFromStaticRenderArray($view, $render_tags_page_1, $do_assert_views_caches);
|
Chris@0
|
275 }
|
Chris@0
|
276
|
Chris@0
|
277 /**
|
Chris@0
|
278 * Ensure that the view renderable contains the cache contexts.
|
Chris@0
|
279 */
|
Chris@0
|
280 public function testBuildRenderableWithCacheContexts() {
|
Chris@0
|
281 $view = View::load('test_view');
|
Chris@0
|
282 $display =& $view->getDisplay('default');
|
Chris@0
|
283 $display['cache_metadata']['contexts'] = ['views_test_cache_context'];
|
Chris@0
|
284 $executable = $view->getExecutable();
|
Chris@0
|
285
|
Chris@0
|
286 $build = $executable->buildRenderable();
|
Chris@0
|
287 $this->assertEqual(['views_test_cache_context'], $build['#cache']['contexts']);
|
Chris@0
|
288 }
|
Chris@0
|
289
|
Chris@0
|
290 /**
|
Chris@0
|
291 * Ensures that saving a view calculates the cache contexts.
|
Chris@0
|
292 */
|
Chris@0
|
293 public function testViewAddCacheMetadata() {
|
Chris@0
|
294 $view = View::load('test_display');
|
Chris@0
|
295 $view->save();
|
Chris@0
|
296
|
Chris@0
|
297 $this->assertEqual(['languages:' . LanguageInterface::TYPE_CONTENT, 'languages:' . LanguageInterface::TYPE_INTERFACE, 'url.query_args', 'user.node_grants:view', 'user.permissions'], $view->getDisplay('default')['cache_metadata']['contexts']);
|
Chris@0
|
298 }
|
Chris@0
|
299
|
Chris@0
|
300 }
|