Index: database/database.mysql =================================================================== RCS file: /cvs/drupal/drupal/database/database.mysql,v retrieving revision 1.180 diff -u -F^f -r1.180 database.mysql --- database/database.mysql 24 Apr 2005 13:49:58 -0000 1.180 +++ database/database.mysql 24 Apr 2005 21:15:03 -0000 @@ -135,11 +135,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; @@ -241,12 +242,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; -- @@ -288,9 +291,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; @@ -401,6 +406,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', @@ -410,16 +416,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), @@ -440,6 +443,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.117 diff -u -F^f -r1.117 database.pgsql --- database/database.pgsql 24 Apr 2005 13:49:58 -0000 1.117 +++ database/database.pgsql 24 Apr 2005 21:15:03 -0000 @@ -133,10 +133,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); @@ -240,12 +240,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) ); -- @@ -288,11 +288,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); -- @@ -404,6 +406,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', @@ -413,17 +416,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); @@ -443,6 +443,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.110 diff -u -F^f -r1.110 updates.inc --- database/updates.inc 24 Apr 2005 11:43:08 -0000 1.110 +++ database/updates.inc 24 Apr 2005 21:15:04 -0000 @@ -109,7 +109,9 @@ "2005-04-10" => "update_130", "2005-04-11" => "update_131", "2005-04-14" => "update_132", - "2005-04-24" => "update_133" + "2005-04-24" => "update_133", + "2005-04-25" => "update_134", + "2005-04-26" => "update_135" ); function update_32() { @@ -2425,6 +2427,158 @@ function update_133() { return $ret; } +function update_134() { + $ret = array(); + + if ($GLOBALS['db_type'] == 'mysql') { + $ret[] = update_sql("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 (vid), + KEY nid (nid), + KEY uid (uid) + )"); + $ret[] = update_sql("ALTER TABLE {node} ADD vid int(10) unsigned NOT NULL default '0'"); + $ret[] = update_sql("ALTER TABLE {files} ADD vid int(10) unsigned NOT NULL default '0'"); + $ret[] = update_sql("ALTER TABLE {book} ADD vid int(10) unsigned NOT NULL default '0'"); + $ret[] = update_sql("ALTER TABLE {forum} ADD vid int(10) unsigned NOT NULL default '0'"); + $ret[] = update_sql("ALTER TABLE {book} DROP PRIMARY KEY"); + $ret[] = update_sql("ALTER TABLE {forum} DROP PRIMARY KEY"); + $ret[] = update_sql("ALTER TABLE {files} DROP PRIMARY KEY"); + $ret[] = update_sql("ALTER TABLE {book} ADD KEY nid (nid)"); + $ret[] = update_sql("ALTER TABLE {forum} ADD KEY nid (nid)"); + $ret[] = update_sql("ALTER TABLE {files} ADD KEY fid (fid)"); + $ret[] = update_sql("ALTER TABLE {files} ADD KEY vid (vid)"); + } + else { + $ret[] = update_sql("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 '', + timestamp integer NOT NULL default '0', + format smallint NOT NULL default '0', + PRIMARY KEY (vid) + )"); + $ret[] = update_sql("ALTER TABLE {node} ADD vid integer NOT NULL default '0'"); + $ret[] = update_sql("ALTER TABLE {files} ADD vid integer NOT NULL default '0'"); + $ret[] = update_sql("ALTER TABLE {book} ADD vid integer NOT NULL default '0'"); + $ret[] = update_sql("ALTER TABLE {forum} ADD vid integer NOT NULL default '0'"); + $ret[] = update_sql("CREATE INDEX node_revisions_uid_idx ON node_revisions(uid)"); + $ret[] = update_sql("CREATE INDEX node_revisions_nid_idx ON node_revisions(nid)"); + $ret[] = update_sql("ALTER TABLE {book} DROP INDEX nid"); + $ret[] = update_sql("ALTER TABLE {forum} DROP INDEX nid"); + $ret[] = update_sql("ALTER TABLE {files} DROP INDEX fid"); +/* This needs to be ported to pgsql + $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("ALTER TABLE {book} ADD KEY nid (nid)"); + $ret[] = update_sql("ALTER TABLE {forum} ADD KEY nid (nid)"); +*/ + } + + return $ret; +} + +function update_135() { + $ret = array(); + + $vid = 0; + $result = db_query("SELECT nid, uid, type, title, body, teaser, changed, format, revisions FROM {node}"); + while ($row = db_fetch_array($result)) { + $nid = $row['nid']; + $vid++; + db_query("INSERT INTO {node_revisions} (nid, vid, uid, title, body, teaser, timestamp, format) VALUES (%d, %d, %d, '%s', '%s', '%s', %d, %d)", $nid, $vid, $row['uid'], $row['title'], $row['body'], $row['teaser'], $row['changed'], $row['format']); + switch ($row['type']) { + case 'forum': + db_query("UPDATE {forum} SET vid = %d WHERE nid = %d", $vid, $nid); + break; + case 'book': + db_query("UPDATE {book} SET vid = %d WHERE nid = %d", $vid, $nid); + break; + } + + db_query("UPDATE {node} SET vid = %d WHERE nid = %d", $vid, $nid); + + $revisions = unserialize($row['revisions']); + if (is_array($revisions) && count($revisions) > 0) { + 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++; + 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': + db_query("INSERT INTO {forum} (vid, nid, tid) VALUES (%d, %d, %d)", $vid, $nid, $revision['tid']); + break; + case 'book': + db_query("INSERT INTO {book} (vid, nid, parent, weight) VALUES (%d, %d, %d, %d, '%s')", $vid, $nid, $revision['parent'], $revision['weight']); + break; + } + } + } + } + + // 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} 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} ( + nid integer NOT NULL default '0', + revisions text NOT NULL default '', + PRIMARY KEY (nid) + )"); + } + else { // pgsql update + } + + // Move old revisions to old_revisions table. + $result = db_query("SELECT nid, revisions FROM {node} WHERE revisions != ''"); + while ($row = db_fetch_object($result)) { + db_query("INSERT INTO {old_revisions} (nid, revisions) VALUES (%d, '%s')", $row->nid, $row->revisions); + } + + $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; +} + function update_sql($sql) { $edit = $_POST["edit"]; $result = db_query($sql); Index: includes/database.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/database.inc,v retrieving revision 1.40 diff -u -F^f -r1.40 database.inc --- includes/database.inc 8 Apr 2005 14:24:03 -0000 1.40 +++ includes/database.inc 24 Apr 2005 21:15:04 -0000 @@ -136,8 +136,13 @@ function db_set_active($name = 'default' * A string containing an SQL query. * @param ... * A variable number of arguments which are substituted into the query using - * printf() syntax. Instead of a variable number of query arguments, you may - * also pass a single array containing the query arguments. + * printf() syntax. The query arguments can be enclosed in one array instead. + * For INSERT and UPDATE queries the arguments should be present in an + * array in which the keys name the database columns. For UPDATE queries + * additional parameters can be passed as single arguments after the array. + * Examples: + * db_query('INSERT INTO {node} %a', array('nid' => 42, 'title' => 'foo bar', ...)); + * db_query('UPDATE {node} SET %a WHERE nid = %d', array('uid' => 42, 'title' => 'foo bar'), $node->nid); * @return * A database query result resource, or FALSE if the query was not executed * correctly. @@ -146,8 +151,20 @@ function db_query($query) { $args = func_get_args(); $query = db_prefix_tables($query); if (count($args) > 1) { + if (strpos($query, '%a') !== FALSE) { + if (strpos($query, 'INSERT') !== FALSE) { + $keys = array_keys($args[1]); + $insert = '('. implode(', ', $keys) .') VALUES ('. implode(', ', array_pad(array(), count($keys), "'%s'")) .')'; + $query = str_replace('%a', $insert, $query); + } + else if (strpos($query, 'UPDATE') !== FALSE) { + $keys = array_keys($args[1]); + $update = implode(" = '%s', ", $keys) ." = '%s'"; + $query = str_replace('%a', $update, $query); + } + } if (is_array($args[1])) { - $args = array_merge(array($query), $args[1]); + $args = array_merge(array($query), $args[1], array_slice($args, 2)); } $args = array_map('db_escape_string', $args); $args[0] = $query; Index: includes/database.mysql.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/database.mysql.inc,v retrieving revision 1.28 diff -u -F^f -r1.28 database.mysql.inc --- includes/database.mysql.inc 14 Apr 2005 18:50:16 -0000 1.28 +++ includes/database.mysql.inc 24 Apr 2005 21:15:04 -0000 @@ -236,7 +236,50 @@ function db_escape_string($text) { } /** + * Begins a transaction/lock + * + * Use this when you need to update multiple tables in such a way that + * either all of the updates go through or none do at all. This is + * especially useful for the improved revisions system. + * + * In order to accomodate older versions of MySQL that don't support + * table types that have transactions, rollback is not used, and we + * must specify which tables are going to be + * + * So, your code will look something like this: + * db_begin_transaction(array('table1', 'table2')); + * // Check if conditions are okay for this update + * if ($conditions_ok) { + * // run queries + * } + * db_commit_transaction(); + * + * You code should ALWAYS call both db_begin_transaction() and + * db_commit_transaction() and ALWAYS call them in the same order + * + * @param $tables array of tables to lock + * @return a DB_Result object or a DB_Error + */ +function db_begin_transaction($tables) { + foreach ($tables as $num => $table) { + $tables[$num]= $table .' WRITE'; + } + return db_query('LOCK TABLES '. implode(', ', $tables)); +} + +/** + * Commits a transaction/lock + * + * See db_begin_transaction() for usage details + * + * @return a DB_Result object or a DB_Error + */ +function db_commit_transaction() { + return db_query('UNLOCK TABLES'); +} + +/** * @} End of "ingroup database". */ -?> \ No newline at end of file +?> Index: includes/database.pgsql.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/database.pgsql.inc,v retrieving revision 1.7 diff -u -F^f -r1.7 database.pgsql.inc --- includes/database.pgsql.inc 8 Apr 2005 11:24:46 -0000 1.7 +++ includes/database.pgsql.inc 24 Apr 2005 21:15:04 -0000 @@ -231,6 +231,45 @@ function db_escape_string($text) { } /** + * Begins a transaction/lock + * + * Use this when you need to update multiple tables in such a way that + * either all of the updates go through or none do at all. This is + * especially useful for the improved revisions system. + * + * In order to accomodate older versions of MySQL that don't support + * table types that have transactions, rollback is not used, and we + * must specify which tables are going to be + * + * So, your code will look something like this: + * db_begin_transaction(array('table1', 'table2')); + * // Check if conditions are okay for this update + * if ($conditions_ok) { + * // run queries + * } + * db_commit_transaction(); + * + * You code should ALWAYS call both db_begin_transaction() and + * db_commit_transaction() and ALWAYS call them in the same order + * + * @param $tables array of tables to lock + * @return a DB_Result object or a DB_Error + */ +function db_begin_transaction($tables) { + return db_query('START TRANSACTION'); +} + +/** + * Commits a transaction/lock + * + * See db_begin_transaction() for usage details + * + * @return a DB_Result object or a DB_Error + */ +function db_commit_transaction() { + return db_query('COMMIT'); +} +/** * @} End of "ingroup database". */ Index: modules/blogapi.module =================================================================== RCS file: /cvs/drupal/drupal/modules/blogapi.module,v retrieving revision 1.41 diff -u -F^f -r1.41 blogapi.module --- modules/blogapi.module 23 Apr 2005 06:38:27 -0000 1.41 +++ modules/blogapi.module 24 Apr 2005 21:15:04 -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.292 diff -u -F^f -r1.292 book.module --- modules/book.module 24 Apr 2005 16:34:33 -0000 1.292 +++ modules/book.module 24 Apr 2005 21:15:04 -0000 @@ -111,7 +111,7 @@ function book_menu($may_cache) { // We don't want to cache these menu items because they could change whenever // a book page or outline node is edited. if (arg(0) == 'admin' && arg(1) == 'node' && arg(2) == 'book') { - $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 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 ORDER BY b.weight, n.title')); while ($book = db_fetch_object($result)) { $items[] = array('path' => 'admin/node/book/'. $book->nid, 'title' => t('"%title" book', array('%title' => $book->title))); } @@ -136,7 +136,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); @@ -163,7 +163,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 @@ -185,14 +185,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); + } } /** @@ -229,6 +234,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')) { @@ -256,13 +262,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('Added the post 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('Updated the book outline.')); drupal_goto("node/$node->nid"); break; @@ -274,10 +282,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')); @@ -325,7 +334,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); @@ -334,7 +343,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); @@ -352,7 +361,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); @@ -361,7 +370,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; } } @@ -371,7 +380,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; } @@ -380,7 +389,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; } @@ -415,10 +424,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 .= '