function node_update_7006 in Drupal 7
Convert body and teaser from node properties to fields, and migrate status/comment/promote and sticky columns to the {node_revision} table.
Related topics
File
- modules/
node/ node.install, line 607 - Install, update and uninstall functions for the node module.
Code
function node_update_7006(&$sandbox) {
$sandbox['#finished'] = 0;
// Get node type info for every invocation.
node_type_cache_reset();
if (!isset($sandbox['total'])) {
// Initial invocation.
// First, create the body field.
$body_field = array(
'field_name' => 'body',
'type' => 'text_with_summary',
'module' => 'text',
'cardinality' => 1,
'entity_types' => array(
'node',
),
'translatable' => TRUE,
);
_update_7000_field_create_field($body_field);
$default_trim_length = variable_get('teaser_length', 600);
// Get node type info, specifically the body field settings.
$node_types = _update_7000_node_get_types();
// Add body field instances for existing node types.
foreach ($node_types as $node_type) {
if ($node_type->has_body) {
$trim_length = variable_get('teaser_length_' . $node_type->type, $default_trim_length);
$instance = array(
'entity_type' => 'node',
'bundle' => $node_type->type,
'label' => $node_type->body_label,
'description' => isset($node_type->description) ? $node_type->description : '',
'required' => isset($node_type->min_word_count) && $node_type->min_word_count > 0 ? 1 : 0,
'widget' => array(
'type' => 'text_textarea_with_summary',
'settings' => array(
'rows' => 20,
'summary_rows' => 5,
),
'weight' => -4,
'module' => 'text',
),
'settings' => array(
'display_summary' => TRUE,
),
'display' => array(
'default' => array(
'label' => 'hidden',
'type' => 'text_default',
),
'teaser' => array(
'label' => 'hidden',
'type' => 'text_summary_or_trimmed',
'trim_length' => $trim_length,
),
),
);
_update_7000_field_create_instance($body_field, $instance);
variable_del('teaser_length_' . $node_type->type);
}
// Leave 'teaser_length' variable for aggregator module upgrade.
$sandbox['node_types_info'][$node_type->type] = array(
'has_body' => $node_type->has_body,
);
}
// Used below when updating the stored text format of each node body.
$sandbox['existing_text_formats'] = db_query("SELECT format FROM {filter_format}")
->fetchCol();
// Initialize state for future calls.
$sandbox['last'] = 0;
$sandbox['count'] = 0;
$query = db_select('node', 'n');
$query
->join('node_revision', 'nr', 'n.nid = nr.nid');
$sandbox['total'] = $query
->countQuery()
->execute()
->fetchField();
$sandbox['body_field_id'] = $body_field['id'];
}
else {
// Subsequent invocations.
$found = FALSE;
if ($sandbox['total']) {
// Operate on every revision of every node (whee!), in batches.
$batch_size = 200;
$query = db_select('node_revision', 'nr');
$query
->innerJoin('node', 'n', 'n.nid = nr.nid');
$query
->fields('nr', array(
'nid',
'vid',
'body',
'teaser',
'format',
))
->fields('n', array(
'type',
'status',
'comment',
'promote',
'sticky',
'language',
))
->condition('nr.vid', $sandbox['last'], '>')
->orderBy('nr.vid', 'ASC')
->range(0, $batch_size);
$revisions = $query
->execute();
// Load each revision of each node, set up 'body'
// appropriately, and save the node's field data. Note that
// node_load() will not return the body or teaser values from
// {node_revision} because those columns have been removed from the
// schema structure in memory (but not yet from the database),
// so we get the values from the explicit query of the table
// instead.
foreach ($revisions as $revision) {
$found = TRUE;
if ($sandbox['node_types_info'][$revision->type]['has_body']) {
$node = (object) array(
'nid' => $revision->nid,
'vid' => $revision->vid,
'type' => $revision->type,
);
// After node_update_7009() we will always have LANGUAGE_NONE as
// language neutral language code, but here we still have empty
// strings.
$langcode = empty($revision->language) ? LANGUAGE_NONE : $revision->language;
if (!empty($revision->teaser) && $revision->teaser != text_summary($revision->body)) {
$node->body[$langcode][0]['summary'] = $revision->teaser;
}
// Do this after text_summary() above.
$break = '<!--break-->';
if (substr($revision->body, 0, strlen($break)) == $break) {
$revision->body = substr($revision->body, strlen($break));
}
$node->body[$langcode][0]['value'] = $revision->body;
// Update the revision's text format for the changes to the Drupal 7
// filter system. This uses the same kind of logic that occurs, for
// example, in user_update_7010(), but we do this here rather than
// via a separate set of database queries, since we are already
// migrating the data.
if (empty($revision->body) && empty($revision->format)) {
$node->body[$langcode][0]['format'] = NULL;
}
elseif (!in_array($revision->format, $sandbox['existing_text_formats'])) {
$node->body[$langcode][0]['format'] = variable_get('filter_default_format', 1);
}
else {
$node->body[$langcode][0]['format'] = $revision->format;
}
// This is a core update and no contrib modules are enabled yet, so
// we can assume default field storage for a faster update.
_update_7000_field_sql_storage_write('node', $node->type, $node->nid, $node->vid, 'body', $node->body);
}
// Migrate the status columns to the {node_revision} table.
db_update('node_revision')
->fields(array(
'status' => $revision->status,
'comment' => $revision->comment,
'promote' => $revision->promote,
'sticky' => $revision->sticky,
))
->condition('vid', $revision->vid)
->execute();
$sandbox['last'] = $revision->vid;
$sandbox['count'] += 1;
}
$sandbox['#finished'] = min(0.99, $sandbox['count'] / $sandbox['total']);
}
if (!$found) {
// All nodes are processed.
// Remove the now-obsolete body info from node_revision.
db_drop_field('node_revision', 'body');
db_drop_field('node_revision', 'teaser');
db_drop_field('node_revision', 'format');
// Remove node_type properties related to the former 'body'.
db_drop_field('node_type', 'has_body');
db_drop_field('node_type', 'body_label');
// We're done.
$sandbox['#finished'] = 1;
}
}
}