Index: modules/comment/comment.install =================================================================== RCS file: /cvs/drupal/drupal/modules/comment/comment.install,v retrieving revision 1.42 diff -u -r1.42 comment.install --- modules/comment/comment.install 30 Jul 2009 19:27:11 -0000 1.42 +++ modules/comment/comment.install 31 Jul 2009 00:52:37 -0000 @@ -296,3 +296,15 @@ return $schema; } + +/** + * Create comment Field API bundles. + */ +function comment_update_7005() { + $ret = array(); + + foreach (node_type_get_types() as $info) { + field_attach_create_bundle('comment_node_' . $info->type); + } + return $ret; +} \ No newline at end of file Index: modules/comment/comment.admin.inc =================================================================== RCS file: /cvs/drupal/drupal/modules/comment/comment.admin.inc,v retrieving revision 1.29 diff -u -r1.29 comment.admin.inc --- modules/comment/comment.admin.inc 30 Jul 2009 19:24:20 -0000 1.29 +++ modules/comment/comment.admin.inc 31 Jul 2009 00:52:37 -0000 @@ -196,14 +196,11 @@ */ function comment_multiple_delete_confirm_submit($form, &$form_state) { if ($form_state['values']['confirm']) { - foreach ($form_state['values']['comments'] as $cid => $value) { - $comment = comment_load($cid); - // Perform the actual comment deletion. - _comment_delete_thread($comment); - _comment_update_node_statistics($comment->nid); - } + comment_delete_multiple(array_keys($form_state['values']['comments'])); cache_clear_all(); - drupal_set_message(t('The comments have been deleted.')); + $count = count($form_state['values']['comments']); + watchdog('content', 'Deleted @count comments.', array('@count' => $count)); + drupal_set_message(t('Deleted @count comments.', array('@count' => $count))); } $form_state['redirect'] = 'admin/content/comment'; } @@ -214,7 +211,7 @@ * @param $cid * The comment to be deleted. */ -function comment_delete($cid = NULL) { +function comment_delete_page($cid = NULL) { $comment = db_query('SELECT c.*, u.name AS registered_name, u.uid FROM {comment} c INNER JOIN {users} u ON u.uid = c.uid WHERE c.cid = :cid', array(':cid' => $cid))->fetch(); $comment->name = $comment->uid ? $comment->registered_name : $comment->name; $output = ''; @@ -252,41 +249,13 @@ * Process comment_confirm_delete form submissions. */ function comment_confirm_delete_submit($form, &$form_state) { - drupal_set_message(t('The comment and all its replies have been deleted.')); $comment = $form['#comment']; // Delete the comment and its replies. - _comment_delete_thread($comment); - _comment_update_node_statistics($comment->nid); + comment_delete($comment->cid); + drupal_set_message(t('The comment and all its replies have been deleted.')); + watchdog('content', t('Deleted comment @cid and its replies.', array('@cid' => $comment->cid))); // Clear the cache so an anonymous user sees that his comment was deleted. cache_clear_all(); $form_state['redirect'] = "node/$comment->nid"; } - -/** - * Perform the actual deletion of a comment and all its replies. - * - * @param $comment - * An associative array describing the comment to be deleted. - */ -function _comment_delete_thread($comment) { - if (!is_object($comment) || !is_numeric($comment->cid)) { - watchdog('content', 'Cannot delete non-existent comment.', array(), WATCHDOG_WARNING); - - return; - } - - // Delete the comment. - db_delete('comment') - ->condition('cid', $comment->cid) - ->execute(); - watchdog('content', 'Comment: deleted %subject.', array('%subject' => $comment->subject)); - module_invoke_all('comment_delete', $comment); - - // Delete the comment's replies. - $result = db_query('SELECT c.*, u.name AS registered_name, u.uid FROM {comment} c INNER JOIN {users} u ON u.uid = c.uid WHERE pid = :cid', array(':cid' => $comment->cid)); - foreach ($result as $comment) { - $comment->name = $comment->uid ? $comment->registered_name : $comment->name; - _comment_delete_thread($comment); - } -} Index: modules/comment/comment.test =================================================================== RCS file: /cvs/drupal/drupal/modules/comment/comment.test,v retrieving revision 1.39 diff -u -r1.39 comment.test --- modules/comment/comment.test 30 Jul 2009 19:24:20 -0000 1.39 +++ modules/comment/comment.test 31 Jul 2009 00:52:38 -0000 @@ -207,7 +207,7 @@ if ($operation == 'delete') { $this->drupalPost(NULL, array(), t('Delete comments')); - $this->assertText(t('The comments have been deleted.'), t('Operation "' . $operation . '" was performed on comment.')); + $this->assertRaw(t('Deleted @count comments.', array('@count' => 1)), t('Operation "' . $operation . '" was performed on comment.')); } else { $this->assertText(t('The update has been performed.'), t('Operation "' . $operation . '" was performed on comment.')); Index: modules/comment/comment.pages.inc =================================================================== RCS file: /cvs/drupal/drupal/modules/comment/comment.pages.inc,v retrieving revision 1.22 diff -u -r1.22 comment.pages.inc --- modules/comment/comment.pages.inc 28 Jul 2009 10:09:25 -0000 1.22 +++ modules/comment/comment.pages.inc 31 Jul 2009 00:52:38 -0000 @@ -73,6 +73,8 @@ } // Display the parent comment $comment = drupal_unpack($comment); + $comment->node_type = 'comment_node_' . $node->type; + field_attach_load('comment', array($comment->cid => $comment)); $comment->name = $comment->uid ? $comment->registered_name : $comment->name; $build['comment_parent'] = comment_build($comment); } Index: modules/comment/comment.module =================================================================== RCS file: /cvs/drupal/drupal/modules/comment/comment.module,v retrieving revision 1.744 diff -u -r1.744 comment.module --- modules/comment/comment.module 30 Jul 2009 19:24:20 -0000 1.744 +++ modules/comment/comment.module 31 Jul 2009 00:52:38 -0000 @@ -148,7 +148,7 @@ ); $items['comment/delete'] = array( 'title' => 'Delete comment', - 'page callback' => 'comment_delete', + 'page callback' => 'comment_delete_page', 'access arguments' => array('administer comments'), 'type' => MENU_CALLBACK, ); @@ -187,21 +187,58 @@ } /** - * Implement hook_node_type(). + * Implement hook_fieldable_info(). */ -function comment_node_type($op, $info) { - $settings = array( - 'comment', - 'comment_default_mode', - 'comment_default_per_page', - 'comment_anonymous', - 'comment_subject_field', - 'comment_preview', - 'comment_form_location', +function comment_fieldable_info() { + $return = array( + 'comment' => array( + 'label' => t('Comment'), + 'object keys' => array( + 'id' => 'cid', + 'bundle' => 'node_type', + ), + 'bundle keys' => array( + 'bundle' => 'type', + ), + 'bundles' => array(), + ), ); + foreach (node_type_get_names() as $type => $name) { + $return['comment']['bundles']['comment_node_' . $type] = array( + 'label' => $name, + ); + } + return $return; +} + +/** + * Implement hook_node_type(). + */ +function comment_node_type($op, $info) { switch ($op) { + case 'insert': + field_attach_create_bundle('comment_node_' . $info->type); + break; + + case 'update': + if (!empty($info->old_type) && $info->type != $info->old_type) { + field_attach_rename_bundle('comment_node_' . $info->old_type, 'comment_node_' . $info->type); + } + break; + case 'delete': + field_attach_delete_bundle('comment_node_' . $info->type); + + $settings = array( + 'comment', + 'comment_default_mode', + 'comment_default_per_page', + 'comment_anonymous', + 'comment_subject_field', + 'comment_preview', + 'comment_form_location', + ); foreach ($settings as $setting) { variable_del($setting . '_' . $info->type); } @@ -782,6 +819,8 @@ '#markup' => check_markup($comment->comment, $comment->format, '', FALSE), ); + $comment->content += field_attach_view('comment', $comment, $build_mode); + if (empty($comment->in_preview)) { $comment->content['links']['comment'] = array( '#theme' => 'links', @@ -1009,9 +1048,8 @@ * Implement hook_node_delete(). */ function comment_node_delete($node) { - db_delete('comment') - ->condition('nid', $node->nid) - ->execute(); + $cids = db_query('SELECT cid FROM {comment} WHERE nid = :nid', array(':nid' => $node->nid))->fetchCol(); + comment_delete_multiple($cids); db_delete('node_comment_statistics') ->condition('nid', $node->nid) ->execute(); @@ -1082,13 +1120,8 @@ case 'user_cancel_delete': module_load_include('inc', 'comment', 'comment.admin'); - $result = db_query('SELECT c.cid FROM {comment} c WHERE uid = :uid', array(':uid' => $account->uid))->fetchCol(); - foreach ($result as $cid) { - $comment = comment_load($cid); - // Delete the comment and its replies. - _comment_delete_thread($comment); - _comment_update_node_statistics($comment->nid); - } + $cids = db_query('SELECT c.cid FROM {comment} c WHERE uid = :uid', array(':uid' => $account->uid))->fetchCol(); + comment_delete_multiple($cids); break; } } @@ -1136,6 +1169,14 @@ $comment->$key = $default; } } + // Make sure we have a bundle name. + if (!isset($comment->node_type)) { + $node = node_load($comment->nid); + $comment->node_type = 'comment_node_' . $node->type; + } + + field_attach_presave('comment', $comment); + if ($comment->cid) { // Update the comment in the database. db_update('comment') @@ -1152,6 +1193,7 @@ )) ->condition('cid', $comment->cid) ->execute(); + field_attach_update('comment', $comment); // Allow modules to respond to the updating of a comment. module_invoke_all('comment_update', $comment); // Add an entry to the watchdog log. @@ -1229,6 +1271,8 @@ // saved node to be propagated to the slave. db_ignore_slave(); + field_attach_insert('comment', $comment); + // Tell the other modules a new comment has been submitted. module_invoke_all('comment_insert', $comment); // Add an entry to the watchdog log. @@ -1244,6 +1288,42 @@ } /** + * Delete a comment and all its replies. + * + * @param $cid + * The comment to delete. + */ +function comment_delete($cid) { + comment_delete_multiple(array($cid)); +} + +/** + * Delete comments and all their replies. + * + * @param $cids + * The comment to delete. + */ +function comment_delete_multiple($cids) { + $comments = comment_load_multiple($cids); + if ($comments) { + + // Delete the comments. + db_delete('comment') + ->condition('cid', array_keys($comments), 'IN') + ->execute(); + foreach ($comments as $comment) { + field_attach_delete('comment', $comment); + module_invoke_all('comment_delete', $comment); + + // Delete the comment's replies. + $child_cids = db_query('SELECT cid FROM {comment} WHERE pid = :cid', array(':cid' => $comment->cid))->fetchCol(); + comment_delete_multiple($child_cids); + _comment_update_node_statistics($comment->nid); + } + } +} + +/** * Implement hook_link(). */ function comment_link($type, $object, $build_mode) { @@ -1366,7 +1446,9 @@ if ($cids || $conditions) { $query = db_select('comment', 'c'); $query->innerJoin('users', 'u', 'c.uid = u.uid'); + $query->innerJoin('node', 'n', 'c.nid = n.nid'); $query->addField('u', 'name', 'registered_name'); + $query->addField('n', 'type', 'node_type'); $query ->fields('c', array('cid', 'nid', 'pid', 'comment', 'subject', 'format', 'timestamp', 'name', 'mail', 'homepage', 'status', 'thread')) ->fields('u', array( 'uid', 'signature', 'picture', 'data', 'status')); @@ -1390,11 +1472,14 @@ $comment = drupal_unpack($comment); $comment->name = $comment->uid ? $comment->registered_name : $comment->name; $comment->new = node_mark($comment->nid, $comment->timestamp); + $comment->node_type = 'comment_node_' . $comment->node_type; $comments[$key] = $comment; } - // Invoke hook_comment_load(). if (!empty($comments)) { + // Attach fields. + field_attach_load('comment', $comments); + // Invoke hook_comment_load(). module_invoke_all('comment_load', $comments); } return $comments; @@ -1752,6 +1837,10 @@ '#type' => 'value', '#value' => !empty($edit['uid']) ? $edit['uid'] : 0, ); + $form['node_type'] = array( + '#type' => 'value', + '#value' => 'comment_node_' . $node->type, + ); // Only show the save button if comment previews are optional or if we are // already previewing the submission. However, if there are form errors, @@ -1776,6 +1865,11 @@ $form['#action'] = url('comment/reply/' . $edit['nid']); } + $comment = (object) $edit; + $comment->node_type = 'comment_node_' . $node->type; + $form['#builder_function'] = 'comment_form_submit_build_comment'; + field_attach_form('comment', $comment, $form, $form_state); + return $form; } @@ -1829,12 +1923,11 @@ } if ($comment->pid) { - $parent_comment = db_query('SELECT c.*, u.uid, u.name AS registered_name, u.signature, u.picture, u.data FROM {comment} c INNER JOIN {users} u ON c.uid = u.uid WHERE c.cid = :cid AND c.status = :status', array( - ':cid' => $comment->pid, - ':status' => COMMENT_PUBLISHED, - ))->fetchObject(); - - $build = comment_build($parent_comment); + $build = array(); + if ($comments = comment_load_multiple(array($comment->pid), array('status' => COMMENT_PUBLISHED))) { + $parent_comment = $comments[$comment->pid]; + $build = comment_build($parent_comment); + } } else { $build = node_build($node); @@ -1851,6 +1944,9 @@ */ function comment_form_validate($form, &$form_state) { global $user; + $comment = (object) $form_state['values']; + field_attach_form_validate('comment', $comment, $form, $form_state); + if ($user->uid === 0) { foreach (array('name', 'homepage', 'mail') as $field) { // Set cookie for 365 days. @@ -1949,6 +2045,8 @@ function comment_form_submit_build_comment($form, &$form_state) { $comment = comment_submit($form_state['values']); + field_attach_submit('comment', $comment, $form, $form_state); + $form_state['comment'] = (array)$comment; $form_state['rebuild'] = TRUE; return $comment; Index: CHANGELOG.txt =================================================================== RCS file: /cvs/drupal/drupal/CHANGELOG.txt,v retrieving revision 1.322 diff -u -r1.322 CHANGELOG.txt --- CHANGELOG.txt 30 Jul 2009 08:28:47 -0000 1.322 +++ CHANGELOG.txt 31 Jul 2009 00:52:36 -0000 @@ -59,7 +59,7 @@ - Aggregator: * Introduced architecture that allows pluggable parsers and processors for syndicating RSS and Atom feeds. - * Added options to suspend updating specific feeds and never discard feeds + * Added options to suspend updating specific feeds and never discard feeds items. - Testing: * Added test framework and tests. @@ -106,7 +106,7 @@ uploading a site logo--that don't require the overhead of databases and hooks, the current unmanaged copy, move and delete operations have been preserved but renamed to file_unmanaged_*(). - * Rewrote file handling to use PHP stream wrappers to enable support for + * Rewrote file handling to use PHP stream wrappers to enable support for both public and private files and to support pluggable storage mechanisms and access to remote resources (e.g. S3 storage or Flickr photos). - Image handling: @@ -120,7 +120,8 @@ * Modules can declare RDF namespaces which are serialized in the tag for RDFa support. - Field API: - * Custom data fields may be attached to nodes and users, and taxonomy terms. + * Custom data fields may be attached to nodes, users, comments and taxonomy + terms. * Node bodies and teasers are now Field API fields instead of being a hard-coded property of node objects. * In addition, any other object type may register with Field API @@ -132,12 +133,12 @@ via a command line script. - Page organization * Made the help text area a full featured region with blocks. - * Site mission is replaced with the highlighted content block region and + * Site mission is replaced with the highlighted content block region and separate RSS feed description settings. - * The footer message setting was removed in favor of custom blocks. + * The footer message setting was removed in favor of custom blocks. * Made the main page content a block which can be moved and ordered with other blocks in the same region. - * Blocks can now return structured arrays for later rendering just + * Blocks can now return structured arrays for later rendering just like page callbacks. - Translation system * The translation system now supports message context (msgctxt).