diff --git a/CHANGELOG.txt b/CHANGELOG.txt index d1add72de5cc1396d778250295a5de52286c4514..71ac270080f7daf2e4232826217d1acb4f54b77d 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -59,7 +59,7 @@ Drupal 7.0, xxxx-xx-xx (development version) - 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. @@ -95,7 +95,7 @@ Drupal 7.0, xxxx-xx-xx (development version) on as contributed themes (http://drupal.org/project/bluemarine, http://drupal.org/project/chameleon and http://drupal.org/project/pushbutton). * Added Stark theme to make analyzing Drupal's default HTML and CSS easier. - * Added Slate theme as the default administration interface theme. + * Added Seven theme as the default administration interface theme. - File handling: * Files are now first class Drupal objects with file_load(), file_save(), and file_validate() functions and corresponding hooks. @@ -106,7 +106,7 @@ Drupal 7.0, xxxx-xx-xx (development version) 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 @@ Drupal 7.0, xxxx-xx-xx (development version) * Modules can declare RDF namespaces which are serialized in the <html> 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 @@ Drupal 7.0, xxxx-xx-xx (development version) 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). diff --git a/modules/block/block.test b/modules/block/block.test index d32f7f2aa6a97a098a0f9756c46869b6fde33a69..ca2d771e4a81d66253484234e3b513655965fd56 100644 --- a/modules/block/block.test +++ b/modules/block/block.test @@ -244,12 +244,12 @@ class NewDefaultThemeBlocks extends DrupalWebTestCase { $this->drupalLogin($admin_user); // Ensure no other theme's blocks are in the block table yet. - $count = db_query_range("SELECT 1 FROM {block} WHERE theme != 'garland'", 0, 1)->fetchField(); - $this->assertFalse($count, t('Only Garland has blocks.')); + $count = db_query_range("SELECT 1 FROM {block} WHERE theme NOT IN ('garland', 'seven')", 0, 1)->fetchField(); + $this->assertFalse($count, t('Only Garland and Seven have blocks.')); // Populate list of all blocks for matching against new theme. $blocks = array(); - $result = db_query('SELECT * FROM {block}'); + $result = db_query("SELECT * FROM {block} WHERE theme = 'garland'"); foreach ($result as $block) { // $block->theme and $block->bid will not match, so remove them. unset($block->theme, $block->bid); diff --git a/modules/blog/blog.test b/modules/blog/blog.test index 9bb73cc2bffa4daa19615d0fbaaa23ed03976d52..70a43ea3f2a249228515024b8922ee441e823121 100644 --- a/modules/blog/blog.test +++ b/modules/blog/blog.test @@ -128,7 +128,6 @@ class BlogTestCase extends DrupalWebTestCase { if ($response2 == 200) { $this->assertTitle(t('Blog | Drupal'), t('Blog help node was displayed')); $this->assertText(t('Blog'), t('Blog help node was displayed')); - $this->assertText(t('Home ' . $crumb . ' Administer ' . $crumb . ' Help'), t('Breadcrumbs were displayed')); } // Verify the blog block was displayed. @@ -147,7 +146,6 @@ class BlogTestCase extends DrupalWebTestCase { $this->assertResponse($response); if ($response == 200) { $this->assertTitle('Edit Blog entry ' . $node->title . ' | Drupal', t('Blog edit node was displayed')); - $this->assertText(t('Home ' . $crumb . ' @title', array('@title' => $node->title)), t('Breadcrumbs were displayed')); } if ($response == 200) { diff --git a/modules/comment/comment.admin.inc b/modules/comment/comment.admin.inc index 3ea0b5d7c7464c03d95d288df1185c2b9bbdae81..dbb8f16c08d104e86f2706d938f9e179bdd6f862 100644 --- a/modules/comment/comment.admin.inc +++ b/modules/comment/comment.admin.inc @@ -196,14 +196,11 @@ function comment_multiple_delete_confirm(&$form_state) { */ 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 @@ function comment_multiple_delete_confirm_submit($form, &$form_state) { * @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 @@ function comment_confirm_delete(&$form_state, $comment) { * 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); - } -} diff --git a/modules/comment/comment.install b/modules/comment/comment.install index 780753c750e0fb46f1897bdf08ec3de65ff1152e..61ca2d14aa15f6599220c34084cd4044c99c5c5c 100644 --- a/modules/comment/comment.install +++ b/modules/comment/comment.install @@ -296,3 +296,15 @@ function comment_schema() { 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 diff --git a/modules/comment/comment.module b/modules/comment/comment.module index f7b4e923497050962addf342d9e5490f17189fda..f09a329801c68af100fa0e54606d36336f1bf0fe 100644 --- a/modules/comment/comment.module +++ b/modules/comment/comment.module @@ -148,7 +148,7 @@ function comment_menu() { ); $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 @@ function comment_menu() { } /** - * 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 @@ function comment_build_content($comment, $build_mode = 'full') { '#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 @@ function comment_node_insert($node) { * 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 @@ function comment_user_cancel($edit, $account, $method) { 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 @@ function comment_save($comment) { $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 @@ function comment_save($comment) { )) ->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 @@ function comment_save($comment) { // 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. @@ -1243,6 +1287,42 @@ function comment_save($comment) { } } +/** + * 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(). */ @@ -1366,7 +1446,9 @@ function comment_load_multiple($cids = array(), $conditions = array()) { 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 @@ function comment_load_multiple($cids = array(), $conditions = array()) { $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 @@ function comment_form(&$form_state, $edit = array()) { '#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 @@ function comment_form(&$form_state, $edit = array()) { $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 @@ function comment_preview($comment) { } 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_preview($comment) { */ 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_submit($comment) { 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; diff --git a/modules/comment/comment.pages.inc b/modules/comment/comment.pages.inc index dc18f803516f39a96a60921009cb31068522e9d4..e575460cf253e06742821c13e2a9d96a96e12820 100644 --- a/modules/comment/comment.pages.inc +++ b/modules/comment/comment.pages.inc @@ -73,6 +73,8 @@ function comment_reply($node, $pid = NULL) { } // 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); } diff --git a/modules/comment/comment.test b/modules/comment/comment.test index baadc2f0321fddb1d98e29b42964b2146073a812..d5de02a28f6e14329d0cc5df478b54f66356a533 100644 --- a/modules/comment/comment.test +++ b/modules/comment/comment.test @@ -207,7 +207,7 @@ class CommentHelperCase extends DrupalWebTestCase { 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.')); diff --git a/modules/forum/forum.test b/modules/forum/forum.test index 142f076ebef97da5ecab3dbd645f1f3143d2b3e9..9abfc5f23a4043f48349853336426079b38e58d4 100644 --- a/modules/forum/forum.test +++ b/modules/forum/forum.test @@ -288,7 +288,6 @@ class ForumTestCase extends DrupalWebTestCase { if ($response2 == 200) { $this->assertTitle(t('Forum | Drupal'), t('Forum help title was displayed')); $this->assertText(t('Forum'), t('Forum help node was displayed')); - $this->assertText(t('Home ' . $crumb . ' Administer ' . $crumb . ' Help'), t('Breadcrumbs were displayed')); } // Verify the forum blocks were displayed. @@ -316,7 +315,6 @@ class ForumTestCase extends DrupalWebTestCase { $this->assertResponse($response); if ($response == 200) { $this->assertTitle('Edit Forum topic ' . $node->title . ' | Drupal', t('Forum edit node was displayed')); - $this->assertText(t('Home ' . $crumb . ' @title', array('@title' => $node->title)), t('Breadcrumbs were displayed')); } if ($response == 200) { diff --git a/modules/help/help.test b/modules/help/help.test index de0ddfa6c483a73d7786edd7a442929cfd675799..7709011857f6a97a4a70d3dd6d156c81fcd66726 100644 --- a/modules/help/help.test +++ b/modules/help/help.test @@ -64,8 +64,6 @@ class HelpTestCase extends DrupalWebTestCase { // continue; // } $this->assertTitle($name . ' | Drupal', t('[' . $module . '] Title was displayed')); - $this->assertRaw('<h2>' . t($name) . '</h2>', t('[' . $module . '] Heading was displayed')); - $this->assertText(t('Home ' . $crumb . ' Administer ' . $crumb . ' Help'), t('[' . $module . '] Breadcrumbs were displayed')); } } } diff --git a/profiles/default/default.profile b/profiles/default/default.profile index 62e0cf79ba262391c673f5be5becaeb7ef6369cc..499121c009a628f04b89d697e1e558406492a0ec 100644 --- a/profiles/default/default.profile +++ b/profiles/default/default.profile @@ -84,6 +84,36 @@ function default_profile_site_setup(&$install_state) { 'pages' => '', 'cache' => -1, ), + array( + 'module' => 'system', + 'delta' => 'main', + 'theme' => 'seven', + 'status' => 1, + 'weight' => 0, + 'region' => 'content', + 'pages' => '', + 'cache' => -1, + ), + array( + 'module' => 'system', + 'delta' => 'help', + 'theme' => 'seven', + 'status' => 1, + 'weight' => 0, + 'region' => 'help', + 'pages' => '', + 'cache' => -1, + ), + array( + 'module' => 'user', + 'delta' => 'login', + 'theme' => 'seven', + 'status' => 1, + 'weight' => 10, + 'region' => 'content', + 'pages' => '', + 'cache' => -1, + ), ); $query = db_insert('block')->fields(array('module', 'delta', 'theme', 'status', 'weight', 'region', 'pages', 'cache')); foreach ($values as $record) { @@ -188,6 +218,15 @@ function default_profile_site_setup(&$install_state) { // Save some default links. $link = array('link_path' => 'admin/structure/menu-customize/main-menu/add', 'link_title' => 'Add a main menu link', 'menu_name' => 'main-menu'); menu_link_save($link); + + // Enable the admin theme. + db_update('system') + ->fields(array('status' => 1)) + ->condition('type', 'theme') + ->condition('name', 'seven') + ->execute(); + variable_set('admin_theme', 'seven'); + variable_set('node_admin_theme', '1'); } /**