Newer
Older
<?php
// $Id$

Angie Byron
committed
/**
* @file
* Install, update and uninstall functions for the node module.
*/

Dries Buytaert
committed
* Implement hook_schema().
*/
function node_schema() {
$schema['node'] = array(

Dries Buytaert
committed
'description' => 'The base table for nodes.',
'fields' => array(
'nid' => array(

Dries Buytaert
committed
'description' => 'The primary identifier for a node.',
'type' => 'serial',
'unsigned' => TRUE,
'not null' => TRUE,
),
'vid' => array(

Dries Buytaert
committed
'description' => 'The current {node_revision}.vid version identifier.',
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => 0,
),
'type' => array(

Dries Buytaert
committed
'description' => 'The {node_type}.type of this node.',
'type' => 'varchar',
'length' => 32,
'not null' => TRUE,
'default' => '',
),
'language' => array(

Dries Buytaert
committed
'description' => 'The {languages}.language of this node.',
'type' => 'varchar',
'length' => 12,
'not null' => TRUE,
'default' => '',
),
'title' => array(

Dries Buytaert
committed
'description' => 'The title of this node, always treated as non-markup plain text.',
'type' => 'varchar',
'length' => 255,
'not null' => TRUE,
'default' => '',
),
'uid' => array(

Angie Byron
committed
'description' => 'The {users}.uid that owns this node; initially, this is the user that created it.',
'type' => 'int',
'not null' => TRUE,
'default' => 0,
),
'status' => array(

Dries Buytaert
committed
'description' => 'Boolean indicating whether the node is published (visible to non-administrators).',
'type' => 'int',
'not null' => TRUE,
'default' => 1,
),
'created' => array(

Dries Buytaert
committed
'description' => 'The Unix timestamp when the node was created.',
'type' => 'int',
'not null' => TRUE,
'default' => 0,
),
'changed' => array(

Dries Buytaert
committed
'description' => 'The Unix timestamp when the node was most recently saved.',
'type' => 'int',
'not null' => TRUE,
'default' => 0,
),
'comment' => array(

Dries Buytaert
committed
'description' => 'Whether comments are allowed on this node: 0 = no, 1 = closed (read only), 2 = open (read/write).',
'type' => 'int',
'not null' => TRUE,
'default' => 0,
),
'promote' => array(

Dries Buytaert
committed
'description' => 'Boolean indicating whether the node should be displayed on the front page.',
'type' => 'int',
'not null' => TRUE,
'default' => 0,
),
'moderate' => array(

Dries Buytaert
committed
'description' => 'Previously, a boolean indicating whether the node was "in moderation"; mostly no longer used.',
'type' => 'int',
'not null' => TRUE,
'default' => 0,
),
'sticky' => array(

Dries Buytaert
committed
'description' => 'Boolean indicating whether the node should be displayed at the top of lists in which it appears.',
'type' => 'int',
'not null' => TRUE,
'default' => 0,
),
'tnid' => array(

Dries Buytaert
committed
'description' => 'The translation set id for this node, which equals the node id of the source post in each set.',
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => 0,
),
'translate' => array(

Dries Buytaert
committed
'description' => 'A boolean indicating whether this translation page needs to be updated.',
'type' => 'int',
'not null' => TRUE,
'default' => 0,
'indexes' => array(
'node_changed' => array('changed'),
'node_created' => array('created'),
'node_moderate' => array('moderate'),

Dries Buytaert
committed
'node_frontpage' => array('promote', 'status', 'sticky', 'created'),
'node_status_type' => array('status', 'type', 'nid'),
'node_title_type' => array('title', array('type', 4)),
'node_type' => array(array('type', 4)),
'uid' => array('uid'),
'tnid' => array('tnid'),
'translate' => array('translate'),
'unique keys' => array(
'vid' => array('vid'),
),
'foreign keys' => array(
'vid' => array('node_revision' => 'vid'),
'uid' => array('users' => 'uid'),
),
'primary key' => array('nid'),
$schema['node_access'] = array(

Dries Buytaert
committed
'description' => 'Identifies which realm/grant pairs a user must possess in order to view, update, or delete specific nodes.',
'fields' => array(
'nid' => array(

Dries Buytaert
committed
'description' => 'The {node}.nid this record affects.',
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => 0,
),
'gid' => array(

Dries Buytaert
committed
'description' => "The grant ID a user must possess in the specified realm to gain this row's privileges on the node.",
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => 0,
),
'realm' => array(

Dries Buytaert
committed
'description' => 'The realm in which the user must possess the grant ID. Each node access node can define one or more realms.',
'type' => 'varchar',
'length' => 255,
'not null' => TRUE,
'default' => '',
),
'grant_view' => array(

Dries Buytaert
committed
'description' => 'Boolean indicating whether a user with the realm/grant pair can view this node.',
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => 0,
'size' => 'tiny',
),
'grant_update' => array(

Dries Buytaert
committed
'description' => 'Boolean indicating whether a user with the realm/grant pair can edit this node.',
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => 0,
'size' => 'tiny',
),
'grant_delete' => array(

Dries Buytaert
committed
'description' => 'Boolean indicating whether a user with the realm/grant pair can delete this node.',
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => 0,
'size' => 'tiny',
'primary key' => array('nid', 'gid', 'realm'),
'foreign keys' => array('node' => 'nid'),

Dries Buytaert
committed
$schema['node_revision'] = array(

Dries Buytaert
committed
'description' => 'Stores information about each saved version of a {node}.',
'fields' => array(
'nid' => array(

Dries Buytaert
committed
'description' => 'The {node} this version belongs to.',
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => 0,
),
'vid' => array(

Dries Buytaert
committed
'description' => 'The primary identifier for this version.',
'type' => 'serial',
'unsigned' => TRUE,
'not null' => TRUE,
),
'uid' => array(

Angie Byron
committed
'description' => 'The {users}.uid that created this version.',
'type' => 'int',
'not null' => TRUE,
'default' => 0,
),
'title' => array(

Dries Buytaert
committed
'description' => 'The title of this version.',
'type' => 'varchar',
'length' => 255,
'not null' => TRUE,
'default' => '',
),
'log' => array(

Dries Buytaert
committed
'description' => 'The log entry explaining the changes in this version.',
'type' => 'text',
'not null' => TRUE,
'size' => 'big',
),
'timestamp' => array(

Dries Buytaert
committed
'description' => 'A Unix timestamp indicating when this version was created.',
'type' => 'int',
'not null' => TRUE,
'default' => 0,
),
),
'indexes' => array(
'nid' => array('nid'),
'uid' => array('uid'),
),
'primary key' => array('vid'),
'foreign keys' => array(
'node' => 'nid',
'users' => 'uid'
),
$schema['node_type'] = array(

Dries Buytaert
committed
'description' => 'Stores information about all defined {node} types.',
'fields' => array(
'type' => array(

Dries Buytaert
committed
'description' => 'The machine-readable name of this type.',
'type' => 'varchar',
'length' => 32,
'not null' => TRUE,
),
'name' => array(

Dries Buytaert
committed
'description' => 'The human-readable name of this type.',
'type' => 'varchar',
'length' => 255,
'not null' => TRUE,
'default' => '',
),
'base' => array(

Dries Buytaert
committed
'description' => 'The base string used to construct callbacks corresponding to this node type.',
'type' => 'varchar',
'length' => 255,
'not null' => TRUE,
),
'description' => array(

Dries Buytaert
committed
'description' => 'A brief description of this type.',
'type' => 'text',
'not null' => TRUE,
'size' => 'medium',
),
'help' => array(

Dries Buytaert
committed
'description' => 'Help information shown to the user when creating a {node} of this type.',
'type' => 'text',
'not null' => TRUE,
'size' => 'medium',
),
'has_title' => array(

Dries Buytaert
committed
'description' => 'Boolean indicating whether this type uses the {node}.title field.',
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'size' => 'tiny',
),
'title_label' => array(

Dries Buytaert
committed
'description' => 'The label displayed for the title field on the edit form.',
'type' => 'varchar',
'length' => 255,
'not null' => TRUE,
'default' => '',
),
'has_body' => array(

Dries Buytaert
committed
'description' => 'Boolean indicating whether this type has the body field attached.',
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'size' => 'tiny',
),
'body_label' => array(

Dries Buytaert
committed
'description' => 'The label displayed for the body field on the edit form.',
'type' => 'varchar',
'length' => 255,
'not null' => TRUE,
'default' => '',
),
'min_word_count' => array(

Dries Buytaert
committed
'description' => 'The minimum number of words the body must contain.',
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'size' => 'small',
),
'custom' => array(

Dries Buytaert
committed
'description' => 'A boolean indicating whether this type is defined by a module (FALSE) or by a user via a module like the Content Construction Kit (TRUE).',
'type' => 'int',
'not null' => TRUE,
'default' => 0,
'size' => 'tiny',
),
'modified' => array(

Dries Buytaert
committed
'description' => 'A boolean indicating whether this type has been modified by an administrator; currently not used in any way.',
'type' => 'int',
'not null' => TRUE,
'default' => 0,
'size' => 'tiny',
),
'locked' => array(

Dries Buytaert
committed
'description' => 'A boolean indicating whether the administrator can change the machine name of this type.',
'type' => 'int',
'not null' => TRUE,
'default' => 0,
'size' => 'tiny',
),
'orig_type' => array(

Dries Buytaert
committed
'description' => 'The original machine-readable name of this node type. This may be different from the current type name if the locked field is 0.',
'type' => 'varchar',
'length' => 255,
'not null' => TRUE,
'default' => '',
'primary key' => array('type'),
return $schema;
}
/**

Dries Buytaert
committed
* @defgroup updates-6.x-to-7.x System updates from 6.x to 7.x
* @{
*/
/**
* Fix node type 'module' attribute to avoid name-space conflicts.
*/
function node_update_7000() {
$ret = array();
$ret[] = update_sql("UPDATE {node_type} SET module = 'node_content' WHERE module = 'node'");
db_change_field($ret, 'node_type', 'module', 'base', array('type' => 'varchar', 'length' => 255, 'not null' => TRUE));
return $ret;
}

Dries Buytaert
committed
/**
* Rename {node_revisions} table to {node_revision}.
*/
function node_update_7001() {
$ret = array();
db_rename_table($ret, 'node_revisions', 'node_revision');
return $ret;
}

Dries Buytaert
committed
/**
* Extend the node_promote_status index to include all fields required for the node page query.
*/
function node_update_7002() {
$ret = array();
db_drop_index($ret, 'node', 'node_promote_status');
db_add_index($ret, 'node', 'node_frontpage', array('promote', 'status', 'sticky', 'created'));
return $ret;
}
/**

Dries Buytaert
committed
* Remove the node_counter if the statistics module is uninstalled.
*/
function node_update_7003() {
$ret = array();

Dries Buytaert
committed
if (drupal_get_installed_schema_version('statistics') == SCHEMA_UNINSTALLED) {

Dries Buytaert
committed
db_drop_table($ret, 'node_counter');
}
return $ret;
}

Dries Buytaert
committed
/**
* Extend the existing default preview and teaser settings to all node types.
*/
function node_update_7004() {
// Get original settings and all types.
$original_length = variable_get('teaser_length', 600);
$original_preview = variable_get('node_preview', 0);
// Map old preview setting to new values order.
$original_preview ? $original_preview = 2 : $original_preview = 1;

Dries Buytaert
committed
$node_types_clear();
$type_list = node_type_get_types();

Dries Buytaert
committed
// Apply original settings to all types.
foreach ($type_list as $type => $object) {

Dries Buytaert
committed
variable_set('teaser_length_' . $type, $original_length);
variable_set('node_preview_' . $type, $original_preview);
}
// Delete old variable but leave 'teaser_length' for aggregator module upgrade.
variable_del('node_preview');
return array();

Dries Buytaert
committed
}

Dries Buytaert
committed
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
/**
* Convert body and teaser from node properties to fields.
*/
function node_update_7005(&$context) {
$ret = array('#finished' => 0);
// Get node type info for every invocation.
node_type_clear();
$node_types = node_type_get_types();
$body_types = array();
foreach ($node_types as $type => $info) {
if ($info->has_body) {
$body_types[] = $type;
}
}
if (!isset($context['total'])) {
// Initial invocation.
// Re-save node types to create body field instances.
foreach ($node_types as $type => $info) {
if ($info->has_body) {
node_type_save($info);
}
}
// Initialize state for future calls.
$context['last'] = 0;
$context['count'] = 0;
$query = db_select('node', 'n');
$query->join('node_revision', 'nr', 'n.vid = nr.vid');
$query->condition('n.type', $body_types, 'IN');
$context['total'] = $query->countQuery()->execute()->fetchField();
}
else {
// Subsequent invocations.
$found = FALSE;
if ($context['total']) {
// Operate on every revision of every node (whee!), in batches.
$batch_size = 50;
$query = db_select('node', 'n');
$nr = $query->innerJoin('node_revision', 'nr', 'n.vid = nr.vid');
$revisions = $query
->fields('n', array('type'))
->fields($nr)
->condition('nr.vid', $context['last'], '>')
->condition('n.type', $body_types, 'IN')
->orderBy('nr.vid', 'ASC')
->execute();
// Load each reversion 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 ($node_types[$revision->type]->has_body) {
$node = (object) array(
'nid' => $revision->nid,
'vid' => $revision->vid,
'type' => $revision->type,
);
if (!empty($revision->teaser) && $revision->teaser != text_summary($revision->body)) {
$node->body[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[0]['value'] = $revision->body;
$node->body[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.
field_sql_storage_field_storage_write('node', $node, FIELD_STORAGE_INSERT, array());
}
$context['last'] = $revision->vid;
$context['count'] += 1;
if (--$batch_size == 0) {
break;
}
}
$ret['#finished'] = min(0.99, $context['count'] / $context['total']);
}
if (!$found) {
// All nodes are processed.
$ret[] = array('success' => TRUE, 'query' => "{$context['total']} node body and teaser properties migrated to the 'body' field.");
// Remove the now-obsolete body info from node_revision.
db_drop_field($ret, 'node_revision', 'body');
db_drop_field($ret, 'node_revision', 'teaser');
db_drop_field($ret, 'node_revision', 'format');
// We're done.
$ret['#finished'] = 1;
}
}
return $ret;
}

Dries Buytaert
committed
/**
* @} End of "defgroup updates-6.x-to-7.x"
* The next series of updates should start at 8000.