comparison core/modules/layout_builder/layout_builder.post_update.php @ 5:12f9dff5fda9 tip

Update to Drupal core 8.7.1
author Chris Cannam
date Thu, 09 May 2019 15:34:47 +0100
parents a9cd425dd02b
children
comparison
equal deleted inserted replaced
4:a9cd425dd02b 5:12f9dff5fda9
5 * Post update functions for Layout Builder. 5 * Post update functions for Layout Builder.
6 */ 6 */
7 7
8 use Drupal\Core\Config\Entity\ConfigEntityUpdater; 8 use Drupal\Core\Config\Entity\ConfigEntityUpdater;
9 use Drupal\layout_builder\Entity\LayoutEntityDisplayInterface; 9 use Drupal\layout_builder\Entity\LayoutEntityDisplayInterface;
10 use Drupal\layout_builder\TempStoreIdentifierInterface;
11 use Drupal\user\Entity\Role;
12 use Drupal\field\Entity\FieldStorageConfig;
13 use Drupal\field\Entity\FieldConfig;
14 use Drupal\layout_builder\Plugin\SectionStorage\OverridesSectionStorage;
10 15
11 /** 16 /**
12 * Rebuild plugin dependencies for all entity view displays. 17 * Rebuild plugin dependencies for all entity view displays.
13 */ 18 */
14 function layout_builder_post_update_rebuild_plugin_dependencies(&$sandbox = NULL) { 19 function layout_builder_post_update_rebuild_plugin_dependencies(&$sandbox = NULL) {
56 } 61 }
57 } 62 }
58 return $result; 63 return $result;
59 }); 64 });
60 } 65 }
66
67 /**
68 * Clear caches due to changes to section storage annotation changes.
69 */
70 function layout_builder_post_update_section_storage_context_definitions() {
71 // Empty post-update hook.
72 }
73
74 /**
75 * Clear caches due to changes to annotation changes to the Overrides plugin.
76 */
77 function layout_builder_post_update_overrides_view_mode_annotation() {
78 // Empty post-update hook.
79 }
80
81 /**
82 * Clear caches due to routing changes for the new discard changes form.
83 */
84 function layout_builder_post_update_cancel_link_to_discard_changes_form() {
85 // Empty post-update hook.
86 }
87
88 /**
89 * Clear caches due to the removal of the layout_is_rebuilding query string.
90 */
91 function layout_builder_post_update_remove_layout_is_rebuilding() {
92 // Empty post-update hook.
93 }
94
95 /**
96 * Clear caches due to routing changes to move the Layout Builder UI to forms.
97 */
98 function layout_builder_post_update_routing_entity_form() {
99 // Empty post-update hook.
100 }
101
102 /**
103 * Clear caches to discover new blank layout plugin.
104 */
105 function layout_builder_post_update_discover_blank_layout_plugin() {
106 // Empty post-update hook.
107 }
108
109 /**
110 * Clear caches due to routing changes to changing the URLs for defaults.
111 */
112 function layout_builder_post_update_routing_defaults() {
113 // Empty post-update hook.
114 }
115
116 /**
117 * Clear caches due to new link added to Layout Builder's contextual links.
118 */
119 function layout_builder_post_update_discover_new_contextual_links() {
120 // Empty post-update hook.
121 }
122
123 /**
124 * Fix Layout Builder tempstore keys of existing entries.
125 */
126 function layout_builder_post_update_fix_tempstore_keys() {
127 /** @var \Drupal\layout_builder\SectionStorage\SectionStorageManagerInterface $section_storage_manager */
128 $section_storage_manager = \Drupal::service('plugin.manager.layout_builder.section_storage');
129 /** @var \Drupal\Core\KeyValueStore\KeyValueExpirableFactoryInterface $key_value_factory */
130 $key_value_factory = \Drupal::service('keyvalue.expirable');
131
132 // Loop through each section storage type.
133 foreach (array_keys($section_storage_manager->getDefinitions()) as $section_storage_type) {
134 $key_value = $key_value_factory->get("tempstore.shared.layout_builder.section_storage.$section_storage_type");
135 foreach ($key_value->getAll() as $key => $value) {
136 $contexts = $section_storage_manager->loadEmpty($section_storage_type)->deriveContextsFromRoute($key, [], '', []);
137 if ($section_storage = $section_storage_manager->load($section_storage_type, $contexts)) {
138
139 // Some overrides were stored with an incorrect view mode value. Update
140 // the view mode on the temporary section storage, if necessary.
141 if ($section_storage_type === 'overrides') {
142 $view_mode = $value->data['section_storage']->getContextValue('view_mode');
143 $new_view_mode = $section_storage->getContextValue('view_mode');
144 if ($view_mode !== $new_view_mode) {
145 $value->data['section_storage']->setContextValue('view_mode', $new_view_mode);
146 $key_value->set($key, $value);
147 }
148 }
149
150 // The previous tempstore key names were exact matches with the section
151 // storage ID. Attempt to load the corresponding section storage and
152 // rename the tempstore entry if the section storage provides a more
153 // granular tempstore key.
154 if ($section_storage instanceof TempStoreIdentifierInterface) {
155 $new_key = $section_storage->getTempstoreKey();
156 if ($key !== $new_key) {
157 if ($key_value->has($new_key)) {
158 $key_value->delete($new_key);
159 }
160 $key_value->rename($key, $new_key);
161 }
162 }
163 }
164 }
165 }
166 }
167
168 /**
169 * Clear caches due to config schema additions.
170 */
171 function layout_builder_post_update_section_third_party_settings_schema() {
172 // Empty post-update hook.
173 }
174
175 /**
176 * Clear caches due to dependency changes in the layout_builder render element.
177 */
178 function layout_builder_post_update_layout_builder_dependency_change() {
179 // Empty post-update hook.
180 }
181
182 /**
183 * Add new custom block permission to all roles with 'configure any layout'.
184 */
185 function layout_builder_post_update_update_permissions() {
186 foreach (Role::loadMultiple() as $role) {
187 if ($role->hasPermission('configure any layout')) {
188 $role->grantPermission('create and edit custom blocks')->save();
189 }
190 }
191 }
192
193 /**
194 * Set the layout builder field as non-translatable where possible.
195 */
196 function layout_builder_post_update_make_layout_untranslatable() {
197 /** @var \Drupal\Core\Entity\EntityFieldManagerInterface $field_manager */
198 $field_manager = \Drupal::service('entity_field.manager');
199 $field_map = $field_manager->getFieldMap();
200 foreach ($field_map as $entity_type_id => $field_infos) {
201 if (isset($field_infos[OverridesSectionStorage::FIELD_NAME]['bundles'])) {
202 $non_translatable_bundle_count = 0;
203 foreach ($field_infos[OverridesSectionStorage::FIELD_NAME]['bundles'] as $bundle) {
204 $field_config = FieldConfig::loadByName($entity_type_id, $bundle, OverridesSectionStorage::FIELD_NAME);
205 if (!$field_config->isTranslatable()) {
206 $non_translatable_bundle_count++;
207 // The layout field is already configured to be non-translatable so it
208 // does not need to be updated.
209 continue;
210 }
211 if (_layout_builder_bundle_has_no_translations($entity_type_id, $bundle) || _layout_builder_bundle_has_no_layouts($entity_type_id, $bundle)) {
212 // Either none of the entities have layouts or none of them have
213 // translations. In either case it is safe to set the field to be
214 // non-translatable.
215 $field_config->setTranslatable(FALSE);
216 $field_config->save();
217 $non_translatable_bundle_count++;
218 }
219 }
220 // Set the field storage to untranslatable if the field config for each
221 // bundle is now untranslatable. This removes layout fields for the
222 // entity type from the Content Translation configuration form.
223 if (count($field_infos[OverridesSectionStorage::FIELD_NAME]['bundles']) === $non_translatable_bundle_count) {
224 $field_storage = FieldStorageConfig::loadByName($entity_type_id, OverridesSectionStorage::FIELD_NAME);
225 $field_storage->setTranslatable(FALSE);
226 $field_storage->save();
227 }
228 }
229 }
230 }
231
232 /**
233 * Determines if there are zero layout overrides for the bundle.
234 *
235 * @param string $entity_type_id
236 * The entity type ID.
237 * @param string $bundle
238 * The bundle name.
239 *
240 * @return bool
241 * TRUE if there are zero layout overrides for the bundle, otherwise FALSE.
242 */
243 function _layout_builder_bundle_has_no_layouts($entity_type_id, $bundle) {
244 $entity_type_manager = \Drupal::entityTypeManager();
245 $entity_type = $entity_type_manager->getDefinition($entity_type_id);
246 $bundle_key = $entity_type->getKey('bundle');
247 $query = $entity_type_manager->getStorage($entity_type_id)->getQuery();
248 if ($bundle_key) {
249 $query->condition($bundle_key, $bundle);
250 }
251 if ($entity_type->isRevisionable()) {
252 $query->allRevisions();
253 }
254 $query->exists(OverridesSectionStorage::FIELD_NAME)
255 ->accessCheck(FALSE)
256 ->range(0, 1);
257 $results = $query->execute();
258 return empty($results);
259 }
260
261 /**
262 * Determines if there are zero translations for the bundle.
263 *
264 * @param string $entity_type_id
265 * The entity type ID.
266 * @param string $bundle
267 * The bundle name.
268 *
269 * @return bool
270 * TRUE if there are zero translations for the bundle, otherwise FALSE.
271 */
272 function _layout_builder_bundle_has_no_translations($entity_type_id, $bundle) {
273 $entity_type_manager = \Drupal::entityTypeManager();
274 $entity_type = $entity_type_manager->getDefinition($entity_type_id);
275 if (!$entity_type->isTranslatable()) {
276 return TRUE;
277 }
278 $query = $entity_type_manager->getStorage($entity_type_id)->getQuery();
279 $bundle_key = $entity_type->getKey('bundle');
280 if ($entity_type->hasKey('default_langcode')) {
281 if ($bundle_key) {
282 $query->condition($bundle_key, $bundle);
283 }
284 if ($entity_type->isRevisionable()) {
285 $query->allRevisions();
286 }
287 $query->condition($entity_type->getKey('default_langcode'), 0)
288 ->accessCheck(FALSE)
289 ->range(0, 1);
290 $results = $query->execute();
291 return empty($results);
292 }
293 // A translatable entity type should always have a default_langcode key. If it
294 // doesn't we have no way to determine if there are translations.
295 return FALSE;
296 }