Chris@0
|
1 <?php
|
Chris@0
|
2
|
Chris@0
|
3 /**
|
Chris@0
|
4 * @file
|
Chris@0
|
5 * Post update functions for Views.
|
Chris@0
|
6 */
|
Chris@0
|
7
|
Chris@17
|
8 use Drupal\Core\Config\Entity\ConfigEntityUpdater;
|
Chris@0
|
9 use Drupal\Core\StringTranslation\TranslatableMarkup;
|
Chris@0
|
10 use Drupal\views\Entity\View;
|
Chris@14
|
11 use Drupal\views\Plugin\views\filter\NumericFilter;
|
Chris@14
|
12 use Drupal\views\Plugin\views\filter\StringFilter;
|
Chris@0
|
13 use Drupal\views\Views;
|
Chris@0
|
14
|
Chris@0
|
15 /**
|
Chris@0
|
16 * Update the cacheability metadata for all views.
|
Chris@0
|
17 */
|
Chris@0
|
18 function views_post_update_update_cacheability_metadata() {
|
Chris@0
|
19 // Load all views.
|
Chris@0
|
20 $views = \Drupal::entityManager()->getStorage('view')->loadMultiple();
|
Chris@0
|
21
|
Chris@0
|
22 /* @var \Drupal\views\Entity\View[] $views */
|
Chris@0
|
23 foreach ($views as $view) {
|
Chris@0
|
24 $displays = $view->get('display');
|
Chris@0
|
25 foreach (array_keys($displays) as $display_id) {
|
Chris@0
|
26 $display =& $view->getDisplay($display_id);
|
Chris@0
|
27 // Unset the cache_metadata key, so all cacheability metadata for the
|
Chris@0
|
28 // display is recalculated.
|
Chris@0
|
29 unset($display['cache_metadata']);
|
Chris@0
|
30 }
|
Chris@0
|
31 $view->save();
|
Chris@0
|
32 }
|
Chris@0
|
33
|
Chris@0
|
34 }
|
Chris@0
|
35
|
Chris@0
|
36 /**
|
Chris@0
|
37 * Update some views fields that were previously duplicated.
|
Chris@0
|
38 */
|
Chris@0
|
39 function views_post_update_cleanup_duplicate_views_data() {
|
Chris@0
|
40 $config_factory = \Drupal::configFactory();
|
Chris@0
|
41 $ids = [];
|
Chris@0
|
42 $message = NULL;
|
Chris@0
|
43 $data_tables = [];
|
Chris@0
|
44 $base_tables = [];
|
Chris@0
|
45 $revision_tables = [];
|
Chris@0
|
46 $entities_by_table = [];
|
Chris@0
|
47 $duplicate_fields = [];
|
Chris@0
|
48 $handler_types = Views::getHandlerTypes();
|
Chris@0
|
49
|
Chris@0
|
50 /** @var \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager */
|
Chris@0
|
51 $entity_type_manager = \Drupal::service('entity_type.manager');
|
Chris@0
|
52 // This will allow us to create an index of all entity types of the site.
|
Chris@0
|
53 foreach ($entity_type_manager->getDefinitions() as $entity_type_id => $entity_type) {
|
Chris@0
|
54 // Store the entity keyed by base table. If it has a data table, use that as
|
Chris@0
|
55 // well.
|
Chris@0
|
56 if ($data_table = $entity_type->getDataTable()) {
|
Chris@0
|
57 $entities_by_table[$data_table] = $entity_type;
|
Chris@0
|
58 }
|
Chris@0
|
59 if ($base_table = $entity_type->getBaseTable()) {
|
Chris@0
|
60 $entities_by_table[$base_table] = $entity_type;
|
Chris@0
|
61 }
|
Chris@0
|
62
|
Chris@0
|
63 // The following code basically contains the same kind of logic as
|
Chris@0
|
64 // \Drupal\Core\Entity\Sql\SqlContentEntityStorage::initTableLayout() to
|
Chris@0
|
65 // prefetch all tables (base, data, revision, and revision data).
|
Chris@0
|
66 $base_tables[$entity_type_id] = $entity_type->getBaseTable() ?: $entity_type->id();
|
Chris@0
|
67 $revisionable = $entity_type->isRevisionable();
|
Chris@0
|
68
|
Chris@0
|
69 $revision_table = '';
|
Chris@0
|
70 if ($revisionable) {
|
Chris@0
|
71 $revision_table = $entity_type->getRevisionTable() ?: $entity_type->id() . '_revision';
|
Chris@0
|
72 }
|
Chris@0
|
73 $revision_tables[$entity_type_id] = $revision_table;
|
Chris@0
|
74
|
Chris@0
|
75 $translatable = $entity_type->isTranslatable();
|
Chris@0
|
76 $data_table = '';
|
Chris@0
|
77 // For example the data table just exists, when the entity type is
|
Chris@0
|
78 // translatable.
|
Chris@0
|
79 if ($translatable) {
|
Chris@0
|
80 $data_table = $entity_type->getDataTable() ?: $entity_type->id() . '_field_data';
|
Chris@0
|
81 }
|
Chris@0
|
82 $data_tables[$entity_type_id] = $data_table;
|
Chris@0
|
83
|
Chris@0
|
84 $duplicate_fields[$entity_type_id] = array_intersect_key($entity_type->getKeys(), array_flip(['id', 'revision', 'bundle']));
|
Chris@0
|
85 }
|
Chris@0
|
86
|
Chris@0
|
87 foreach ($config_factory->listAll('views.view.') as $view_config_name) {
|
Chris@0
|
88 $changed = FALSE;
|
Chris@0
|
89 $view = $config_factory->getEditable($view_config_name);
|
Chris@0
|
90
|
Chris@0
|
91 $displays = $view->get('display');
|
Chris@0
|
92 if (isset($entities_by_table[$view->get('base_table')])) {
|
Chris@0
|
93 $entity_type = $entities_by_table[$view->get('base_table')];
|
Chris@0
|
94 $entity_type_id = $entity_type->id();
|
Chris@0
|
95 $data_table = $data_tables[$entity_type_id];
|
Chris@0
|
96 $base_table = $base_tables[$entity_type_id];
|
Chris@0
|
97 $revision_table = $revision_tables[$entity_type_id];
|
Chris@0
|
98
|
Chris@0
|
99 if ($data_table) {
|
Chris@0
|
100 foreach ($displays as $display_name => &$display) {
|
Chris@0
|
101 foreach ($handler_types as $handler_type) {
|
Chris@0
|
102 if (!empty($display['display_options'][$handler_type['plural']])) {
|
Chris@0
|
103 foreach ($display['display_options'][$handler_type['plural']] as $field_name => &$field) {
|
Chris@0
|
104 $table = $field['table'];
|
Chris@0
|
105 if (($table === $base_table || $table === $revision_table) && in_array($field_name, $duplicate_fields[$entity_type_id])) {
|
Chris@0
|
106 $field['table'] = $data_table;
|
Chris@0
|
107 $changed = TRUE;
|
Chris@0
|
108 }
|
Chris@0
|
109 }
|
Chris@0
|
110 }
|
Chris@0
|
111 }
|
Chris@0
|
112 }
|
Chris@0
|
113 }
|
Chris@0
|
114 }
|
Chris@0
|
115
|
Chris@0
|
116 if ($changed) {
|
Chris@0
|
117 $view->set('display', $displays);
|
Chris@0
|
118 $view->save();
|
Chris@0
|
119 $ids[] = $view->get('id');
|
Chris@0
|
120 }
|
Chris@0
|
121 }
|
Chris@0
|
122 if (!empty($ids)) {
|
Chris@0
|
123 $message = new TranslatableMarkup('Updated tables for field handlers for views: @ids', ['@ids' => implode(', ', array_unique($ids))]);
|
Chris@0
|
124 }
|
Chris@0
|
125
|
Chris@0
|
126 return $message;
|
Chris@0
|
127 }
|
Chris@0
|
128
|
Chris@0
|
129 /**
|
Chris@0
|
130 * Include field formatter dependencies in a view when the formatter is used.
|
Chris@0
|
131 */
|
Chris@0
|
132 function views_post_update_field_formatter_dependencies() {
|
Chris@0
|
133 $views = View::loadMultiple();
|
Chris@0
|
134 array_walk($views, function (View $view) {
|
Chris@0
|
135 $view->save();
|
Chris@0
|
136 });
|
Chris@0
|
137 }
|
Chris@0
|
138
|
Chris@0
|
139 /**
|
Chris@0
|
140 * Fix views with dependencies on taxonomy terms that don't exist.
|
Chris@0
|
141 */
|
Chris@0
|
142 function views_post_update_taxonomy_index_tid() {
|
Chris@0
|
143 $views = View::loadMultiple();
|
Chris@0
|
144 array_walk($views, function (View $view) {
|
Chris@0
|
145 $old_dependencies = $view->getDependencies();
|
Chris@0
|
146 $new_dependencies = $view->calculateDependencies()->getDependencies();
|
Chris@0
|
147 if ($old_dependencies !== $new_dependencies) {
|
Chris@0
|
148 $view->save();
|
Chris@0
|
149 }
|
Chris@0
|
150 });
|
Chris@0
|
151 }
|
Chris@0
|
152
|
Chris@0
|
153 /**
|
Chris@0
|
154 * Fix views with serializer dependencies.
|
Chris@0
|
155 */
|
Chris@0
|
156 function views_post_update_serializer_dependencies() {
|
Chris@0
|
157 $views = View::loadMultiple();
|
Chris@0
|
158 array_walk($views, function (View $view) {
|
Chris@0
|
159 $old_dependencies = $view->getDependencies();
|
Chris@0
|
160 $new_dependencies = $view->calculateDependencies()->getDependencies();
|
Chris@0
|
161 if ($old_dependencies !== $new_dependencies) {
|
Chris@0
|
162 $view->save();
|
Chris@0
|
163 }
|
Chris@0
|
164 });
|
Chris@0
|
165 }
|
Chris@0
|
166
|
Chris@0
|
167 /**
|
Chris@0
|
168 * Set all boolean filter values to strings.
|
Chris@0
|
169 */
|
Chris@0
|
170 function views_post_update_boolean_filter_values() {
|
Chris@0
|
171 $config_factory = \Drupal::configFactory();
|
Chris@0
|
172 foreach ($config_factory->listAll('views.view.') as $view_config_name) {
|
Chris@0
|
173 $view = $config_factory->getEditable($view_config_name);
|
Chris@0
|
174 $save = FALSE;
|
Chris@0
|
175 foreach ($view->get('display') as $display_name => $display) {
|
Chris@0
|
176 if (isset($display['display_options']['filters'])) {
|
Chris@0
|
177 foreach ($display['display_options']['filters'] as $filter_name => $filter) {
|
Chris@0
|
178 if (isset($filter['plugin_id']) && $filter['plugin_id'] === 'boolean') {
|
Chris@0
|
179 $new_value = FALSE;
|
Chris@0
|
180 // Update all boolean and integer values to strings.
|
Chris@0
|
181 if ($filter['value'] === TRUE || $filter['value'] === 1) {
|
Chris@0
|
182 $new_value = '1';
|
Chris@0
|
183 }
|
Chris@0
|
184 elseif ($filter['value'] === FALSE || $filter['value'] === 0) {
|
Chris@0
|
185 $new_value = '0';
|
Chris@0
|
186 }
|
Chris@0
|
187 if ($new_value !== FALSE) {
|
Chris@0
|
188 $view->set("display.$display_name.display_options.filters.$filter_name.value", $new_value);
|
Chris@0
|
189 $save = TRUE;
|
Chris@0
|
190 }
|
Chris@0
|
191 }
|
Chris@0
|
192 }
|
Chris@0
|
193 }
|
Chris@0
|
194 }
|
Chris@0
|
195 if ($save) {
|
Chris@0
|
196 $view->save();
|
Chris@0
|
197 }
|
Chris@0
|
198 }
|
Chris@0
|
199 }
|
Chris@0
|
200
|
Chris@0
|
201 /**
|
Chris@0
|
202 * Rebuild caches to ensure schema changes are read in.
|
Chris@0
|
203 */
|
Chris@0
|
204 function views_post_update_grouped_filters() {
|
Chris@0
|
205 // Empty update to cause a cache rebuild so that the schema changes are read.
|
Chris@0
|
206 }
|
Chris@0
|
207
|
Chris@0
|
208 /**
|
Chris@0
|
209 * Fix table names for revision metadata fields.
|
Chris@16
|
210 *
|
Chris@16
|
211 * @see https://www.drupal.org/node/2831499
|
Chris@0
|
212 */
|
Chris@0
|
213 function views_post_update_revision_metadata_fields() {
|
Chris@0
|
214 // The table names are fixed automatically in
|
Chris@0
|
215 // \Drupal\views\Entity\View::preSave(), so we just need to re-save all views.
|
Chris@0
|
216 $views = View::loadMultiple();
|
Chris@0
|
217 array_walk($views, function (View $view) {
|
Chris@0
|
218 $view->save();
|
Chris@0
|
219 });
|
Chris@0
|
220 }
|
Chris@14
|
221
|
Chris@14
|
222 /**
|
Chris@14
|
223 * Add additional settings to the entity link field and convert node_path usage
|
Chris@14
|
224 * to entity_link.
|
Chris@14
|
225 */
|
Chris@14
|
226 function views_post_update_entity_link_url() {
|
Chris@14
|
227 // Load all views.
|
Chris@14
|
228 $views = \Drupal::entityTypeManager()->getStorage('view')->loadMultiple();
|
Chris@14
|
229
|
Chris@14
|
230 /* @var \Drupal\views\Entity\View[] $views */
|
Chris@14
|
231 foreach ($views as $view) {
|
Chris@14
|
232 $displays = $view->get('display');
|
Chris@14
|
233 $changed = FALSE;
|
Chris@14
|
234 foreach ($displays as $display_name => &$display) {
|
Chris@14
|
235 if (isset($display['display_options']['fields'])) {
|
Chris@14
|
236 foreach ($display['display_options']['fields'] as $field_name => &$field) {
|
Chris@14
|
237 if (isset($field['plugin_id']) && $field['plugin_id'] === 'entity_link') {
|
Chris@14
|
238 // Add any missing settings for entity_link.
|
Chris@14
|
239 if (!isset($field['output_url_as_text'])) {
|
Chris@14
|
240 $field['output_url_as_text'] = FALSE;
|
Chris@14
|
241 $changed = TRUE;
|
Chris@14
|
242 }
|
Chris@14
|
243 if (!isset($field['absolute'])) {
|
Chris@14
|
244 $field['absolute'] = FALSE;
|
Chris@14
|
245 $changed = TRUE;
|
Chris@14
|
246 }
|
Chris@14
|
247 }
|
Chris@14
|
248 elseif (isset($field['plugin_id']) && $field['plugin_id'] === 'node_path') {
|
Chris@14
|
249 // Convert the use of node_path to entity_link.
|
Chris@14
|
250 $field['plugin_id'] = 'entity_link';
|
Chris@14
|
251 $field['field'] = 'view_node';
|
Chris@14
|
252 $field['output_url_as_text'] = TRUE;
|
Chris@14
|
253 $changed = TRUE;
|
Chris@14
|
254 }
|
Chris@14
|
255 }
|
Chris@14
|
256 }
|
Chris@14
|
257 }
|
Chris@14
|
258 if ($changed) {
|
Chris@14
|
259 $view->set('display', $displays);
|
Chris@14
|
260 $view->save();
|
Chris@14
|
261 }
|
Chris@14
|
262 }
|
Chris@14
|
263 }
|
Chris@14
|
264
|
Chris@14
|
265 /**
|
Chris@14
|
266 * Update dependencies for moved bulk field plugin.
|
Chris@14
|
267 */
|
Chris@14
|
268 function views_post_update_bulk_field_moved() {
|
Chris@14
|
269 $views = View::loadMultiple();
|
Chris@14
|
270 array_walk($views, function (View $view) {
|
Chris@14
|
271 $old_dependencies = $view->getDependencies();
|
Chris@14
|
272 $new_dependencies = $view->calculateDependencies()->getDependencies();
|
Chris@14
|
273 if ($old_dependencies !== $new_dependencies) {
|
Chris@14
|
274 $view->save();
|
Chris@14
|
275 }
|
Chris@14
|
276 });
|
Chris@14
|
277 }
|
Chris@14
|
278
|
Chris@14
|
279 /**
|
Chris@14
|
280 * Add placeholder settings to string or numeric filters.
|
Chris@14
|
281 */
|
Chris@14
|
282 function views_post_update_filter_placeholder_text() {
|
Chris@14
|
283 // Load all views.
|
Chris@14
|
284 $views = \Drupal::entityTypeManager()->getStorage('view')->loadMultiple();
|
Chris@14
|
285 /** @var \Drupal\views\Plugin\ViewsHandlerManager $filter_manager */
|
Chris@14
|
286 $filter_manager = \Drupal::service('plugin.manager.views.filter');
|
Chris@14
|
287
|
Chris@14
|
288 /* @var \Drupal\views\Entity\View[] $views */
|
Chris@14
|
289 foreach ($views as $view) {
|
Chris@14
|
290 $displays = $view->get('display');
|
Chris@14
|
291 $save = FALSE;
|
Chris@14
|
292 foreach ($displays as $display_name => &$display) {
|
Chris@14
|
293 if (isset($display['display_options']['filters'])) {
|
Chris@14
|
294 foreach ($display['display_options']['filters'] as $filter_name => &$filter) {
|
Chris@14
|
295 // Any of the children of the modified classes will also be inheriting
|
Chris@14
|
296 // the new settings.
|
Chris@14
|
297 $filter_instance = $filter_manager->getHandler($filter);
|
Chris@14
|
298 if ($filter_instance instanceof StringFilter) {
|
Chris@14
|
299 if (!isset($filter['expose']['placeholder'])) {
|
Chris@14
|
300 $filter['expose']['placeholder'] = '';
|
Chris@14
|
301 $save = TRUE;
|
Chris@14
|
302 }
|
Chris@14
|
303 }
|
Chris@14
|
304 elseif ($filter_instance instanceof NumericFilter) {
|
Chris@14
|
305 if (!isset($filter['expose']['placeholder'])) {
|
Chris@14
|
306 $filter['expose']['placeholder'] = '';
|
Chris@14
|
307 $save = TRUE;
|
Chris@14
|
308 }
|
Chris@14
|
309 if (!isset($filter['expose']['min_placeholder'])) {
|
Chris@14
|
310 $filter['expose']['min_placeholder'] = '';
|
Chris@14
|
311 $save = TRUE;
|
Chris@14
|
312 }
|
Chris@14
|
313 if (!isset($filter['expose']['max_placeholder'])) {
|
Chris@14
|
314 $filter['expose']['max_placeholder'] = '';
|
Chris@14
|
315 $save = TRUE;
|
Chris@14
|
316 }
|
Chris@14
|
317 }
|
Chris@14
|
318 }
|
Chris@14
|
319 }
|
Chris@14
|
320 }
|
Chris@14
|
321 if ($save) {
|
Chris@14
|
322 $view->set('display', $displays);
|
Chris@14
|
323 $view->save();
|
Chris@14
|
324 }
|
Chris@14
|
325 }
|
Chris@14
|
326 }
|
Chris@14
|
327
|
Chris@14
|
328 /**
|
Chris@14
|
329 * Include views data table provider in views dependencies.
|
Chris@14
|
330 */
|
Chris@14
|
331 function views_post_update_views_data_table_dependencies(&$sandbox = NULL) {
|
Chris@14
|
332 $storage = \Drupal::entityTypeManager()->getStorage('view');
|
Chris@14
|
333 if (!isset($sandbox['views'])) {
|
Chris@14
|
334 $sandbox['views'] = $storage->getQuery()->accessCheck(FALSE)->execute();
|
Chris@14
|
335 $sandbox['count'] = count($sandbox['views']);
|
Chris@14
|
336 }
|
Chris@14
|
337
|
Chris@14
|
338 // Process 10 views at a time.
|
Chris@14
|
339 $views = $storage->loadMultiple(array_splice($sandbox['views'], 0, 10));
|
Chris@14
|
340 foreach ($views as $view) {
|
Chris@14
|
341 $original_dependencies = $view->getDependencies();
|
Chris@14
|
342 // Only re-save if dependencies have changed.
|
Chris@14
|
343 if ($view->calculateDependencies()->getDependencies() !== $original_dependencies) {
|
Chris@14
|
344 // We can trust the data because we've already recalculated the
|
Chris@14
|
345 // dependencies.
|
Chris@14
|
346 $view->trustData();
|
Chris@14
|
347 $view->save();
|
Chris@14
|
348 }
|
Chris@14
|
349 }
|
Chris@14
|
350
|
Chris@14
|
351 $sandbox['#finished'] = empty($sandbox['views']) ? 1 : ($sandbox['count'] - count($sandbox['views'])) / $sandbox['count'];
|
Chris@14
|
352 }
|
Chris@14
|
353
|
Chris@14
|
354 /**
|
Chris@14
|
355 * Fix cache max age for table displays.
|
Chris@14
|
356 */
|
Chris@14
|
357 function views_post_update_table_display_cache_max_age(&$sandbox = NULL) {
|
Chris@17
|
358 \Drupal::classResolver(ConfigEntityUpdater::class)->update($sandbox, 'view', function ($view) {
|
Chris@17
|
359 /** @var \Drupal\views\ViewEntityInterface $view */
|
Chris@17
|
360 $displays = $view->get('display');
|
Chris@17
|
361 foreach ($displays as $display_name => &$display) {
|
Chris@17
|
362 if (isset($display['display_options']['style']['type']) && $display['display_options']['style']['type'] === 'table') {
|
Chris@17
|
363 return TRUE;
|
Chris@14
|
364 }
|
Chris@14
|
365 }
|
Chris@17
|
366 return FALSE;
|
Chris@17
|
367 });
|
Chris@14
|
368 }
|
Chris@18
|
369
|
Chris@18
|
370 /**
|
Chris@18
|
371 * Update exposed filter blocks label display to be disabled.
|
Chris@18
|
372 */
|
Chris@18
|
373 function views_post_update_exposed_filter_blocks_label_display(&$sandbox = NULL) {
|
Chris@18
|
374 \Drupal::classResolver(ConfigEntityUpdater::class)->update($sandbox, 'block', function ($block) {
|
Chris@18
|
375 /** @var \Drupal\block\BlockInterface $block */
|
Chris@18
|
376 if (strpos($block->getPluginId(), 'views_exposed_filter_block:') === 0) {
|
Chris@18
|
377 $block->getPlugin()->setConfigurationValue('label_display', '0');
|
Chris@18
|
378 return TRUE;
|
Chris@18
|
379 }
|
Chris@18
|
380
|
Chris@18
|
381 return FALSE;
|
Chris@18
|
382 });
|
Chris@18
|
383 }
|
Chris@18
|
384
|
Chris@18
|
385 /**
|
Chris@18
|
386 * Rebuild cache to allow placeholder texts to be translatable.
|
Chris@18
|
387 */
|
Chris@18
|
388 function views_post_update_make_placeholders_translatable() {
|
Chris@18
|
389 // Empty update to cause a cache rebuild to allow placeholder texts to be
|
Chris@18
|
390 // translatable.
|
Chris@18
|
391 }
|