Index: database/database.mysql =================================================================== RCS file: /cvs/drupal/drupal/database/database.mysql,v retrieving revision 1.186 diff -u -F^f -r1.186 database.mysql --- database/database.mysql 10 May 2005 20:48:31 -0000 1.186 +++ database/database.mysql 11 May 2005 03:31:41 -0000 @@ -134,11 +134,12 @@ -- CREATE TABLE book ( + vid int(10) unsigned NOT NULL default '0', nid int(10) unsigned NOT NULL default '0', parent int(10) NOT NULL default '0', weight tinyint(3) NOT NULL default '0', - log longtext, - PRIMARY KEY (nid), + PRIMARY KEY (vid), + KEY nid (nid), KEY parent (parent) ) TYPE=MyISAM; @@ -240,12 +241,14 @@ CREATE TABLE files ( fid int(10) unsigned NOT NULL default '0', nid int(10) unsigned NOT NULL default '0', + vid int(10) unsigned NOT NULL default '0', filename varchar(255) NOT NULL default '', filepath varchar(255) NOT NULL default '', filemime varchar(255) NOT NULL default '', filesize int(10) unsigned NOT NULL default '0', list tinyint(1) unsigned NOT NULL default '0', - PRIMARY KEY (fid) + KEY vid (vid), + KEY fid (fid) ) TYPE=MyISAM; -- @@ -287,9 +290,11 @@ -- CREATE TABLE forum ( + vid int(10) unsigned NOT NULL default '0', nid int(10) unsigned NOT NULL default '0', tid int(10) unsigned NOT NULL default '0', - PRIMARY KEY (nid), + PRIMARY KEY (vid), + KEY nid (nid), KEY tid (tid) ) TYPE=MyISAM; @@ -400,6 +405,7 @@ CREATE TABLE node ( nid int(10) unsigned NOT NULL auto_increment, + vid int(10) unsigned NOT NULL default '1', type varchar(16) NOT NULL default '', title varchar(128) NOT NULL default '', uid int(10) NOT NULL default '0', @@ -409,16 +415,13 @@ comment int(2) NOT NULL default '0', promote int(2) NOT NULL default '0', moderate int(2) NOT NULL default '0', - teaser longtext NOT NULL, - body longtext NOT NULL, - revisions longtext NOT NULL, sticky int(2) NOT NULL default '0', - format int(4) NOT NULL default '0', PRIMARY KEY (nid), KEY node_type (type(4)), KEY node_title_type (title,type(4)), KEY status (status), KEY uid (uid), + KEY vid (vid), KEY node_moderate (moderate), KEY node_promote_status (promote, status), KEY node_created (created), @@ -439,6 +442,24 @@ grant_delete tinyint(1) unsigned NOT NULL default '0', PRIMARY KEY (nid,gid,realm) ) TYPE=MyISAM; + +-- +-- Table structure for table 'node_revisions' +-- + +CREATE TABLE node_revisions ( + nid int(10) unsigned NOT NULL, + vid int(10) unsigned NOT NULL, + uid int(10) NOT NULL default '0', + title varchar(128) NOT NULL default '', + body longtext NOT NULL default '', + teaser longtext NOT NULL default '', + log longtext NOT NULL default '', + timestamp int(11) NOT NULL default '0', + format int(4) NOT NULL default '0', + PRIMARY KEY (nid,vid), + KEY uid (uid) +) TYPE=MyISAM; -- -- Table structure for table 'profile_fields' Index: database/database.pgsql =================================================================== RCS file: /cvs/drupal/drupal/database/database.pgsql,v retrieving revision 1.123 diff -u -F^f -r1.123 database.pgsql --- database/database.pgsql 10 May 2005 20:48:32 -0000 1.123 +++ database/database.pgsql 11 May 2005 03:31:41 -0000 @@ -132,10 +132,10 @@ -- CREATE TABLE book ( + vid integer NOT NULL default '0', nid integer NOT NULL default '0', parent integer NOT NULL default '0', weight smallint NOT NULL default '0', - log text default '', PRIMARY KEY (nid) ); CREATE INDEX book_nid_idx ON book(nid); @@ -239,12 +239,12 @@ CREATE TABLE files ( fid SERIAL, nid integer NOT NULL default '0', + vid integer NOT NULL default '0', filename varchar(255) NOT NULL default '', filepath varchar(255) NOT NULL default '', filemime varchar(255) NOT NULL default '', filesize integer NOT NULL default '0', list smallint NOT NULL default '0', - PRIMARY KEY (fid) ); -- @@ -287,11 +287,13 @@ -- CREATE TABLE forum ( + vid integer NOT NULL default '0', nid integer NOT NULL default '0', tid integer NOT NULL default '0', - shadow integer NOT NULL default '0', - PRIMARY KEY (nid) + PRIMARY KEY (vid) ); +CREATE INDEX forum_vid_idx ON forum(vid); +CREATE INDEX forum_nid_idx ON forum(nid); CREATE INDEX forum_tid_idx ON forum(tid); -- @@ -403,6 +405,7 @@ CREATE TABLE node ( nid SERIAL, + vid integer NOT NULL default '0', type varchar(16) NOT NULL default '', title varchar(128) NOT NULL default '', uid integer NOT NULL default '0', @@ -412,17 +415,14 @@ comment integer NOT NULL default '0', promote integer NOT NULL default '0', moderate integer NOT NULL default '0', - teaser text NOT NULL default '', - body text NOT NULL default '', - revisions text NOT NULL default '', sticky integer NOT NULL default '0', - format smallint NOT NULL default '0', PRIMARY KEY (nid) ); CREATE INDEX node_type_idx ON node(type); CREATE INDEX node_title_idx ON node(title,type); CREATE INDEX node_status_idx ON node(status); CREATE INDEX node_uid_idx ON node(uid); +CREATE INDEX node_vid_idx ON node(vid); CREATE INDEX node_moderate_idx ON node (moderate); CREATE INDEX node_promote_status_idx ON node (promote, status); CREATE INDEX node_created ON node(created); @@ -442,6 +442,26 @@ PRIMARY KEY (nid,gid,realm) ); +-- +-- Table structure for table 'node_revisions' +-- + +CREATE TABLE node_revisions ( + vid integer NOT NULL default '0', + nid integer NOT NULL default '0', + uid integer NOT NULL default '0', + title varchar(128) NOT NULL default '', + body text NOT NULL default '', + teaser text NOT NULL default '', + log text NOT NULL default '', + format smallint NOT NULL default '0', + timestamp integer NOT NULL default '0', + data text NOT NULL default '', + PRIMARY KEY (vid) +); + +CREATE INDEX node_revisions_nid_idx ON node_revisions(nid); +CREATE INDEX node_revisions_uid_idx ON node_revisions(uid); -- -- Table structure for table 'node_counter' Index: database/updates.inc =================================================================== RCS file: /cvs/drupal/drupal/database/updates.inc,v retrieving revision 1.117 diff -u -F^f -r1.117 updates.inc --- database/updates.inc 10 May 2005 20:48:32 -0000 1.117 +++ database/updates.inc 11 May 2005 03:31:41 -0000 @@ -1,5 +1,5 @@ 0) { + $revisions_query = array(); + $revisions_args = array(); + $book_query = array(); + $book_args = array(); + $forum_query = array(); + $forum_args = array(); + foreach ($revisions as $version) { + $revision = array(); + foreach ($version['node'] as $node_field => $node_value) { + $revision[$node_field] = $node_value; + } + $revision['uid'] = $version['uid']; + $revision['timestamp'] = $version['timestamp']; + + $vid++; + $revisions_query[] = " (%d, %d, %d, '%s', '%s', '%s', '%s', %d, %d) "; + $revisions_args = array_merge($revisions_args, array($nid, $vid, $revision['uid'], $revision['title'], $revision['body'], $revision['teaser'], $revision['log'], $revision['timestamp'], $revision['format'])); + // db_query("INSERT INTO {node_revisions} (nid, vid, uid, title, body, teaser, log, timestamp, format) VALUES (%d, %d, %d, '%s', '%s', '%s', '%s', %d, %d)", $nid, $vid, $revision['uid'], $revision['title'], $revision['body'], $revision['teaser'], $revision['log'], $revision['timestamp'], $revision['format']); + switch ($row['type']) { + case 'forum': + if ($revision['tid'] > 0) { + $forum_query[] = "(%d, %d, %d)"; + $forum_args[] = array_merge($forum_args, array($vid, $nid, $revision['tid'])); + db_query("INSERT INTO {forum} (vid, nid, tid) VALUES (%d, %d, %d)", $vid, $nid, $revision['tid']); + } + break; + case 'book': + $book_query[] = "(%d, %d, %d, %d)"; + $book_args[] = array_merge($book_args, array($vid, $nid, $revision['parent'], $revision['weight'])); + break; + } + } + if (count($revisions_query)) { + db_query("INSERT INTO {node_revisions} (nid, vid, uid, title, body, teaser, log, timestamp, format) VALUES ". implode(',', $revisions_query), $revisions_args); + } + if (count($forum_query)) { + db_query("INSERT INTO {forum} (vid, nid, tid) VALUES ". implode(',', $forum_query), $forum_args); + } + if (count($book_query)) { + db_query("INSERT INTO {book} (vid, nid, parent, weight) VALUES ". implode(',', $book_query), $book_args); + } + } + } + + // Other node types might be added to the book. Move logs too. + $result = db_query("SELECT n.nid, n.vid, n.type, b.log FROM {book} b INNER JOIN {node} n ON b.nid = n.nid"); + while ($row = db_fetch_object($result)) { + if ($row->type != 'book') { + db_query("UPDATE {book} SET vid = %d WHERE nid = %d", $row->vid, $row->nid); + } + if ($row->log != '') { + db_query("UPDATE {node_revisions} SET log = '%s' WHERE vid = %d", $row->log, $row->vid); + } + } + + // Assign existing files to current vid + $result = db_query("SELECT n.nid, n.vid FROM {node} n INNER JOIN {files} f ON n.nid = f.nid"); + while ($row = db_fetch_object($result)) { + db_query("UPDATE {files} SET vid = %d WHERE nid = %d", $row->vid, $row->nid); + } + + if ($GLOBALS['db_type'] == 'mysql') { + $ret[] = update_sql("ALTER TABLE {book} ADD PRIMARY KEY vid (vid)"); + $ret[] = update_sql("ALTER TABLE {forum} ADD PRIMARY KEY vid (vid)"); + $ret[] = update_sql("CREATE TABLE {old_revisions} SELECT nid, revisions FROM {node} WHERE revisions != ''"); + } + else { // pgsql update + } + + $ret[] = update_sql("INSERT INTO {sequences} (name, id) VALUES ('{node_revisions}_vid', $vid)"); + $ret[] = update_sql("ALTER TABLE {book} DROP log"); + $ret[] = update_sql("ALTER TABLE {node} DROP teaser"); + $ret[] = update_sql("ALTER TABLE {node} DROP body"); + $ret[] = update_sql("ALTER TABLE {node} DROP format"); + $ret[] = update_sql("ALTER TABLE {node} DROP revisions"); + return $ret; } Index: modules/blogapi.module =================================================================== RCS file: /cvs/drupal/drupal/modules/blogapi.module,v retrieving revision 1.42 diff -u -F^f -r1.42 blogapi.module --- modules/blogapi.module 27 Apr 2005 17:07:03 -0000 1.42 +++ modules/blogapi.module 11 May 2005 03:31:41 -0000 @@ -372,7 +372,12 @@ function blogapi_get_recent_posts($req_p } $type = _blogapi_blogid($params[0]); - $result = db_query_range('SELECT n.nid, n.title,'. ($bodies ? ' n.body,' : '') ." n.created, u.name FROM {node} n, {users} u WHERE n.uid=u.uid AND n.type = '%s' AND n.uid = %d ORDER BY n.created DESC", $type, $user->uid, 0, $params[3]); + if ($bodies) { + $result = db_query_range("SELECT n.nid, n.title, r.body, n.created, u.name FROM {node} n, {node_revisions} r, {users} u WHERE n.uid = u.uid AND n.vid = r.vid AND n.type = '%s' AND n.uid = %d ORDER BY n.created DESC", $type, $user->uid, 0, $params[3]); + } + else { + $result = db_query_range("SELECT n.nid, n.title, n.created, u.name FROM {node} n, {users} u WHERE n.uid = u.uid AND n.type = '%s' AND n.uid = %d ORDER BY n.created DESC", $type, $user->uid, 0, $params[3]); + } while ($blog = db_fetch_object($result)) { $xmlrpcval = _blogapi_get_post($blog, $bodies); $blogs[] = $xmlrpcval; Index: modules/book.module =================================================================== RCS file: /cvs/drupal/drupal/modules/book.module,v retrieving revision 1.297 diff -u -F^f -r1.297 book.module --- modules/book.module 6 May 2005 08:43:21 -0000 1.297 +++ modules/book.module 11 May 2005 03:31:41 -0000 @@ -127,7 +127,7 @@ function book_block($op = 'list', $delta else if ($op == 'view') { // Only display this block when the user is browsing a book: if (arg(0) == 'node' && is_numeric(arg(1))) { - $result = db_query(db_rewrite_sql('SELECT n.nid, n.title, b.parent FROM {node} n INNER JOIN {book} b ON n.nid = b.nid WHERE n.nid = %d'), arg(1)); + $result = db_query(db_rewrite_sql('SELECT n.nid, n.title, b.parent FROM {node} n INNER JOIN {book} b ON n.vid = b.vid WHERE n.nid = %d'), arg(1)); if (db_num_rows($result) > 0) { $node = db_fetch_object($result); @@ -154,7 +154,7 @@ function book_block($op = 'list', $delta function book_load($node) { global $user; - $book = db_fetch_object(db_query('SELECT parent, weight, log FROM {book} WHERE nid = %d', $node->nid)); + $book = db_fetch_object(db_query('SELECT parent, weight FROM {book} WHERE vid = %d', $node->vid)); if (arg(2) == 'edit' && !user_access('administer nodes')) { // If a user is about to update a book page, we overload some @@ -176,14 +176,19 @@ function book_load($node) { * Implementation of hook_insert(). */ function book_insert($node) { - db_query("INSERT INTO {book} (nid, parent, weight, log) VALUES (%d, %d, %d, '%s')", $node->nid, $node->parent, $node->weight, $node->log); + db_query("INSERT INTO {book} (nid, vid, parent, weight) VALUES (%d, %d, %d, %d)", $node->nid, $node->vid, $node->parent, $node->weight); } /** * Implementation of hook_update(). */ function book_update($node) { - db_query("UPDATE {book} SET parent = %d, weight = %d, log = '%s' WHERE nid = %d", $node->parent, $node->weight, $node->log, $node->nid); + if ($node->is_new || $node->revision) { + db_query("INSERT INTO {book} (nid, vid, parent, weight) VALUES (%d, %d, %d, %d, '%s')", $node->nid, $node->vid, $node->parent, $node->weight); + } + else { + db_query("UPDATE {book} SET parent = %d, weight = %d WHERE vid = %d", $node->parent, $node->weight, $node->vid); + } } /** @@ -220,6 +225,7 @@ function book_form(&$node) { $output .= form_textarea(t('Body'), 'body', $node->body, 60, 20, '', NULL, TRUE); $output .= filter_form('format', $node->format); + $output .= form_textarea(t('Log message'), 'log', $node->log, 60, 5, t('An explanation of the additions or updates being made to help other authors understand your motivations.')); if (user_access('administer nodes')) { @@ -247,13 +253,15 @@ function book_outline() { if ($node->nid) { switch ($op) { case t('Add to book outline'): - db_query('INSERT INTO {book} (nid, parent, weight) VALUES (%d, %d, %d)', $node->nid, $edit['parent'], $edit['weight']); + db_query('INSERT INTO {book} (nid, vid, parent, weight) VALUES (%d, %d, %d, %d)', $node->nid, $node->vid, $edit['parent'], $edit['weight']); + db_query("UPDATE {node_revisions} SET log = '%s' WHERE vid = %d", $edit['log'], $node->vid); drupal_set_message(t('The post has been added to the book.')); drupal_goto("node/$node->nid"); break; case t('Update book outline'): - db_query('UPDATE {book} SET parent = %d, weight = %d WHERE nid = %d', $edit['parent'], $edit['weight'], $node->nid); + db_query('UPDATE {book} SET parent = %d, weight = %d WHERE vid = %d', $edit['parent'], $edit['weight'], $node->vid); + db_query("UPDATE {node_revisions} SET log = '%s' WHERE vid = %d", $edit['log'], $node->vid); drupal_set_message(t('The book outline has been updated.')); drupal_goto("node/$node->nid"); break; @@ -265,10 +273,11 @@ function book_outline() { break; default: - $page = db_fetch_object(db_query('SELECT * FROM {book} WHERE nid = %d', $node->nid)); + $page = db_fetch_object(db_query('SELECT * FROM {book} WHERE vid = %d', $node->vid)); $output = form_select(t('Parent'), 'parent', $page->parent, book_toc($node->nid), t('The parent page in the book.')); - $output .= form_weight(t('Weight'), 'weight', $node->weight, 15, t('Pages at a given level are ordered first by weight and then by title.')); + $output .= form_weight(t('Weight'), 'weight', $page->weight, 15, t('Pages at a given level are ordered first by weight and then by title.')); + $output .= form_textarea(t('Log message'), 'log', $node->log, 60, 5, t('An explanation to help other authors understand your motivations to put this post into the book.')); if ($page->nid) { $output .= form_submit(t('Update book outline')); @@ -316,7 +325,7 @@ function book_revision_load($page, $cond * Return the path (call stack) to a certain book page. */ function book_location($node, $nodes = array()) { - $parent = db_fetch_object(db_query(db_rewrite_sql('SELECT n.nid, n.title, b.parent, b.weight FROM {node} n INNER JOIN {book} b ON n.nid = b.nid WHERE n.nid = %d'), $node->parent)); + $parent = db_fetch_object(db_query(db_rewrite_sql('SELECT n.nid, n.title, b.parent, b.weight FROM {node} n INNER JOIN {book} b ON n.vid = b.vid WHERE n.nid = %d'), $node->parent)); if ($parent->title) { $nodes = book_location($parent, $nodes); array_push($nodes, $parent); @@ -325,7 +334,7 @@ function book_location($node, $nodes = a } function book_location_down($node, $nodes = array()) { - $last_direct_child = db_fetch_object(db_query(db_rewrite_sql('SELECT n.nid, n.title, b.parent, b.weight FROM {node} n INNER JOIN {book} b ON n.nid = b.nid WHERE b.parent = %d ORDER BY b.weight DESC, n.title DESC'), $node->nid)); + $last_direct_child = db_fetch_object(db_query(db_rewrite_sql('SELECT n.nid, n.title, b.parent, b.weight FROM {node} n INNER JOIN {book} b ON n.vid = b.vid WHERE b.parent = %d ORDER BY b.weight DESC, n.title DESC'), $node->nid)); if ($last_direct_child) { array_push($nodes, $last_direct_child); $nodes = book_location_down($last_direct_child, $nodes); @@ -343,7 +352,7 @@ function book_prev($node) { } // Previous on the same level: - $direct_above = db_fetch_object(db_query(db_rewrite_sql("SELECT n.nid, n.title FROM {node} n INNER JOIN {book} b ON n.nid = b.nid WHERE b.parent = %d AND n.status = 1 AND n.moderate = 0 AND (b.weight < %d OR (b.weight = %d AND n.title < '%s')) ORDER BY b.weight DESC, n.title DESC"), $node->parent, $node->weight, $node->weight, $node->title)); + $direct_above = db_fetch_object(db_query(db_rewrite_sql("SELECT n.nid, n.title FROM {node} n INNER JOIN {book} b ON n.vid = b.vid WHERE b.parent = %d AND n.status = 1 AND n.moderate = 0 AND (b.weight < %d OR (b.weight = %d AND n.title < '%s')) ORDER BY b.weight DESC, n.title DESC"), $node->parent, $node->weight, $node->weight, $node->title)); if ($direct_above) { // Get last leaf of $above. $path = book_location_down($direct_above); @@ -352,7 +361,7 @@ function book_prev($node) { } else { // Direct parent: - $prev = db_fetch_object(db_query(db_rewrite_sql('SELECT n.nid, n.title FROM {node} n INNER JOIN {book} b ON n.nid = b.nid WHERE n.nid = %d AND n.status = 1 AND n.moderate = 0'), $node->parent)); + $prev = db_fetch_object(db_query(db_rewrite_sql('SELECT n.nid, n.title FROM {node} n INNER JOIN {book} b ON n.vid = b.vid WHERE n.nid = %d AND n.status = 1 AND n.moderate = 0'), $node->parent)); return $prev; } } @@ -362,7 +371,7 @@ function book_prev($node) { */ function book_next($node) { // get first direct child - $child = db_fetch_object(db_query(db_rewrite_sql('SELECT n.nid, n.title, b.weight FROM {node} n INNER JOIN {book} b ON n.nid = b.nid WHERE b.parent = %d AND n.status = 1 AND n.moderate = 0 ORDER BY b.weight ASC, n.title ASC'), $node->nid)); + $child = db_fetch_object(db_query(db_rewrite_sql('SELECT n.nid, n.title, b.weight FROM {node} n INNER JOIN {book} b ON n.vid = b.vid WHERE b.parent = %d AND n.status = 1 AND n.moderate = 0 ORDER BY b.weight ASC, n.title ASC'), $node->nid)); if ($child) { return $child; } @@ -371,7 +380,7 @@ function book_next($node) { array_push($path = book_location($node), $node); // Path to top-level node including this one. while (($leaf = array_pop($path)) && count($path)) { - $next = db_fetch_object(db_query(db_rewrite_sql("SELECT n.nid, n.title, b.weight FROM {node} n INNER JOIN {book} b ON n.nid = b.nid WHERE b.parent = %d AND n.status = 1 AND n.moderate = 0 AND (b.weight > %d OR (b.weight = %d AND n.title > '%s')) ORDER BY b.weight ASC, n.title ASC"), $leaf->parent, $leaf->weight, $leaf->weight, $leaf->title)); + $next = db_fetch_object(db_query(db_rewrite_sql("SELECT n.nid, n.title, b.weight FROM {node} n INNER JOIN {book} b ON n.vid = b.vid WHERE b.parent = %d AND n.status = 1 AND n.moderate = 0 AND (b.weight > %d OR (b.weight = %d AND n.title > '%s')) ORDER BY b.weight ASC, n.title ASC"), $leaf->parent, $leaf->weight, $leaf->weight, $leaf->title)); if ($next) { return $next; } @@ -406,10 +415,6 @@ function book_content($node, $teaser = F */ function book_view(&$node, $teaser = FALSE, $page = FALSE) { $node = book_content($node, $teaser); - - if (!$teaser && $node->moderate) { - $node->body .= '
'. t('Log') .':
'. $node->log .'
'; - } } /** @@ -421,7 +426,7 @@ function book_nodeapi(&$node, $op, $teas switch ($op) { case 'view': if (!$teaser) { - $book = db_fetch_array(db_query('SELECT * FROM {book} WHERE nid = %d', $node->nid)); + $book = db_fetch_array(db_query('SELECT * FROM {book} WHERE vid = %d', $node->vid)); if ($book) { if ($node->moderate && user_access('administer nodes')) { drupal_set_message(t("The post has been submitted for moderation and won't be accessible until it has been approved.")); @@ -514,7 +519,7 @@ function book_toc_recurse($nid, $indent, } function book_toc($exclude = 0) { - $result = db_query(db_rewrite_sql('SELECT n.nid, n.title, b.parent, b.weight FROM {node} n INNER JOIN {book} b ON n.nid = b.nid WHERE n.status = 1 ORDER BY b.weight, n.title')); + $result = db_query(db_rewrite_sql('SELECT n.nid, n.title, b.parent, b.weight FROM {node} n INNER JOIN {book} b ON n.vid = b.vid WHERE n.status = 1 ORDER BY b.weight, n.title')); while ($node = db_fetch_object($result)) { if (!$children[$node->parent]) { @@ -567,7 +572,7 @@ function book_tree_recurse($nid, $depth, } function book_tree($parent = 0, $depth = 3, $unfold = array()) { - $result = db_query(db_rewrite_sql('SELECT n.nid, n.title, b.parent, b.weight FROM {node} n INNER JOIN {book} b ON n.nid = b.nid WHERE n.status = 1 AND n.moderate = 0 ORDER BY b.weight, n.title')); + $result = db_query(db_rewrite_sql('SELECT n.nid, n.title, b.parent, b.weight FROM {node} n INNER JOIN {book} b ON n.vid = b.vid WHERE n.status = 1 AND n.moderate = 0 ORDER BY b.weight, n.title')); while ($node = db_fetch_object($result)) { $list = $children[$node->parent] ? $children[$node->parent] : array(); @@ -584,7 +589,7 @@ function book_tree($parent = 0, $depth = * Menu callback; prints a listing of all books. */ function book_render() { - $result = db_query(db_rewrite_sql('SELECT n.nid, n.title FROM {node} n INNER JOIN {book} b ON n.nid = b.nid WHERE b.parent = 0 AND n.status = 1 AND n.moderate = 0 ORDER BY b.weight, n.title')); + $result = db_query(db_rewrite_sql('SELECT n.nid, n.title FROM {node} n INNER JOIN {book} b ON n.vid = b.vid WHERE b.parent = 0 AND n.status = 1 AND n.moderate = 0 ORDER BY b.weight, n.title')); return $output; } @@ -627,7 +632,7 @@ function book_print($nid = 0, $depth = 1 } function book_print_recurse($parent = '', $depth = 1) { - $result = db_query(db_rewrite_sql('SELECT n.nid, n.title, b.weight FROM {node} n INNER JOIN {book} b ON n.nid = b.nid WHERE n.status = 1 AND b.parent = %d AND n.moderate = 0 ORDER BY b.weight, n.title'), $parent); + $result = db_query(db_rewrite_sql('SELECT n.nid, n.title, b.weight FROM {node} n INNER JOIN {book} b ON n.vid = b.vid WHERE n.status = 1 AND b.parent = %d AND n.moderate = 0 ORDER BY b.weight, n.title'), $parent); while ($page = db_fetch_object($result)) { // Load the node: @@ -664,7 +669,7 @@ function book_admin_edit_line($node, $de } function book_admin_edit_book($nid, $depth = 1) { - $result = db_query(db_rewrite_sql('SELECT n.nid FROM {node} n INNER JOIN {book} b ON n.nid = b.nid WHERE b.parent = %d ORDER BY b.weight, n.title'), $nid); + $result = db_query(db_rewrite_sql('SELECT n.nid FROM {node} n INNER JOIN {book} b ON n.vid = b.vid WHERE b.parent = %d ORDER BY b.weight, n.title'), $nid); while ($node = db_fetch_object($result)) { $node = node_load(array('nid' => $node->nid)); @@ -702,15 +707,16 @@ function book_admin_save($nid, $edit = a foreach ($edit as $nid => $value) { // Check to see whether the title needs updating: - $title = db_result(db_query('SELECT title FROM {node} WHERE nid = %d', $nid)); - if ($title != $value['title']) { + $node = db_fetch_object(db_query('SELECT title, vid FROM {node} WHERE nid = %d', $nid)); + if ($node->title != $value['title']) { db_query("UPDATE {node} SET title = '%s' WHERE nid = %d", $value['title'], $nid); + db_query("UPDATE {book} SET title = '%s' WHERE vid = %d", $value['title'], $node->vid); } // Check to see whether the weight needs updating: - $weight = db_result(db_query('SELECT weight FROM {book} WHERE nid = %d', $nid)); - if ($weight != $value['weight']) { - db_query('UPDATE {book} SET weight = %d WHERE nid = %d', $value['weight'], $nid); + $node = db_fetch_object(db_query('SELECT b.vid, b.weight FROM {book} b INNER JOIN {node} n ON n.vid = b.vid WHERE n.nid = %d', $nid)); + if ($node->weight != $value['weight']) { + db_query('UPDATE {book} SET weight = %d WHERE vid = %d', $value['weight'], $node->vid); } } @@ -725,7 +731,7 @@ function book_admin_save($nid, $edit = a * Menu callback; displays a listing of all orphaned book pages. */ function book_admin_orphan() { - $result = db_query(db_rewrite_sql('SELECT n.nid, n.title, n.status, b.parent FROM {node} n INNER JOIN {book} b ON n.nid = b.nid')); + $result = db_query(db_rewrite_sql('SELECT n.nid, n.title, n.status, b.parent FROM {node} n INNER JOIN {book} b ON v.nid = b.vid')); while ($page = db_fetch_object($result)) { $pages[$page->nid] = $page; Index: modules/forum.module =================================================================== RCS file: /cvs/drupal/drupal/modules/forum.module,v retrieving revision 1.252 diff -u -F^f -r1.252 forum.module --- modules/forum.module 7 May 2005 01:48:06 -0000 1.252 +++ modules/forum.module 11 May 2005 03:31:41 -0000 @@ -320,7 +320,7 @@ function forum_admin_configure() { * Implementation of hook_load(). */ function forum_load($node) { - $forum = db_fetch_object(db_query('SELECT * FROM {forum} WHERE nid = %d', $node->nid)); + $forum = db_fetch_object(db_query('SELECT * FROM {forum} WHERE vid = %d', $node->vid)); return $forum; } @@ -525,7 +525,12 @@ function forum_validate(&$node) { * Implementation of hook_update(). */ function forum_update($node) { - db_query('UPDATE {forum} SET tid = %d WHERE nid = %d', $node->tid, $node->nid); + if ($node->is_new || $node->revision) { + db_query("INSERT INTO {forum} (nid, vid, tid) VALUES (%d, %d, %d)", $node->nid, $node->vid, $node->tid); + } + else { + db_query('UPDATE {forum} SET tid = %d WHERE vid = %d', $node->tid, $node->vid); + } } /** @@ -558,7 +563,7 @@ function forum_form(&$node) { * Implementation of hook_insert(). */ function forum_insert($node) { - db_query('INSERT INTO {forum} (nid, tid) VALUES (%d, %d)', $node->nid, $node->tid); + db_query('INSERT INTO {forum} (nid, vid, tid) VALUES (%d, %d, %d)', $node->nid, $node->vid, $node->tid); } /** @@ -683,7 +688,7 @@ function forum_get_topics($tid, $sortby, $term = taxonomy_get_term($tid); - $sql = db_rewrite_sql("SELECT n.nid, f.tid, n.title, n.sticky, u.name, u.uid, n.created AS timestamp, n.comment AS comment_mode, l.last_comment_timestamp, IF(l.last_comment_uid, cu.name, l.last_comment_name) AS last_comment_name, l.last_comment_uid, l.comment_count AS num_comments FROM {node} n, {node_comment_statistics} l, {users} cu, {term_node} r, {users} u, {forum} f WHERE n.status = 1 AND l.last_comment_uid = cu.uid AND n.nid = l.nid AND n.nid = r.nid AND r.tid = %d AND n.uid = u.uid AND n.nid = f.nid"); + $sql = db_rewrite_sql("SELECT n.nid, f.tid, n.title, n.sticky, u.name, u.uid, n.created AS timestamp, n.comment AS comment_mode, l.last_comment_timestamp, IF(l.last_comment_uid, cu.name, l.last_comment_name) AS last_comment_name, l.last_comment_uid, l.comment_count AS num_comments FROM {node} n, {node_comment_statistics} l, {users} cu, {term_node} r, {users} u, {forum} f WHERE n.status = 1 AND l.last_comment_uid = cu.uid AND n.nid = l.nid AND n.nid = r.nid AND r.tid = %d AND n.uid = u.uid AND n.vid = f.vid"); $sql .= tablesort_sql($forum_topic_list_header, 'n.sticky DESC,'); $sql_count = db_rewrite_sql("SELECT COUNT(n.nid) FROM {node} n INNER JOIN {term_node} r ON n.nid = r.nid AND r.tid = %d WHERE n.status = 1 AND n.type = 'forum'"); Index: modules/node.module =================================================================== RCS file: /cvs/drupal/drupal/modules/node.module,v retrieving revision 1.487 diff -u -F^f -r1.487 node.module --- modules/node.module 24 Apr 2005 16:34:34 -0000 1.487 +++ modules/node.module 11 May 2005 03:31:41 -0000 @@ -388,31 +388,27 @@ function node_load($conditions, $revisio } // Retrieve the node. - $node = db_fetch_object(db_query('SELECT n.*, u.uid, u.name, u.picture, u.data FROM {node} n INNER JOIN {users} u ON u.uid = n.uid WHERE '. implode(' AND ', $cond))); - $node = drupal_unpack($node); - - // Unserialize the revisions and user data fields. - if ($node->revisions) { - $node->revisions = unserialize($node->revisions); + if ($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.moderate, 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 '. implode(' AND ', $cond), $revision)); } - - // Call the node specific callback (if any) and piggy-back the - // results to the node or overwrite some values. - if ($extra = node_invoke($node, 'load')) { - foreach ($extra as $key => $value) { - $node->$key = $value; - } + 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.moderate, 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 '. implode(' AND ', $cond))); } - if ($extra = node_invoke_nodeapi($node, 'load')) { - foreach ($extra as $key => $value) { - $node->$key = $value; + if ($node->nid) { + // Call the node specific callback (if any) and piggy-back the + // results to the node or overwrite some values. + if ($extra = node_invoke($node, 'load')) { + foreach ($extra as $key => $value) { + $node->$key = $value; + } } - } - // Return the desired revision. - if (!is_null($revision) && is_array($node->revisions[$revision])) { - $node = $node->revisions[$revision]['node']; + if ($extra = node_invoke_nodeapi($node, 'load')) { + foreach ($extra as $key => $value) { + $node->$key = $value; + } + } } if ($cachable) { @@ -426,61 +422,99 @@ function node_load($conditions, $revisio * Save a node object into the database. */ function node_save($node) { - // Fetch fields to save to node table: - $fields = node_invoke_nodeapi($node, 'fields'); + global $user; - // Serialize the revisions field: - if ($node->revisions) { - $node->revisions = serialize($node->revisions); - } + $node->is_new = false; // Apply filters to some default node fields: if (empty($node->nid)) { // Insert a new node. + $node->is_new = true; // Set some required fields: if (!$node->created) { $node->created = time(); } - if (!$node->changed) { - $node->changed = time(); - } $node->nid = db_next_id('{node}_nid'); - - // Prepare the query: - foreach ($node as $key => $value) { - if (in_array((string) $key, $fields)) { - $k[] = db_escape_string($key); - $v[] = $value; - $s[] = "'%s'"; - } + $node->vid = db_next_id('{node_revisions}_vid');; + } + else { + // We need to ensure that all node fields are filled. + $node_current = node_load(array('nid' => $node->nid)); + foreach ($node as $field => $data) { + $node_current->$field = $data; } + $node = $node_current; - // Insert the node into the database: - db_query("INSERT INTO {node} (". implode(", ", $k) .") VALUES(". implode(", ", $s) .")", $v); - - // Call the node specific callback (if any): - node_invoke($node, 'insert'); - node_invoke_nodeapi($node, 'insert'); + if ($node->revision) { + $node->old_vid = $node->vid; + $node->vid = db_next_id('{node_revisions}_vid');; + } } - else { - // Update an existing node. - // Set some required fields: + if (!$node->changed) { $node->changed = time(); + } - // Prepare the query: - foreach ($node as $key => $value) { - if (in_array($key, $fields)) { - $q[] = db_escape_string($key) ." = '%s'"; - $v[] = $value; + // 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, 'log' => $node->log, 'timestamp' => $node->changed, + 'uid' => $user->uid, 'format' => $node->format); + $revisions_table_types = array('nid' => '%d', 'vid' => '%d', + 'title' => "'%s'", 'body' => "'%s'", + 'teaser' => "'%s'", 'log' => "'%s'", 'timestamp' => '%d', + 'uid' => '%d', 'format' => '%d'); + $node_table_values = array('nid' => $node->nid, 'vid' => $node->vid, + 'title' => $node->title, 'type' => $node->type, 'uid' => $node->uid, + 'status' => $node->status, 'created' => $node->created, + 'changed' => $node->changed, 'comment' => $node->comment, + 'promote' => $node->promote, 'moderate' => $node->moderate, + 'sticky' => $node->sticky); + $node_table_types = array('nid' => '%d', 'vid' => '%d', + 'title' => "'%s'", 'type' => "'%s'", 'uid' => '%d', + 'status' => '%d', 'created' => '%d', + 'changed' => '%d', 'comment' => '%d', + 'promote' => '%d', 'moderate' => '%d', + 'sticky' => '%d'); + + //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(); + foreach ($node_table_types as $key => $value) { + $arr[] = $key .' = '. $value; + } + $node_table_values[] = $node->nid; + $node_query = 'UPDATE {node} SET '. implode(', ', $arr) .' WHERE nid = %d'; + if ($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'; } + } + + //Generate the node_revisions table query - // Update the node in the database: - db_query("UPDATE {node} SET ". implode(', ', $q) ." WHERE nid = '$node->nid'", $v); + // 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): + // Call the node specific callback (if any): + if ($node->is_new) { + node_invoke($node, 'insert'); + node_invoke_nodeapi($node, 'insert'); + } + else { node_invoke($node, 'update'); node_invoke_nodeapi($node, 'update'); } @@ -514,6 +548,10 @@ function node_view($node, $teaser = FALS // TODO: this strips legitimate uses of '' also. $node->body = str_replace('', '', $node->body); + if ($node->log != '' && !$teaser && $node->moderate) { + $node->body .= '
'. t('Log') .':
'. $node->log .'
'; + } + // The 'view' hook can be implemented to overwrite the default function // to display nodes. if (node_hook($node, 'view')) { @@ -708,8 +746,7 @@ function node_menu($may_cache) { 'access' => node_access('delete', $node), 'weight' => 1, 'type' => MENU_CALLBACK); - - if ($node->revisions) { + if (user_access('administer nodes') && db_result(db_query('SELECT COUNT(vid) FROM {node_revisions} WHERE nid = %d', arg(1))) > 1) { $items[] = array('path' => 'node/'. arg(1) .'/revisions', 'title' => t('revisions'), 'callback' => 'node_page', 'access' => user_access('administer nodes'), @@ -993,13 +1030,39 @@ function node_revision_overview($nid) { if (user_access('administer nodes')) { $node = node_load(array('nid' => $nid)); - drupal_set_title(check_plain($node->title)); + drupal_set_title(t('Revisions for %title', array('%title' => $node->title))); - if ($node->revisions) { - $header = array(t('Older revisions'), array('colspan' => '3', 'data' => t('Operations'))); + if ($node->vid) { + $header = array('', t('Author'), t('Title'), t('Date'), array('colspan' => '3', 'data' => t('Operations'))); - foreach ($node->revisions as $key => $revision) { - $rows[] = array(t('revision #%r revised by %u on %d', array('%r' => $key, '%u' => format_name(user_load(array('uid' => $revision['uid']))), '%d' => format_date($revision['timestamp'], 'small'))) . ($revision['history'] ? '
'. $revision['history'] .'' : ''), l(t('view'), "node/$node->nid", array(), "revision=$key"), l(t('rollback'), "node/$node->nid/rollback-revision/$key"), l(t('delete'), "node/$node->nid/delete-revision/$key")); + $revisions = node_revision_list($node); + + $i = 0; + $revisions_count = count($revisions); + foreach ($revisions as $revision) { + $row = ++$i; + if ($row < $revisions_count) { + $rows[] = array( + array('data' => $row, 'rowspan' => ($revision->log != '') ? 2 : 1), + format_name($revision), + $revision->title, + format_date($revision->timestamp, 'small'), + l(t('view'), "node/$node->nid/revision/". $revision->vid), + l(t('roll back'), "node/$node->nid/rollback-revision/". $revision->vid), + l(t('delete'), "node/$node->nid/delete-revision/". $revision->vid)); + } + else { + $rows[] = array( + array('data' => t('current'), 'rowspan' => ($revision->log != '') ? 2 : 1), + format_name($revision), + $revision->title, + format_date($revision->timestamp, 'small'), + l(t('view'), "node/$node->nid"), + '', ''); + } + if ($revision->log != '') { + $rows[] = array(array('data' => $revision->log, 'colspan' => 6)); + } } $output .= theme('table', $header, $rows); } @@ -1008,32 +1071,6 @@ function node_revision_overview($nid) { return $output; } - -/** - * Return the revision with the specified revision number. - */ -function node_revision_load($node, $revision) { - return $node->revisions[$revision]['node']; -} - -/** - * Create and return a new revision of the given node. - */ -function node_revision_create($node) { - global $user; - - // "Revision" is the name of the field used to indicate that we have to - // create a new revision of a node. - if ($node->nid && $node->revision) { - $prev = node_load(array('nid' => $node->nid)); - $node->revisions = $prev->revisions; - unset($prev->revisions); - $node->revisions[] = array('uid' => $user->uid, 'timestamp' => time(), 'node' => $prev, 'history' => $node->history); - } - - return $node; -} - /** * Roll back to the revision with the specified revision number. */ @@ -1041,29 +1078,13 @@ function node_revision_rollback($nid, $r global $user; if (user_access('administer nodes')) { - $node = node_load(array('nid' => $nid)); - - // Extract the specified revision: - $rev = $node->revisions[$revision]['node']; - - // Inherit all the past revisions: - $rev->revisions = $node->revisions; - - // Save the original/current node: - $rev->revisions[] = array('uid' => $user->uid, 'timestamp' => time(), 'node' => $node); - - // Remove the specified revision: - unset($rev->revisions[$revision]); - - // Save the node: - foreach ($node as $key => $value) { - $filter[] = $key; - } - - node_save($rev, $filter); + $node = node_load(array('nid' => $nid), $revision); + $node->revision = TRUE; + $node->changed = time(); + node_save($node); - drupal_set_message(t('Rolled back to revision %revision of %title', array('%revision' => "#$revision", '%title' => theme('placeholder', $node->title)))); - drupal_goto('node/'. $nid .'/revisions'); + drupal_set_message(t('Rolled back to the revision with the ID %revision of %title', array('%revision' => "$revision", '%title' => "$node->title"))); + drupal_goto("node/$nid/revisions"); } } @@ -1072,14 +1093,17 @@ function node_revision_rollback($nid, $r */ function node_revision_delete($nid, $revision) { if (user_access('administer nodes')) { - $node = node_load(array('nid' => $nid)); - - unset($node->revisions[$revision]); - - node_save($node, array('nid', 'revisions')); + $count_revisions = db_result(db_query('SELECT COUNT(vid) FROM {node_revisions} WHERE nid = %d', $nid)); + // Don't delete the last revision of the node or the current revision + if ($count_revisions > 1) { + db_query("DELETE FROM {node_revisions} WHERE nid = %d AND vid = %d", $nid, $revision); + drupal_set_message(t('Deleted revision with the ID %revision.', array('%revision' => "$revision"))); + } + else { + drupal_set_message(t('Deletion failed. You tried to delete the current revision.')); + } - drupal_set_message(t('Deleted revision %revision of %title', array('%revision' => "#$revision", '%title' => theme('placeholder', $node->title)))); - drupal_goto('node/'. $nid . (count($node->revisions) ? '/revisions' : '')); + drupal_goto("node/$nid/revisions"); } } @@ -1087,12 +1111,13 @@ function node_revision_delete($nid, $rev * Return a list of all the existing revision numbers. */ function node_revision_list($node) { - if (is_array($node->revisions)) { - return array_keys($node->revisions); - } - else { - return array(); + $revisions = array(); + $result = db_query('SELECT r.vid, r.title, r.log, r.uid, r.timestamp, u.name FROM {node_revisions} r INNER JOIN {users} u ON u.uid = r.uid WHERE r.nid = %d ORDER BY r.timestamp ASC', $node->nid); + while ($revision = db_fetch_object($result)) { + $revisions[] = $revision; } + + return $revisions; } /** @@ -1268,9 +1293,6 @@ function node_validate($node) { unset($node->created); } - // Create a new revision when required. - $node = node_revision_create($node); - // Do node-type-specific validation checks. node_invoke($node, 'validate'); node_invoke_nodeapi($node, 'validate'); @@ -1590,8 +1612,8 @@ function node_delete($edit) { if (node_access('delete', $node)) { if ($edit['confirm']) { - // Delete the specified 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'); @@ -1679,9 +1701,21 @@ function node_page() { case 'delete-revision': node_revision_delete(arg(1), arg(3)); break; + case 'revision': + if (is_numeric(arg(1)) && is_numeric(arg(3))) { + $node = node_load(array('nid' => arg(1)), arg(3)); + if ($node->nid) { + drupal_set_title(t('Revision of %title', array('%title' => $node->title))); + print theme('page', node_show($node, arg(2))); + } + else { + drupal_not_found(); + } + } + break; case 'view': if (is_numeric(arg(1))) { - $node = node_load(array('nid' => arg(1)), $_GET['revision']); + $node = node_load(array('nid' => arg(1))); if ($node->nid) { drupal_set_title(check_plain($node->title)); return node_show($node, arg(2)); @@ -1781,9 +1815,6 @@ function node_nodeapi(&$node, $op, $arg case 'settings': // $node contains the type name in this operation return form_checkboxes(t('Default options'), 'node_options_'. $node->type, variable_get('node_options_'. $node->type, array('status', 'promote')), array('status' => t('Published'), 'moderate' => t('In moderation queue'), 'promote' => t('Promoted to front page'), 'sticky' => t('Sticky at top of lists'), 'revision' => t('Create new revision')), t('Users with the administer nodes permission will be able to override these options.')); - - case 'fields': - return array('nid', 'uid', 'type', 'title', 'teaser', 'body', 'revisions', 'status', 'promote', 'moderate', 'sticky', 'created', 'changed', 'format'); } } Index: modules/page.module =================================================================== RCS file: /cvs/drupal/drupal/modules/page.module,v retrieving revision 1.132 diff -u -F^f -r1.132 page.module --- modules/page.module 8 Feb 2005 19:44:39 -0000 1.132 +++ modules/page.module 11 May 2005 03:31:41 -0000 @@ -74,6 +74,8 @@ function page_form(&$node) { $output .= form_textarea(t('Body'), 'body', $node->body, 60, 20, '', NULL, TRUE); $output .= filter_form('format', $node->format); + $output .= form_textarea(t('Log message'), 'log', $node->log, 60, 5, t('An explanation of the additions or updates being made to help other authors understand your motivations.')); + return $output; } Index: modules/upload.module =================================================================== RCS file: /cvs/drupal/drupal/modules/upload.module,v retrieving revision 1.34 diff -u -F^f -r1.34 upload.module --- modules/upload.module 7 May 2005 02:00:34 -0000 1.34 +++ modules/upload.module 11 May 2005 03:31:41 -0000 @@ -316,10 +316,10 @@ function upload_nodeapi(&$node, $op, $ar function upload_count_size($uid = 0) { if ($uid) { - $result = db_query("SELECT SUM(f.filesize) FROM {files} f INNER JOIN {node} n ON f.nid = n.nid WHERE uid = %d", $uid); + $result = db_query("SELECT SUM(f.filesize) FROM {files} f INNER JOIN {node_revisions} n ON f.vid = n.vid WHERE uid = %d", $uid); } else { - $result = db_query("SELECT SUM(f.filesize) FROM {files} f INNER JOIN {node} n ON f.nid = n.nid"); + $result = db_query("SELECT SUM(f.filesize) FROM {files} f INNER JOIN {node_revisions} n ON f.vid = n.vid"); } return db_result($result); @@ -334,18 +334,31 @@ function upload_save($node) { // Insert new files: if ($file = file_save_upload($file, $file->filename)) { $fid = db_next_id('{files}_fid'); - db_query("INSERT INTO {files} (fid, nid, filename, filepath, filemime, filesize, list) VALUES (%d, %d, '%s', '%s', '%s', %d, %d)", - $fid, $node->nid, $file->filename, $file->filepath, $file->filemime, $file->filesize, $node->list[$key]); + db_query("INSERT INTO {files} (fid, nid, vid, filename, filepath, filemime, filesize, list) VALUES (%d, %d, %d, '%s', '%s', '%s', %d, %d)", + $fid, $node->nid, $node->vid, $file->filename, $file->filepath, $file->filemime, $file->filesize, $node->list[$key]); } } else { // Remove or update existing files: if ($node->remove[$key]) { - file_delete($file->filepath); - db_query("DELETE FROM {files} WHERE fid = %d", $key); + db_query('DELETE FROM {files} WHERE fid = %d AND vid = %d', $key, $node->vid); + // We only delete a file if it isn't used anymore by any revision. + $count = db_result(db_query('SELECT COUNT(fid) FROM {files} WHERE fid = %d', $key)); + if (!($count > 0)) { + file_delete($file->filepath); + } } if ($file->list != $node->list[$key]) { - db_query("UPDATE {files} SET list = %d WHERE fid = %d", $node->list[$key], $key); + db_query('UPDATE {files} SET list = %d WHERE fid = %d AND vid = %d', $node->list[$key], $key, $node->vid); + } + } + } + if ($node->old_vid) { + foreach ((array)$node->remove as $key => $remove) { + if (!$remove) { + $file = db_fetch_object(db_query('SELECT * FROM {files} WHERE vid = %d AND fid = %d', $node->old_vid, $key)); + db_query("INSERT INTO {files} (fid, nid, vid, filename, filepath, filemime, filesize, list) VALUES (%d, %d, %d, '%s', '%s', '%s', %d, %d)", + $key, $node->nid, $node->vid, $file->filename, $file->filepath, $file->filemime, $file->filesize, $file->list); } } } @@ -389,8 +402,8 @@ function upload_form($node) { function upload_load($node) { $files = array(); - if ($node->nid) { - $result = db_query("SELECT * FROM {files} WHERE nid = %d", $node->nid); + if ($node->vid) { + $result = db_query("SELECT * FROM {files} WHERE vid = %d", $node->vid); while ($file = db_fetch_object($result)) { $files[$file->fid] = $file; }