commit 1a97de5570bf233f357e005131f670c18580e6a5 Merge: 0f65b45 85c8d12 Author: Lee Rowlands Date: Tue Jan 1 09:49:16 2013 +1000 Merge branch '8.x' into comment-fieldapi4 commit 0f65b45f4547c4e647da3e5af6be210cdf1fadd8 Author: Lee Rowlands Date: Tue Jan 1 09:48:57 2013 +1000 Patch 256 diff --git a/core/modules/comment/comment.module b/core/modules/comment/comment.module index 779df04..0e49aeb 100644 --- a/core/modules/comment/comment.module +++ b/core/modules/comment/comment.module @@ -2275,9 +2275,5 @@ function comment_field_delete_instance($instance) { $field = field_info_field($instance['field_name']); if ($field['type'] == 'comment') { cache()->delete('comment_entity_info'); - if (module_exists('views')) { - // Refresh views data. - views_fetch_data('comment'); - } } } commit 6f675c5f19c4da19aaea3b2c88b7529f1250277b Merge: 89f46ab 65e54ed Author: Lee Rowlands Date: Wed Jan 16 07:47:42 2013 +1000 Merging origin/8.x into comment-fieldapi4 diff --cc core/modules/comment/comment.admin.inc index 37f6384,b9d34a6..d6853d3 --- a/core/modules/comment/comment.admin.inc +++ b/core/modules/comment/comment.admin.inc @@@ -166,12 -107,10 +166,12 @@@ function comment_admin_overview($form, $destination = drupal_get_destination(); foreach ($comments as $comment) { - // Remove the first node title from the node_titles array and attach to - // the comment. - $node_title = array_shift($node_titles); + // Use the first entity label. - $entity = $entities[$comment->entity_type][$comment->entity_id]; ++ $entity = $entities[$comment->entity_type->value][$comment->entity_id->value]; + $comment->entity_title = $entity->label(); + $comment->entity_uri = $entity->uri(); - $comment_body = field_get_items('comment', $comment, 'comment_body'); - $options[$comment->cid] = array( ++ $comment_body = field_get_items($comment, 'comment_body'); + $options[$comment->id()] = array( 'subject' => array( 'data' => array( '#type' => 'link', @@@ -184,12 -123,11 +184,12 @@@ 'posted_in' => array( 'data' => array( '#type' => 'link', - '#title' => $node_title, - '#href' => 'node/' . $comment->nid->value, + '#title' => $comment->entity_title, + '#href' => $comment->entity_uri['path'], + '#options' => $comment->entity_uri['options'] ), ), - 'changed' => format_date($comment->changed, 'short'), + 'changed' => format_date($comment->changed->value, 'short'), ); $links = array(); $links['edit'] = array( @@@ -351,13 -289,11 +351,13 @@@ function comment_confirm_delete_page($c function comment_confirm_delete($form, &$form_state, Comment $comment) { $form_state['comment'] = $comment; // Always provide entity id in the same form key as in the entity edit form. - $form['cid'] = array('#type' => 'value', '#value' => $comment->cid); - $entity = entity_load($comment->entity_type, $comment->entity_id); + $form['cid'] = array('#type' => 'value', '#value' => $comment->id()); ++ $entity = entity_load($comment->entity_type->value, $comment->entity_id->value); + $uri = $entity->uri(); return confirm_form( $form, - t('Are you sure you want to delete the comment %title?', array('%title' => $comment->subject)), + t('Are you sure you want to delete the comment %title?', array('%title' => $comment->subject->value)), - 'node/' . $comment->nid->value, + $uri['path'], t('Any replies to this comment will be lost. This action cannot be undone.'), t('Delete'), t('Cancel'), @@@ -376,7 -312,5 +376,7 @@@ function comment_confirm_delete_submit( // Clear the cache so an anonymous user sees that his comment was deleted. cache_invalidate_tags(array('content' => TRUE)); - $entity = entity_load($comment->entity_type, $comment->entity_id); - $form_state['redirect'] = "node/{$comment->nid->value}"; ++ $entity = entity_load($comment->entity_type->value, $comment->entity_id->value); + $uri = $entity->uri(); + $form_state['redirect'] = $uri['path']; } diff --cc core/modules/comment/comment.api.php index 7792f23,1762c69..ce7b0f4 --- a/core/modules/comment/comment.api.php +++ b/core/modules/comment/comment.api.php @@@ -34,9 -34,7 +34,9 @@@ function hook_comment_presave(Drupal\co */ function hook_comment_insert(Drupal\comment\Comment $comment) { // Reindex the node when comments are added. - search_touch_node($comment->nid->value); + if ($comment->entity_type == 'node') { - search_touch_node($comment->entity_id); ++ search_touch_node($comment->entity_id->value); + } } /** @@@ -47,9 -45,7 +47,9 @@@ */ function hook_comment_update(Drupal\comment\Comment $comment) { // Reindex the node when comments are updated. - search_touch_node($comment->nid->value); + if ($comment->entity_type == 'node') { - search_touch_node($comment->entity_id); ++ search_touch_node($comment->entity_id->value); + } } /** @@@ -68,11 -64,14 +68,14 @@@ function hook_comment_load(Drupal\comme /** * Act on a comment that is being assembled before rendering. * - * @param Drupal\comment\Comment $comment + * @param \Drupal\comment\Plugin\Core\Entity\Comment $comment $comment * Passes in the comment the action is being performed on. - * @param string $view_mode + * @param \Drupal\entity\Plugin\Core\Entity\EntityDisplay $display + * The entity_display object holding the display options configured for the + * comment components. + * @param $view_mode * View mode, e.g. 'full', 'teaser'... - * @param $langcode + * @param string $langcode * The language code used for rendering. * * @see hook_entity_view() @@@ -95,10 -101,13 +105,13 @@@ function hook_comment_view(\Drupal\comm * comment.tpl.php. See drupal_render() and theme() documentation respectively * for details. * - * @param $build + * @param array $build * A renderable array representing the comment. - * @param Drupal\comment\Comment $comment + * @param \Drupal\comment\Plugin\Core\Entity\Comment $comment * The comment being rendered. + * @param \Drupal\entity\Plugin\Core\Entity\EntityDisplay $display + * The entity_display object holding the display options configured for the + * comment components. * * @see comment_view() * @see hook_entity_view_alter() diff --cc core/modules/comment/comment.field.inc index 779e34a,0000000..0fe9695 mode 100644,000000..100644 --- a/core/modules/comment/comment.field.inc +++ b/core/modules/comment/comment.field.inc @@@ -1,293 -1,0 +1,294 @@@ + array( + 'label' => t('Comments'), + 'default_widget' => 'comment_default', + 'settings' => array(), + 'instance_settings' => array( + 'comment' => array( + 'comment' => COMMENT_OPEN, + 'comment_default_mode' => COMMENT_MODE_THREADED, + 'comment_default_per_page' => 50, + 'comment_anonymous' => COMMENT_ANONYMOUS_MAYNOT_CONTACT, + 'comment_subject_field' => 1, + 'comment_form_location' => COMMENT_FORM_BELOW, + 'comment_preview' => DRUPAL_OPTIONAL + ) + ), + 'description' => t('This field manages configuration and presentation of comments on an entity'), + 'default_formatter' => 'comment_default' + ) + ); +} + +/** + * Implements hook_field_instance_settings_form(). + */ +function comment_field_instance_settings_form($field, $instance) { + $settings = $instance['settings']; + $form['comment'] = array( + '#type' => 'details', + '#title' => t('Comment settings'), + '#collapsible' => TRUE, + '#collapsed' => FALSE, + '#field_name' => $field['field_name'], + '#process' => array('comment_instance_settings_translation_entity_process'), + '#attributes' => array( + 'class' => array('comment-instance-settings-form'), + ), + '#attached' => array( + 'library' => array(array('comment', 'drupal.comment')), + ), + ); + $form['comment']['comment'] = array( + '#type' => 'select', + '#title' => t('Default comment setting for new content'), + '#default_value' => empty($settings['comment']) ? COMMENT_OPEN : $settings['comment'], + '#options' => array( + COMMENT_OPEN => t('Open'), + COMMENT_CLOSED => t('Closed'), + COMMENT_HIDDEN => t('Hidden'), + ), + ); + $form['comment']['comment_default_mode'] = array( + '#type' => 'checkbox', + '#title' => t('Threading'), + '#default_value' => empty($settings['comment_default_mode']) ? COMMENT_MODE_THREADED : $settings['comment_default_mode'], + '#description' => t('Show comment replies in a threaded list.'), + ); + $form['comment']['comment_default_per_page'] = array( + '#type' => 'select', + '#title' => t('Comments per page'), + '#default_value' => empty($settings['comment_default_per_page']) ? 50 : $settings['comment_default_per_page'], + '#options' => _comment_per_page(), + ); + $form['comment']['comment_anonymous'] = array( + '#type' => 'select', + '#title' => t('Anonymous commenting'), + '#default_value' => empty($settings['comment_anonymous']) ? COMMENT_ANONYMOUS_MAYNOT_CONTACT : $settings['comment_anonymous'], + '#options' => array( + COMMENT_ANONYMOUS_MAYNOT_CONTACT => t('Anonymous posters may not enter their contact information'), + COMMENT_ANONYMOUS_MAY_CONTACT => t('Anonymous posters may leave their contact information'), + COMMENT_ANONYMOUS_MUST_CONTACT => t('Anonymous posters must leave their contact information'), + ), + '#access' => user_access('post comments', drupal_anonymous_user()), + ); + $form['comment']['comment_subject_field'] = array( + '#type' => 'checkbox', + '#title' => t('Allow comment title'), + '#default_value' => empty($settings['comment_subject_field']) ? 1 : $settings['comment_subject_field'], + ); + $form['comment']['comment_form_location'] = array( + '#type' => 'checkbox', + '#title' => t('Show reply form on the same page as comments'), + '#default_value' => empty($settings['comment_form_location']) ? COMMENT_FORM_BELOW : $settings['comment_form_location'], + ); + $form['comment']['comment_preview'] = array( + '#type' => 'radios', + '#title' => t('Preview comment'), + '#default_value' => empty($settings['comment_preview']) ? DRUPAL_OPTIONAL : $settings['comment_preview'], + '#options' => array( + DRUPAL_DISABLED => t('Disabled'), + DRUPAL_OPTIONAL => t('Optional'), + DRUPAL_REQUIRED => t('Required'), + ), + ); + return $form; +} + +/** + * Process callback to add submit handler for instance settings form. + * + * Attaches the required translation entity handlers for the instance which + * correlates one to one with the comment bundle. + */ +function comment_instance_settings_translation_entity_process($element, $form_state) { + if (module_exists('translation_entity')) { + $comment_form = $element; + $comment_form_state['translation_entity']['key'] = 'language_configuration'; + $element += translation_entity_enable_widget('comment', $element['#field_name'], $comment_form, $comment_form_state); + $element['translation_entity']['#parents'] = $element['translation_entity']['#array_parents'] = array( + 'translation_entity' + ); + } + return $element; +} + +/** + * Implements hook_field_formatter_info(). + */ +function comment_field_formatter_info() { + return array( + 'comment_default' => array( + 'label' => t('Comments'), + 'field types' => array('comment'), + ), + ); +} + +/** + * Implements hook_field_widget_info(). + * + * @todo convert this to a WidgetPlugin. + */ +function comment_field_widget_info() { + return array( + 'comment_default' => array( + 'label' => t('Comment'), + 'field types' => array('comment'), + 'settings' => array(), + 'behaviors' => array( + 'multiple values' => FIELD_BEHAVIOR_CUSTOM, + 'default value' => FIELD_BEHAVIOR_NONE, + ), + ), + ); +} + +/** + * Implements hook_field_widget_form(). + * + * @todo convert this to a WidgetPlugin. + */ +function comment_field_widget_form(&$form, &$form_state, $field, $instance, $langcode, $items, $delta, $element) { + $entity = $element['#entity']; + $settings = $instance['settings']['comment']; + $element += array( + '#type' => 'details', + '#access' => user_access('administer comments'), + '#collapsible' => TRUE, + '#collapsed' => TRUE, + '#group' => 'additional_settings', + '#attributes' => array( + 'class' => array('comment-node-settings-form'), + ), + '#attached' => array( + 'library' => array('comment', 'drupal.comment'), + ), + '#weight' => 30, + ); + $values = reset($items); + if (empty($values)) { + $values = array( + // Default taken from instance settings. + 'comment' => $settings['comment'], + ); + } + $entity_id = $entity->id(); + $comment_count = empty($entity->comment_statistics[$field['field_name']]->comment_count) ? 0 : $entity->comment_statistics[$field['field_name']]->comment_count; + $comment_settings = ($values['comment'] == COMMENT_HIDDEN && empty($comment_count)) ? COMMENT_CLOSED : $values['comment']; + $element['comment'] = array( + '#type' => 'radios', + '#title' => t('Comments'), + '#title_display' => 'invisible', + '#default_value' => $comment_settings, + '#options' => array( + COMMENT_OPEN => t('Open'), + COMMENT_CLOSED => t('Closed'), + COMMENT_HIDDEN => t('Hidden'), + ), + COMMENT_OPEN => array( + '#description' => t('Users with the "Post comments" permission can post comments.'), + ), + COMMENT_CLOSED => array( + '#description' => t('Users cannot post comments, but existing comments will be displayed.'), + ), + COMMENT_HIDDEN => array( + '#description' => t('Comments are hidden from view.'), + ), + ); + // If the node doesn't have any comments, the "hidden" option makes no + // sense, so don't even bother presenting it to the user. + if (empty($comment_count)) { + $element['comment'][COMMENT_HIDDEN]['#access'] = FALSE; + // Also adjust the description of the "closed" option. + $element['comment'][COMMENT_CLOSED]['#description'] = t('Users cannot post comments.'); + } + return array($element); +} + +/** + * Implements hook_field_formatter_view(). + */ - function comment_field_formatter_view($entity_type, $entity, $field, $instance, $langcode, $items, $display) { ++function comment_field_formatter_view(EntityInterface $entity, $field, $instance, $langcode, $items, $display) { + $element = array(); + + switch ($display['type']) { + case 'comment_default': + // We only ever have one value. + $values = reset($items); + if ($values['comment'] != COMMENT_HIDDEN) { + $additions = FALSE; + if ($values['comment'] && empty($entity->in_preview)) { + // Only attempt to render comments if the node has visible comments. + // Unpublished comments are not included in + // $node->entity_statistics[$field_name]->comment_count, so show + // comments unconditionally if the user is an administrator. + $comment_settings = $instance['settings']['comment']; + if (((!empty($entity->comment_statistics[$field['field_name']]->comment_count) && user_access('access comments')) || user_access('administer comments')) && + !empty($entity->content['#view_mode']) && + !in_array($entity->content['#view_mode'], array('search_result', 'search_index'))) { + // Comment threads aren't added to search results/indexes using the + // formatter, @see comment_node_update_index(). + $mode = $comment_settings['comment_default_mode']; + $comments_per_page = $comment_settings['comment_default_per_page']; + if ($cids = comment_get_thread($entity, $field['field_name'], $mode, $comments_per_page)) { + $comments = comment_load_multiple($cids); + comment_prepare_thread($comments); + $build = comment_view_multiple($comments); + $build['pager']['#theme'] = 'pager'; + $additions['comments'] = $build; + } + } + + // Append comment form if needed. + if ($values['comment'] == COMMENT_OPEN && $comment_settings['comment_form_location'] == COMMENT_FORM_BELOW) { + // Only show the add comment form if the user has permission and the + // view mode is not search_result or search_index. + if (user_access('post comments') && !empty($entity->content['#view_mode']) && + !in_array($entity->content['#view_mode'], array('search_result', 'search_index'))) { + $additions['comment_form'] = comment_add($entity, $field['field_name']); + } + } + if ($additions) { + $additions += array( + '#theme' => 'comment_wrapper__' . $entity->entityType() . '__' . $entity->bundle() . '__' . $field['field_name'], + '#entity' => $entity, + '#display_mode' => $instance['settings']['comment']['comment_default_mode'], + 'comments' => array(), + 'comment_form' => array(), + ); + } + if (!empty($additions)) { + $element[] = $additions; + } + } + } + break; + + } + + return $element; +} + +/** + * Implements hook_field_is_empty(). + */ +function comment_field_is_empty($item, $field) { + // We always want the values saved so we can rely on them. + return FALSE; +} diff --cc core/modules/comment/comment.module index e6b8d31,9cb4ebf..d188eb8 --- a/core/modules/comment/comment.module +++ b/core/modules/comment/comment.module @@@ -122,135 -99,26 +123,135 @@@ function comment_help($path, $arg) } /** - * Implements hook_entity_info(). + * Implements hook_entity_view(). + */ +function comment_entity_view($entity, $view_mode, $langcode) { + $fields = field_info_instances($entity->entityType(), $entity->bundle()); + foreach ($fields as $field_name => $instance) { + $links = array(); + $field = field_info_field($instance['field_name']); + if ($field['type'] != 'comment') { + continue; + } - $values = field_get_items($entity->entityType(), $entity, $field_name); ++ $values = field_get_items($entity, $field_name); + if ($values && is_array($values) && ($value = reset($values)) && + !empty($value['comment']) && + $value['comment'] != COMMENT_HIDDEN) { + $uri = $entity->uri(); + if ($view_mode == 'rss') { + // Add a comments RSS element which is a URL to the comments of this node. + if (!empty($uri['options'])) { + $uri['options']['fragment'] = 'comments'; + $uri['options']['absolute'] = TRUE; + } + $entity->rss_elements[] = array( + 'key' => 'comments', + 'value' => url($uri['path'], $uri['options']) + ); + } + elseif ($view_mode == 'teaser') { + // Teaser view: display the number of comments that have been posted, + // or a link to add new comments if the user has permission, the node + // is open to new comments, and there currently are none. + if (user_access('access comments')) { + if (!empty($entity->comment_statistics[$field_name]->comment_count)) { + $links['comment-comments'] = array( + 'title' => format_plural($entity->comment_statistics[$field_name]->comment_count, '1 comment', '@count comments'), + 'href' => $uri['path'], + 'attributes' => array('title' => t('Jump to the first comment of this posting.')), + 'fragment' => 'comments', + 'html' => TRUE, + ); + // Show a link to the first new comment. + if ($new = comment_num_new($entity->id(), $entity->entityType(), $field_name)) { + $links['comment-new-comments'] = array( + 'title' => format_plural($new, '1 new comment', '@count new comments'), + 'href' => $uri['path'], + 'query' => comment_new_page_count($entity->comment_statistics[$field_name]->comment_count, $new, $entity, $field_name), + 'attributes' => array('title' => t('Jump to the first new comment of this posting.')), + 'fragment' => 'new', + 'html' => TRUE, + ); + } + } + } - $values = field_get_items($entity->entityType(), $entity, $field_name); ++ $values = field_get_items($entity, $field_name); + $value = reset($values); + if (!empty($value['comment']) && $value['comment'] == COMMENT_OPEN) { + $comment_form_location = $instance['settings']['comment']['comment_form_location']; + if (user_access('post comments')) { + $links['comment-add'] = array( + 'title' => t('Add new comment'), + 'href' => $uri['path'], + 'attributes' => array('title' => t('Add a new comment to this page.')), + 'fragment' => 'comment-form', + ); + if ($comment_form_location == COMMENT_FORM_SEPARATE_PAGE) { + $links['comment-add']['href'] = 'comment/reply/'. $entity->entityType() . '/' . $entity->id() .'/' . $field_name; + } + } + else { + $links['comment-forbidden'] = array( + 'title' => theme('comment_post_forbidden', array('entity' => $entity, 'field_name' => $field_name)), + 'html' => TRUE, + ); + } + } + } + elseif ($view_mode != 'search_index' && $view_mode != 'search_result') { + // Entity in other view modes: add a "post comment" link if the user is + // allowed to post comments and if this entity is allowing new comments. + // But we don't want this link if we're building the entity for search + // indexing or constructing a search result excerpt. - $values = field_get_items($entity->entityType(), $entity, $field_name); ++ $values = field_get_items($entity, $field_name); + if (is_array($values) && ($value = reset($values)) && + !empty($value['comment']) && $value['comment'] == COMMENT_OPEN) { + $comment_form_location = $instance['settings']['comment']['comment_form_location']; + if (user_access('post comments')) { + // Show the "post comment" link if the form is on another page, or + // if there are existing comments that the link will skip past. + if ($comment_form_location == COMMENT_FORM_SEPARATE_PAGE || (!empty($entity->comment_statistics[$field_name]->comment_count) && user_access('access comments'))) { + $links['comment-add'] = array( + 'title' => t('Add new comment'), + 'attributes' => array('title' => t('Share your thoughts and opinions related to this item.')), + 'href' => $uri['path'], + 'fragment' => 'comment-form', + ); + if ($comment_form_location == COMMENT_FORM_SEPARATE_PAGE) { + $links['comment-add']['href'] = 'comment/reply/'. $entity->entityType() . '/' . $entity->id() .'/' . $field_name; + } + } + } + else { + $links['comment-forbidden'] = array( + 'title' => theme('comment_post_forbidden', array('entity' => $entity, 'field_name' => $field_name)), + 'html' => TRUE, + ); + } + } + } + } + + $entity->content['links']['comment__' . $field_name] = array( + '#theme' => 'links__entity__comment__' . $field_name, + '#links' => $links, + '#attributes' => array('class' => array('links', 'inline')), + ); + } +} + +/** + * Implements hook_entity_info_alter(). */ -function comment_entity_info(&$info) { - foreach (node_type_get_names() as $type => $name) { - $info['comment']['bundles']['comment_node_' . $type] = array( - 'label' => t('@node_type comment', array('@node_type' => $name)), - // Provide the node type/bundle name for other modules, so it does not - // have to be extracted manually from the bundle name. - 'node bundle' => $type, +function comment_entity_info_alter(&$info) { + foreach (comment_get_comment_fields() as $field_name => $field_info) { + $info['comment']['bundles'][$field_name] = array( + 'label' => $field_name, 'admin' => array( - // Place the Field UI paths for comments one level below the - // corresponding paths for nodes, so that they appear in the same set - // of local tasks. Note that the paths use a different placeholder name - // and thus a different menu loader callback, so that Field UI page - // callbacks get a comment bundle name from the node type in the URL. - // See comment_node_type_load() and comment_menu_alter(). - 'path' => 'admin/structure/types/manage/%comment_node_type/comment', - 'bundle argument' => 4, - 'real path' => 'admin/structure/types/manage/' . $type . '/comment', - 'access arguments' => array('administer content types'), + 'path' => 'admin/structure/comments/%comment_field_name', + 'bundle argument' => 3, + 'real path' => 'admin/structure/comments/' . strtr($field_name, '_', '-'), + 'access arguments' => array('administer comments'), ), ); } @@@ -581,11 -430,10 +582,11 @@@ function comment_permission() * The comment listing set to the page on which the comment appears. */ function comment_permalink($cid) { - if (($comment = comment_load($cid)) && ($entity = entity_load($comment->entity_type, $comment->entity_id))) { - if (($comment = comment_load($cid)) && ($node = $comment->nid->entity)) { ++ if (($comment = comment_load($cid)) && ($entity = entity_load($comment->entity_type->value, $comment->entity_id->value))) { - $instance = field_info_instance($entity->entityType(), $comment->field_name, $entity->bundle()); ++ $instance = field_info_instance($entity->entityType(), $comment->field_name->value, $entity->bundle()); // Find the current display page for this comment. - $page = comment_get_display_page($comment->cid, $instance); - $page = comment_get_display_page($comment->id(), $node->type); ++ $page = comment_get_display_page($comment->id(), $instance); // @todo: Cleaner sub request handling. $request = drupal_container()->get('request'); @@@ -735,12 -565,163 +736,11 @@@ function theme_comment_block($variables } /** - * Returns a rendered form to comment on the given entity. - * Implements hook_node_view(). - */ -function comment_node_view(Node $node, EntityDisplay $display, $view_mode) { - $links = array(); - - if ($node->comment != COMMENT_NODE_HIDDEN) { - if ($view_mode == 'rss') { - // Add a comments RSS element which is a URL to the comments of this node. - $node->rss_elements[] = array( - 'key' => 'comments', - 'value' => url('node/' . $node->nid, array('fragment' => 'comments', 'absolute' => TRUE)) - ); - } - elseif ($view_mode == 'teaser') { - // Teaser view: display the number of comments that have been posted, - // or a link to add new comments if the user has permission, the node - // is open to new comments, and there currently are none. - if (user_access('access comments')) { - if (!empty($node->comment_count)) { - $links['comment-comments'] = array( - 'title' => format_plural($node->comment_count, '1 comment', '@count comments'), - 'href' => "node/$node->nid", - 'attributes' => array('title' => t('Jump to the first comment of this posting.')), - 'fragment' => 'comments', - 'html' => TRUE, - ); - // Show a link to the first new comment. - if ($new = comment_num_new($node->nid)) { - $links['comment-new-comments'] = array( - 'title' => format_plural($new, '1 new comment', '@count new comments'), - 'href' => "node/$node->nid", - 'query' => comment_new_page_count($node->comment_count, $new, $node), - 'attributes' => array('title' => t('Jump to the first new comment of this posting.')), - 'fragment' => 'new', - 'html' => TRUE, - ); - } - } - } - if ($node->comment == COMMENT_NODE_OPEN) { - $comment_form_location = variable_get('comment_form_location_' . $node->type, COMMENT_FORM_BELOW); - if (user_access('post comments')) { - $links['comment-add'] = array( - 'title' => t('Add new comment'), - 'href' => "node/$node->nid", - 'attributes' => array('title' => t('Add a new comment to this page.')), - 'fragment' => 'comment-form', - ); - if ($comment_form_location == COMMENT_FORM_SEPARATE_PAGE) { - $links['comment-add']['href'] = "comment/reply/$node->nid"; - } - } - else { - $links['comment-forbidden'] = array( - 'title' => theme('comment_post_forbidden', array('node' => $node)), - 'html' => TRUE, - ); - } - } - } - elseif ($view_mode != 'search_index' && $view_mode != 'search_result') { - // Node in other view modes: add a "post comment" link if the user is - // allowed to post comments and if this node is allowing new comments. - // But we don't want this link if we're building the node for search - // indexing or constructing a search result excerpt. - if ($node->comment == COMMENT_NODE_OPEN) { - $comment_form_location = variable_get('comment_form_location_' . $node->type, COMMENT_FORM_BELOW); - if (user_access('post comments')) { - // Show the "post comment" link if the form is on another page, or - // if there are existing comments that the link will skip past. - if ($comment_form_location == COMMENT_FORM_SEPARATE_PAGE || (!empty($node->comment_count) && user_access('access comments'))) { - $links['comment-add'] = array( - 'title' => t('Add new comment'), - 'attributes' => array('title' => t('Share your thoughts and opinions related to this posting.')), - 'href' => "node/$node->nid", - 'fragment' => 'comment-form', - ); - if ($comment_form_location == COMMENT_FORM_SEPARATE_PAGE) { - $links['comment-add']['href'] = "comment/reply/$node->nid"; - } - } - } - else { - $links['comment-forbidden'] = array( - 'title' => theme('comment_post_forbidden', array('node' => $node)), - 'html' => TRUE, - ); - } - } - } - - $node->content['links']['comment'] = array( - '#theme' => 'links__node__comment', - '#links' => $links, - '#attributes' => array('class' => array('links', 'inline')), - ); - - // Only append comments when we are building a node on its own node detail - // page. We compare $node and $page_node to ensure that comments are not - // appended to other nodes shown on the page, for example a node_reference - // displayed in 'full' view mode within another node. - if ($node->comment && $view_mode == 'full' && node_is_page($node) && empty($node->in_preview)) { - $node->content['comments'] = comment_node_page_additions($node); - } - } -} - -/** - * Builds the comment-related elements for node detail pages. * - * @param Drupal\node\Node $node - * The node entity for which to build the comment-related elements. - * - * @return - * A renderable array representing the comment-related page elements for the - * node. - */ -function comment_node_page_additions(Node $node) { - $additions = array(); - - // Only attempt to render comments if the node has visible comments. - // Unpublished comments are not included in $node->comment_count, so show - // comments unconditionally if the user is an administrator. - if (($node->comment_count && user_access('access comments')) || user_access('administer comments')) { - $mode = variable_get('comment_default_mode_' . $node->type, COMMENT_MODE_THREADED); - $comments_per_page = variable_get('comment_default_per_page_' . $node->type, 50); - if ($cids = comment_get_thread($node, $mode, $comments_per_page)) { - $comments = comment_load_multiple($cids); - comment_prepare_thread($comments); - $build = comment_view_multiple($comments); - $build['pager']['#theme'] = 'pager'; - $additions['comments'] = $build; - } - } - - // Append comment form if needed. - if (user_access('post comments') && $node->comment == COMMENT_NODE_OPEN && (variable_get('comment_form_location_' . $node->type, COMMENT_FORM_BELOW) == COMMENT_FORM_BELOW)) { - $additions['comment_form'] = comment_add($node); - } - - if ($additions) { - $additions += array( - '#theme' => 'comment_wrapper__node_' . $node->type, - '#node' => $node, - 'comments' => array(), - 'comment_form' => array(), - ); - } - - return $additions; -} - -/** - * Returns a rendered form to comment the given node. - * - * @param Drupal\node\Node $node - * The node entity to be commented. + * @param \Drupal\Core\Entity\EntityInterface $entity + * The entity to which the comments are in reply to. + * @param string $field_name + * The field name where the comments were entered. * @param int $pid * (optional) Some comments are replies to other comments. In those cases, * $pid is the parent comment's comment ID. Defaults to NULL. @@@ -748,9 -729,9 +748,10 @@@ * @return array * The renderable array for the comment addition form. */ - function comment_add(\Drupal\Core\Entity\EntityInterface $entity, $field_name = 'comment', $pid = NULL) { -function comment_add(Node $node, $pid = NULL) { - $values = array('nid' => $node->nid, 'pid' => $pid, 'node_type' => 'comment_node_' . $node->type); ++function comment_add(EntityInterface $entity, $field_name = 'comment', $pid = NULL) { + $values = array('entity_id' => $entity->id(), 'pid' => $pid, 'entity_type' => $entity->entityType(), 'field_name' => $field_name); $comment = entity_create('comment', $values); ++ return entity_get_form($comment); } @@@ -949,11 -918,9 +950,11 @@@ function comment_view(Comment $comment * @return * A structured array of links. */ -function comment_links(Comment $comment, Node $node) { +function comment_links(Comment $comment, \Drupal\Core\Entity\EntityInterface $entity, $field_name) { $links = array(); - $items = field_get_items($entity->entityType(), $entity, $field_name); - if ($node->comment == COMMENT_NODE_OPEN) { ++ $items = field_get_items($entity, $field_name); + $status = reset($items); + if ($status['comment'] == COMMENT_OPEN) { if (user_access('administer comments') && user_access('post comments')) { $links['comment-delete'] = array( 'title' => t('delete'), @@@ -967,15 -934,15 +968,15 @@@ ); $links['comment-reply'] = array( 'title' => t('reply'), - 'href' => "comment/reply/$comment->entity_type/$comment->entity_id/$comment->field_name/$comment->cid", - 'href' => "comment/reply/{$comment->nid->value}/{$comment->id()}", ++ 'href' => "comment/reply/{$comment->entity_type->value}/{$comment->entity_id->value}/{$comment->field_name->value}/{$comment->id()}", 'html' => TRUE, ); - if ($comment->status == COMMENT_NOT_PUBLISHED) { + if ($comment->status->value == COMMENT_NOT_PUBLISHED) { $links['comment-approve'] = array( 'title' => t('approve'), - 'href' => "comment/$comment->cid/approve", + 'href' => "comment/{$comment->id()}/approve", 'html' => TRUE, - 'query' => array('token' => drupal_get_token("comment/$comment->cid/approve")), + 'query' => array('token' => drupal_get_token("comment/{$comment->id()}/approve")), ); } } @@@ -989,7 -956,7 +990,7 @@@ } $links['comment-reply'] = array( 'title' => t('reply'), - 'href' => "comment/reply/$comment->entity_type/$comment->entity_id/$comment->field_name/$comment->cid", - 'href' => "comment/reply/{$comment->nid->value}/{$comment->id()}", ++ 'href' => "comment/reply/{$comment->entity_type->value}/{$comment->entity_id->value}/{$comment->field_name->value}/{$comment->id()}", 'html' => TRUE, ); } @@@ -1186,24 -1256,17 +1187,24 @@@ function comment_node_update_index(Nod } } + $return = ''; + if ($index_comments) { - $mode = variable_get('comment_default_mode_' . $node->type, COMMENT_MODE_THREADED); - $comments_per_page = variable_get('comment_default_per_page_' . $node->type, 50); - if ($node->comment && $cids = comment_get_thread($node, $mode, $comments_per_page)) { - $comments = comment_load_multiple($cids); - comment_prepare_thread($comments); - $build = comment_view_multiple($comments, $langcode); - return drupal_render($build); + foreach (comment_get_comment_fields('node') as $field_name => $info) { + $instance = field_info_instance('node', $field_name, $node->type); + $mode = $instance['settings']['comment']['comment_default_mode']; + $comments_per_page = $instance['settings']['comment']['comment_default_per_page']; - if (($items = field_get_items('node', $node, $field_name)) && ++ if (($items = field_get_items($node, $field_name)) && + ($item = reset($items)) && + $item['comment'] && $cids = comment_get_thread($node, $field_name, $mode, $comments_per_page)) { + $comments = comment_load_multiple($cids); + comment_prepare_thread($comments); + $build = comment_view_multiple($comments); + $return .= drupal_render($build); + } } } - return ''; + return $return; } /** @@@ -1220,30 -1283,16 +1221,30 @@@ function comment_update_index() * Formats a comment count string and returns it, for display with search * results. */ -function comment_node_search_result(Node $node) { - // Do not make a string if comments are hidden. - if (user_access('access comments') && $node->comment != COMMENT_NODE_HIDDEN) { - $comments = db_query('SELECT comment_count FROM {node_comment_statistics} WHERE nid = :nid', array('nid' => $node->nid))->fetchField(); - // Do not make a string if comments are closed and there are currently - // zero comments. - if ($node->comment != COMMENT_NODE_CLOSED || $comments > 0) { - return array('comment' => format_plural($comments, '1 comment', '@count comments')); +function comment_node_search_result($node) { + $comment_fields = comment_get_comment_fields('node'); + $return = FALSE; + $comments = 0; + $open = FALSE; + foreach ($comment_fields as $field_name => $info) { + // Do not make a string if comments are hidden. - if (user_access('access comments') && ($items = field_get_items('node', $node, $field_name)) && ++ if (user_access('access comments') && ($items = field_get_items($node, $field_name)) && + ($item = reset($items)) && $item['comment'] != COMMENT_HIDDEN) { + if ($item['comment'] == COMMENT_OPEN) { + // At least one comment field is open. + $open = TRUE; + } + $comments += db_query("SELECT comment_count FROM {comment_entity_statistics} WHERE entity_id = :nid AND entity_type = 'node' AND field_name = :field_name", array( + 'nid' => $node->nid, + 'field_name' => $field_name) + )->fetchField(); } } + // Do not make a string if there are no comment fields, or no comments exist + // or all comment fields are hidden. + if ($comments > 0 || $open) { + return array('comment' => format_plural($comments, '1 comment', '@count comments')); + } } /** @@@ -1515,14 -1538,11 +1516,12 @@@ function comment_edit_page(Comment $com function comment_preview(Comment $comment) { global $user; $preview_build = array(); - $entity = entity_load($comment->entity_type, $comment->entity_id); ++ $entity = entity_load($comment->entity_type->value, $comment->entity_id->value); if (!form_get_errors()) { - $comment_body = field_get_items('comment', $comment, 'comment_body'); - $comment->format = $comment_body[0]['format']; // Attach the user and time information. - if (!empty($comment->name)) { - $account = user_load_by_name($comment->name); + if (!empty($comment->name->value)) { + $account = user_load_by_name($comment->name->value); } elseif ($user->uid && empty($comment->is_anonymous)) { $account = $user; @@@ -1547,20 -1565,15 +1544,20 @@@ $preview_build['comment_preview'] = $comment_build; } - if ($comment->pid) { + if ($comment->pid->value) { $build = array(); - $parent = comment_load($comment->pid); - if ($parent && $parent->status == COMMENT_PUBLISHED) { - $comment = $comment->pid->entity; - if ($comment && $comment->status->value == COMMENT_PUBLISHED) { - $build = comment_view($comment); ++ $parent = $comment->pid->entity; ++ if ($parent && $parent->status->value == COMMENT_PUBLISHED) { + $build = comment_view($parent); } } else { - $build = node_view($comment->nid->entity); + // We temporarily disable rendering of this field to prevent infinite + // loop. - $values = $entity->{$comment->field_name}; - unset($entity->{$comment->field_name}); ++ $values = $entity->{$comment->field_name->value}; ++ unset($entity->{$comment->field_name->value}); + $build = entity_view($entity, 'full'); - $entity->{$comment->field_name} = $values; ++ $entity->{$comment->field_name->value} = $values; } $preview_build['comment_output_below'] = $build; @@@ -1585,15 -1616,16 +1600,16 @@@ function comment_prepare_author(Commen */ function template_preprocess_comment(&$variables) { $comment = $variables['elements']['#comment']; - $comment_entity = entity_load($comment->entity_type, $comment->entity_id); - $node = $variables['elements']['#node']; ++ $comment_entity = entity_load($comment->entity_type->value, $comment->entity_id->value); $variables['comment'] = $comment; - $variables['node'] = $node; + $variables['comment_entity'] = $comment_entity; - $variables['author'] = theme('username', array('account' => $comment)); - - $variables['created'] = format_date($comment->created); + $account = comment_prepare_author($comment); + $variables['author'] = theme('username', array('account' => $account)); + $variables['new'] = $comment->new->value ? t('new') : ''; + $variables['created'] = format_date($comment->created->value); // Avoid calling format_date() twice on the same timestamp. - if ($comment->changed == $comment->created) { + if ($comment->changed->value == $comment->created->value) { $variables['changed'] = $variables['created']; } else { @@@ -1676,10 -1713,10 +1697,10 @@@ $variables['attributes']['class'][] = 'by-anonymous'; } else { - if (!empty($comment_entity->uid) && $comment->uid == $comment_entity->uid) { - if ($comment->uid->value == $variables['node']->uid) { - $variables['attributes']['class'][] = 'by-node-author'; ++ if (!empty($comment_entity->uid->value) && $comment->uid->value == $comment_entity->uid->value) { + $variables['attributes']['class'][] = 'by-' . $comment_entity->entityType() . '-author'; } - if ($comment->uid == $variables['user']->uid) { + if ($comment->uid->value == $variables['user']->uid) { $variables['attributes']['class'][] = 'by-viewer'; } } @@@ -2020,17 -2052,9 +2041,17 @@@ function comment_rdf_mapping() */ function comment_file_download_access($field, EntityInterface $entity, File $file) { if ($entity->entityType() == 'comment') { - if (user_access('access comments') && $entity->status == COMMENT_PUBLISHED || user_access('administer comments')) { + if (user_access('access comments') && $entity->status->value == COMMENT_PUBLISHED || user_access('administer comments')) { - $node = $entity->nid->entity; - return node_access('view', $node); + // @todo replace this with entity access controls once generic access controller lands, + // @see http://drupal.org/node/1696660 - $function = $entity->entity_type . '_access'; ++ $function = $entity->entity_type->value . '_access'; + if (function_exists($function)) { - $entity = entity_load($entity->entity_type, $entity->entity_id); ++ $entity = entity_load($comment->entity_type->value, $comment->entity_id->value); + return $function('view', $entity); + } + // Return NULL as there is no entity access callback for this entity + // type, we rely on other modules intervening. + return; } return FALSE; } @@@ -2055,180 -2079,3 +2076,180 @@@ function comment_library_info() return $libraries; } + +/** + * Utility function to return an array of comment fields. + * + * @param string $entity_type + * (optional) Specify a entity type if you want to just return fields which + * are attached on a certain entity type. Defaults to NULL. + * + * @return array + * An array of comment field definitions, keyed by field name. Each field has + * an additional property, 'bundles', which is an array of all the bundles to + * which this field belongs, keyed by entity type. + * + * @see field_info_fields(). + */ +function comment_get_comment_fields($entity_type = NULL) { + return array_filter(field_info_fields(), function ($value) use($entity_type) { + if ($value['type'] == 'comment') { + if (isset($entity_type)) { + return in_array($entity_type, array_keys($value['bundles'])); + } + return TRUE; + } + }); +} + +/** + * Decide on the type of marker to be shown for a comment. + * + * @param Comment $comment + * The comment for which the marker is to be shown. + * + * @return int + * The type of marker to be shown one of MARK_READ, MARK_UPDATED or MARK_NEW. + */ +function comment_mark(Comment $comment) { + global $user; + $cache = &drupal_static(__FUNCTION__, array()); - $cid = $comment->entity_id . '__' . $comment->entity_type; ++ $cid = $comment->entity_id->value . '__' . $comment->entity_type->value; + + if (!$user->uid) { + return MARK_READ; + } + if (!isset($cache[$cid])) { - if ($comment->entity_type == 'node' && module_exists('history')) { - $cache[$cid] = history_read($comment->entity_id); ++ if ($comment->entity_type->value == 'node' && module_exists('history')) { ++ $cache[$cid] = history_read($comment->entity_id->value); + } + else { + // @todo - decide how to handle last viewed for other entities. For now + // assume REQUEST_TIME. + $cache[$cid] = REQUEST_TIME; + } + } - if ($cache[$cid] == 0 && $comment->changed > COMMENT_NEW_LIMIT) { ++ if ($cache[$cid] == 0 && $comment->changed->value > COMMENT_NEW_LIMIT) { + return MARK_NEW; + } - elseif ($comment->changed > $cache[$cid] && $comment->changed > COMMENT_NEW_LIMIT) { ++ elseif ($comment->changed->value > $cache[$cid] && $comment->changed->value > COMMENT_NEW_LIMIT) { + return MARK_UPDATED; + } + return MARK_READ; +} + +/** + * Utility method to add the default comment field to an entity. + * + * Attaches a comment field named 'comment' to the given entity type and bundle. + * Largely replicates the default behaviour in Drupal 7 and earlier. + * + * @param string $entity_type + * The entity type to attach the default comment field to. + * @param string $bundle + * The bundle to attach the default comment field instance to. + * @param string $field_name + * (optional) Field name to use for the comment field. Defaults to 'comment'. + * @param string $default_value + * (optional) Default value, one of COMMENT_HIDDEN, COMMENT_OPEN, + * COMMENT_CLOSED. Defaults to COMMENT_HIDDEN. + */ +function comment_add_default_comment_field($entity_type, $bundle, $field_name = 'comment', $default_value = COMMENT_HIDDEN) { + // Make sure field doesn't already exist. + if (!field_info_field($field_name)) { + // Add a default comment field for existing node comments. + $field = array( + 'field_name' => $field_name, + 'settings' => array(), + 'type' => 'comment', + ); + // Create the field. + field_create_field($field); + } + // Make sure the instance doesn't already exist. + if (!field_info_instance($entity_type, $field_name, $bundle)) { + $instance = array( + 'bundle' => $bundle, + 'default_value' => array(array('comment' => $default_value)), + 'deleted' => '0', + 'description' => '', + 'display' => array( + 'default' => array( + 'label' => 'hidden', + 'module' => 'comment', + 'settings' => array(), + 'type' => 'comment_default', + 'weight' => '1', + ), + 'rss' => array( + 'type' => 'hidden', + 'label' => 'hidden', + ), + 'teaser' => array( + 'type' => 'hidden', + 'label' => 'hidden', + ), + 'search_index' => array( + 'type' => 'hidden', + 'label' => 'hidden', + ), + 'search_result' => array( + 'type' => 'hidden', + 'label' => 'hidden', + ) + ), + 'entity_type' => $entity_type, + 'field_name' => $field_name, + 'label' => 'Comment settings', + 'required' => 1, + 'settings' => array( + 'comment' => array( + 'comment' => COMMENT_OPEN, + 'comment_default_mode' => COMMENT_MODE_THREADED, + 'comment_default_per_page' => 50, + 'comment_anonymous' => COMMENT_ANONYMOUS_MAYNOT_CONTACT, + 'comment_subject_field' => 1, + 'comment_form_location' => COMMENT_FORM_BELOW, + 'comment_preview' => DRUPAL_OPTIONAL + ) + ), + 'widget' => array( + 'active' => 0, + 'module' => 'comment', + 'settings' => array(), + 'type' => 'comment_default', + 'weight' => '50', + ), + ); + field_create_instance($instance); + entity_get_display($entity_type, $bundle, 'default') + ->setComponent($field_name, array( + 'label' => 'hidden', + 'type' => 'comment_default', + 'weight' => 1, + )) + ->save(); + } + _comment_body_field_create($entity_type, $bundle, $field_name); +} + +/** + * Implements hook_field_create_instance(). + */ +function comment_field_create_instance($instance) { + $field = field_info_field($instance['field_name']); + if ($field['type'] == 'comment') { + _comment_body_field_create($instance['entity_type'], $instance['bundle'], $instance['field_name']); + cache()->delete('comment_entity_info'); + } +} + +/** + * Implements hook_field_delete_instance(). + */ +function comment_field_delete_instance($instance) { + $field = field_info_field($instance['field_name']); + if ($field['type'] == 'comment') { + cache()->delete('comment_entity_info'); + } +} diff --cc core/modules/comment/comment.pages.inc index b33d1e8,e333dd7..1420049 --- a/core/modules/comment/comment.pages.inc +++ b/core/modules/comment/comment.pages.inc @@@ -66,21 -56,15 +66,21 @@@ function comment_reply(Drupal\Core\Enti if (user_access('access comments')) { // Load the parent comment. $comment = comment_load($pid); - if ($comment->status == COMMENT_PUBLISHED) { + if ($comment->status->value == COMMENT_PUBLISHED) { // If that comment exists, make sure that the current comment and the // parent comment both belong to the same parent node. - if ($comment->entity_id != $entity->id() || - $comment->field_name != $field_name || - $comment->entity_type != $entity->entityType()) { - if ($comment->nid->value != $node->nid) { - // Attempting to reply to a comment not belonging to the current nid. ++ if ($comment->entity_id->value != $entity->id() || ++ $comment->field_name->value != $field_name || ++ $comment->entity_type->value != $entity->entityType()) { + // Attempting to reply to a comment not belonging to the current entity. drupal_set_message(t('The comment you are replying to does not exist.'), 'error'); - drupal_goto("node/$node->nid"); + drupal_goto($uri['path']); } - // Display the parent comment + // Display the parent comment. - $comment->entity_type = $entity->entityType(); - $comment->field_name = $field_name; - field_attach_load('comment', array($comment->cid => $comment)); - $comment->name = $comment->uid ? $comment->registered_name : $comment->name; ++ $comment->entity_type->value = $entity->entityType(); ++ $comment->field_name->value = $field_name; ++ field_attach_load('comment', array($comment->id() => $comment)); ++ $comment->name->value = $comment->uid->value ? $comment->registered_name : $comment->name->value; $build['comment_parent'] = comment_view($comment); } else { @@@ -107,14 -83,12 +107,14 @@@ } // Should we show the reply box? - $items = field_get_items($entity->entityType(), $entity, $field_name); - if ($node->comment != COMMENT_NODE_OPEN) { ++ $items = field_get_items($entity, $field_name); + $status = reset($items); + if (isset($status['comment']) && $status['comment'] != COMMENT_OPEN) { drupal_set_message(t("This discussion is closed: you can't post new comments."), 'error'); - drupal_goto("node/$node->nid"); + drupal_goto($uri['path']); } elseif (user_access('post comments')) { - $build['comment_form'] = comment_add($node, $pid); + $build['comment_form'] = comment_add($entity, $field_name, $pid); } else { drupal_set_message(t('You are not authorized to post comments.'), 'error'); @@@ -147,34 -121,7 +147,34 @@@ function comment_approve($cid) comment_save($comment); drupal_set_message(t('Comment approved.')); - $entity = entity_load($comment->entity_type, $comment->entity_id); - drupal_goto('node/' . $comment->nid->value); ++ $entity = entity_load($comment->entity_type->value, $comment->entity_id->value); + if ($entity) { + $uri = $entity->uri(); + drupal_goto($uri['path']); + } + } + throw new NotFoundHttpException(); +} + +/** + * Page callback: Legacy handler to redirect old comment reply urls to new url. + * + * @param \Drupal\node\Plugin\Core\Entity\Node $node + * The node to which the comments are attached. + * @param int $pid + * (optional) Some comments are replies to other comments. In those cases, + * $pid is the parent comment's comment ID. Defaults to NULL. + * + * @throw Symfony\Component\HttpKernel\Exception\NotFoundHttpException + * When there are no comment fields attached to the node. + */ +function comment_node_redirect(\Drupal\node\Plugin\Core\Entity\Node $node, $pid = NULL) { + $fields = comment_get_comment_fields('node'); + foreach ($fields as $field_name => $detail) { + // Pick the first comment field found on the node. + if (in_array($node->bundle(), $detail['bundles']['node'], TRUE)) { + drupal_goto('comment/reply/node/' . $node->id() . '/' . $field_name); + } } throw new NotFoundHttpException(); } diff --cc core/modules/comment/comment.tokens.inc index 594f0b0,ec56287..d17f523 --- a/core/modules/comment/comment.tokens.inc +++ b/core/modules/comment/comment.tokens.inc @@@ -186,9 -175,9 +182,9 @@@ function comment_tokens($type, $tokens break; case 'parent': - if (!empty($comment->pid)) { - $parent = comment_load($comment->pid); - $replacements[$original] = $sanitize ? filter_xss($parent->subject) : $parent->subject; + if (!empty($comment->pid->value)) { + $parent = comment_load($comment->pid->value); - $replacements[$original] = $sanitize ? filter_xss($parent->subject) : $parent->subject; ++ $replacements[$original] = $sanitize ? filter_xss($parent->subject->value) : $parent->subject->value; } break; @@@ -197,36 -186,20 +193,36 @@@ break; case 'changed': - $replacements[$original] = format_date($comment->changed, 'medium', '', NULL, $langcode); + $replacements[$original] = format_date($comment->changed->value, 'medium', '', NULL, $langcode); break; - case 'node': - $node = $comment->nid->entity; - $title = $node->label(); + case 'entity': - $entity = entity_load($comment->entity_type, $comment->entity_id); ++ $entity = entity_load($comment->entity_type->value, $comment->entity_id->value); + $title = $entity->label(); $replacements[$original] = $sanitize ? filter_xss($title) : $title; break; + + case 'node': - if ($comment->entity_type== 'node') { - $entity = entity_load($comment->entity_type, $comment->entity_id); ++ if ($comment->entity_type->value == 'node') { ++ $entity = entity_load($comment->entity_type->value, $comment->entity_id->value); + $title = $entity->label(); + $replacements[$original] = $sanitize ? filter_xss($title) : $title; + } + else { + $replacements[$original] = NULL; + } + break; } } // Chained token relationships. - if ($node_tokens = token_find_with_prefix($tokens, 'node')) { - $node = $comment->nid->entity; + if ($entity_tokens = token_find_with_prefix($tokens, 'entity')) { - $entity = entity_load($comment->entity_type, $comment->entity_id); - $replacements += token_generate($comment->entity_type, $entity_tokens, array($comment->entity_type => $entity), $options); ++ $entity = entity_load($comment->entity_type->value, $comment->entity_id->value); ++ $replacements += token_generate($comment->entity_type->value, $entity_tokens, array($comment->entity_type->value => $entity), $options); + } + - if (($node_tokens = token_find_with_prefix($tokens, 'node')) && $comment->entity_type == 'node') { - $node = node_load($comment->entity_id); ++ if (($node_tokens = token_find_with_prefix($tokens, 'node')) && $comment->entity_type->value == 'node') { ++ $node = entity_load($comment->entity_type->value, $comment->entity_id->value); $replacements += token_generate('node', $node_tokens, array('node' => $node), $options); } diff --cc core/modules/comment/lib/Drupal/comment/CommentFormController.php index 180d5bc,fca09ba..ff7d2d3 --- a/core/modules/comment/lib/Drupal/comment/CommentFormController.php +++ b/core/modules/comment/lib/Drupal/comment/CommentFormController.php @@@ -14,24 -14,21 +14,23 @@@ use Drupal\Core\Entity\EntityFormContro /** * Base for controller for comment forms. */ - class CommentFormController extends EntityFormController { + class CommentFormController extends EntityFormControllerNG { /** -- * Overrides Drupal\Core\Entity\EntityFormController::form(). ++ * Overrides Drupal\Core\Entity\EntityFormControllerNG::form(). */ public function form(array $form, array &$form_state, EntityInterface $comment) { global $user; - $node = $comment->nid->entity; - $entity = entity_load($comment->entity_type, $comment->entity_id); - $instance = field_info_instance($comment->entity_type, $comment->field_name, $entity->bundle()); - $form_state['comment']['entity'] = $entity; - // Use #comment-form as unique jump target, regardless of node type. ++ $entity = entity_load($comment->entity_type->value, $comment->entity_id->value); ++ $instance = field_info_instance($comment->entity_type->value, $comment->field_name->value, $entity->bundle()); + + // Use #comment-form as unique jump target, regardless of entity type. $form['#id'] = drupal_html_id('comment_form'); - $form['#theme'] = array('comment_form__' . $comment->entity_type . '__' . $entity->bundle() . '__' . $comment->field_name, 'comment_form'); - $form['#theme'] = array('comment_form__node_' . $node->type, 'comment_form'); ++ $form['#theme'] = array('comment_form__' . $comment->entity_type->value . '__' . $entity->bundle() . '__' . $comment->field_name->value, 'comment_form'); - $anonymous_contact = variable_get('comment_anonymous_' . $node->type, COMMENT_ANONYMOUS_MAYNOT_CONTACT); - $is_admin = $comment->id() && user_access('administer comments'); + $anonymous_contact = $instance['settings']['comment']['comment_anonymous']; - $is_admin = (!empty($comment->cid) && user_access('administer comments')); ++ $is_admin = ($comment->id() && user_access('administer comments')); if (!$user->uid && $anonymous_contact != COMMENT_ANONYMOUS_MAYNOT_CONTACT) { $form['#attached']['library'][] = array('system', 'jquery.cookie'); @@@ -39,9 -36,9 +38,9 @@@ } // If not replying to a comment, use our dedicated page callback for new - // comments on nodes. - if (!$comment->id() && !$comment->pid->value) { - $form['#action'] = url('comment/reply/' . $comment->nid->value); + // comments on entities. - if (empty($comment->cid) && empty($comment->pid)) { - $form['#action'] = url('comment/reply/' . $comment->entity_type . '/' . $comment->entity_id . '/' . $comment->field_name); ++ if (!$comment->id() && empty($comment->pid->value)) { ++ $form['#action'] = url('comment/reply/' . $comment->entity_type->value . '/' . $comment->entity_id->value . '/' . $comment->field_name->value); } if (isset($form_state['comment_preview'])) { @@@ -159,32 -156,27 +158,27 @@@ '#type' => 'textfield', '#title' => t('Subject'), '#maxlength' => 64, - '#default_value' => $comment->subject, + '#default_value' => $comment->subject->value, - '#access' => variable_get('comment_subject_field_' . $node->type, 1) == 1, + '#access' => $instance['settings']['comment']['comment_subject_field'], ); // Used for conditional validation of author fields. $form['is_anonymous'] = array( '#type' => 'value', - '#value' => ($comment->cid ? !$comment->uid : !$user->uid), + '#value' => ($comment->id() ? !$comment->uid->value : !$user->uid), ); - // Add internal comment properties. - foreach (array('cid', 'pid', 'entity_id', 'entity_type', 'field_name', 'uid') as $key) { - $form[$key] = array('#type' => 'value', '#value' => $comment->$key); - } - - // Make the comment inherit the entity language unless specifically set. - $comment_langcode = $comment->langcode; + // Make the comment inherit the current content language unless specifically + // set. if ($comment->isNew()) { $language_content = language(LANGUAGE_TYPE_CONTENT); - $comment->langcode = $language_content->langcode; + $comment->langcode->value = $language_content->langcode; } - $form['langcode'] = array( - '#type' => 'value', - '#value' => $comment->langcode, - ); + // Add internal comment properties. - foreach (array('cid', 'pid', 'nid', 'uid', 'node_type', 'langcode') as $key) { ++ foreach (array('cid', 'pid', 'entity_id', 'entity_type', 'field_name', 'uid', 'langcode') as $key) { + $form[$key] = array('#type' => 'value', '#value' => $comment->$key->value); + } return parent::form($form, $form_state, $comment); } @@@ -195,9 -187,8 +189,9 @@@ protected function actions(array $form, array &$form_state) { $element = parent::actions($form, $form_state); $comment = $this->getEntity($form_state); - $entity = $form_state['comment']['entity']; - $instance = field_info_instance($comment->entity_type, $comment->field_name, $entity->bundle()); - $node = $comment->nid->entity; - $preview_mode = variable_get('comment_preview_' . $node->type, DRUPAL_OPTIONAL); ++ $entity = entity_load($comment->entity_type->value, $comment->entity_id->value); ++ $instance = field_info_instance($comment->entity_type->value, $comment->field_name->value, $entity->bundle()); + $preview_mode = $instance['settings']['comment']['comment_preview']; // No delete action on the comment form. unset($element['delete']); @@@ -333,15 -321,10 +324,15 @@@ * Overrides Drupal\Core\Entity\EntityFormController::save(). */ public function save(array $form, array &$form_state) { - $node = node_load($form_state['values']['nid']); + $entity = entity_load($form_state['values']['entity_type'], $form_state['values']['entity_id']); $comment = $this->getEntity($form_state); + $field_name = $form_state['values']['field_name']; + $instance = field_info_instance($entity->entityType(), $field_name, $entity->bundle()); - $items = field_get_items($entity->entityType(), $entity, $field_name); ++ $items = field_get_items($entity, $field_name); + $status = reset($items); + $uri = $entity->uri(); - if (user_access('post comments') && (user_access('administer comments') || $node->comment == COMMENT_NODE_OPEN)) { + if (user_access('post comments') && (user_access('administer comments') || $status['comment'] == COMMENT_OPEN)) { // Save the anonymous user information to a cookie for reuse. if (user_is_anonymous()) { user_cookie_save(array_intersect_key($form_state['values'], array_flip(array('name', 'mail', 'homepage')))); @@@ -364,18 -347,18 +355,18 @@@ } $query = array(); // Find the current display page for this comment. - $page = comment_get_display_page($comment->cid, $instance); - $page = comment_get_display_page($comment->id(), $node->type); ++ $page = comment_get_display_page($comment->id(), $instance); if ($page > 0) { $query['page'] = $page; } - // Redirect to the newly posted comment. - $redirect = array('node/' . $node->nid, array('query' => $query, 'fragment' => 'comment-' . $comment->id())); + // Redirect to the newly posted comment. @todo up to here. - $redirect = array($uri['path'], array('query' => $query, 'fragment' => 'comment-' . $comment->cid) + $uri['options']); ++ $redirect = array($uri['path'], array('query' => $query, 'fragment' => 'comment-' . $comment->id()) + $uri['options']); } else { - watchdog('content', 'Comment: unauthorized comment submitted or comment submitted to a closed post %subject.', array('%subject' => $comment->subject), WATCHDOG_WARNING); - drupal_set_message(t('Comment: unauthorized comment submitted or comment submitted to a closed post %subject.', array('%subject' => $comment->subject)), 'error'); + watchdog('content', 'Comment: unauthorized comment submitted or comment submitted to a closed post %subject.', array('%subject' => $comment->subject->value), WATCHDOG_WARNING); + drupal_set_message(t('Comment: unauthorized comment submitted or comment submitted to a closed post %subject.', array('%subject' => $comment->subject->value)), 'error'); - // Redirect the user to the node they are commenting on. - $redirect = 'node/' . $node->nid; + // Redirect the user to the entity they are commenting on. + $redirect = $uri['path']; } $form_state['redirect'] = $redirect; // Clear the block and page caches so that anonymous users see the comment diff --cc core/modules/comment/lib/Drupal/comment/CommentRenderController.php index de1bf04,a5ace07..6e61777 --- a/core/modules/comment/lib/Drupal/comment/CommentRenderController.php +++ b/core/modules/comment/lib/Drupal/comment/CommentRenderController.php @@@ -19,39 -20,39 +20,44 @@@ class CommentRenderController extends E * Overrides Drupal\Core\Entity\EntityRenderController::buildContent(). * * In addition to modifying the content key on entities, this implementation - * will also set the node key which all comments carry. + * will also set the comment entity key which all comments carry. */ - public function buildContent(array $entities = array(), $view_mode = 'full', $langcode = NULL) { + public function buildContent(array $entities, array $displays, $view_mode, $langcode = NULL) { $return = array(); if (empty($entities)) { return $return; } - // Attach user account. - user_attach_accounts($entities); + // Pre-load associated users into cache to leverage multiple loading. + $uids = array(); + foreach ($entities as $entity) { + $uids[] = $entity->uid->value; + } + user_load_multiple(array_unique($uids)); - parent::buildContent($entities, $view_mode, $langcode); + parent::buildContent($entities, $displays, $view_mode, $langcode); - // Load all nodes of all comments at once. - $nids = array(); + // Load all entities of all comments at once. + $comment_entity_ids = array(); + $comment_entities = array(); foreach ($entities as $entity) { - $comment_entity_ids[$entity->entity_type][] = $entity->entity_id; - $nids[$entity->nid->value] = $entity->nid->value; ++ $comment_entity_ids[$entity->entity_type->value][] = $entity->entity_id->value; + } - // Load entities in bulk. ++ // Load entities in bulk, this is more performant than using ++ // $comment->entity_id->value as we can load them in bulk per-type. + foreach ($comment_entity_ids as $entity_type => $entity_ids) { + $comment_entities[$entity_type] = entity_load_multiple($entity_type, $entity_ids); } - $nodes = node_load_multiple($nids); foreach ($entities as $entity) { - if (isset($comment_entities[$entity->entity_type][$entity->entity_id])) { - $comment_entity = $comment_entities[$entity->entity_type][$entity->entity_id]; - if (isset($nodes[$entity->nid->value])) { - $node = $nodes[$entity->nid->value]; ++ if (isset($comment_entities[$entity->entity_type->value][$entity->entity_id->value])) { ++ $comment_entity = $comment_entities[$entity->entity_type->value][$entity->entity_id->value]; } else { - throw new \InvalidArgumentException(t('Invalid node for comment.')); + throw new \InvalidArgumentException(t('Invalid entity for comment.')); } - $entity->content['#node'] = $node; - $entity->content['#theme'] = 'comment__node_' . $node->bundle(); + $entity->content['#entity'] = $entity; - $entity->content['#theme'] = 'comment__' . $entity->entity_type . '__' . $comment_entity->bundle() . '__' . $entity->field_name; ++ $entity->content['#theme'] = 'comment__' . $entity->entity_type->value . '__' . $comment_entity->bundle() . '__' . $entity->field_name->value; $entity->content['links'] = array( '#theme' => 'links__comment', '#pre_render' => array('drupal_pre_render_links'), @@@ -60,8 -61,8 +66,9 @@@ if (empty($entity->in_preview)) { $entity->content['links'][$this->entityType] = array( '#theme' => 'links__comment__comment', - // The "entity" property is specified to be present, so no need to check. - '#links' => comment_links($entity, $comment_entity, $entity->field_name), - // The "node" property is specified to be present, so no need to check. - '#links' => comment_links($entity, $node), ++ // The "entity" property is specified to be present, so no need to ++ // check. ++ '#links' => comment_links($entity, $comment_entity, $entity->field_name->value), '#attributes' => array('class' => array('links', 'inline')), ); } @@@ -71,14 -72,12 +78,14 @@@ /** * Overrides Drupal\Core\Entity\EntityRenderController::alterBuild(). */ - protected function alterBuild(array &$build, EntityInterface $comment, $view_mode, $langcode = NULL) { - parent::alterBuild($build, $comment, $view_mode, $langcode); + protected function alterBuild(array &$build, EntityInterface $comment, EntityDisplay $display, $view_mode, $langcode = NULL) { + parent::alterBuild($build, $comment, $display, $view_mode, $langcode); if (empty($comment->in_preview)) { $prefix = ''; - $comment_entity = entity_load($comment->entity_type, $comment->entity_id); - $instance = field_info_instance($comment_entity->entityType(), $comment->field_name, $comment_entity->bundle()); ++ $comment_entity = entity_load($comment->entity_type->value, $comment->entity_id->value); ++ $instance = field_info_instance($comment_entity->entityType(), $comment->field_name->value, $comment_entity->bundle()); $is_threaded = isset($comment->divs) - && variable_get('comment_default_mode_' . $comment->bundle(), COMMENT_MODE_THREADED) == COMMENT_MODE_THREADED; + && $instance['settings']['comment']['comment_default_mode'] == COMMENT_MODE_THREADED; // Add 'new' anchor if needed. if (!empty($comment->first_new)) { diff --cc core/modules/comment/lib/Drupal/comment/CommentStorageController.php index ac90932,4c91741..2f30275 --- a/core/modules/comment/lib/Drupal/comment/CommentStorageController.php +++ b/core/modules/comment/lib/Drupal/comment/CommentStorageController.php @@@ -29,24 -29,50 +29,41 @@@ class CommentStorageController extends */ protected function buildQuery($ids, $revision_id = FALSE) { $query = parent::buildQuery($ids, $revision_id); - // Specify additional fields from the user and node tables. - $query->innerJoin('node', 'n', 'base.nid = n.nid'); - $query->addField('n', 'type', 'node_type'); + // Specify additional fields from the user table. $query->innerJoin('users', 'u', 'base.uid = u.uid'); + // @todo: Move to a computed 'name' field instead. $query->addField('u', 'name', 'registered_name'); - $query->fields('u', array('uid', 'signature', 'signature_format')); return $query; } /** * Overrides Drupal\Core\Entity\DatabaseStorageController::attachLoad(). */ - protected function attachLoad(&$comments, $load_revision = FALSE) { + protected function attachLoad(&$records, $load_revision = FALSE) { - // Prepare standard comment fields. - foreach ($records as $key => $record) { + // Set up standard comment properties. - foreach ($comments as $key => $comment) { - $comment->name = $comment->uid ? $comment->registered_name : $comment->name; - $comment->new = comment_mark($comment); - $comments[$key] = $comment; ++ foreach ($records as $key => &$record) { + $record->name = $record->uid ? $record->registered_name : $record->name; - $record->node_type = 'comment_node_' . $record->node_type; - $records[$key] = $record; } - parent::attachLoad($comments, $load_revision); + parent::attachLoad($records, $load_revision); + } + + /** + * Overrides Drupal\Core\Entity\DatabaseStorageControllerNG::create(). + */ + public function create(array $values) { - // We have to determine the bundle first. - if (empty($values['node_type']) && !empty($values['nid'])) { - $node = node_load($values['nid']); - $values['node_type'] = 'comment_node_' . $node->type; - } - $comment = new $this->entityClass(array(), $this->entityType, $values['node_type']); ++ $comment = new $this->entityClass(array(), $this->entityType, $values['field_name']); + + // Set all other given values. + foreach ($values as $name => $value) { + $comment->$name = $value; + } + + // Assign a new UUID if there is none yet. + if ($this->uuidKey && !isset($comment->{$this->uuidKey})) { + $uuid = new Uuid(); + $comment->{$this->uuidKey}->value = $uuid->generate(); + } + return $comment; } /** @@@ -58,15 -84,19 +75,15 @@@ protected function preSave(EntityInterface $comment) { global $user; - if (!isset($comment->status)) { - $comment->status = user_access('skip comment approval') ? COMMENT_PUBLISHED : COMMENT_NOT_PUBLISHED; + if (!isset($comment->status->value)) { + $comment->status->value = user_access('skip comment approval') ? COMMENT_PUBLISHED : COMMENT_NOT_PUBLISHED; } - if (!$comment->cid) { - // Make sure we have a proper bundle name. - if (!isset($comment->node_type->value)) { - $comment->node_type->value = 'comment_node_' . $comment->nid->entity->type; - } + if ($comment->isNew()) { // Add the comment to database. This next section builds the thread field. // Also see the documentation for comment_view(). - if (!empty($comment->thread)) { + if (!empty($comment->thread->value)) { // Allow calling code to set thread itself. - $thread = $comment->thread; + $thread = $comment->thread->value; } else { if ($this->threadLock) { @@@ -74,16 -104,10 +91,16 @@@ // is extended in a faulty manner. throw new LogicException('preSave is called again without calling postSave() or releaseThreadLock()'); } - if ($comment->pid == 0) { + if ($comment->pid->value == 0) { // This is a comment with no parent comment (depth 0): we start // by retrieving the maximum thread level. - $max = db_query('SELECT MAX(thread) FROM {comment} WHERE nid = :nid', array(':nid' => $comment->nid->value))->fetchField(); + $query = db_select('comment', 'c') - ->condition('entity_id', $comment->entity_id) - ->condition('field_name', $comment->field_name) - ->condition('entity_type', $comment->entity_type); ++ ->condition('entity_id', $comment->entity_id->value) ++ ->condition('field_name', $comment->field_name->value) ++ ->condition('entity_type', $comment->entity_type->value); + $query->addExpression('MAX(thread)', 'thread'); + $max = $query->execute() + ->fetchField(); // Strip the "/" from the end of the thread. $max = rtrim($max, '/'); // We need to get the value at the correct depth. @@@ -94,20 -118,17 +111,20 @@@ else { // This is a comment with a parent comment, so increase the part of // the thread value at the proper depth. - // Get the parent comment: - $parent = comment_load($comment->pid); + $parent = $comment->pid->entity; // Strip the "/" from the end of the parent thread. - $parent->thread = (string) rtrim((string) $parent->thread, '/'); - $prefix = $parent->thread . '.'; + $parent->thread->value = (string) rtrim((string) $parent->thread->value, '/'); + $prefix = $parent->thread->value . '.'; // Get the max value in *this* thread. - $max = db_query("SELECT MAX(thread) FROM {comment} WHERE thread LIKE :thread AND nid = :nid", array( - ':thread' => $parent->thread->value . '.%', - ':nid' => $comment->nid->value, - ))->fetchField(); + $query = db_select('comment', 'c') - ->condition('entity_id', $comment->entity_id) - ->condition('field_name', $comment->field_name) - ->condition('entity_type', $comment->entity_type) - ->condition('thread', $parent->thread . '.%', 'LIKE'); ++ ->condition('entity_id', $comment->entity_id->value) ++ ->condition('field_name', $comment->field_name->value) ++ ->condition('entity_type', $comment->entity_type->value) ++ ->condition('thread', $parent->thread->value . '.%', 'LIKE'); + $query->addExpression('MAX(thread)', 'thread'); + $max = $query->execute() + ->fetchField(); if ($max == '') { // First child of this parent. As the other two cases do an @@@ -129,14 -150,14 +146,14 @@@ // has the lock, just move to the next integer. do { $thread = $prefix . comment_int_to_alphadecimal(++$n) . '/'; - } while (!lock()->acquire("comment:$comment->entity_id:$comment->entity_type:$thread")); - } while (!lock()->acquire("comment:{$comment->nid->value}:$thread")); ++ } while (!lock()->acquire("comment:{$comment->entity_id->value}:{$comment->entity_type->value}:$thread")); $this->threadLock = $thread; } - if (empty($comment->created)) { - $comment->created = REQUEST_TIME; + if (empty($comment->created->value)) { + $comment->created->value = REQUEST_TIME; } - if (empty($comment->changed)) { - $comment->changed = $comment->created; + if (empty($comment->changed->value)) { + $comment->changed->value = $comment->created->value; } // We test the value with '===' because we need to modify anonymous // users as well. @@@ -154,9 -175,9 +171,9 @@@ */ protected function postSave(EntityInterface $comment, $update) { $this->releaseThreadLock(); - // Update the {node_comment_statistics} table prior to executing the hook. - $this->updateNodeStatistics($comment->nid->value); + // Update the {comment_entity_statistics} table prior to executing the hook. + $this->updateEntityStatistics($comment); - if ($comment->status == COMMENT_PUBLISHED) { + if ($comment->status->value == COMMENT_PUBLISHED) { module_invoke_all('comment_publish', $comment); } } @@@ -201,28 -221,18 +218,28 @@@ return; } - $count = db_query('SELECT COUNT(cid) FROM {comment} WHERE nid = :nid AND status = :status', array( - ':nid' => $nid, - ':status' => COMMENT_PUBLISHED, - ))->fetchField(); + $query = db_select('comment', 'c'); + $query->addExpression('COUNT(cid)'); - $count = $query->condition('c.entity_id', $comment->entity_id) - ->condition('c.entity_type', $comment->entity_type) - ->condition('c.field_name', $comment->field_name) ++ $count = $query->condition('c.entity_id', $comment->entity_id->value) ++ ->condition('c.entity_type', $comment->entity_type->value) ++ ->condition('c.field_name', $comment->field_name->value) + ->condition('c.status', COMMENT_PUBLISHED) + ->execute() + ->fetchField(); if ($count > 0) { // Comments exist. - $last_reply = db_query_range('SELECT cid, name, changed, uid FROM {comment} WHERE nid = :nid AND status = :status ORDER BY cid DESC', 0, 1, array( - ':nid' => $nid, - ':status' => COMMENT_PUBLISHED, - ))->fetchObject(); - db_update('node_comment_statistics') + $last_reply = db_select('comment', 'c') + ->fields('c', array('cid', 'name', 'changed', 'uid')) - ->condition('c.entity_id', $comment->entity_id) - ->condition('c.entity_type', $comment->entity_type) - ->condition('c.field_name', $comment->field_name) ++ ->condition('c.entity_id', $comment->entity_id->value) ++ ->condition('c.entity_type', $comment->entity_type->value) ++ ->condition('c.field_name', $comment->field_name->value) + ->condition('c.status', COMMENT_PUBLISHED) + ->orderBy('c.created', 'DESC') + ->range(0, 1) + ->execute() + ->fetchObject(); + db_update('comment_entity_statistics') ->fields(array( 'cid' => $last_reply->cid, 'comment_count' => $count, @@@ -230,29 -240,21 +247,29 @@@ 'last_comment_name' => $last_reply->uid ? '' : $last_reply->name, 'last_comment_uid' => $last_reply->uid, )) - ->condition('entity_id', $comment->entity_id) - ->condition('entity_type', $comment->entity_type) - ->condition('field_name', $comment->field_name) - ->condition('nid', $nid) ++ ->condition('entity_id', $comment->entity_id->value) ++ ->condition('entity_type', $comment->entity_type->value) ++ ->condition('field_name', $comment->field_name->value) ->execute(); } else { // Comments do not exist. - $entity = entity_load($comment->entity_type, $comment->entity_id); - $node = db_query('SELECT uid, created FROM {node} WHERE nid = :nid', array(':nid' => $nid))->fetchObject(); - db_update('node_comment_statistics') ++ $entity = entity_load($comment->entity_type->value, $comment->entity_id->value); + db_update('comment_entity_statistics') ->fields(array( 'cid' => 0, 'comment_count' => 0, - 'last_comment_timestamp' => $node->created, + // Use created date of entity or default to REQUEST_TIME if none + // exists. + 'last_comment_timestamp' => isset($entity->created) ? $entity->created : REQUEST_TIME, 'last_comment_name' => '', - 'last_comment_uid' => $node->uid, + // @todo refactor when http://drupal.org/node/585838 lands. + // Get uid from entity or default to logged in user if none exists. + 'last_comment_uid' => isset($entity->uid) ? $entity->uid : $user->uid, )) - ->condition('entity_id', $comment->entity_id) - ->condition('entity_type', $comment->entity_type) - ->condition('field_name', $comment->field_name) - ->condition('nid', $nid) ++ ->condition('entity_id', $comment->entity_id->value) ++ ->condition('entity_type', $comment->entity_type->value) ++ ->condition('field_name', $comment->field_name->value) ->execute(); } } @@@ -266,4 -268,105 +283,107 @@@ $this->threadLock = ''; } } + + /** + * Implements \Drupal\Core\Entity\DataBaseStorageControllerNG::basePropertyDefinitions(). + */ + public function baseFieldDefinitions() { + $properties['cid'] = array( + 'label' => t('ID'), + 'description' => t('The comment ID.'), + 'type' => 'integer_field', + 'read-only' => TRUE, + ); + $properties['uuid'] = array( + 'label' => t('UUID'), + 'description' => t('The comment UUID.'), + 'type' => 'string_field', + ); + $properties['pid'] = array( + 'label' => t('Parent ID'), + 'description' => t('The parent comment ID if this is a reply to a comment.'), + 'type' => 'entityreference_field', + 'settings' => array('entity type' => 'comment'), + ); - $properties['nid'] = array( - 'label' => t('Node ID'), - 'description' => t('The ID of the node of which this comment is a reply.'), - 'type' => 'entityreference_field', - 'settings' => array('entity type' => 'node'), ++ $properties['entity_id'] = array( ++ 'label' => t('Entity ID'), ++ 'description' => t('The ID of the entity of which this comment is a reply.'), ++ 'type' => 'integer_field', + 'required' => TRUE, + ); + $properties['langcode'] = array( + 'label' => t('Language code'), + 'description' => t('The comment language code.'), + 'type' => 'language_field', + ); + $properties['subject'] = array( + 'label' => t('Subject'), + 'description' => t('The comment title or subject.'), + 'type' => 'string_field', + ); + $properties['uid'] = array( + 'label' => t('User ID'), + 'description' => t('The user ID of the comment author.'), + 'type' => 'entityreference_field', + 'settings' => array('entity type' => 'user'), + ); + $properties['name'] = array( + 'label' => t('Name'), + 'description' => t("The comment author's name."), + 'type' => 'string_field', + ); + $properties['mail'] = array( + 'label' => t('e-mail'), + 'description' => t("The comment author's e-mail address."), + 'type' => 'string_field', + ); + $properties['homepage'] = array( + 'label' => t('Homepage'), + 'description' => t("The comment author's home page address."), + 'type' => 'string_field', + ); + $properties['hostname'] = array( + 'label' => t('Hostname'), + 'description' => t("The comment author's hostname."), + 'type' => 'string_field', + ); + $properties['created'] = array( + 'label' => t('Created'), + 'description' => t('The time that the comment was created.'), + 'type' => 'integer_field', + ); + $properties['changed'] = array( + 'label' => t('Changed'), + 'description' => t('The time that the comment was last edited.'), + 'type' => 'integer_field', + ); + $properties['status'] = array( + 'label' => t('Publishing status'), + 'description' => t('A boolean indicating whether the comment is published.'), + 'type' => 'boolean_field', + ); + $properties['thread'] = array( + 'label' => t('Thread place'), + 'description' => t("The alphadecimal representation of the comment's place in a thread, consisting of a base 36 string prefixed by an integer indicating its length."), + 'type' => 'string_field', + ); - $properties['node_type'] = array( - // @todo: The bundle property should be stored so it's queryable. - 'label' => t('Node type'), - 'description' => t("The comment node type."), ++ $properties['field_name'] = array( ++ 'label' => t('Field name'), ++ 'description' => t("The comment field name."), ++ 'type' => 'string_field', ++ ); ++ $properties['entity_type'] = array( ++ 'label' => t('Entity type'), ++ 'description' => t("The entity type to which this comment is attached."), + 'type' => 'string_field', - 'queryable' => FALSE, + ); + $properties['new'] = array( + 'label' => t('Comment new marker'), + 'description' => t("The comment 'new' marker for the current user (0 read, 1 new, 2 updated)."), + 'type' => 'integer_field', + 'computed' => TRUE, + 'class' => '\Drupal\comment\FieldNewItem', + ); + return $properties; + } } diff --cc core/modules/comment/lib/Drupal/comment/FieldNewValue.php index 0000000,c3e0d94..9734f4b mode 000000,100644..100644 --- a/core/modules/comment/lib/Drupal/comment/FieldNewValue.php +++ b/core/modules/comment/lib/Drupal/comment/FieldNewValue.php @@@ -1,0 -1,44 +1,44 @@@ + value)) { + if (!isset($this->parent)) { + throw new InvalidArgumentException('Computed properties require context for computation.'); + } + $field = $this->parent->getParent(); + $entity = $field->getParent(); - $this->value = node_mark($entity->nid->value, $entity->changed->value); ++ $this->value = comment_mark($entity); + } + return $this->value; + } + + /** + * Implements \Drupal\Core\TypedData\TypedDataInterface::setValue(). + */ + public function setValue($value) { + if (isset($value)) { + throw new ReadOnlyException('Unable to set a computed property.'); + } + } + } diff --cc core/modules/comment/lib/Drupal/comment/Plugin/Core/Entity/Comment.php index 80380b2,c6175af..ad218bd --- a/core/modules/comment/lib/Drupal/comment/Plugin/Core/Entity/Comment.php +++ b/core/modules/comment/lib/Drupal/comment/Plugin/Core/Entity/Comment.php @@@ -32,7 -32,7 +32,7 @@@ use Drupal\Core\Annotation\Translation * static_cache = FALSE, * entity_keys = { * "id" = "cid", -- * "bundle" = "node_type", ++ * "bundle" = "field_name", * "label" = "subject", * "uuid" = "uuid" * }, @@@ -61,44 -63,27 +63,41 @@@ class Comment extends EntityNG implemen public $uuid; /** - * The parent comment ID if this is a reply to a comment. + * The entity ID to which this comment is attached. * - * @var integer - * @todo: Rename to 'parent_id'. ++ * @var \Drupal\Core\Entity\Field\FieldInterface + */ + public $entity_id; + + /** + * The entity type to which this comment is attached. * - * @var string + * @var \Drupal\Core\Entity\Field\FieldInterface */ - public $pid; + public $entity_type; /** - * The ID of the node to which the comment is attached. + * The field to which this comment is attached. * - * @var string + * @var \Drupal\Core\Entity\Field\FieldInterface */ - public $field_name = 'comment'; - public $nid; ++ public $field_name; + + /** + * The parent comment ID if this is a reply to a comment. + * - * @var integer ++ * @todo: Rename to 'parent_id'. ++ * ++ * @var \Drupal\Core\Entity\Field\FieldInterface + */ + public $pid; /** - * The ID of the node to which the comment is attached. - */ - public $nid; - - /** * The comment language code. * - * @var string + * @var \Drupal\Core\Entity\Field\FieldInterface */ - public $langcode = LANGUAGE_NOT_SPECIFIED; + public $langcode; /** * The comment title. @@@ -143,23 -128,95 +142,96 @@@ public $homepage; /** - * The entity which this comment is attached. + * The comment author's hostname. * - * @var Drupal\Core\Entity\EntityInterface + * @var \Drupal\Core\Entity\Field\FieldInterface */ - protected $entity; + public $hostname; /** - * Implements Drupal\Core\Entity\EntityInterface::id(). + * The time that the comment was created. + * + * @var \Drupal\Core\Entity\Field\FieldInterface */ - public function id() { - return $this->cid; + public $created; + + /** + * The time that the comment was last edited. + * + * @var \Drupal\Core\Entity\Field\FieldInterface + */ + public $changed; + + /** + * A boolean field indicating whether the comment is published. + * + * @var \Drupal\Core\Entity\Field\FieldInterface + */ + public $status; + + /** + * The alphadecimal representation of the comment's place in a thread. + * + * @var \Drupal\Core\Entity\Field\FieldInterface + */ + public $thread; + + /** - * The comment node type. - * - * @var \Drupal\Core\Entity\Field\FieldInterface - */ - public $node_type; - - /** + * The comment 'new' marker for the current user. + * + * @var \Drupal\Core\Entity\Field\FieldInterface + */ + public $new; + + /** + * The plain data values of the contained properties. + * + * Define default values. + * + * @var array + */ + protected $values = array( + 'langcode' => array(LANGUAGE_DEFAULT => array(0 => array('value' => LANGUAGE_NOT_SPECIFIED))), + 'name' => array(LANGUAGE_DEFAULT => array(0 => array('value' => ''))), + 'uid' => array(LANGUAGE_DEFAULT => array(0 => array('value' => 0))), + ); + + /** + * Initialize the object. Invoked upon construction and wake up. + */ + protected function init() { + parent::init(); + // We unset all defined properties, so magic getters apply. + unset($this->cid); + unset($this->uuid); + unset($this->pid); - unset($this->nid); ++ unset($this->entity_id); ++ unset($this->field_name); + unset($this->subject); + unset($this->uid); + unset($this->name); + unset($this->mail); + unset($this->homepage); + unset($this->hostname); + unset($this->created); + unset($this->changed); + unset($this->status); + unset($this->thread); - unset($this->node_type); ++ unset($this->entity_type); + unset($this->new); } /** + * Implements Drupal\Core\Entity\EntityInterface::bundle(). + */ + public function bundle() { - return $this->field_name; ++ return $this->get('field_name')->value; ++ } ++ ++ /** + * Implements Drupal\Core\Entity\EntityInterface::id(). + */ + public function id() { + return $this->get('cid')->value; } } diff --cc core/modules/comment/lib/Drupal/comment/Tests/CommentAnonymousTest.php index 6647f697,86f778a..bd18fc8 --- a/core/modules/comment/lib/Drupal/comment/Tests/CommentAnonymousTest.php +++ b/core/modules/comment/lib/Drupal/comment/Tests/CommentAnonymousTest.php @@@ -161,7 -161,7 +161,7 @@@ class CommentAnonymousTest extends Comm $this->assertFieldByName('subject', '', 'Subject field found.'); $this->assertFieldByName("comment_body[$langcode][0][value]", '', 'Comment field found.'); - $this->drupalGet('comment/reply/node/' . $this->node->nid . '/comment/' . $anonymous_comment3->id); - $this->drupalGet('comment/reply/' . $this->node->nid . '/' . $anonymous_comment3->id()); ++ $this->drupalGet('comment/reply/node/' . $this->node->nid . '/comment/' . $anonymous_comment3->id()); $this->assertText('You are not authorized to view comments', 'Error attempting to post reply.'); $this->assertNoText($author_name, 'Comment not displayed.'); } diff --cc core/modules/comment/lib/Drupal/comment/Tests/CommentApprovalTest.php index 62a7812,e123fc4..3662a01 --- a/core/modules/comment/lib/Drupal/comment/Tests/CommentApprovalTest.php +++ b/core/modules/comment/lib/Drupal/comment/Tests/CommentApprovalTest.php @@@ -47,7 -47,7 +47,14 @@@ class CommentApprovalTest extends Comme // Get unapproved comment id. $this->drupalLogin($this->admin_user); $anonymous_comment4 = $this->getUnapprovedComment($subject); - $anonymous_comment4 = entity_create('comment', array('id' => $anonymous_comment4, 'subject' => $subject, 'comment' => $body)); - $anonymous_comment4 = entity_create('comment', array('cid' => $anonymous_comment4, 'subject' => $subject, 'comment_body' => $body, 'nid' => $this->node->nid)); ++ $anonymous_comment4 = entity_create('comment', array( ++ 'cid' => $anonymous_comment4, ++ 'subject' => $subject, ++ 'comment_body' => $body, ++ 'entity_id' => $this->node->nid, ++ 'entity_type' => 'node', ++ 'field_name' => 'comment' ++ )); $this->drupalLogout(); $this->assertFalse($this->commentExists($anonymous_comment4), 'Anonymous comment was not published.'); @@@ -111,7 -111,7 +118,14 @@@ // Get unapproved comment id. $this->drupalLogin($this->admin_user); $anonymous_comment4 = $this->getUnapprovedComment($subject); - $anonymous_comment4 = entity_create('comment', array('id' => $anonymous_comment4, 'subject' => $subject, 'comment' => $body)); - $anonymous_comment4 = entity_create('comment', array('cid' => $anonymous_comment4, 'subject' => $subject, 'comment_body' => $body, 'nid' => $this->node->nid)); ++ $anonymous_comment4 = entity_create('comment', array( ++ 'cid' => $anonymous_comment4, ++ 'subject' => $subject, ++ 'comment_body' => $body, ++ 'entity_id' => $this->node->nid, ++ 'entity_type' => 'node', ++ 'field_name' => 'comment' ++ )); $this->drupalLogout(); $this->assertFalse($this->commentExists($anonymous_comment4), 'Anonymous comment was not published.'); diff --cc core/modules/comment/lib/Drupal/comment/Tests/CommentInterfaceTest.php index aec91e0,36f9f43..4e19986 --- a/core/modules/comment/lib/Drupal/comment/Tests/CommentInterfaceTest.php +++ b/core/modules/comment/lib/Drupal/comment/Tests/CommentInterfaceTest.php @@@ -90,17 -86,17 +86,17 @@@ class CommentInterfaceTest extends Comm // Reply to comment #2 creating comment #3 with optional preview and no // subject though field enabled. $this->drupalLogin($this->web_user); - $this->drupalGet('comment/reply/node/' . $this->node->nid . '/comment/' . $comment->id); - $this->drupalGet('comment/reply/' . $this->node->nid . '/' . $comment->id()); ++ $this->drupalGet('comment/reply/node/' . $this->node->nid . '/comment/' . $comment->id()); $this->assertText($subject_text, 'Individual comment-reply subject found.'); $this->assertText($comment_text, 'Individual comment-reply body found.'); $reply = $this->postComment(NULL, $this->randomName(), '', TRUE); - $reply_loaded = comment_load($reply->id); + $reply_loaded = comment_load($reply->id()); $this->assertTrue($this->commentExists($reply, TRUE), 'Reply found.'); - $this->assertEqual($comment->id, $reply_loaded->pid, 'Pid of a reply to a comment is set correctly.'); - $this->assertEqual(rtrim($comment_loaded->thread, '/') . '.00/', $reply_loaded->thread, 'Thread of reply grows correctly.'); + $this->assertEqual($comment->id(), $reply_loaded->pid->value, 'Pid of a reply to a comment is set correctly.'); + $this->assertEqual(rtrim($comment->thread->value, '/') . '.00/', $reply_loaded->thread->value, 'Thread of reply grows correctly.'); // Second reply to comment #3 creating comment #4. - $this->drupalGet('comment/reply/node/' . $this->node->nid . '/comment/' . $comment->id); - $this->drupalGet('comment/reply/' . $this->node->nid . '/' . $comment->id()); ++ $this->drupalGet('comment/reply/node/' . $this->node->nid . '/comment/' . $comment->id()); $this->assertText($subject_text, 'Individual comment-reply subject found.'); $this->assertText($comment_text, 'Individual comment-reply body found.'); $reply = $this->postComment(NULL, $this->randomName(), $this->randomName(), TRUE); @@@ -126,9 -122,9 +122,9 @@@ $this->setCommentsPerPage(50); // Attempt to reply to an unpublished comment. - $reply_loaded->status = COMMENT_NOT_PUBLISHED; + $reply_loaded->status->value = COMMENT_NOT_PUBLISHED; $reply_loaded->save(); - $this->drupalGet('comment/reply/node/' . $this->node->nid . '/comment/' . $reply_loaded->cid); - $this->drupalGet('comment/reply/' . $this->node->nid . '/' . $reply_loaded->id()); ++ $this->drupalGet('comment/reply/node/' . $this->node->nid . '/comment/' . $reply_loaded->id()); $this->assertText(t('The comment you are replying to does not exist.'), 'Replying to an unpublished comment'); // Attempt to post to node with comments disabled. diff --cc core/modules/comment/lib/Drupal/comment/Tests/CommentNodeAccessTest.php index 93c64f5,7910196..f8a8afd --- a/core/modules/comment/lib/Drupal/comment/Tests/CommentNodeAccessTest.php +++ b/core/modules/comment/lib/Drupal/comment/Tests/CommentNodeAccessTest.php @@@ -75,7 -73,7 +73,7 @@@ class CommentNodeAccessTest extends Com $this->assertText($comment_text, 'Individual comment body found.'); // Reply to comment, creating second comment. - $this->drupalGet('comment/reply/node/' . $this->node->nid . '/comment/' . $comment->id); - $this->drupalGet('comment/reply/' . $this->node->nid . '/' . $comment->id()); ++ $this->drupalGet('comment/reply/node/' . $this->node->nid . '/comment/' . $comment->id()); $reply_text = $this->randomName(); $reply_subject = $this->randomName(); $reply = $this->postComment(NULL, $reply_text, $reply_subject, TRUE); diff --cc core/modules/comment/lib/Drupal/comment/Tests/CommentPagerTest.php index af94601,644001c..faa94b2 --- a/core/modules/comment/lib/Drupal/comment/Tests/CommentPagerTest.php +++ b/core/modules/comment/lib/Drupal/comment/Tests/CommentPagerTest.php @@@ -66,7 -66,7 +66,7 @@@ class CommentPagerTest extends CommentT // Post a reply to the oldest comment and test again. $replies = array(); $oldest_comment = reset($comments); - $this->drupalGet('comment/reply/node/' . $node->nid . '/comment/' . $oldest_comment->id); - $this->drupalGet('comment/reply/' . $node->nid . '/' . $oldest_comment->id()); ++ $this->drupalGet('comment/reply/node/' . $node->nid . '/comment/' . $oldest_comment->id()); $reply = $this->postComment(NULL, $this->randomName(), $this->randomName(), TRUE); $this->setCommentsPerPage(2); @@@ -114,19 -114,19 +114,19 @@@ $comments[] = $this->postComment($node, $this->randomName(), $this->randomName(), TRUE); // Post a reply to the second comment. - $this->drupalGet('comment/reply/node/' . $node->nid . '/comment/' . $comments[1]->id); - $this->drupalGet('comment/reply/' . $node->nid . '/' . $comments[1]->id()); ++ $this->drupalGet('comment/reply/node/' . $node->nid . '/comment/' . $comments[1]->id()); $comments[] = $this->postComment(NULL, $this->randomName(), $this->randomName(), TRUE); // Post a reply to the first comment. - $this->drupalGet('comment/reply/node/' . $node->nid . '/comment/' . $comments[0]->id); - $this->drupalGet('comment/reply/' . $node->nid . '/' . $comments[0]->id()); ++ $this->drupalGet('comment/reply/node/' . $node->nid . '/comment/' . $comments[0]->id()); $comments[] = $this->postComment(NULL, $this->randomName(), $this->randomName(), TRUE); // Post a reply to the last comment. - $this->drupalGet('comment/reply/node/' . $node->nid . '/comment/' . $comments[2]->id); - $this->drupalGet('comment/reply/' . $node->nid . '/' . $comments[2]->id()); ++ $this->drupalGet('comment/reply/node/' . $node->nid . '/comment/' . $comments[2]->id()); $comments[] = $this->postComment(NULL, $this->randomName(), $this->randomName(), TRUE); // Post a reply to the second comment. - $this->drupalGet('comment/reply/node/' . $node->nid . '/comment/' . $comments[3]->id); - $this->drupalGet('comment/reply/' . $node->nid . '/' . $comments[3]->id()); ++ $this->drupalGet('comment/reply/node/' . $node->nid . '/comment/' . $comments[3]->id()); $comments[] = $this->postComment(NULL, $this->randomName(), $this->randomName(), TRUE); // At this point, the comment tree is: @@@ -215,15 -214,15 +214,15 @@@ $comments[] = $this->postComment($node, $this->randomName(), $this->randomName(), TRUE); // Post a reply to the second comment. - $this->drupalGet('comment/reply/node/' . $node->nid . '/comment/' . $comments[1]->id); - $this->drupalGet('comment/reply/' . $node->nid . '/' . $comments[1]->id()); ++ $this->drupalGet('comment/reply/node/' . $node->nid . '/comment/' . $comments[1]->id()); $comments[] = $this->postComment(NULL, $this->randomName(), $this->randomName(), TRUE); // Post a reply to the first comment. - $this->drupalGet('comment/reply/node/' . $node->nid . '/comment/' . $comments[0]->id); - $this->drupalGet('comment/reply/' . $node->nid . '/' . $comments[0]->id()); ++ $this->drupalGet('comment/reply/node/' . $node->nid . '/comment/' . $comments[0]->id()); $comments[] = $this->postComment(NULL, $this->randomName(), $this->randomName(), TRUE); // Post a reply to the last comment. - $this->drupalGet('comment/reply/node/' . $node->nid . '/comment/' . $comments[2]->id); - $this->drupalGet('comment/reply/' . $node->nid . '/' . $comments[2]->id()); ++ $this->drupalGet('comment/reply/node/' . $node->nid . '/comment/' . $comments[2]->id()); $comments[] = $this->postComment(NULL, $this->randomName(), $this->randomName(), TRUE); // At this point, the comment tree is: diff --cc core/modules/comment/lib/Drupal/comment/Tests/CommentStatisticsTest.php index 390a10b,4578ade..77b5efd --- a/core/modules/comment/lib/Drupal/comment/Tests/CommentStatisticsTest.php +++ b/core/modules/comment/lib/Drupal/comment/Tests/CommentStatisticsTest.php @@@ -80,9 -78,8 +78,9 @@@ class CommentStatisticsTest extends Com $this->drupalLogout(); // Post comment #2 as anonymous (comment approval enabled). - $this->drupalGet('comment/reply/' . $this->node->nid); - $this->postComment($this->node, $this->randomName(), '', TRUE); + $this->drupalGet('comment/reply/node/' . $this->node->nid . '/comment'); + $anonymous_comment = $this->postComment($this->node, $this->randomName(), '', TRUE); - $comment_unpublished_loaded = comment_load($anonymous_comment->id); ++ $comment_unpublished_loaded = comment_load($anonymous_comment->id()); // Checks the new values of node comment statistics with comment #2 and // ensure they haven't changed since the comment has not been moderated. @@@ -102,16 -99,15 +100,16 @@@ $this->drupalLogout(); // Post comment #3 as anonymous. - $this->drupalGet('comment/reply/' . $this->node->nid); - $comment_loaded = $this->postComment($this->node, $this->randomName(), '', array('name' => $this->randomName())); + $this->drupalGet('comment/reply/node/' . $this->node->nid . '/comment'); + $anonymous_comment = $this->postComment($this->node, $this->randomName(), '', array('name' => $this->randomName())); - $comment_loaded = comment_load($anonymous_comment->id); ++ $comment_loaded = comment_load($anonymous_comment->id()); // Checks the new values of node comment statistics with comment #3. // The node needs to be reloaded with a node_load_multiple cache reset. $node = node_load($this->node->nid, TRUE); - $this->assertEqual($node->comment_statistics['comment']->last_comment_name, $comment_loaded->name, 'The value of node last_comment_name is the name of the anonymous user.'); - $this->assertEqual($node->last_comment_name, $comment_loaded->name->value, 'The value of node last_comment_name is the name of the anonymous user.'); - $this->assertEqual($node->last_comment_uid, 0, 'The value of node last_comment_uid is zero.'); - $this->assertEqual($node->comment_count, 2, 'The value of node comment_count is 2.'); ++ $this->assertEqual($node->comment_statistics['comment']->last_comment_name, $comment_loaded->name->value, 'The value of node last_comment_name is the name of the anonymous user.'); + $this->assertEqual($node->comment_statistics['comment']->last_comment_uid, 0, 'The value of node last_comment_uid is zero.'); + $this->assertEqual($node->comment_statistics['comment']->comment_count, 2, 'The value of node comment_count is 2.'); } } diff --cc core/modules/comment/lib/Drupal/comment/Tests/CommentThreadingTest.php index 7c59f37,6f2837a..b8dd07a --- a/core/modules/comment/lib/Drupal/comment/Tests/CommentThreadingTest.php +++ b/core/modules/comment/lib/Drupal/comment/Tests/CommentThreadingTest.php @@@ -50,35 -49,32 +49,32 @@@ class CommentThreadingTest extends Comm // Reply to comment #1 creating comment #2. $this->drupalLogin($this->web_user); - $this->drupalGet('comment/reply/node/' . $this->node->nid . '/comment/' . $comment1->id); - $this->drupalGet('comment/reply/' . $this->node->nid . '/' . $comment1->id()); ++ $this->drupalGet('comment/reply/node/' . $this->node->nid . '/comment/' . $comment1->id()); $comment2 = $this->postComment(NULL, $this->randomName(), '', TRUE); // Confirm that the comment was created and has the correct threading. - $comment2_loaded = comment_load($comment2->id); $this->assertTrue($this->commentExists($comment2, TRUE), 'Comment #2. Reply found.'); - $this->assertEqual($comment2_loaded->thread, '01.00/'); + $this->assertEqual($comment2->thread->value, '01.00/'); // Confirm that there is a link to the parent comment. - $this->assertParentLink($comment2->id, $comment1->id); + $this->assertParentLink($comment2->id(), $comment1->id()); // Reply to comment #2 creating comment #3. - $this->drupalGet('comment/reply/node/' . $this->node->nid . '/comment/' . $comment2->id); - $this->drupalGet('comment/reply/' . $this->node->nid . '/' . $comment2->id()); ++ $this->drupalGet('comment/reply/node/' . $this->node->nid . '/comment/' . $comment2->id()); $comment3 = $this->postComment(NULL, $this->randomName(), $this->randomName(), TRUE); // Confirm that the comment was created and has the correct threading. - $comment3_loaded = comment_load($comment3->id); $this->assertTrue($this->commentExists($comment3, TRUE), 'Comment #3. Second reply found.'); - $this->assertEqual($comment3_loaded->thread, '01.00.00/'); + $this->assertEqual($comment3->thread->value, '01.00.00/'); // Confirm that there is a link to the parent comment. - $this->assertParentLink($comment3->id, $comment2->id); + $this->assertParentLink($comment3->id(), $comment2->id()); // Reply to comment #1 creating comment #4. $this->drupalLogin($this->web_user); - $this->drupalGet('comment/reply/node/' . $this->node->nid . '/comment/' . $comment1->id); - $this->drupalGet('comment/reply/' . $this->node->nid . '/' . $comment1->id()); ++ $this->drupalGet('comment/reply/node/' . $this->node->nid . '/comment/' . $comment1->id()); $comment4 = $this->postComment(NULL, $this->randomName(), '', TRUE); // Confirm that the comment was created and has the correct threading. - $comment4_loaded = comment_load($comment4->id); $this->assertTrue($this->commentExists($comment4), 'Comment #4. Third reply found.'); - $this->assertEqual($comment4_loaded->thread, '01.01/'); + $this->assertEqual($comment4->thread->value, '01.01/'); // Confirm that there is a link to the parent comment. - $this->assertParentLink($comment4->id, $comment1->id); + $this->assertParentLink($comment4->id(), $comment1->id()); // Post comment #2 overall comment #5. $this->drupalLogin($this->web_user); @@@ -94,35 -89,32 +89,32 @@@ // Reply to comment #5 creating comment #6. $this->drupalLogin($this->web_user); - $this->drupalGet('comment/reply/node/' . $this->node->nid . '/comment/' . $comment5->id); - $this->drupalGet('comment/reply/' . $this->node->nid . '/' . $comment5->id()); ++ $this->drupalGet('comment/reply/node/' . $this->node->nid . '/comment/' . $comment5->id()); $comment6 = $this->postComment(NULL, $this->randomName(), '', TRUE); // Confirm that the comment was created and has the correct threading. - $comment6_loaded = comment_load($comment6->id); $this->assertTrue($this->commentExists($comment6, TRUE), 'Comment #6. Reply found.'); - $this->assertEqual($comment6_loaded->thread, '02.00/'); + $this->assertEqual($comment6->thread->value, '02.00/'); // Confirm that there is a link to the parent comment. - $this->assertParentLink($comment6->id, $comment5->id); + $this->assertParentLink($comment6->id(), $comment5->id()); // Reply to comment #6 creating comment #7. - $this->drupalGet('comment/reply/node/' . $this->node->nid . '/comment/' . $comment6->id); - $this->drupalGet('comment/reply/' . $this->node->nid . '/' . $comment6->id()); ++ $this->drupalGet('comment/reply/node/' . $this->node->nid . '/comment/' . $comment6->id()); $comment7 = $this->postComment(NULL, $this->randomName(), $this->randomName(), TRUE); // Confirm that the comment was created and has the correct threading. - $comment7_loaded = comment_load($comment7->id); $this->assertTrue($this->commentExists($comment7, TRUE), 'Comment #7. Second reply found.'); - $this->assertEqual($comment7_loaded->thread, '02.00.00/'); + $this->assertEqual($comment7->thread->value, '02.00.00/'); // Confirm that there is a link to the parent comment. - $this->assertParentLink($comment7->id, $comment6->id); + $this->assertParentLink($comment7->id(), $comment6->id()); // Reply to comment #5 creating comment #8. $this->drupalLogin($this->web_user); - $this->drupalGet('comment/reply/node/' . $this->node->nid . '/comment/' . $comment5->id); - $this->drupalGet('comment/reply/' . $this->node->nid . '/' . $comment5->id()); ++ $this->drupalGet('comment/reply/node/' . $this->node->nid . '/comment/' . $comment5->id()); $comment8 = $this->postComment(NULL, $this->randomName(), '', TRUE); // Confirm that the comment was created and has the correct threading. - $comment8_loaded = comment_load($comment8->id); $this->assertTrue($this->commentExists($comment8), 'Comment #8. Third reply found.'); - $this->assertEqual($comment8_loaded->thread, '02.01/'); + $this->assertEqual($comment8->thread->value, '02.01/'); // Confirm that there is a link to the parent comment. - $this->assertParentLink($comment8->id, $comment5->id); + $this->assertParentLink($comment8->id(), $comment5->id()); } /** diff --cc core/modules/comment/lib/Drupal/comment/Tests/CommentTokenReplaceTest.php index 6cb7d57,5421c0b..956388e --- a/core/modules/comment/lib/Drupal/comment/Tests/CommentTokenReplaceTest.php +++ b/core/modules/comment/lib/Drupal/comment/Tests/CommentTokenReplaceTest.php @@@ -39,33 -39,33 +39,33 @@@ class CommentTokenReplaceTest extends C $parent_comment = $this->postComment($node, $this->randomName(), $this->randomName(), TRUE); // Post a reply to the comment. - $this->drupalGet('comment/reply/node/' . $node->nid . '/comment/' . $parent_comment->id); - $this->drupalGet('comment/reply/' . $node->nid . '/' . $parent_comment->id()); ++ $this->drupalGet('comment/reply/node/' . $node->nid . '/comment/' . $parent_comment->id()); $child_comment = $this->postComment(NULL, $this->randomName(), $this->randomName()); - $comment = comment_load($child_comment->id); - $comment->homepage = 'http://example.org/'; + $comment = comment_load($child_comment->id()); + $comment->homepage->value = 'http://example.org/'; // Add HTML to ensure that sanitation of some fields tested directly. - $comment->subject = 'Blinking Comment'; + $comment->subject->value = 'Blinking Comment'; $instance = field_info_instance('comment', 'body', 'comment_body'); // Generate and test sanitized tokens. $tests = array(); - $tests['[comment:cid]'] = $comment->cid; - $tests['[comment:hostname]'] = check_plain($comment->hostname); - $tests['[comment:name]'] = filter_xss($comment->name); + $tests['[comment:cid]'] = $comment->id(); + $tests['[comment:hostname]'] = check_plain($comment->hostname->value); + $tests['[comment:name]'] = filter_xss($comment->name->value); $tests['[comment:mail]'] = check_plain($this->admin_user->mail); - $tests['[comment:homepage]'] = check_url($comment->homepage); - $tests['[comment:title]'] = filter_xss($comment->subject); - $tests['[comment:body]'] = _text_sanitize($instance, LANGUAGE_NOT_SPECIFIED, $comment->comment_body[LANGUAGE_NOT_SPECIFIED][0], 'value'); - $tests['[comment:url]'] = url('comment/' . $comment->cid, $url_options + array('fragment' => 'comment-' . $comment->cid)); - $tests['[comment:edit-url]'] = url('comment/' . $comment->cid . '/edit', $url_options); - $tests['[comment:created:since]'] = format_interval(REQUEST_TIME - $comment->created, 2, $language_interface->langcode); - $tests['[comment:changed:since]'] = format_interval(REQUEST_TIME - $comment->changed, 2, $language_interface->langcode); - $tests['[comment:parent:cid]'] = $comment->pid; - $tests['[comment:parent:title]'] = check_plain($parent_comment->subject); - $tests['[comment:node:nid]'] = $comment->entity_id; + $tests['[comment:homepage]'] = check_url($comment->homepage->value); + $tests['[comment:title]'] = filter_xss($comment->subject->value); + $tests['[comment:body]'] = $comment->comment_body->processed; + $tests['[comment:url]'] = url('comment/' . $comment->id(), $url_options + array('fragment' => 'comment-' . $comment->id())); + $tests['[comment:edit-url]'] = url('comment/' . $comment->id() . '/edit', $url_options); + $tests['[comment:created:since]'] = format_interval(REQUEST_TIME - $comment->created->value, 2, $language_interface->langcode); + $tests['[comment:changed:since]'] = format_interval(REQUEST_TIME - $comment->changed->value, 2, $language_interface->langcode); + $tests['[comment:parent:cid]'] = $comment->pid->value; + $tests['[comment:parent:title]'] = check_plain($parent_comment->subject->value); - $tests['[comment:node:nid]'] = $comment->nid->value; ++ $tests['[comment:node:nid]'] = $comment->entity_id->value; $tests['[comment:node:title]'] = check_plain($node->title); - $tests['[comment:author:uid]'] = $comment->uid; + $tests['[comment:author:uid]'] = $comment->uid->value; $tests['[comment:author:name]'] = check_plain($this->admin_user->name); // Test to make sure that we generated something for each token. diff --cc core/modules/comment/lib/Drupal/comment/Tests/CommentUserTest.php index 6a8a584,30ebbf6..dfeb730 --- a/core/modules/comment/lib/Drupal/comment/Tests/CommentUserTest.php +++ b/core/modules/comment/lib/Drupal/comment/Tests/CommentUserTest.php @@@ -158,7 -145,8 +158,7 @@@ class CommentUserTest extends WebTestBa } if (isset($match[1])) { - return entity_create('comment', array('id' => $match[1], 'subject' => $subject, 'comment' => $comment)); - $entity = comment_load($match[1]); - return $entity; ++ return comment_load($match[1]); } } @@@ -176,9 -164,9 +176,9 @@@ function commentExists(Comment $comment = NULL, $reply = FALSE) { if ($comment) { $regex = '/' . ($reply ? '
(.*?)' : ''); - $regex .= 'subject . '(.*?)'; // Match subject. - $regex .= $comment->comment . '(.*?)'; // Match comment. + $regex .= 'subject->value . '(.*?)'; // Match subject. - $regex .= $comment->comment_body->value . '(.*?)'; // Match comment. ++ $regex .= $comment->comment->value . '(.*?)'; // Match comment. $regex .= '/s'; return (boolean)preg_match($regex, $this->drupalGetContent()); @@@ -250,93 -321,4 +250,93 @@@ return $match[2]; } + /** + * Tests anonymous comment functionality. + */ + function testCommentUser() { + $this->drupalLogin($this->admin_user); + + // Post a comment. + $comment1 = $this->postComment($this->web_user, $this->randomName(), $this->randomName()); + $this->assertTrue($this->commentExists($comment1), 'Comment on web user exists.'); + + // Unpublish comment. + $this->performCommentOperation($comment1, 'unpublish'); + + $this->drupalGet('admin/content/comment/approval'); + $this->assertRaw('comments[' . $comment1->id . ']', 'Comment was unpublished.'); + + // Publish comment. + $this->performCommentOperation($comment1, 'publish', TRUE); + + $this->drupalGet('admin/content/comment'); + $this->assertRaw('comments[' . $comment1->id . ']', 'Comment was published.'); + + // Delete comment. + $this->performCommentOperation($comment1, 'delete'); + + $this->drupalGet('admin/content/comment'); + $this->assertNoRaw('comments[' . $comment1->id . ']', 'Comment was deleted.'); + + // Post another comment. + $comment1 = $this->postComment($this->web_user, $this->randomName(), $this->randomName()); + $this->assertTrue($this->commentExists($comment1), 'Comment on web user exists.'); + + // Check comment was found. + $this->drupalGet('admin/content/comment'); + $this->assertRaw('comments[' . $comment1->id . ']', 'Comment was published.'); + + $this->drupalLogout(); + + // Reset. + user_role_change_permissions(DRUPAL_ANONYMOUS_RID, array( + 'access comments' => FALSE, + 'post comments' => FALSE, + 'skip comment approval' => FALSE, + 'access user profiles' => TRUE, + )); + + // Attempt to view comments while disallowed. + // NOTE: if authenticated user has permission to post comments, then a + // "Login or register to post comments" type link may be shown. + $this->drupalGet('user/' . $this->web_user->uid); + $this->assertNoPattern('@]*>Comments@', 'Comments were not displayed.'); + $this->assertNoLink('Add new comment', 'Link to add comment was found.'); + + // Attempt to view user-comment form while disallowed. + $this->drupalGet('comment/reply/user/' . $this->web_user->uid . '/comment'); + $this->assertText('You are not authorized to post comments', 'Error attempting to post comment.'); + $this->assertNoFieldByName('subject', '', 'Subject field not found.'); + $langcode = LANGUAGE_NOT_SPECIFIED; + $this->assertNoFieldByName("comment_body[$langcode][0][value]", '', 'Comment field not found.'); + + user_role_change_permissions(DRUPAL_ANONYMOUS_RID, array( + 'access comments' => TRUE, + 'post comments' => FALSE, + 'access user profiles' => TRUE, + 'skip comment approval' => FALSE, + )); + // Ensure the page cache is flushed. + drupal_flush_all_caches(); + $this->drupalGet('user/' . $this->web_user->uid); + $this->assertPattern('@]*>Comments@', 'Comments were displayed.'); + $this->assertLink('Log in', 1, 'Link to log in was found.'); + $this->assertLink('register', 1, 'Link to register was found.'); + + user_role_change_permissions(DRUPAL_ANONYMOUS_RID, array( + 'access comments' => FALSE, + 'post comments' => TRUE, + 'skip comment approval' => TRUE, + 'access user profiles' => TRUE, + )); + $this->drupalGet('user/' . $this->web_user->uid); + $this->assertNoPattern('@]*>Comments@', 'Comments were not displayed.'); + $this->assertFieldByName('subject', '', 'Subject field found.'); + $this->assertFieldByName("comment_body[$langcode][0][value]", '', 'Comment field found.'); + + $this->drupalGet('comment/reply/user/' . $this->web_user->uid . '/comment/' . $comment1->id); + $this->assertText('You are not authorized to view comments', 'Error attempting to post reply.'); - $this->assertNoText($comment1->subject, 'Comment not displayed.'); ++ $this->assertNoText($comment1->subject->value, 'Comment not displayed.'); + } + } diff --cc core/modules/comment/lib/Drupal/comment/Tests/Views/DefaultViewRecentComments.php index 266e370,fa0145d..d1383a1 --- a/core/modules/comment/lib/Drupal/comment/Tests/Views/DefaultViewRecentComments.php +++ b/core/modules/comment/lib/Drupal/comment/Tests/Views/DefaultViewRecentComments.php @@@ -72,26 -71,18 +72,25 @@@ class DefaultViewRecentComments extend // Add a node of the new content type. $node_data = array( 'type' => $content_type->type, + "comment[$language_not_specified][0][comment]" => COMMENT_OPEN ); + comment_add_default_comment_field('node', $content_type->type); $this->node = $this->drupalCreateNode($node_data); + views_invalidate_cache(); + // Create some comments and attach them to the created node. for ($i = 0; $i < $this->masterDisplayResults; $i++) { - $comment = entity_create('comment', array()); - $comment->uid = 0; - $comment->entity_type = 'node'; - $comment = entity_create('comment', array('node_type' => 'comment_node_' . $this->node->type)); ++ $comment = entity_create('comment', array('field_name' => 'comment')); + $comment->uid->value = 0; - $comment->nid->value = $this->node->nid; ++ $comment->entity_type->value = 'node'; + // Stagger the comments so the timestamp sorting works. - $comment->created = REQUEST_TIME - $i; - $comment->field_name = 'comment'; - $comment->entity_id = $this->node->nid; - $comment->subject = 'Test comment ' . $i; - $comment->comment_body[LANGUAGE_NOT_SPECIFIED][0]['value'] = 'Test body ' . $i; - $comment->comment_body[LANGUAGE_NOT_SPECIFIED][0]['format'] = 'full_html'; ++ $comment->created->value = REQUEST_TIME - $i; ++ $comment->entity_id->value = $this->node->nid; + $comment->subject->value = 'Test comment ' . $i; + $comment->comment_body->value = 'Test body ' . $i; + $comment->comment_body->format = 'full_html'; comment_save($comment); } @@@ -116,10 -107,10 +115,10 @@@ ); $expected_result = array(); foreach (array_values($this->commentsCreated) as $key => $comment) { - $expected_result[$key]['entity_id'] = $comment->entity_id; - $expected_result[$key]['subject'] = $comment->subject; - $expected_result[$key]['cid'] = $comment->cid; - $expected_result[$key]['changed'] = $comment->changed; - $expected_result[$key]['nid'] = $comment->nid->value; ++ $expected_result[$key]['entity_id'] = $comment->entity_id->value; + $expected_result[$key]['subject'] = $comment->subject->value; + $expected_result[$key]['cid'] = $comment->id(); + $expected_result[$key]['changed'] = $comment->changed->value; } $this->assertIdenticalResultset($view, $expected_result, $map); @@@ -148,11 -139,11 +147,11 @@@ ); $expected_result = array(); foreach (array_values($this->commentsCreated) as $key => $comment) { - $expected_result[$key]['entity_id'] = $comment->entity_id; - $expected_result[$key]['subject'] = $comment->subject; - $expected_result[$key]['changed'] = $comment->changed; - $expected_result[$key]['created'] = $comment->created; - $expected_result[$key]['cid'] = $comment->cid; - $expected_result[$key]['nid'] = $comment->nid->value; ++ $expected_result[$key]['entity_id'] = $comment->entity_id->value; + $expected_result[$key]['subject'] = $comment->subject->value; + $expected_result[$key]['changed'] = $comment->changed->value; + $expected_result[$key]['created'] = $comment->created->value; + $expected_result[$key]['cid'] = $comment->id(); } $this->assertIdenticalResultset($view, $expected_result, $map); diff --cc core/modules/forum/forum.module index ec06136,e9cd043..9a9de78 --- a/core/modules/forum/forum.module +++ b/core/modules/forum/forum.module @@@ -482,9 -484,7 +484,9 @@@ function forum_taxonomy_term_delete(Ter * comment_save() calls hook_comment_publish() for all published comments. */ function forum_comment_publish($comment) { - if ($comment->entity_type == 'node') { - _forum_update_forum_index($comment->entity_id); - _forum_update_forum_index($comment->nid->value); ++ if ($comment->entity_type->value == 'node') { ++ _forum_update_forum_index($comment->entity_id->value); + } } /** @@@ -496,8 -496,8 +498,8 @@@ function forum_comment_update($comment) { // comment_save() calls hook_comment_publish() for all published comments, // so we need to handle all other values here. - if (!$comment->status && $comment->entity_type == 'node') { - _forum_update_forum_index($comment->entity_id); - if (!$comment->status->value) { - _forum_update_forum_index($comment->nid->value); ++ if (!$comment->status->value && $comment->entity_type->value == 'node') { ++ _forum_update_forum_index($comment->entity_id->value); } } @@@ -505,18 -505,14 +507,18 @@@ * Implements hook_comment_unpublish(). */ function forum_comment_unpublish($comment) { - if ($comment->entity_type == 'node') { - _forum_update_forum_index($comment->entity_id); - _forum_update_forum_index($comment->nid->value); ++ if ($comment->entity_type->value == 'node') { ++ _forum_update_forum_index($comment->entity_id->value); + } } /** * Implements hook_comment_delete(). */ function forum_comment_delete($comment) { - if ($comment->entity_type == 'node') { - _forum_update_forum_index($comment->entity_id); - _forum_update_forum_index($comment->nid->value); ++ if ($comment->entity_type->value == 'node') { ++ _forum_update_forum_index($comment->entity_id->value); + } } /** diff --cc core/modules/forum/lib/Drupal/forum/Tests/ForumBlockTest.php index 2226884,7f5405d..92b71cf --- a/core/modules/forum/lib/Drupal/forum/Tests/ForumBlockTest.php +++ b/core/modules/forum/lib/Drupal/forum/Tests/ForumBlockTest.php @@@ -113,11 -103,9 +103,11 @@@ class ForumBlockTest extends WebTestBas // Get the node from the topic title. $node = $this->drupalGetNodeByTitle($topics[$index]); $comment = entity_create('comment', array( - 'nid' => $node->nid, + 'entity_id' => $node->nid, + 'field_name' => 'comment_node_forum', + 'entity_type' => 'node', 'subject' => $this->randomString(20), - 'comment_body' => array(LANGUAGE_NOT_SPECIFIED => $this->randomString(256)), + 'comment_body' => $this->randomString(256), 'created' => $timestamp + $index, )); comment_save($comment); diff --cc core/modules/node/lib/Drupal/node/Tests/NodeAccessPagerTest.php index fabb576,4044bdc..3e83e7f --- a/core/modules/node/lib/Drupal/node/Tests/NodeAccessPagerTest.php +++ b/core/modules/node/lib/Drupal/node/Tests/NodeAccessPagerTest.php @@@ -51,14 -46,10 +51,12 @@@ class NodeAccessPagerTest extends WebTe // Create 60 comments. for ($i = 0; $i < 60; $i++) { $comment = entity_create('comment', array( - 'nid' => $node->nid, + 'entity_id' => $node->nid, + 'entity_type' => 'node', + 'field_name' => 'comment', 'subject' => $this->randomName(), 'comment_body' => array( - LANGUAGE_NOT_SPECIFIED => array( - array('value' => $this->randomName()), - ), + array('value' => $this->randomName()), ), )); $comment->save(); diff --cc core/modules/rdf/lib/Drupal/rdf/Tests/CommentAttributesTest.php index 289a7b2,814ab3c..e468f32 --- a/core/modules/rdf/lib/Drupal/rdf/Tests/CommentAttributesTest.php +++ b/core/modules/rdf/lib/Drupal/rdf/Tests/CommentAttributesTest.php @@@ -160,7 -156,7 +160,7 @@@ class CommentAttributesTest extends Com $this->assertFalse($result, 'No RDFa markup referring to the comment itself is present.'); // Posts a reply to the first comment. - $this->drupalGet('comment/reply/node/' . $this->node1->nid . '/comment/' . $comments[0]->id); - $this->drupalGet('comment/reply/' . $this->node1->nid . '/' . $comments[0]->id()); ++ $this->drupalGet('comment/reply/node/' . $this->node1->nid . '/comment/' . $comments[0]->id()); $comments[] = $this->postComment(NULL, $this->randomName(), $this->randomName(), TRUE); // Tests the reply_of relationship of a second level comment. diff --cc core/modules/rdf/rdf.module index 06b88dc,cff64e5..ba46bde --- a/core/modules/rdf/rdf.module +++ b/core/modules/rdf/rdf.module @@@ -428,12 -418,10 +418,12 @@@ function rdf_comment_load($comments) // Pages with many comments can show poor performance. This information // isn't needed until rdf_preprocess_comment() is called, but set it here // to optimize performance for websites that implement an entity cache. - $comment->rdf_data['date'] = rdf_rdfa_attributes($comment->rdf_mapping['created'], $comment->created); - $entity = entity_load($comment->entity_type, $comment->entity_id); + $comment->rdf_data['date'] = rdf_rdfa_attributes($comment->rdf_mapping['created'], $comment->created->value); - $comment->rdf_data['nid_uri'] = url('node/' . $comment->nid->value); ++ $entity = entity_load($comment->entity_type->value, $comment->entity_id->value); + $uri = $entity->uri(); + $comment->rdf_data['entity_uri'] = url($uri['path'], $uri['options']); - if ($comment->pid) { - $comment->rdf_data['pid_uri'] = url('comment/' . $comment->pid, array('fragment' => 'comment-' . $comment->pid)); + if ($comment->pid->value) { + $comment->rdf_data['pid_uri'] = url('comment/' . $comment->pid->value, array('fragment' => 'comment-' . $comment->pid->value)); } } } @@@ -749,18 -737,18 +743,18 @@@ function rdf_preprocess_comment(&$varia $variables['title_attributes']['datatype'] = ''; } - // Annotates the parent relationship between the current comment and the node - // it belongs to. If available, the parent comment is also annotated. + // Annotates the parent relationship between the current comment and the + // entity it belongs to. If available, the parent comment is also annotated. if (!empty($comment->rdf_mapping['pid'])) { - // Adds the relation to the parent node. - $parent_node_attributes['rel'] = $comment->rdf_mapping['pid']['predicates']; - // The parent node URI is precomputed as part of the rdf_data so that it can + // Adds the relation to the parent entity. + $parent_entity_attributes['rel'] = $comment->rdf_mapping['pid']['predicates']; + // The parent entity URI is precomputed as part of the rdf_data so that it can // be cached as part of the entity. - $parent_node_attributes['resource'] = $comment->rdf_data['nid_uri']; - $variables['rdf_metadata_attributes'][] = $parent_node_attributes; + $parent_entity_attributes['resource'] = $comment->rdf_data['entity_uri']; + $variables['rdf_metadata_attributes'][] = $parent_entity_attributes; // Adds the relation to parent comment, if it exists. - if ($comment->pid != 0) { + if ($comment->pid->value != 0) { $parent_comment_attributes['rel'] = $comment->rdf_mapping['pid']['predicates']; // The parent comment URI is precomputed as part of the rdf_data so that // it can be cached as part of the entity. diff --cc core/modules/search/search.module index 4ea7c2a,a465e3a..de26282 --- a/core/modules/search/search.module +++ b/core/modules/search/search.module @@@ -815,9 -810,7 +815,9 @@@ function search_node_update(Node $node */ function search_comment_insert($comment) { // Reindex the node when comments are added. - if ($comment->entity_type == 'node') { - search_touch_node($comment->entity_id); - search_touch_node($comment->nid->value); ++ if ($comment->entity_type->value == 'node') { ++ search_touch_node($comment->entity_id->value); + } } /** @@@ -825,9 -818,7 +825,9 @@@ */ function search_comment_update($comment) { // Reindex the node when comments are changed. - if ($comment->entity_type == 'node') { - search_touch_node($comment->entity_id); - search_touch_node($comment->nid->value); ++ if ($comment->entity_type->value == 'node') { ++ search_touch_node($comment->entity_id->value); + } } /** @@@ -835,9 -826,7 +835,9 @@@ */ function search_comment_delete($comment) { // Reindex the node when comments are deleted. - if ($comment->entity_type == 'node') { - search_touch_node($comment->entity_id); - search_touch_node($comment->nid->value); ++ if ($comment->entity_type->value == 'node') { ++ search_touch_node($comment->entity_id->value); + } } /** @@@ -845,9 -834,7 +845,9 @@@ */ function search_comment_publish($comment) { // Reindex the node when comments are published. - if ($comment->entity_type == 'node') { - search_touch_node($comment->entity_id); - search_touch_node($comment->nid->value); ++ if ($comment->entity_type->value == 'node') { ++ search_touch_node($comment->entity_id->value); + } } /** @@@ -855,9 -842,7 +855,9 @@@ */ function search_comment_unpublish($comment) { // Reindex the node when comments are unpublished. - if ($comment->entity_type == 'node') { - search_touch_node($comment->entity_id); - search_touch_node($comment->nid->value); ++ if ($comment->entity_type->value == 'node') { ++ search_touch_node($comment->entity_id->value); + } } /** diff --cc core/modules/system/system.module index 6d16229,cdf7b90..cfa92fe --- a/core/modules/system/system.module +++ b/core/modules/system/system.module @@@ -2245,6 -2279,6 +2279,12 @@@ function system_data_type_info() 'class' => '\Drupal\Core\Entity\Field\Type\EntityReferenceItem', 'list class' => '\Drupal\Core\Entity\Field\Type\Field', ), ++ 'entityreference_field_dynamic' => array( ++ 'label' => t('Dynamic entity reference field item'), ++ 'description' => t('An entity field containing a dynamic entity reference.'), ++ 'class' => '\Drupal\Core\Entity\Field\Type\DynamicEntityReferenceItem', ++ 'list class' => '\Drupal\Core\Entity\Field\Type\Field', ++ ), ); } diff --cc core/modules/tracker/tracker.module index 27b2e07,d33a878..ac3d8c7 --- a/core/modules/tracker/tracker.module +++ b/core/modules/tracker/tracker.module @@@ -231,8 -229,8 +231,8 @@@ function tracker_node_predelete(Node $n function tracker_comment_update($comment) { // comment_save() calls hook_comment_publish() for all published comments // so we need to handle all other values here. - if ($comment->status != COMMENT_PUBLISHED && $comment->entity_type == 'node') { - _tracker_remove($comment->entity_id, $comment->uid, $comment->changed); - if ($comment->status->value != COMMENT_PUBLISHED) { - _tracker_remove($comment->nid->value, $comment->uid->value, $comment->changed->value); ++ if ($comment->status->value != COMMENT_PUBLISHED && $comment->entity_type->value == 'node') { ++ _tracker_remove($comment->entity_id->value, $comment->uid->value, $comment->changed->value); } } @@@ -243,27 -241,21 +243,27 @@@ * comment_save() calls hook_comment_publish() for all published comments. */ function tracker_comment_publish($comment) { - if ($comment->entity_type == 'node') { - _tracker_add($comment->entity_id, $comment->uid, $comment->changed); - _tracker_add($comment->nid->value, $comment->uid->value, $comment->changed->value); ++ if ($comment->entity_type->value == 'node') { ++ _tracker_add($comment->entity_id->value, $comment->uid->value, $comment->changed->value); + } } /** * Implements hook_comment_unpublish(). */ function tracker_comment_unpublish($comment) { - if ($comment->entity_type == 'node') { - _tracker_remove($comment->entity_id, $comment->uid, $comment->changed); - _tracker_remove($comment->nid->value, $comment->uid->value, $comment->changed->value); ++ if ($comment->entity_type->value == 'node') { ++ _tracker_remove($comment->entity_id->value, $comment->uid->value, $comment->changed->value); + } } /** * Implements hook_comment_delete(). */ function tracker_comment_delete($comment) { - if ($comment->entity_type == 'node') { - _tracker_remove($comment->entity_id, $comment->uid, $comment->changed); - _tracker_remove($comment->nid->value, $comment->uid->value, $comment->changed->value); ++ if ($comment->entity_type->value == 'node') { ++ _tracker_remove($comment->entity_id->value, $comment->uid->value, $comment->changed->value); + } } /** commit fe7e10fa84680b7585b3ed63c8c5184dc995c886 Author: Lee Rowlands Date: Mon Jan 21 18:31:09 2013 +1000 Patch 271 diff --git a/core/modules/comment/comment.field.inc b/core/modules/comment/comment.field.inc index 0fe9695..66dc039 100644 --- a/core/modules/comment/comment.field.inc +++ b/core/modules/comment/comment.field.inc @@ -172,7 +172,7 @@ function comment_field_widget_form(&$form, &$form_state, $field, $instance, $lan '#access' => user_access('administer comments'), '#collapsible' => TRUE, '#collapsed' => TRUE, - '#group' => 'additional_settings', + '#group' => 'advanced', '#attributes' => array( 'class' => array('comment-node-settings-form'), ), diff --git a/core/modules/comment/comment.module b/core/modules/comment/comment.module index 6a7261b..65dc2fa 100644 --- a/core/modules/comment/comment.module +++ b/core/modules/comment/comment.module @@ -14,6 +14,7 @@ use Drupal\entity\Plugin\Core\Entity\EntityDisplay; use Drupal\file\Plugin\Core\Entity\File; use Drupal\Core\Entity\EntityInterface; +use Drupal\Core\Entity\EntityNG; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; use Symfony\Component\HttpKernel\HttpKernelInterface; @@ -1696,7 +1697,8 @@ function template_preprocess_comment(&$variables) { $variables['attributes']['class'][] = 'by-anonymous'; } else { - if (!empty($comment_entity->uid->value) && $comment->uid->value == $comment_entity->uid->value) { + if (($comment_entity instanceof EntityNG && !empty($comment_entity->uid->value) && $comment->uid->value == $comment_entity->uid->value) || + (!empty($comment_entity->uid) && $comment->uid->value == $comment_entity->uid)) { $variables['attributes']['class'][] = 'by-' . $comment_entity->entityType() . '-author'; } if ($comment->uid->value == $variables['user']->uid) { diff --git a/core/modules/comment/lib/Drupal/comment/Tests/CommentInterfaceTest.php b/core/modules/comment/lib/Drupal/comment/Tests/CommentInterfaceTest.php index 4e19986..658c968 100644 --- a/core/modules/comment/lib/Drupal/comment/Tests/CommentInterfaceTest.php +++ b/core/modules/comment/lib/Drupal/comment/Tests/CommentInterfaceTest.php @@ -96,9 +96,9 @@ function testCommentInterface() { $this->assertEqual(rtrim($comment->thread->value, '/') . '.00/', $reply_loaded->thread->value, 'Thread of reply grows correctly.'); // Second reply to comment #3 creating comment #4. - $this->drupalGet('comment/reply/node/' . $this->node->nid . '/comment/' . $comment->id()); - $this->assertText($subject_text, 'Individual comment-reply subject found.'); - $this->assertText($comment_text, 'Individual comment-reply body found.'); + $this->drupalGet('comment/reply/node/' . $this->node->nid . '/comment/' . $reply_loaded->id()); + $this->assertText($reply_loaded->subject->value, 'Individual comment-reply subject found.'); + $this->assertText($reply_loaded->comment_body->value, 'Individual comment-reply body found.'); $reply = $this->postComment(NULL, $this->randomName(), $this->randomName(), TRUE); $reply_loaded = comment_load($reply->id()); $this->assertTrue($this->commentExists($reply, TRUE), 'Second reply found.'); diff --git a/core/modules/comment/lib/Drupal/comment/Tests/CommentUserTest.php b/core/modules/comment/lib/Drupal/comment/Tests/CommentUserTest.php index dfeb730..5b481ec 100644 --- a/core/modules/comment/lib/Drupal/comment/Tests/CommentUserTest.php +++ b/core/modules/comment/lib/Drupal/comment/Tests/CommentUserTest.php @@ -178,7 +178,7 @@ function commentExists(Comment $comment = NULL, $reply = FALSE) { $regex = '/' . ($reply ? '
(.*?)' : ''); $regex .= 'subject->value . '(.*?)'; // Match subject. - $regex .= $comment->comment->value . '(.*?)'; // Match comment. + $regex .= $comment->comment_body->value . '(.*?)'; // Match comment. $regex .= '/s'; return (boolean)preg_match($regex, $this->drupalGetContent()); commit 7969fd8d1b60faf3f500bd1f008066b6cff57492 Merge: 6f675c5 e86e706 Author: Lee Rowlands Date: Mon Jan 21 16:39:05 2013 +1000 Merge remote-tracking branch 'origin/8.x' into comment-fieldapi4 Conflicts: core/modules/comment/comment.module core/modules/comment/lib/Drupal/comment/Tests/CommentApprovalTest.php core/modules/comment/lib/Drupal/comment/Tests/CommentCSSTest.php core/modules/file/lib/Drupal/file/Tests/FileFieldTestBase.php core/modules/forum/lib/Drupal/forum/Tests/ForumBlockTest.php core/modules/node/lib/Drupal/node/Tests/NodeAccessPagerTest.php core/modules/rdf/lib/Drupal/rdf/Tests/CommentAttributesTest.php core/modules/translation_entity/lib/Drupal/translation_entity/Tests/EntityTranslationSettingsTest.php core/modules/views/lib/Drupal/views/Tests/DefaultViewsTest.php core/modules/views/lib/Drupal/views/Tests/ViewExecutableTest.php diff --cc core/modules/comment/comment.module index d188eb8,3bcabfe..6a7261b --- a/core/modules/comment/comment.module +++ b/core/modules/comment/comment.module @@@ -123,135 -99,25 +123,134 @@@ function comment_help($path, $arg) } /** - * Implements hook_entity_info(). + * Implements hook_entity_view(). + */ +function comment_entity_view($entity, $view_mode, $langcode) { + $fields = field_info_instances($entity->entityType(), $entity->bundle()); + foreach ($fields as $field_name => $instance) { + $links = array(); + $field = field_info_field($instance['field_name']); + if ($field['type'] != 'comment') { + continue; + } + $values = field_get_items($entity, $field_name); + if ($values && is_array($values) && ($value = reset($values)) && + !empty($value['comment']) && + $value['comment'] != COMMENT_HIDDEN) { + $uri = $entity->uri(); + if ($view_mode == 'rss') { + // Add a comments RSS element which is a URL to the comments of this node. + if (!empty($uri['options'])) { + $uri['options']['fragment'] = 'comments'; + $uri['options']['absolute'] = TRUE; + } + $entity->rss_elements[] = array( + 'key' => 'comments', + 'value' => url($uri['path'], $uri['options']) + ); + } + elseif ($view_mode == 'teaser') { + // Teaser view: display the number of comments that have been posted, + // or a link to add new comments if the user has permission, the node + // is open to new comments, and there currently are none. + if (user_access('access comments')) { + if (!empty($entity->comment_statistics[$field_name]->comment_count)) { + $links['comment-comments'] = array( + 'title' => format_plural($entity->comment_statistics[$field_name]->comment_count, '1 comment', '@count comments'), + 'href' => $uri['path'], + 'attributes' => array('title' => t('Jump to the first comment of this posting.')), + 'fragment' => 'comments', + 'html' => TRUE, + ); + // Show a link to the first new comment. + if ($new = comment_num_new($entity->id(), $entity->entityType(), $field_name)) { + $links['comment-new-comments'] = array( + 'title' => format_plural($new, '1 new comment', '@count new comments'), + 'href' => $uri['path'], + 'query' => comment_new_page_count($entity->comment_statistics[$field_name]->comment_count, $new, $entity, $field_name), + 'attributes' => array('title' => t('Jump to the first new comment of this posting.')), + 'fragment' => 'new', + 'html' => TRUE, + ); + } + } + } + $values = field_get_items($entity, $field_name); + $value = reset($values); + if (!empty($value['comment']) && $value['comment'] == COMMENT_OPEN) { + $comment_form_location = $instance['settings']['comment']['comment_form_location']; + if (user_access('post comments')) { + $links['comment-add'] = array( + 'title' => t('Add new comment'), + 'href' => $uri['path'], + 'attributes' => array('title' => t('Add a new comment to this page.')), + 'fragment' => 'comment-form', + ); + if ($comment_form_location == COMMENT_FORM_SEPARATE_PAGE) { + $links['comment-add']['href'] = 'comment/reply/'. $entity->entityType() . '/' . $entity->id() .'/' . $field_name; + } + } + else { + $links['comment-forbidden'] = array( + 'title' => theme('comment_post_forbidden', array('entity' => $entity, 'field_name' => $field_name)), + 'html' => TRUE, + ); + } + } + } + elseif ($view_mode != 'search_index' && $view_mode != 'search_result') { + // Entity in other view modes: add a "post comment" link if the user is + // allowed to post comments and if this entity is allowing new comments. + // But we don't want this link if we're building the entity for search + // indexing or constructing a search result excerpt. + $values = field_get_items($entity, $field_name); + if (is_array($values) && ($value = reset($values)) && + !empty($value['comment']) && $value['comment'] == COMMENT_OPEN) { + $comment_form_location = $instance['settings']['comment']['comment_form_location']; + if (user_access('post comments')) { + // Show the "post comment" link if the form is on another page, or + // if there are existing comments that the link will skip past. + if ($comment_form_location == COMMENT_FORM_SEPARATE_PAGE || (!empty($entity->comment_statistics[$field_name]->comment_count) && user_access('access comments'))) { + $links['comment-add'] = array( + 'title' => t('Add new comment'), + 'attributes' => array('title' => t('Share your thoughts and opinions related to this item.')), + 'href' => $uri['path'], + 'fragment' => 'comment-form', + ); + if ($comment_form_location == COMMENT_FORM_SEPARATE_PAGE) { + $links['comment-add']['href'] = 'comment/reply/'. $entity->entityType() . '/' . $entity->id() .'/' . $field_name; + } + } + } + else { + $links['comment-forbidden'] = array( + 'title' => theme('comment_post_forbidden', array('entity' => $entity, 'field_name' => $field_name)), + 'html' => TRUE, + ); + } + } + } + } + + $entity->content['links']['comment__' . $field_name] = array( + '#theme' => 'links__entity__comment__' . $field_name, + '#links' => $links, + '#attributes' => array('class' => array('links', 'inline')), + ); + } +} + +/** + * Implements hook_entity_info_alter(). */ -function comment_entity_info(&$info) { - foreach (node_type_get_names() as $type => $name) { - $info['comment']['bundles']['comment_node_' . $type] = array( - 'label' => t('@node_type comment', array('@node_type' => $name)), - // Provide the node type/bundle name for other modules, so it does not - // have to be extracted manually from the bundle name. - 'node bundle' => $type, +function comment_entity_info_alter(&$info) { + foreach (comment_get_comment_fields() as $field_name => $field_info) { + $info['comment']['bundles'][$field_name] = array( + 'label' => $field_name, 'admin' => array( - // Place the Field UI paths for comments one level below the - // corresponding paths for nodes, so that they appear in the same set - // of local tasks. Note that the paths use a different placeholder name - // and thus a different menu loader callback, so that Field UI page - // callbacks get a comment bundle name from the node type in the URL. - // See comment_node_type_load() and comment_menu_alter(). - 'path' => 'admin/structure/types/manage/%comment_node_type/comment', - 'bundle argument' => 4, - 'real path' => 'admin/structure/types/manage/' . $type . '/comment', + 'path' => 'admin/structure/comments/%comment_field_name', + 'bundle argument' => 3, + 'real path' => 'admin/structure/comments/' . strtr($field_name, '_', '-'), - 'access arguments' => array('administer comments'), ), ); } diff --cc core/modules/comment/lib/Drupal/comment/Tests/Views/CommentTestBase.php index 4ab056b,c913883..e6f277e --- a/core/modules/comment/lib/Drupal/comment/Tests/Views/CommentTestBase.php +++ b/core/modules/comment/lib/Drupal/comment/Tests/Views/CommentTestBase.php @@@ -56,11 -45,10 +56,12 @@@ abstract class CommentTestBase extends $comment = array( 'uid' => $this->loggedInUser->uid, - 'nid' => $this->node_user_commented->nid, + 'entity_id' => $this->node_user_commented->nid, + 'entity_type' => 'node', + 'field_name' => 'comment', 'cid' => '', 'pid' => '', + 'node_type' => '', ); $this->comment = entity_create('comment', $comment); $this->comment->save(); diff --cc core/modules/file/lib/Drupal/file/Tests/FileFieldTestBase.php index 67c661b,458eb4c..8f4428b --- a/core/modules/file/lib/Drupal/file/Tests/FileFieldTestBase.php +++ b/core/modules/file/lib/Drupal/file/Tests/FileFieldTestBase.php @@@ -19,7 -19,7 +19,7 @@@ abstract class FileFieldTestBase extend * * @var array */ - public static $modules = array('file', 'file_module_test', 'field_test'); - public static $modules = array('file', 'file_module_test', 'field_ui'); ++ public static $modules = array('file', 'file_module_test', 'field_ui', 'field_test'); protected $profile = 'standard'; @@@ -27,7 -27,7 +27,20 @@@ function setUp() { parent::setUp(); - $this->admin_user = $this->drupalCreateUser(array('administer comments', 'access content', 'access administration pages', 'administer site configuration', 'administer users', 'administer permissions', 'administer content types', 'administer nodes', 'bypass node access')); - $this->admin_user = $this->drupalCreateUser(array('access content', 'access administration pages', 'administer site configuration', 'administer users', 'administer permissions', 'administer content types', 'administer node fields', 'administer node display', 'administer comment fields', 'administer nodes', 'bypass node access')); ++ $this->admin_user = $this->drupalCreateUser(array( ++ 'administer node fields', ++ 'administer node display', ++ 'administer comment fields', ++ 'administer comments', ++ 'access content', ++ 'access administration pages', ++ 'administer site configuration', ++ 'administer users', ++ 'administer permissions', ++ 'administer content types', ++ 'administer nodes', ++ 'bypass node access' ++ )); $this->drupalLogin($this->admin_user); } diff --cc core/modules/forum/lib/Drupal/forum/Tests/ForumBlockTest.php index 92b71cf,f36c5a9..b83e68a --- a/core/modules/forum/lib/Drupal/forum/Tests/ForumBlockTest.php +++ b/core/modules/forum/lib/Drupal/forum/Tests/ForumBlockTest.php @@@ -103,9 -102,8 +102,10 @@@ class ForumBlockTest extends WebTestBas // Get the node from the topic title. $node = $this->drupalGetNodeByTitle($topics[$index]); $comment = entity_create('comment', array( - 'nid' => $node->nid, + 'entity_id' => $node->nid, + 'field_name' => 'comment_node_forum', + 'entity_type' => 'node', + 'node_type' => 'node_type_' . $node->bundle(), 'subject' => $this->randomString(20), 'comment_body' => $this->randomString(256), 'created' => $timestamp + $index, diff --cc core/modules/rdf/lib/Drupal/rdf/Tests/CommentAttributesTest.php index e468f32,bce0f35..107b053 --- a/core/modules/rdf/lib/Drupal/rdf/Tests/CommentAttributesTest.php +++ b/core/modules/rdf/lib/Drupal/rdf/Tests/CommentAttributesTest.php @@@ -61,11 -45,9 +49,13 @@@ class CommentAttributesTest extends Com $this->setCommentSubject(TRUE); $this->setCommentSettings('comment_default_mode', COMMENT_MODE_THREADED, 'Comment paging changed.'); + // Creates the nodes on which the test comments will be posted. + $this->drupalLogin($this->web_user); - $this->node1 = $this->drupalCreateNode(array('type' => 'article', 'promote' => 1, 'comment' => array(LANGUAGE_NOT_SPECIFIED => array(array('comment' => COMMENT_OPEN))))); - $this->node2 = $this->drupalCreateNode(array('type' => 'article', 'promote' => 1, 'comment' => array(LANGUAGE_NOT_SPECIFIED => array(array('comment' => COMMENT_OPEN))))); ++ $this->node = $this->drupalCreateNode(array('type' => 'article', 'promote' => 1, 'comment' => array(LANGUAGE_NOT_SPECIFIED => array(array('comment' => COMMENT_OPEN))))); + $this->drupalLogout(); + // Prepares commonly used URIs. + $this->base_uri = url('', array('absolute' => TRUE)); + $this->node_uri = url('node/' . $this->node->nid, array('absolute' => TRUE)); } /** @@@ -181,18 -175,116 +183,117 @@@ * @param $account * An array containing information about an anonymous user. */ - function _testBasicCommentRdfaMarkup($comment, $account = array()) { - $comment_container = $this->xpath('//div[contains(@class, "comment") and contains(@typeof, "sioct:Comment")]'); - $this->assertTrue(!empty($comment_container), 'Comment RDF type for comment found.'); - $comment_title = $this->xpath('//div[contains(@class, "comment") and contains(@typeof, "sioct:Comment")]//h3[@property="dc:title"]'); - $this->assertEqual((string) $comment_title[0]->a, $comment->subject->value, 'RDFa markup for the comment title found.'); - $comment_date = $this->xpath('//div[contains(@class, "comment") and contains(@typeof, "sioct:Comment")]//*[contains(@property, "dc:date") and contains(@property, "dc:created")]'); - $this->assertTrue(!empty($comment_date), 'RDFa markup for the date of the comment found.'); - // The author tag can be either a or span - $comment_author = $this->xpath('//div[contains(@class, "comment") and contains(@typeof, "sioct:Comment")]//span[@rel="sioc:has_creator"]/*[contains(@class, "username") and @typeof="sioc:UserAccount" and @property="foaf:name" and @datatype=""]'); + function _testBasicCommentRdfaMarkup($graph, $comment, $account = array()) { + $comment_uri = url('comment/' . $comment->id(), array('fragment' => 'comment-' . $comment->id(), 'absolute' => TRUE)); + + // Comment type. + $expected_value = array( + 'type' => 'uri', + 'value' => 'http://rdfs.org/sioc/types#Comment', + ); + $this->assertTrue($graph->hasProperty($comment_uri, 'http://www.w3.org/1999/02/22-rdf-syntax-ns#type', $expected_value), 'Comment type found in RDF output (sioct:Comment).'); + // Comment type. + $expected_value = array( + 'type' => 'uri', + 'value' => 'http://rdfs.org/sioc/ns#Post', + ); + $this->assertTrue($graph->hasProperty($comment_uri, 'http://www.w3.org/1999/02/22-rdf-syntax-ns#type', $expected_value), 'Comment type found in RDF output (sioc:Post).'); + + // Comment title. + $expected_value = array( + 'type' => 'literal', + 'value' => $comment->subject->value, + 'lang' => 'en', + ); + $this->assertTrue($graph->hasProperty($comment_uri, 'http://purl.org/dc/terms/title', $expected_value), 'Comment title found in RDF output (dc:title).'); + + // Comment date. + $expected_value = array( + 'type' => 'literal', + 'value' => date('c', $comment->created->value), + 'datatype' => 'http://www.w3.org/2001/XMLSchema#dateTime', + ); + $this->assertTrue($graph->hasProperty($comment_uri, 'http://purl.org/dc/terms/date', $expected_value), 'Comment date found in RDF output (dc:date).'); + // Comment date. + $expected_value = array( + 'type' => 'literal', + 'value' => date('c', $comment->created->value), + 'datatype' => 'http://www.w3.org/2001/XMLSchema#dateTime', + ); + $this->assertTrue($graph->hasProperty($comment_uri, 'http://purl.org/dc/terms/created', $expected_value), 'Comment date found in RDF output (dc:created).'); + + // Comment body. + $expected_value = array( + 'type' => 'literal', + 'value' => $comment->comment_body->value . "\n", + 'lang' => 'en', + ); + $this->assertTrue($graph->hasProperty($comment_uri, 'http://purl.org/rss/1.0/modules/content/encoded', $expected_value), 'Comment body found in RDF output (content:encoded).'); + + // The comment author can be a registered user or an anonymous user. + if ($comment->uid->value > 0) { + $author_uri = url('user/' . $comment->uid->value, array('absolute' => TRUE)); + // Comment relation to author. + $expected_value = array( + 'type' => 'uri', + 'value' => $author_uri, + ); + $this->assertTrue($graph->hasProperty($comment_uri, 'http://rdfs.org/sioc/ns#has_creator', $expected_value), 'Comment relation to author found in RDF output (sioc:has_creator).'); + } + else { + // The author is expected to be a blank node. + $author_uri = $graph->get($comment_uri, ''); + $this->assertTrue($author_uri->isBnode(), 'Comment relation to author found in RDF output (sioc:has_creator).'); + } + + // Author name. $name = empty($account["name"]) ? $this->web_user->name : $account["name"] . " (not verified)"; - $this->assertEqual((string) $comment_author[0], $name, 'RDFa markup for the comment author found.'); - $comment_body = $this->xpath('//div[contains(@class, "comment") and contains(@typeof, "sioct:Comment")]//div[@class="content"]//div[contains(@class, "comment-body")]//div[@property="content:encoded"]'); - $this->assertEqual((string) $comment_body[0]->p, $comment->comment_body->value, 'RDFa markup for the comment body found.'); + $expected_value = array( + 'type' => 'literal', + 'value' => $name, + ); + $this->assertTrue($graph->hasProperty($author_uri, 'http://xmlns.com/foaf/0.1/name', $expected_value), 'Comment author name found in RDF output (foaf:name).'); + + // Comment author homepage (only for anonymous authors). + if ($comment->uid->value == 0) { + $expected_value = array( + 'type' => 'uri', + 'value' => 'http://example.org/', + ); + $this->assertTrue($graph->hasProperty($author_uri, 'http://xmlns.com/foaf/0.1/page', $expected_value), 'Comment author link found in RDF output (foaf:page).'); + } } + + /** + * Creates a comment entity. + * + * @param $nid + * Node id which will hold the comment. + * @param $uid + * User id of the author of the comment. Can be NULL if $contact provided. + * @param $contact + * Set to NULL for no contact info, TRUE to ignore success checking, and + * array of values to set contact info. + * @param $pid + * Comment id of the parent comment in a thread. + */ + function saveComment($nid, $uid, $contact = NULL, $pid = 0) { + $values = array( - 'nid' => $nid, ++ 'entity_id' => $nid, ++ 'entity_type' => 'node', ++ 'field_name' => 'comment', + 'uid' => $uid, + 'pid' => $pid, - 'node_type' => 'comment_node_article', + 'subject' => $this->randomName(), + 'comment_body' => $this->randomName(), + 'status' => 1, + ); + if ($contact) { + $values += $contact; + } + + $comment = entity_create('comment', $values); + $comment->save(); + return $comment; + } } diff --cc core/modules/system/lib/Drupal/system/Tests/Entity/EntityCrudHookTest.php index 0ee93e4,6b7d73d..da40dc0 --- a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityCrudHookTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityCrudHookTest.php @@@ -93,11 -134,10 +141,12 @@@ class EntityCrudHookTest extends WebTes $nid = $node->nid; $comment = entity_create('comment', array( + 'node_type' => 'node_type_' . $node->bundle(), 'cid' => NULL, 'pid' => 0, - 'nid' => $nid, + 'entity_id' => $nid, + 'entity_type' => 'node', + 'field_name' => 'comment', 'uid' => 1, 'subject' => 'Test comment', 'created' => REQUEST_TIME, diff --cc core/modules/translation_entity/lib/Drupal/translation_entity/Tests/EntityTranslationSettingsTest.php index b286d1f,80d4202..8d3955c --- a/core/modules/translation_entity/lib/Drupal/translation_entity/Tests/EntityTranslationSettingsTest.php +++ b/core/modules/translation_entity/lib/Drupal/translation_entity/Tests/EntityTranslationSettingsTest.php @@@ -71,31 -69,31 +71,31 @@@ class EntityTranslationSettingsTest ext // language is set as default and the language selector is hidden. $edit = array( 'entity_types[comment]' => TRUE, - 'settings[comment][comment_node_article][settings][language][langcode]' => LANGUAGE_NOT_SPECIFIED, - 'settings[comment][comment_node_article][settings][language][language_show]' => FALSE, - 'settings[comment][comment_node_article][translatable]' => TRUE, - 'settings[comment][comment_node_article][fields][comment_body]' => TRUE, + 'settings[comment][comment][settings][language][langcode]' => LANGUAGE_NOT_SPECIFIED, - 'settings[comment][comment][settings][language][language_hidden]' => TRUE, ++ 'settings[comment][comment][settings][language][language_show]' => TRUE, + 'settings[comment][comment][translatable]' => TRUE, + 'settings[comment][comment][fields][comment_body]' => TRUE, ); - $this->assertSettings('comment', 'comment_node_article', FALSE, $edit); + $this->assertSettings('comment', 'comment', FALSE, $edit); $this->assertTrue($this->xpath($xpath_err), 'Enabling translation with a fixed non-configurable language generates a form error.'); // Test that a field shared among different bundles can be enabled without // needing to make all the related bundles translatable. $edit = array( 'entity_types[comment]' => TRUE, - 'settings[comment][comment_node_article][settings][language][langcode]' => 'current_interface', - 'settings[comment][comment_node_article][settings][language][language_show]' => TRUE, - 'settings[comment][comment_node_article][translatable]' => TRUE, - 'settings[comment][comment_node_article][fields][comment_body]' => TRUE, + 'settings[comment][comment][settings][language][langcode]' => 'current_interface', - 'settings[comment][comment][settings][language][language_hidden]' => FALSE, ++ 'settings[comment][comment][settings][language][language_show]' => FALSE, + 'settings[comment][comment][translatable]' => TRUE, + 'settings[comment][comment][fields][comment_body]' => TRUE, ); - $this->assertSettings('comment', 'comment_node_article', TRUE, $edit); + $this->assertSettings('comment', 'comment', TRUE, $edit); $field = field_info_field('comment_body'); $this->assertTrue($field['translatable'], 'Comment body is translatable.'); // Test that language settings are correctly stored. - $language_configuration = language_get_default_configuration('comment', 'comment_node_article'); + $language_configuration = language_get_default_configuration('comment', 'comment'); $this->assertEqual($language_configuration['langcode'], 'current_interface', 'The default language for article comments is set to the current interface language.'); - $this->assertFalse($language_configuration['language_hidden'], 'The language selector for article comments is shown.'); + $this->assertTrue($language_configuration['language_show'], 'The language selector for article comments is shown.'); } /** diff --cc core/modules/views/lib/Drupal/views/Tests/ViewExecutableTest.php index 29ea6f1,eaa8817..cea5d3c --- a/core/modules/views/lib/Drupal/views/Tests/ViewExecutableTest.php +++ b/core/modules/views/lib/Drupal/views/Tests/ViewExecutableTest.php @@@ -78,17 -78,8 +78,18 @@@ class ViewExecutableTest extends ViewUn protected function setUp() { parent::setUp(); - - $this->enableModules(array('system', 'node', 'comment', 'user', 'filter')); + $this->enableModules(array( + 'entity', + 'field', + 'field_sql_storage', + 'text', + 'node', ++ 'system', + 'comment', + 'user', + 'filter' + )); + comment_add_default_comment_field('node', 'page'); } /**