? files ? mw.patch ? tmp.patch ? sites/all/modules ? sites/all/themes ? sites/default/mw.patch ? sites/default/tmp.patch Index: includes/common.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/common.inc,v retrieving revision 1.681 diff -u -F^f -r1.681 common.inc --- includes/common.inc 29 Aug 2007 18:38:55 -0000 1.681 +++ includes/common.inc 30 Aug 2007 16:13:12 -0000 @@ -2973,6 +2973,127 @@ function _drupal_initialize_schema($modu } } +// Based on the schema field type, return the db_query() substitution to use. +function drupal_schema_get_placeholder($type) { + switch ($type) { + case 'serial': + return '%s'; + case 'int': + return '%d'; + case 'float': + case 'numeric': + return '%f'; + case 'blob': + return '%b'; + default: + return "'%s'"; + } +} + +/** + * Retrieve a comma delimited list of fields from a table schema. The list is suitable for use in a SQL query. + * + * @param $table + * The name of the table from which to retrieve fields. + * @param + * An optional prefix to to all fields. + * + * @return A comma delimited list of fields. + **/ +function drupal_schema_fields_sql($table, $prefix = NULL) { + $schema = drupal_get_schema($table); + $fields = array_keys($schema['fields']); + if ($prefix) { + foreach ($fields as $field) { + $columns[] = "$prefix.$field"; + } + } + else { + $columns = $fields; + } + return implode(', ', $columns); +} + +/** + * Save a record to the database based upon the schema. Default values are + * filled in for missing items, and 'serial' (auto increment) types are + * filled in with IDs. + * + * @param $table + * The name of the table; this must exist in schema API. + * @param $object + * The object to write. This is a reference, as defaults according to + * the schema may be filled in on the object, as well as ID on the serial + * type(s). + * @param $update + * Set this to the primary key's field name if this is an update, FALSE if this is an insert. It is the + * caller's responsibility to know if a record for this object already + * exists in the database. + */ +function drupal_write_record($table, &$object, $update = NULL) { + $schema = drupal_get_schema($table); + if (empty($schema)) { + return FALSE; + } + + $fields = $defs = $values = $serials = array(); + + // Go through our schema, build correlations, and when inserting, fill in defaults for + // fields that are not set. + foreach ($schema['fields'] as $field => $info) { + // Special case -- skip serial types if we are updating. + if ($info['type'] == 'serial' && $update) { + continue; + } + + if (!isset($object->$field) && !$update) { + $object->$field = isset($info['default']) ? $info['default'] : ''; + } + + // Build arrays for the fields, placeholders, and values in our query. + if (isset($object->$field)) { + $fields[] = $field; + $placeholders[] = drupal_schema_get_placeholder($info['type']); + if ($info['type'] == 'serial') { + $object->$field = 'NULL'; + $serials[] = $field; + } + + if (empty($info['serialize'])) { + $values[] = $object->$field; + } + else { + $values[] = serialize($object->$field); + } + } + } + + // Build the SQL. + $query = ''; + if (!$update) { + $query = "INSERT INTO {$table} (" . implode(', ', $fields) . ') VALUES (' . implode(', ', $placeholders) . ')'; + } + else { + $query = ''; + foreach ($fields as $id => $field) { + if ($query) { + $query .= ', '; + } + $query .= $field . ' = ' . $placeholders[$id]; + } + $query = "UPDATE {$table} SET " . $query . " WHERE $update = " . $object->$update; + } + db_query($query, $values); + + if ($serials) { + // Get last insert ids and fill them in. + foreach ($serials as $field) { + $object->$field = db_last_insert_id($table, $field); + } + } + return TRUE; +} + /** * @} End of "ingroup schemaapi". */ Index: modules/node/node.module =================================================================== RCS file: /cvs/drupal/drupal/modules/node/node.module,v retrieving revision 1.875 diff -u -F^f -r1.875 node.module --- modules/node/node.module 26 Aug 2007 14:15:51 -0000 1.875 +++ modules/node/node.module 30 Aug 2007 16:13:12 -0000 @@ -659,14 +659,19 @@ function node_load($param = array(), $re return FALSE; } + // Retrieve a field list based on the site's schema. + $fields = drupal_schema_fields_sql('node', 'n'); + $fields .= ', '. drupal_schema_fields_sql('node_revisions', 'r'); + $fields .= ', u.name, u.data'; + // 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.language, n.created, n.changed, n.comment, n.promote, n.sticky, n.tnid, n.translate, 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 '. $fields. ' 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)); } else { - $node = db_fetch_object(db_query('SELECT n.nid, n.vid, n.type, n.status, n.language, n.created, n.changed, n.comment, n.promote, n.sticky, n.tnid, n.translate, 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 '. $fields. ' 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)); } if ($node && $node->nid) { @@ -769,7 +774,7 @@ function node_submit($node) { $node->created = $node->date ? strtotime($node->date) : NULL; } - + $node->validated = TRUE; return $node; @@ -790,17 +795,12 @@ function node_save(&$node) { // Insert a new node. $node->is_new = TRUE; } + elseif (!empty($node->revision)) { + $node->old_vid = $node->vid; + } else { - // We need to ensure that all node fields are filled. - $node_current = node_load($node->nid); - foreach ($node as $field => $data) { - $node_current->$field = $data; - } - $node = $node_current; - - if (!empty($node->revision)) { - $node->old_vid = $node->vid; - } + // When updating a node, avoid overwriting an existing log entry when we don't save a new revision. + unset($node->log); } // Set some required fields: @@ -809,66 +809,23 @@ function node_save(&$node) { } // 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, - 'title' => $node->title, 'body' => isset($node->body) ? $node->body : '', - 'teaser' => $node->teaser, 'timestamp' => $node->changed, - 'uid' => $user->uid, 'format' => isset($node->format) ? $node->format : FILTER_FORMAT_DEFAULT); - $revisions_table_types = array('nid' => '%d', - 'title' => "'%s'", 'body' => "'%s'", - 'teaser' => "'%s'", 'timestamp' => '%d', - 'uid' => '%d', 'format' => '%d'); - if (!empty($node->log) || $node->is_new || (isset($node->revision) && $node->revision)) { - // 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'"; - } - $node_table_values = array( - 'title' => $node->title, 'type' => $node->type, 'uid' => $node->uid, - 'status' => $node->status, 'language' => $node->language, 'created' => $node->created, - 'changed' => $node->changed, 'comment' => $node->comment, - 'promote' => $node->promote, 'sticky' => $node->sticky); - $node_table_types = array( - 'title' => "'%s'", 'type' => "'%s'", 'uid' => '%d', - 'status' => '%d', 'language' => "'%s'",'created' => '%d', - 'changed' => '%d', 'comment' => '%d', - 'promote' => '%d', 'sticky' => '%d'); + $node->timestamp = time(); + $node->format = isset($node->format) ? $node->format : FILTER_FORMAT_DEFAULT; + $update_node = TRUE; - //Generate the node table query and the - //the node_revisions table query + if ($node->is_new) { - $node_query = 'INSERT INTO {node} ('. implode(', ', array_keys($node_table_types)) .') VALUES ('. implode(', ', $node_table_types) .')'; - db_query($node_query, $node_table_values); - $node->nid = db_last_insert_id('node', 'nid'); - $revisions_query = 'INSERT INTO {node_revisions} ('. implode(', ', array_keys($revisions_table_types)) .') VALUES ('. implode(', ', $revisions_table_types) .')'; - db_query($revisions_query, $revisions_table_values); - $node->vid = db_last_insert_id('node_revisions', 'vid'); + drupal_write_record('node', $node, FALSE); + drupal_write_record('node_revisions', $node, FALSE); $op = 'insert'; } 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'; - db_query($node_query, $node_table_values); + drupal_write_record('node', $node, 'nid'); if (!empty($node->revision)) { - $revisions_query = 'INSERT INTO {node_revisions} ('. implode(', ', array_keys($revisions_table_types)) .') VALUES ('. implode(', ', $revisions_table_types) .')'; - db_query($revisions_query, $revisions_table_values); - $node->vid = db_last_insert_id('node_revisions', 'vid'); + drupal_write_record('node_revisions', $node, FALSE); } 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'; - db_query($revisions_query, $revisions_table_values); + drupal_write_record('node_revisions', $node, 'vid'); $update_node = FALSE; } $op = 'update';