function phone_update_7200 in Phone 7.2
File
- ./
phone.install, line 96 - Install/Update/Uninstall functions for phone module
Code
function phone_update_7200(&$sandbox) {
// First loop of batch processing: update overall information including
// table schemas and instance settings.
if (!isset($sandbox['phone_instances'])) {
$sandbox['phone_instances'] = array();
$sandbox['phone_tables'] = array();
$sandbox['progress'] = 0;
$sandbox['max'] = 0;
$sandbox['#finished'] = 0;
// Get the 7200 version of the schema.
// This needs to be the 7200-specific schema so that updates can be
// done in sequence correctly, even if there are future schema changes.
// (see http://drupal.org/node/150220).
$columns = array(
'numbertype' => array(
'type' => 'varchar',
'length' => 255,
'not null' => FALSE,
'default' => NULL,
),
'number' => array(
'type' => 'varchar',
'length' => 30,
'not null' => FALSE,
'default' => NULL,
),
'countrycode' => array(
'type' => 'varchar',
'length' => 2,
'not null' => FALSE,
'default' => NULL,
),
'extension' => array(
'type' => 'varchar',
'length' => 7,
'not null' => FALSE,
'default' => NULL,
),
);
$schema = array(
'columns' => $columns,
'indexes' => array(
'countrycode' => array(
'countrycode',
),
'numbertype' => array(
'numbertype',
),
),
);
// Get list of phone field instances directly from field_config_instance
// database table, in order to be sure to get now-obsolete instance
// settings. This is also more efficient than using field_info_instances(),
// since field_info_instances() does not provide a way to directly limit the
// list based on field type.
$query = db_select('field_config', 'fc')
->condition('fc.type', 'phone');
$query
->addField('fc', 'field_name', 'fc_field_name');
$query
->addField('fc', 'data', 'fc_data');
$query
->leftJoin('field_config_instance', 'fci', 'fc.id = fci.field_id');
$query
->fields('fci');
$results = $query
->execute();
$tables_done = array();
$field_country = array();
foreach ($results as $row) {
$field_name = $row->fc_field_name;
// Update the schema of this instance's database table (if it has not yet
// been done).
// Note: although built-in functions such as field_udpate_field() and
// field_update_instance() exist, they explicitly don't allow schema
// changes. So stick to manually changing the information that needs
// be changed.
if (empty($tables_done[$field_name])) {
$tables_done[$field_name] = TRUE;
$data = unserialize($row->fc_data);
// Get country setting -- being moved from field_config level to
// instance level
$country = _phone_update_phone_country($data['settings']['country']);
$field_country[$field_name] = array(
'orig' => $data['settings']['country'],
'new' => $country,
);
foreach (array(
'data',
'revision',
) as $table_type) {
$table_name = 'field_' . $table_type . '_' . $field_name;
if (!db_table_exists($table_name)) {
continue;
}
$nrows = db_select($table_name)
->countQuery()
->execute()
->fetchField();
$sandbox['phone_tables'][$table_name] = array(
'field_name' => $field_name,
'nrows' => $nrows,
'country' => $field_country[$field_name],
);
$sandbox['max'] += $nrows;
// Add all new schema columns.
// Don't want to delete the value column until after data has been
// transferred.
foreach ($schema['columns'] as $column => $coldata) {
// Note that the column name is the field-version of the column;
// need to prepend $field_name to get the database column name.
db_add_field($table_name, $field_name . '_' . $column, $coldata);
}
// Do not add indexes manually, because field_update_field()
// automatically manages the indexes, causing 'index already
// exists' errors later.
}
// Call field_update_field to force indexes to be updated, along with
// internal information about indexes.
// Note that this does NOT update the rest of the lists of fields under
// FIELD_LOAD_CURRENT and FIELD_LOAD_REVISION, but there's no apparent
// way to do that, nor is it done by any schema update examples.
field_update_field(array(
'field_name' => $field_name,
));
}
// Skip instance processing if a field does not have any associated instances.
if (empty($row->data)) {
continue;
}
$data = unserialize($row->data);
_phone_update_phone_instance_settings($data, $field_country[$field_name]);
db_update('field_config_instance')
->fields(array(
'data' => serialize($data),
))
->condition('id', $row->id)
->execute();
}
// Clear the field cache.
field_cache_clear();
}
elseif (empty($sandbox['phone_tables'])) {
$sandbox['#finished'] = 1;
$sandbox['progress'] = $sandbox['max'];
}
else {
$phone_table = array_shift(array_keys($sandbox['phone_tables']));
$table_data = $sandbox['phone_tables'][$phone_table];
$field_name = $table_data['field_name'];
$process_limit = 20;
// Get next set of rows to process.
// Only condition is that the number is null, because all non-processed
// rows have null numbers.
$query = db_select($phone_table)
->fields($phone_table)
->isNull($table_data['field_name'] . '_number')
->range(0, $process_limit);
$result = $query
->execute();
$nrows_done = 0;
foreach ($result as $row) {
$nrows_done++;
// Convert number to individual entries
$newvals = _phone_migrate_phone_number($row->{$field_name . '_value'}, $table_data['country']['new']);
// Prefix $field_name onto each field value's name
foreach ($newvals as $valname => $value) {
$newvals[$field_name . '_' . $valname] = $value;
unset($newvals[$valname]);
}
if (empty($newvals[$field_name . '_number'])) {
// Make sure to set number to a non-NULL value, because a NULL value
// implies that the row has not been processed -- which will cause an
// infinite batch processing loop.
$newvals[$field_name . '_number'] = '';
}
db_update($phone_table)
->fields($newvals)
->condition('entity_type', $row->entity_type)
->condition('entity_id', $row->entity_id)
->condition('revision_id', $row->revision_id)
->condition('delta', $row->delta)
->condition('language', $row->language)
->execute();
}
// If done processing this table, drop it from the sandbox and
// delete the value column.
// We're done if the query returned less than the maximum number of rows.
// Note that in the case where there were exactly $process_limit rows left
// to process, the table won't be tagged as done until the next loop, at
// which point the query will return 0 rows.
if ($nrows_done < $process_limit) {
unset($sandbox['phone_tables'][$phone_table]);
db_drop_field($phone_table, $field_name . '_value');
}
$sandbox['progress'] += $nrows_done;
if (empty($sandbox['phone_tables'])) {
$sandbox['#finished'] = 1;
}
else {
// We're not directly using progress/max to determine when processing
// is done, so don't allow this value to reach 1 until phone_tables has
// been emptied (otherwise, the final table cleanup could get skipped).
$sandbox['#finished'] = min(0.99, $sandbox['progress'] / $sandbox['max']);
}
}
}