5 * Install, update and uninstall functions for the metatag module.
9 * Implements hook_install().
11 function metatag_install() {
12 // Don't display the message during site installation, it looks funny.
13 if (!drupal_installation_attempted()) {
14 drupal_set_message(t("To adjust global defaults, go to admin/config/search/metatag. If you need to set meta tags for a specific entity, edit its bundle and add the Metatag field."));
19 * Implements hook_requirements().
21 function metatag_requirements($phase) {
24 if ($phase == 'runtime') {
25 // Recommend the Schema.org Metatag module.
26 if (!\Drupal::moduleHandler()->moduleExists('schema_metatag')) {
27 $requirements['metatag_schema'] = [
28 'severity' => REQUIREMENT_INFO,
30 'value' => t('Schema.org Metatag is recommended'),
31 'description' => t('The <a href="@module">Schema.org Metatag</a> module is highly recommended to add <a href="@jsonld">JSON-LD</a> -formatted <a href="@schema">schema.org</a> compatible data structures to the site.', [
32 '@module' => 'https://www.drupal.org/project/schema_metatag',
33 '@jsonld' => 'https://json-ld.org',
34 '@schema' => 'http://schema.org',
39 $requirements['metatag_schema'] = [
40 'severity' => REQUIREMENT_OK,
42 'value' => t('Schema.org Metatag is installed'),
43 'description' => t('The <a href="@module">Schema.org Metatag</a> module is installed.', [
44 '@module' => 'https://www.drupal.org/project/schema_metatag',
54 * Remove tags in field storage that match default or are empty.
56 function metatag_update_8101() {
57 // Get all of the field storage entities of type metatag.
58 $field_storage_configs = \Drupal::entityTypeManager()
59 ->getStorage('field_storage_config')
60 ->loadByProperties(['type' => 'metatag']);
62 foreach ($field_storage_configs as $key => $field_storage) {
63 $field_name = $field_storage->getName();
65 // Get the individual fields (field instances) associated with bundles.
66 $fields = \Drupal::entityTypeManager()
67 ->getStorage('field_config')
68 ->loadByProperties(['field_name' => $field_name]);
70 // For each of the fields, delete all records that match the defaults.
71 foreach ($fields as $field) {
72 // Get the bundle this field is attached to.
73 $bundle = $field->getTargetBundle();
75 // Get the default value for this field on this bundle.
76 $field_default_tags_value = $field->getDefaultValueLiteral();
77 $field_default_tags_value = $field_default_tags_value[0]['value'];
78 $field_default_tags = unserialize($field_default_tags_value);
80 // Determine the table and "value" field names.
81 $field_table = "node__" . $field_name;
82 $field_value_field = $field_name . "_value";
84 // Delete all records where the field value and default are identical.
85 \Drupal::database()->delete($field_table)
86 ->condition('bundle', $bundle, '=')
87 ->condition($field_value_field, $field_default_tags_value, '=')
92 return t('Removed all default meta tag records so they can be automatically inherited when the page is loaded.');
96 * Remove tags in field storage that match default or are empty.
98 function metatag_update_8102(&$sandbox) {
99 // This whole top section only needs to be done the first time.
100 if (!isset($sandbox['records_processed'])) {
101 $sandbox['records_processed'] = 0;
102 $sandbox['total_records'] = 0;
103 $sandbox['current_field'] = 0;
104 $sandbox['current_record'] = 0;
106 // Counter to enumerate the fields so we can access them in the array
107 // by number rather than name.
110 // Get all of the field storage entities of type metatag.
111 $field_storage_configs = \Drupal::entityTypeManager()
112 ->getStorage('field_storage_config')
113 ->loadByProperties(['type' => 'metatag']);
115 foreach ($field_storage_configs as $key => $field_storage) {
116 $field_name = $field_storage->getName();
118 // Get the individual fields (field instances) associated with bundles.
119 $fields = \Drupal::entityTypeManager()
120 ->getStorage('field_config')
121 ->loadByProperties(['field_name' => $field_name]);
123 // For each of the fields, do the mass delete of exact matches but
124 // store the overridden records in the sandbox to be batch processed.
125 foreach ($fields as $field) {
126 // Get the bundle this field is attached to.
127 $bundle = $field->getTargetBundle();
129 // Get the default value for this field on this bundle.
130 $field_default_tags_value = $field->getDefaultValueLiteral();
131 $field_default_tags_value = $field_default_tags_value[0]['value'];
132 $field_default_tags = unserialize($field_default_tags_value);
134 // Determine the table and "value" field names.
135 $field_table = "node__" . $field_name;
136 $field_value_field = $field_name . "_value";
138 // Get all records where the field data does not match the default.
139 $query = \Drupal::database()->select($field_table);
140 $query->addField($field_table, 'entity_id');
141 $query->addField($field_table, 'revision_id');
142 $query->addField($field_table, 'langcode');
143 $query->addField($field_table, $field_value_field);
144 $query->condition('bundle', $bundle, '=');
145 $result = $query->execute();
146 $records = $result->fetchAll();
148 // Fill in all the sandbox information so we can batch the individual
149 // record comparing and updating.
150 $sandbox['fields'][$field_counter]['field_table'] = $field_table;
151 $sandbox['fields'][$field_counter]['field_value_field'] = $field_value_field;
152 $sandbox['fields'][$field_counter]['field_default_tags'] = $field_default_tags;
153 $sandbox['fields'][$field_counter]['records'] = $records;
155 $sandbox['total_records'] += count($sandbox['fields'][$field_counter]['records'] = $records);
161 if ($sandbox['total_records'] == 0) {
162 // No partially overridden fields so we can skip the whole batch process.
163 $sandbox['#finished'] = 1;
166 // Begin the batch processing of individual field records.
170 $current_field = $sandbox['current_field'];
171 $current_field_records = $sandbox['fields'][$current_field]['records'];
172 $current_record = $sandbox['current_record'];
174 $field_table = $sandbox['fields'][$current_field]['field_table'];
175 $field_value_field = $sandbox['fields'][$current_field]['field_value_field'];
176 $field_default_tags = $sandbox['fields'][$current_field]['field_default_tags'];
178 // Loop through the field(s) and remove any field data that matches the
179 // field default for that bundle. Because the ability to override a default
180 // with "nothing" didn't exist prior to this and because any tag that had
181 // a default of "nothing" would have that also in the field data, we are
182 // removing those as well.
183 while ($counter <= $max_per_batch && $record = $current_field_records[$current_record]) {
184 // Strip any empty tags or ones matching the field's defaults and leave
185 // only the overridden tags in $new_tags.
186 $current_tags = unserialize($record->$field_value_field);
188 foreach ($current_tags as $key => $tag) {
189 if (!empty($tag) && $field_default_tags[$key] != $tag) {
190 $new_tags[$key] = $tag;
194 if (empty($new_tags)) {
195 // All tags were either empty or matched the default so the record can
197 \Drupal::database()->delete($field_table)
198 ->condition('entity_id', $record->entity_id)
199 ->condition('revision_id', $record->revision_id)
200 ->condition('langcode', $record->langcode)
204 // There are some overridden tags so update the record with just those.
205 $tags_string = serialize($new_tags);
206 \Drupal::database()->update($field_table)
208 $field_value_field => $tags_string,
210 ->condition('entity_id', $record->entity_id)
211 ->condition('revision_id', $record->revision_id)
212 ->condition('langcode', $record->langcode)
220 // We ran out of records for the field so start the next batch out with the
222 if (!isset($current_field_records[$current_record])) {
227 // We have finished all the fields. All done.
228 if (!isset($sandbox['fields'][$current_field])) {
229 $sandbox['records_processed'] += $counter - 1;
230 $sandbox['#finished'] = 1;
232 // Update the sandbox values to prepare for the next round.
234 $sandbox['current_field'] = $current_field;
235 $sandbox['current_record'] = $current_record;
236 $sandbox['records_processed'] += $counter - 1;
237 $sandbox['#finished'] = $sandbox['records_processed'] / $sandbox['total_records'];
241 if ($sandbox['total_records'] > 0) {
242 return (string) t('Processed @processed of @total overridden Metatag records.', [
243 '@processed' => $sandbox['records_processed'],
244 '@total' => $sandbox['total_records'],
248 return (string) t("There were no overridden Metatag records.");
253 * Move field defaults to Metatag Defaults.
255 function metatag_update_8103() {
256 $config_installer = \Drupal::service('config.installer');
257 $entity_manager = \Drupal::entityTypeManager();
259 // 1. Install cofiguration.
260 $sync_status = $config_installer->isSyncing();
262 $source_storage = $config_installer->getSourceStorage();
265 // Clear plugin manager caches.
266 \Drupal::getContainer()->get('plugin.cache_clearer')->clearCachedDefinitions();
267 // Install default configuration of the module.
271 ->setSourceStorage($source_storage);
274 // Install new configuration for Metatag.
275 $config_installer->installDefaultConfig('module', 'metatag');
277 // Apply all entity definition changes.
278 \Drupal::entityDefinitionUpdateManager()->applyUpdates();
280 // 2. Extract Metatag field defaults.
281 $entity_info = $entity_manager->getDefinitions();
284 // Get all of the field storage entities of type metatag.
285 $field_storage_configs = $entity_manager
286 ->getStorage('field_storage_config')
287 ->loadByProperties(['type' => 'metatag']);
289 foreach ($field_storage_configs as $key => $field_storage) {
290 $field_name = $field_storage->getName();
292 // Get the individual fields (field instances) associated with bundles.
293 $fields = $entity_manager->getStorage('field_config')
294 ->loadByProperties(['field_name' => $field_name]);
295 foreach ($fields as $field) {
296 // Adjust the config id depending on whether these are entity defaults
297 // or bundle defaults.
298 $entity_type = $field->getTargetEntityTypeId();
299 $bundle = $field->getTargetBundle();
300 $metatag_defaults_id = $entity_type;
301 if ($entity_type != $bundle) {
302 // This is a bundle override.
303 $metatag_defaults_id = $entity_type . '__' . $bundle;
305 // Extract field default values.
306 $field_default_tags_value = $field->getDefaultValueLiteral();
307 $field_default_tags_value = unserialize($field_default_tags_value[0]['value']);
308 $field_default_tags_value = array_filter($field_default_tags_value);
309 // Don't bother copying empty values.
310 if (!empty($field_default_tags_value)) {
311 $tags[$metatag_defaults_id] = $field_default_tags_value;
316 // 3. Create Config entities with field default values.
318 $bundleInfoManager = \Drupal::service('entity_type.bundle.info');
319 foreach ($tags as $metatag_defaults_id => $values) {
320 list($entity_type, $entity_bundle) = explode('__', $metatag_defaults_id);
321 $entity_label = (string) $entity_info[$entity_type]->get('label');
322 $bundle_info = $bundleInfoManager->getBundleInfo($entity_type);
323 $bundle_label = $bundle_info[$entity_bundle]['label'];
324 $label = $entity_label . ': ' . $bundle_label;
326 $metatags_global_manager = $entity_manager->getStorage('metatag_defaults');
328 $entity = $metatags_global_manager->load($metatag_defaults_id);
330 // These are defaults for an existing config entity, such as User.
331 $entity->set('tags', $values);
334 // These are bundle overrides.
335 $entity = $metatags_global_manager->create([
336 'id' => $metatag_defaults_id,
343 return (string) t("@count Metatag field defaults have been converted to using global entity defaults.", ['@count' => count($tags)]);
346 return (string) t("There were Metatag field configurations that needed to be converted.");
351 * Rebuild routes after moving Metatag admin from Structure to Config.
353 function metatag_update_8104() {
354 \Drupal::service('router.builder')->setRebuildNeeded();
358 * Rebuild routes after renaming.
360 function metatag_update_8105() {
361 \Drupal::service('router.builder')->setRebuildNeeded();
365 * Add the metatag_defaults config entity to the site.
367 function metatag_update_8106() {
368 \Drupal::entityDefinitionUpdateManager()->applyUpdates();
372 * Enable the new metatag_open_graph module.
374 function metatag_update_8107() {
375 \Drupal::service('module_installer')->install(['metatag_open_graph']);
376 return (string) t("The new Metatag: Open Graph module has been enabled.");