diff --git a/metatag.install b/metatag.install index 10f11c5..f60f8da 100644 --- a/metatag.install +++ b/metatag.install @@ -1280,3 +1280,226 @@ function metatag_update_7021() { function metatag_update_7022() { variable_del('metatag_skip_update_7015'); } + +/** + * Upgrade data from Metatags Quick. + */ +function metatag_update_7023(&$sandbox) { + // Use the sandbox at your convenience to store the information needed + // to track progression between successive calls to the function. + if (!isset($sandbox['progress'])) { + // The count of records visited so far. + $sandbox['progress'] = 0; + + // Get a list of all entities that use a Metatags Quick field. + $fields = array(); + foreach (field_info_instances() as $entity_type => $bundles) { + // Skip the custon entity type provided by Metatags Quick. + if ($entity_type == 'metatags_path_based') { + continue; + } + foreach ($bundles as $bundle_name => $bundle) { + foreach ($bundle as $field_name => $field) { + if ($field['widget']['module'] == 'metatags_quick') { + $fields[$field_name] = $field_name; + } + } + } + } + + // Metatags Quick is not being used for any fields! *phew* + if (empty($fields)) { + watchdog('metatag', 'Update 7023: Metatags Quick is not being used for any fields.', array(), WATCHDOG_INFO); + if (drupal_is_cli()) { + drupal_set_message(t('Update 7023: Metatags Quick is not being used for any fields.')); + } + return t('Metatags Quick is not being used for any fields.'); + } + + // Get a list of the records. + $sandbox['records'] = array(); + $sandbox['ids'] = array(); + foreach ($fields as $field_name) { + $meta_tag = str_replace('meta_', '', str_replace('field_', '', $field_name)); + if (in_array($meta_tag, array('description', 'keywords', 'title'))) { + $results = db_select('field_data_' . $field_name, 'f') + ->fields('f', array('entity_type', 'bundle', 'entity_id', 'revision_id', 'language', $field_name . '_metatags_quick')) + ->condition('f.entity_type', array('metatags_path_based'), '<>') + ->orderBy('f.entity_type', 'ASC') + ->orderBy('f.entity_id', 'ASC') + ->orderBy('f.revision_id', 'ASC') + ->execute(); + foreach ($results as $result) { + $id = implode(':', array($result->entity_type, $result->entity_id, $result->revision_id, $result->language)); + if (!isset($sandbox['records'][$id])) { + $sandbox['records'][$id] = array( + 'entity_type' => $result->entity_type, + 'bundle' => $result->bundle, + 'entity_id' => $result->entity_id, + 'revision_id' => $result->revision_id, + 'language' => $result->language, + 'fields' => array(), + ); + $sandbox['ids'][] = $id; + } + $sandbox['records'][$id]['fields'][$field_name] = array( + 'field_name' => $field_name, + 'value' => $result->{$field_name . '_metatags_quick'}, + 'meta_tag' => $meta_tag, + ); + } + } + } + + // If there's no data, don't bother with the extra work. + if (empty($sandbox['records'])) { + watchdog('metatag', 'Update 7023: No Metatags Quick records need migrating.', array(), WATCHDOG_INFO); + if (drupal_is_cli()) { + drupal_set_message(t('Update 7023: No Metatags Quick records need migrating.')); + } + return t('No Metatags Quick records need migrating.'); + } + + // Total records that must be visited. + $sandbox['max'] = count($sandbox['records']); + + // A place to store messages during the run. + $sandbox['messages'] = array(); + + // An initial record of the number of records to be updated. + watchdog('metatag', 'Update 7023: !count records to migrate.', array('!count' => $sandbox['max']), WATCHDOG_INFO); + if (drupal_is_cli()) { + drupal_set_message(t('Update 7023: !count records to migrate.', array('!count' => $sandbox['max']))); + } + + // Last record processed. + $sandbox['current_record'] = -1; + } + + // Process records by groups of 10 (arbitrary value). + // When a group is processed, the batch update engine determines whether it + // should continue processing in the same request or provide progress + // feedback to the user and wait for the next request. + $limit = 10; + // When ran through Drush it's Ok to process a larger number of objects at a + // time. + if (drupal_is_cli()) { + $limit = 100; + } + // On the first loop, just migrate one record. + elseif ($sandbox['current_record'] == -1) { + $limit = 1; + } + + // Map source meta tags to destinations. + $tag_map = array( + 'title' => 'title', + 'keywords' => 'keywords', + 'description' => 'description', + 'og:title' => 'title', + 'og:description' => 'description', + 'twitter:title' => 'title', + 'twitter:description' => 'description', + ); + + // Set default values. + $ctr = 0; + for (; $ctr < $limit; $ctr++) { + $sandbox['current_record']++; + + // A shortcut. + $quick = $sandbox['records'][$sandbox['ids'][$sandbox['current_record']]]; + + // Check for an existing record. + $data = db_select('metatag', 'm') + ->fields('m', array('data')) + ->condition('m.entity_type', $quick['entity_type']) + ->condition('m.entity_id', $quick['entity_id']) + ->condition('m.revision_id', $quick['revision_id']) + ->condition('m.language', $quick['language']) + ->execute() + ->fetchField(); + $record_exists = !empty($data); + + // Assign the meta tag value. + if (!is_array($data)) { + $data = array(); + } + + // Map the Quick meta tags. + foreach ($tag_map as $dest => $source) { + if (!empty($quick['fields'][$source])) { + $data[$dest] = array('value' => $field['value']); + // Add the default suffix to the page title. + if ($dest == 'title') { + $data[$dest] .= ' | [site:name]'; + } + } + } + + // Create or update the {metatag} record. + if ($record_exists) { + db_update('metatag') + ->fields(array('data' => serialize($data))) + ->condition('entity_type', $quick['entity_type']) + ->condition('entity_id', $quick['entity_id']) + ->condition('revision_id', $quick['revision_id']) + ->condition('language', $quick['language']) + ->execute(); + } + else { + db_insert('metatag') + ->fields(array( + 'entity_type' => $quick['entity_type'], + 'entity_id' => $quick['entity_id'], + 'revision_id' => $quick['revision_id'], + 'language' => $quick['language'], + 'data' => serialize($data), + )) + ->execute(); + } + + // Delete the old metatags_quick records. + foreach ($quick['fields'] as $field) { + db_delete('field_data_' . $field['field_name']) + ->condition('entity_type', $quick['entity_type']) + ->condition('entity_id', $quick['entity_id']) + ->condition('revision_id', $quick['revision_id']) + ->condition('language', $quick['language']) + ->execute(); + db_delete('field_revision_' . $field['field_name']) + ->condition('entity_type', $quick['entity_type']) + ->condition('entity_id', $quick['entity_id']) + ->condition('revision_id', $quick['revision_id']) + ->condition('language', $quick['language']) + ->execute(); + } + + // Reset the entity cache. If entity cache module is used, this also resets + // its permanent cache. + entity_get_controller($quick['entity_type'])->resetCache(array($quick['entity_id'])); + + // Update our progress information. + $sandbox['progress']++; + } + + // Set the "finished" status, to tell batch engine whether this function + // needs to run again. If you set a float, this will indicate the progress of + // the batch so the progress bar will update. + $sandbox['#finished'] = ($sandbox['progress'] >= $sandbox['max']) ? TRUE : ($sandbox['progress'] / $sandbox['max']); + + if ($sandbox['#finished'] === TRUE) { + // Clear all caches so the fixed data will be reloaded. + cache_clear_all('*', 'cache_metatag', TRUE); + + // A final log of the number of records that were converted. + watchdog('metatag', 'Update 7023: !count records were updated in total.', array('!count' => $sandbox['progress']), WATCHDOG_INFO); + if (drupal_is_cli()) { + drupal_set_message(t('Update 7023: All done! !count records were updated.', array('!count' => $sandbox['progress']))); + } + + // hook_update_N() may optionally return a string which will be displayed + // to the user. + return t('!count records were updated in total.', array('!count' => $sandbox['progress'])); + } +}