Index: modules/system/system.install =================================================================== --- modules/system/system.install (revision 3) +++ modules/system/system.install (working copy) @@ -358,9 +358,12 @@ function system_install() { db_query("CREATE TABLE {node} ( nid int unsigned NOT NULL auto_increment, vid int unsigned NOT NULL default '0', + uid int NOT NULL default '0', type varchar(32) NOT NULL default '', title varchar(128) NOT NULL default '', - uid int NOT NULL default '0', + body longtext NOT NULL, + teaser longtext NOT NULL, + format int NOT NULL default '0', status int NOT NULL default '1', created int NOT NULL default '0', changed int NOT NULL default '0', @@ -833,9 +836,12 @@ function system_install() { db_query("CREATE TABLE {node} ( nid serial CHECK (nid >= 0), vid int_unsigned NOT NULL default '0', + uid int NOT NULL default '0', type varchar(32) NOT NULL default '', title varchar(128) NOT NULL default '', - uid int NOT NULL default '0', + body text NOT NULL default '', + teaser text NOT NULL default '', + format int NOT NULL default '0', status int NOT NULL default '1', created int NOT NULL default '0', changed int NOT NULL default '0', @@ -874,9 +880,9 @@ function system_install() { title varchar(128) NOT NULL default '', body text NOT NULL default '', teaser text NOT NULL default '', + format int NOT NULL default '0', log text NOT NULL default '', timestamp int NOT NULL default '0', - format int NOT NULL default '0', PRIMARY KEY (vid) )"); db_query("CREATE INDEX {node_revisions}_nid_idx ON {node_revisions} (nid)"); @@ -3579,6 +3585,59 @@ function system_update_2001() { } /** - * @} End of "defgroup updates-5.0-to-x.x" + * Make node revisions optional. + */ +function system_update_2002() { + $ret = array(); + + // Migrate over information. We create a new node table because the update + // would be prohibitively slow. + $ret[] = update_sql(' + CREATE TABLE {node_temp} AS + SELECT n.nid, n.vid, n.uid, n.type, n.title, r.body, r.teaser, r.format, n.status, n.created, + n.changed, n.promote, n.moderate, n.sticky + FROM {node} n + INNER JOIN {node_revisions} r ON n.vid = r.vid + '); + switch ($GLOBALS['db_type']) { + case 'mysql': + case 'mysqli': + $ret[] = update_sql('RENAME TABLE {node} TO {node_old}'); + $ret[] = update_sql('RENAME TABLE {node_temp} TO {node}'); + break; + case 'pgsql': + $ret[] = update_sql('ALTER TABLE {node} RENAME TO {node_old}'); + $ret[] = update_sql('ALTER TABLE {node_temp} RENAME TO {node}'); + break; + } + + // Check to make sure that the node tables match, before proceeding. + $new_count = db_result(db_query('SELECT COUNT(1) FROM {node}')); + $old_count = db_result(db_query('SELECT COUNT(1) FROM {node_old}')); + if ($new_count == $old_count) { + $ret[] = update_sql('DROP TABLE {node_old}'); + + // Remove single revisions from the node_revisions table. + $ret[] = update_sql('CREATE TABLE {revisions_temp} AS SELECT * FROM {node_revisions} GROUP BY nid HAVING COUNT(nid) > 1'); + $ret[] = update_sql('DROP TABLE {node_revisions}'); + switch ($GLOBALS['db_type']) { + case 'mysql': + case 'mysqli': + $ret[] = update_sql('RENAME TABLE {revisions_temp} TO {node_revisions}'); + break; + case 'pgsql': + $ret[] = update_sql('ALTER TABLE {revisions_temp} RENAME TO {node_revisions}'); + break; + } + + // Update sequences table. + $ret[] = update_sql("UPDATE {sequences} SET name = '{node}_vid' WHERE name = '{node_revisions}_vid'"); + } + + return $ret; +} + +/** + * @} End of "defgroup updates-5.0-to-6.0" * The next series of updates should start at 3000. */ Index: modules/node/content_types.inc =================================================================== --- modules/node/content_types.inc (revision 3) +++ modules/node/content_types.inc (working copy) @@ -161,7 +161,6 @@ function node_type_form($type = NULL) { 'status' => t('Published'), 'promote' => t('Promoted to front page'), 'sticky' => t('Sticky at top of lists'), - 'revision' => t('Create new revision'), ), '#description' => t('Users with the administer nodes permission will be able to override these options.'), ); Index: modules/node/node.module =================================================================== --- modules/node/node.module (revision 3) +++ modules/node/node.module (working copy) @@ -35,10 +35,6 @@ function node_help($section) { return '

'. t('To create a new content type, enter the human-readable name, the machine-readable name, and all other relevant fields that are on this page. Once created, users of your site will be able to create posts that are instances of this content type.') .'

'; } - if (arg(0) == 'node' && is_numeric(arg(1)) && arg(2) == 'revisions') { - return '

'. t('The revisions let you track differences between multiple versions of a post.') .'

'; - } - if (arg(0) == 'node' && arg(1) == 'add' && $type = arg(2)) { $type = node_get_types('type', str_replace('-', '_', arg(2))); return '

'. (isset($type->help) ? filter_xss_admin($type->help) : '') .'

'; @@ -475,20 +471,15 @@ function node_invoke_nodeapi(&$node, $op * * @param $param * Either the nid of the node or an array of conditions to match against in the database query - * @param $revision - * Which numbered revision to load. Defaults to the current version. * @param $reset * Whether to reset the internal node_load cache. * * @return * A fully-populated node object. */ -function node_load($param = array(), $revision = NULL, $reset = NULL) { +function node_load($param = array(), $reset = NULL) { static $nodes = array(); - - if ($reset) { - $nodes = array(); - } + $revision = NULL; $cachable = ($revision == NULL); $arguments = array(); @@ -506,16 +497,18 @@ function node_load($param = array(), $re $arguments[] = $value; } $cond = implode(' AND ', $cond); + if (isset($param['vid'])) { + $revision = $param['vid']; + } } // Retrieve the node. // No db_rewrite_sql is applied so as to get complete indexing for search. if ($revision) { - array_unshift($arguments, $revision); - $node = db_fetch_object(db_query('SELECT n.nid, r.vid, n.type, n.status, n.created, n.changed, n.comment, n.promote, n.sticky, r.timestamp AS revision_timestamp, r.title, r.body, r.teaser, r.log, r.format, u.uid, u.name, u.picture, u.data FROM {node} n INNER JOIN {users} u ON u.uid = n.uid INNER JOIN {node_revisions} r ON r.nid = n.nid AND r.vid = %d WHERE '. $cond, $arguments)); + $node = db_fetch_object(db_query('SELECT n.nid, r.vid, n.type, n.status, n.created, n.changed, n.comment, n.promote, n.sticky, r.timestamp AS revision_timestamp, r.title, r.body, r.teaser, r.log, r.format, u.uid, u.name, u.picture, u.data FROM {node} n INNER JOIN {users} u ON u.uid = n.uid INNER JOIN {node_revisions} r ON r.nid = n.nid WHERE r.vid = %d', $revision)); } else { - $node = db_fetch_object(db_query('SELECT n.nid, n.vid, n.type, n.status, n.created, n.changed, n.comment, n.promote, n.sticky, r.timestamp AS revision_timestamp, r.title, r.body, r.teaser, r.log, r.format, u.uid, u.name, u.picture, u.data FROM {node} n INNER JOIN {users} u ON u.uid = n.uid INNER JOIN {node_revisions} r ON r.vid = n.vid WHERE '. $cond, $arguments)); + $node = db_fetch_object(db_query('SELECT n.nid, n.vid, n.type, n.status, n.created, n.changed, n.comment, n.promote, n.sticky, n.title, n.body, n.teaser, n.format, u.uid, u.name, u.picture, u.data FROM {node} n INNER JOIN {users} u ON u.uid = n.uid WHERE '. $cond, $arguments)); } if ($node->nid) { @@ -554,7 +547,6 @@ function node_save(&$node) { $node->is_new = TRUE; $node->nid = db_next_id('{node}_nid'); - $node->vid = db_next_id('{node_revisions}_vid'); } else { // We need to ensure that all node fields are filled. @@ -563,52 +555,35 @@ function node_save(&$node) { $node_current->$field = $data; } $node = $node_current; - - if (!empty($node->revision)) { - $node->old_vid = $node->vid; - $node->vid = db_next_id('{node_revisions}_vid'); - } - } - + } // Set some required fields: if (empty($node->created)) { $node->created = time(); } - // The changed timestamp is always updated for bookkeeping purposes (revisions, searching, ...) + // The changed timestamp is always updated for bookkeeping purposes + // (revisions, searching, ...) $node->changed = time(); - // Split off revisions data to another structure - $revisions_table_values = array('nid' => $node->nid, 'vid' => $node->vid, - 'title' => $node->title, 'body' => $node->body, - 'teaser' => $node->teaser, 'timestamp' => $node->changed, - 'uid' => $user->uid, 'format' => $node->format); - $revisions_table_types = array('nid' => '%d', 'vid' => '%d', - 'title' => "'%s'", 'body' => "'%s'", - 'teaser' => "'%s'", 'timestamp' => '%d', - 'uid' => '%d', 'format' => '%d'); - if (!empty($node->log) || $node->is_new) { - // Only store the log message if there's something to store; this prevents - // existing log messages from being unintentionally overwritten by a blank - // message. A new revision will have an empty log message (or $node->log). - $revisions_table_values['log'] = $node->log; - $revisions_table_types['log'] = "'%s'"; - } + // Revision ID. + $node->vid = db_next_id('{node}_vid'); + $node_table_values = array('nid' => $node->nid, 'vid' => $node->vid, - 'title' => $node->title, 'type' => $node->type, 'uid' => $node->uid, + 'title' => $node->title, 'type' => $node->type, + 'body' => $node->body, 'teaser' => $node->teaser, + 'format' => $node->format, 'uid' => $node->uid, 'status' => $node->status, 'created' => $node->created, 'changed' => $node->changed, 'comment' => $node->comment, 'promote' => $node->promote, 'sticky' => $node->sticky); $node_table_types = array('nid' => '%d', 'vid' => '%d', - 'title' => "'%s'", 'type' => "'%s'", 'uid' => '%d', + 'title' => "'%s'", 'type' => "'%s'", 'body' => "'%s'", + 'teaser' => "'%s'", 'format' => "'%s'", 'uid' => '%d', 'status' => '%d', 'created' => '%d', 'changed' => '%d', 'comment' => '%d', 'promote' => '%d', 'sticky' => '%d'); - //Generate the node table query and the - //the node_revisions table query + // Generate the node table query. if ($node->is_new) { $node_query = 'INSERT INTO {node} ('. implode(', ', array_keys($node_table_types)) .') VALUES ('. implode(', ', $node_table_types) .')'; - $revisions_query = 'INSERT INTO {node_revisions} ('. implode(', ', array_keys($revisions_table_types)) .') VALUES ('. implode(', ', $revisions_table_types) .')'; } else { $arr = array(); @@ -617,22 +592,10 @@ function node_save(&$node) { } $node_table_values[] = $node->nid; $node_query = 'UPDATE {node} SET '. implode(', ', $arr) .' WHERE nid = %d'; - if (!empty($node->revision)) { - $revisions_query = 'INSERT INTO {node_revisions} ('. implode(', ', array_keys($revisions_table_types)) .') VALUES ('. implode(', ', $revisions_table_types) .')'; - } - else { - $arr = array(); - foreach ($revisions_table_types as $key => $value) { - $arr[] = $key .' = '. $value; - } - $revisions_table_values[] = $node->vid; - $revisions_query = 'UPDATE {node_revisions} SET '. implode(', ', $arr) .' WHERE vid = %d'; - } } // Insert the node into the database: db_query($node_query, $node_table_values); - db_query($revisions_query, $revisions_table_values); // Call the node specific callback (if any): if ($node->is_new) { @@ -775,7 +738,7 @@ function node_show($node, $cid) { * Implementation of hook_perm(). */ function node_perm() { - $perms = array('administer content types', 'administer nodes', 'access content', 'view revisions', 'revert revisions'); + $perms = array('administer content types', 'administer nodes', 'access content'); foreach (node_get_types() as $type) { if ($type->module == 'node') { @@ -939,10 +902,9 @@ function node_search($op = 'search', $ke /** * Implementation of hook_user(). */ -function node_user($op, &$edit, &$user) { +function node_user($op, &$edit, &$account) { if ($op == 'delete') { - db_query('UPDATE {node} SET uid = 0 WHERE uid = %d', $user->uid); - db_query('UPDATE {node_revisions} SET uid = 0 WHERE uid = %d', $user->uid); + db_query('UPDATE {node} SET uid = 0 WHERE uid = %d', $account->uid); } } @@ -1054,10 +1016,6 @@ function node_link($type, $node = NULL, return $links; } -function _node_revision_access($node) { - return (user_access('view revisions') || user_access('administer nodes')) && node_access('view', $node) && db_result(db_query('SELECT COUNT(vid) FROM {node_revisions} WHERE nid = %d', $node->nid)) > 1; -} - /** * Implementation of hook_menu(). */ @@ -1191,14 +1149,6 @@ function node_menu() { 'access arguments' => array('delete', 1), 'weight' => 1, 'type' => MENU_CALLBACK); - $items['node/%node/revisions'] = array( - 'title' => t('Revisions'), - 'page callback' => 'node_revisions', - 'access callback' => '_node_revision_access', - 'access arguments' => array(1), - 'weight' => 2, - 'type' => MENU_LOCAL_TASK, - ); return $items; } @@ -1600,127 +1550,6 @@ function node_multiple_delete_confirm_su return 'admin/content/node'; } -/** - * Generate an overview table of older revisions of a node. - */ -function node_revision_overview($node) { - drupal_set_title(t('Revisions for %title', array('%title' => $node->title))); - - $header = array(t('Revision'), array('data' => t('Operations'), 'colspan' => 2)); - - $revisions = node_revision_list($node); - - $rows = array(); - $revert_permission = FALSE; - if ((user_access('revert revisions') || user_access('administer nodes')) && node_access('update', $node)) { - $revert_permission = TRUE; - } - $delete_permission = FALSE; - if (user_access('administer nodes')) { - $delete_permission = TRUE; - } - foreach ($revisions as $revision) { - $row = array(); - $operations = array(); - - if ($revision->current_vid > 0) { - $row[] = array('data' => t('!date by !username', array('!date' => l(format_date($revision->timestamp, 'small'), "node/$node->nid"), '!username' => theme('username', $revision))) - . (($revision->log != '') ? '

'. filter_xss($revision->log) .'

' : ''), - 'class' => 'revision-current'); - $operations[] = array('data' => theme('placeholder', t('current revision')), 'class' => 'revision-current', 'colspan' => 2); - } - else { - $row[] = t('!date by !username', array('!date' => l(format_date($revision->timestamp, 'small'), "node/$node->nid/revisions/$revision->vid/view"), '!username' => theme('username', $revision))) - . (($revision->log != '') ? '

'. filter_xss($revision->log) .'

' : ''); - if ($revert_permission) { - $operations[] = l(t('revert'), "node/$node->nid/revisions/$revision->vid/revert"); - } - if ($delete_permission) { - $operations[] = l(t('delete'), "node/$node->nid/revisions/$revision->vid/delete"); - } - } - $rows[] = array_merge($row, $operations); - } - $output .= theme('table', $header, $rows); - - return $output; -} - -/** - * Revert to the revision with the specified revision number. A node and nodeapi "update" event is triggered - * (via the node_save() call) when a revision is reverted. - */ -function node_revision_revert($nid, $revision) { - global $user; - - $node = node_load($nid, $revision); - if ((user_access('revert revisions') || user_access('administer nodes')) && node_access('update', $node)) { - if ($node->vid) { - $node->revision = 1; - $node->log = t('Copy of the revision from %date.', array('%date' => format_date($node->revision_timestamp))); - if (module_exists('taxonomy')) { - $node->taxonomy = array_keys($node->taxonomy); - } - - node_save($node); - - drupal_set_message(t('%title has been reverted back to the revision from %revision-date', array('%revision-date' => format_date($node->revision_timestamp), '%title' => $node->title))); - watchdog('content', t('@type: reverted %title revision %revision.', array('@type' => t($node->type), '%title' => $node->title, '%revision' => $revision))); - } - else { - drupal_set_message(t('You tried to revert to an invalid revision.'), 'error'); - } - drupal_goto('node/'. $nid .'/revisions'); - } - drupal_access_denied(); -} - -/** - * Delete the revision with specified revision number. A "delete revision" nodeapi event is invoked when a - * revision is deleted. - */ -function node_revision_delete($nid, $revision) { - if (user_access('administer nodes')) { - $node = node_load($nid); - if (node_access('delete', $node)) { - // Don't delete the current revision - if ($revision != $node->vid) { - $node = node_load($nid, $revision); - - db_query("DELETE FROM {node_revisions} WHERE nid = %d AND vid = %d", $nid, $revision); - node_invoke_nodeapi($node, 'delete revision'); - drupal_set_message(t('Deleted %title revision %revision.', array('%title' => $node->title, '%revision' => $revision))); - watchdog('content', t('@type: deleted %title revision %revision.', array('@type' => t($node->type), '%title' => $node->title, '%revision' => $revision))); - } - - else { - drupal_set_message(t('Deletion failed. You tried to delete the current revision.')); - } - if (db_result(db_query('SELECT COUNT(vid) FROM {node_revisions} WHERE nid = %d', $nid)) > 1) { - drupal_goto("node/$nid/revisions"); - } - else { - drupal_goto("node/$nid"); - } - } - } - - drupal_access_denied(); -} - -/** - * Return a list of all the existing revision numbers. - */ -function node_revision_list($node) { - $revisions = array(); - $result = db_query('SELECT r.vid, r.title, r.log, r.uid, n.vid AS current_vid, r.timestamp, u.name FROM {node_revisions} r LEFT JOIN {node} n ON n.vid = r.vid INNER JOIN {users} u ON u.uid = r.uid WHERE r.nid = %d ORDER BY r.timestamp DESC', $node->nid); - while ($revision = db_fetch_object($result)) { - $revisions[] = $revision; - } - - return $revisions; -} - function node_admin_search() { $keys = isset($_POST['keys']) ? $_POST['keys'] : NULL; return drupal_get_form('search_form', url('admin/content/search'), $keys, 'node') . search_data($keys, 'node'); @@ -1973,30 +1802,14 @@ function node_form($node, $form_values = $node_options = variable_get('node_options_'. $node->type, array('status', 'promote')); // If this is a new node, fill in the default values. if (!isset($node->nid)) { - foreach (array('status', 'promote', 'sticky', 'revision') as $key) { + foreach (array('status', 'promote', 'sticky') as $key) { $node->$key = in_array($key, $node_options); } global $user; $node->uid = $user->uid; } - else { - // Nodes being edited should always be preset with the default revision setting. - $node->revision = in_array('revision', $node_options); - } $form['#node'] = $node; - // Add a log field if the "Create new revision" option is checked, or if the - // current user has the ability to check that option. - if ($node->revision || user_access('administer nodes')) { - $form['log'] = array( - '#type' => 'textarea', - '#title' => t('Log message'), - '#rows' => 2, - '#weight' => 20, - '#description' => t('An explanation of the additions or updates being made to help other authors understand your motivations.'), - ); - } - // Node author information for administrators $form['author'] = array( '#type' => 'fieldset', @@ -2025,7 +1838,6 @@ function node_form($node, $form_values = $form['options']['status'] = array('#type' => 'checkbox', '#title' => t('Published'), '#default_value' => $node->status); $form['options']['promote'] = array('#type' => 'checkbox', '#title' => t('Promoted to front page'), '#default_value' => $node->promote); $form['options']['sticky'] = array('#type' => 'checkbox', '#title' => t('Sticky at top of lists'), '#default_value' => $node->sticky); - $form['options']['revision'] = array('#type' => 'checkbox', '#title' => t('Create new revision'), '#default_value' => $node->revision); // These values are used when the user has no administrator access. foreach (array('uid', 'created') as $key) { $form[$key] = array('#type' => 'value', '#value' => $node->$key); @@ -2218,10 +2030,6 @@ function theme_node_preview($node) { return $output; } -function theme_node_log_message($log) { - return '
'. t('Log') .':
'. $log .'
'; -} - function node_form_submit($form_id, $form_values) { global $user; @@ -2284,7 +2092,6 @@ function node_delete($nid) { if (node_access('delete', $node)) { db_query('DELETE FROM {node} WHERE nid = %d', $node->nid); - db_query('DELETE FROM {node_revisions} WHERE nid = %d', $node->nid); // Call the node-specific callback (if any): node_invoke($node, 'delete'); @@ -2303,44 +2110,6 @@ function node_delete($nid) { } /** - * Menu callback for revisions related activities. - */ -function node_revisions() { - if (is_numeric(arg(1)) && arg(2) == 'revisions') { - $op = arg(4) ? arg(4) : 'overview'; - switch ($op) { - case 'overview': - $node = node_load(arg(1)); - if ((user_access('view revisions') || user_access('administer nodes')) && node_access('view', $node)) { - return node_revision_overview($node); - } - drupal_access_denied(); - return; - case 'view': - if (is_numeric(arg(3))) { - $node = node_load(arg(1), arg(3)); - if ($node->nid) { - if ((user_access('view revisions') || user_access('administer nodes')) && node_access('view', $node)) { - drupal_set_title(t('Revision of %title from %date', array('%title' => $node->title, '%date' => format_date($node->revision_timestamp)))); - return node_show($node, arg(2)); - } - drupal_access_denied(); - return; - } - } - break; - case 'revert': - node_revision_revert(arg(1), arg(3)); - break; - case 'delete': - node_revision_delete(arg(1), arg(3)); - break; - } - } - drupal_not_found(); -} - -/** * Menu callback; Generate a listing of promoted nodes. */ function node_page_default() {