diff --git a/core/modules/comment/comment.admin.inc b/core/modules/comment/comment.admin.inc index 1ca6a52..450e942 100644 --- a/core/modules/comment/comment.admin.inc +++ b/core/modules/comment/comment.admin.inc @@ -10,207 +10,6 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; /** - * Page callback: Presents an administrative comment listing. - * - * @param $type - * The type of the overview form ('approval' or 'new'). See - * comment_admin_overview() for details. - * - * @see comment_menu() - * @see comment_multiple_delete_confirm() - */ -function comment_admin($type = 'new') { - $edit = Drupal::request()->request->all(); - - if (isset($edit['operation']) && ($edit['operation'] == 'delete') && isset($edit['comments']) && $edit['comments']) { - return drupal_get_form('comment_multiple_delete_confirm'); - } - else { - return drupal_get_form('comment_admin_overview', $type); - } -} - -/** - * Form constructor for the comment overview administration form. - * - * @param $arg - * The type of overview form ('approval' or 'new'). - * - * @ingroup forms - * @see comment_admin() - * @see comment_admin_overview_validate() - * @see comment_admin_overview_submit() - * @see theme_comment_admin_overview() - */ -function comment_admin_overview($form, &$form_state, $arg) { - // Build an 'Update options' form. - $form['options'] = array( - '#type' => 'details', - '#title' => t('Update options'), - '#attributes' => array('class' => array('container-inline')), - ); - - if ($arg == 'approval') { - $options['publish'] = t('Publish the selected comments'); - } - else { - $options['unpublish'] = t('Unpublish the selected comments'); - } - $options['delete'] = t('Delete the selected comments'); - - $form['options']['operation'] = array( - '#type' => 'select', - '#title' => t('Action'), - '#title_display' => 'invisible', - '#options' => $options, - '#default_value' => 'publish', - ); - $form['options']['submit'] = array( - '#type' => 'submit', - '#value' => t('Update'), - ); - - // Load the comments that need to be displayed. - $status = ($arg == 'approval') ? COMMENT_NOT_PUBLISHED : COMMENT_PUBLISHED; - $header = array( - 'subject' => array('data' => t('Subject'), 'field' => 'subject'), - 'author' => array('data' => t('Author'), 'field' => 'name', 'class' => array(RESPONSIVE_PRIORITY_MEDIUM)), - 'posted_in' => array('data' => t('Posted in'), 'field' => 'node_title', 'class' => array(RESPONSIVE_PRIORITY_LOW)), - 'changed' => array('data' => t('Updated'), 'field' => 'c.changed', 'sort' => 'desc', 'class' => array(RESPONSIVE_PRIORITY_LOW)), - 'operations' => t('Operations'), - ); - - $query = db_select('comment', 'c') - ->extend('Drupal\Core\Database\Query\PagerSelectExtender') - ->extend('Drupal\Core\Database\Query\TableSortExtender'); - $query->join('node_field_data', 'n', 'n.nid = c.nid'); - $query->addTag('node_access'); - $result = $query - ->fields('c', array('cid', 'nid', 'subject', 'name', 'changed')) - ->condition('c.status', $status) - ->limit(50) - ->orderByHeader($header) - ->execute(); - - $nids = array(); - $cids = array(); - - // We collect a sorted list of node_titles during the query to attach to the - // comments later. - foreach ($result as $row) { - $nids[] = $row->nid; - $cids[] = $row->cid; - } - // Ensure all nodes are statically cached so that we do not have to load them - // individually when getting their labels below. - node_load_multiple($nids); - $comments = comment_load_multiple($cids); - - // Build a table listing the appropriate comments. - $options = array(); - $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 = $comment->nid->entity->label(); - $options[$comment->id()] = array( - 'subject' => array( - 'data' => array( - '#type' => 'link', - '#title' => $comment->subject->value, - '#href' => 'comment/' . $comment->id(), - '#options' => array('attributes' => array('title' => truncate_utf8($comment->comment_body->value, 128)), 'fragment' => 'comment-' . $comment->id()), - ), - ), - 'author' => theme('username', array('account' => comment_prepare_author($comment))), - 'posted_in' => array( - 'data' => array( - '#type' => 'link', - '#title' => $node_title, - '#href' => 'node/' . $comment->nid->target_id, - ), - ), - 'changed' => format_date($comment->changed->value, 'short'), - ); - $links = array(); - $links['edit'] = array( - 'title' => t('edit'), - 'href' => 'comment/' . $comment->id() . '/edit', - 'query' => $destination, - ); - if (module_invoke('content_translation', 'translate_access', $comment)) { - $links['translate'] = array( - 'title' => t('translate'), - 'href' => 'comment/' . $comment->id() . '/translations', - 'query' => $destination, - ); - } - $options[$comment->id()]['operations']['data'] = array( - '#type' => 'operations', - '#links' => $links, - ); - } - - $form['comments'] = array( - '#type' => 'tableselect', - '#header' => $header, - '#options' => $options, - '#empty' => t('No comments available.'), - ); - - $form['pager'] = array('#theme' => 'pager'); - - return $form; -} - -/** - * Form validation handler for comment_admin_overview(). - * - * @see comment_admin_overview_submit() - */ -function comment_admin_overview_validate($form, &$form_state) { - $form_state['values']['comments'] = array_diff($form_state['values']['comments'], array(0)); - // We can't execute any 'Update options' if no comments were selected. - if (count($form_state['values']['comments']) == 0) { - form_set_error('', t('Select one or more comments to perform the update on.')); - } -} - -/** - * Form submission handler for comment_admin_overview(). - * - * Executes the chosen 'Update option' on the selected comments, such as - * publishing, unpublishing or deleting. - * - * @see comment_admin_overview_validate() - */ -function comment_admin_overview_submit($form, &$form_state) { - $operation = $form_state['values']['operation']; - $cids = $form_state['values']['comments']; - - if ($operation == 'delete') { - entity_delete_multiple('comment', $cids); - } - else { - foreach ($cids as $cid => $value) { - $comment = comment_load($value); - - if ($operation == 'unpublish') { - $comment->status->value = COMMENT_NOT_PUBLISHED; - } - elseif ($operation == 'publish') { - $comment->status->value = COMMENT_PUBLISHED; - } - $comment->save(); - } - } - drupal_set_message(t('The update has been performed.')); - $form_state['redirect'] = 'admin/content/comment'; - cache_invalidate_tags(array('content' => TRUE)); -} - -/** * Form constructor for the confirmation form for bulk comment deletion. * * @ingroup forms @@ -269,6 +68,8 @@ function comment_multiple_delete_confirm_submit($form, &$form_state) { * @param \Drupal\comment\Plugin\Core\Entity\Comment $comment * The comment entity that is about to be deleted. * + * @return array + * The confirmation form for the delete operation. * @see comment_menu() * @see comment_confirm_delete() */ @@ -279,7 +80,7 @@ function comment_confirm_delete_page(Comment $comment) { /** * Form constructor for the confirmation form for comment deletion. * - * @param Drupal\comment\Comment $comment + * @param Drupal\comment\CommentInterface $comment * The comment that is about to be deleted. * * @ingroup forms @@ -315,3 +116,153 @@ function comment_confirm_delete_submit($form, &$form_state) { $form_state['redirect'] = "node/{$comment->nid->target_id}"; } + +/* + * Build the comments overview screen. + * + * @ingroup forms + */ +function comment_admin_comments() { + drupal_set_title(t('Comments')); + // Build the sortable table header. + $header = array( + 'subject' => array( + 'data' => t('Subject'), + 'field' => 'c.subject', + ), + 'author' => array( + 'data' => t('Author'), + 'class' => array(RESPONSIVE_PRIORITY_LOW), + ), + 'posted_in' => array( + 'data' => t('Posted in'), + 'field' => 'n.title', + ), + 'status' => array( + 'data' => t('Status'), + 'field' => 'c.status', + 'class' => array(RESPONSIVE_PRIORITY_LOW) + ), + 'changed' => array( + 'data' => t('Updated'), + 'field' => 'c.changed', + 'sort' => 'desc', + 'class' => array(RESPONSIVE_PRIORITY_LOW) + ), + 'operations' => array( + 'data' => t('Operations'), + ), + ); + + $query = db_select('comment', 'c') + ->extend('Drupal\Core\Database\Query\PagerSelectExtender') + ->extend('Drupal\Core\Database\Query\TableSortExtender'); + $query->join('node_field_data', 'n', 'n.nid = c.nid'); + $query->addTag('node_access'); + $result = $query + ->fields('c', array('cid', 'nid', 'subject', 'name', 'changed', 'status')) + ->limit(50) + ->orderByHeader($header) + ->execute(); + + $nids = array(); + $cids = array(); + + // We collect a sorted list of node_titles during the query to attach to the + // comments later. + foreach ($result as $row) { + $nids[] = $row->nid; + $cids[] = $row->cid; + } + // Ensure all nodes are statically cached so that we do not have to load them + // individually when getting their labels below. + node_load_multiple($nids); + $comments = comment_load_multiple($cids); + + // Build a table listing the appropriate comments. + $destination = drupal_get_destination(); + $form['comments'] = array( + '#type' => 'table', + '#header' => $header, + '#empty' => t('No comments available.'), + ); + + foreach ($comments as $comment) { + $cid = $comment->id(); + // Get the title of the node associated with the comment. + $node_title = $comment->nid->entity->label(); + $form['comments'][$comment->id()] = array( + 'subject' => array( + 'data' => array( + '#type' => 'link', + '#title' => $comment->subject->value, + '#href' => 'comment/' . $cid, + '#options' => array('attributes' => array('title' => truncate_utf8(isset($comment->comment_body->value) ? $comment->comment_body->value : $comment->subject->title, 128)), 'fragment' => 'comment-' . $cid), + ), + ), + 'author' => array( + '#theme' => 'username', + '#account' => comment_prepare_author($comment) + ), + 'posted_in' => array( + 'data' => array( + '#type' => 'link', + '#title' => $node_title, + '#href' => 'node/' . $comment->nid->target_id, + ), + ), + 'status' => array( + '#markup' => $comment->status->value ? t('approved') : t('unapproved'), + ), + 'changed' => array( + '#markup' => format_date($comment->changed->value, 'short'), + ) + ); + $operations = array(); + + if ($comment->access('update')) { + $operations['edit'] = array( + 'title' => t('Edit'), + 'href' => 'comment/' . $cid . '/edit', + 'query' => $destination, + ); + } + if ($comment->access('delete')) { + $operations['delete'] = array( + 'title' => t('Delete'), + 'href' => 'comment/' . $cid . '/delete', + 'query' => $destination, + ); + } + if (module_invoke('content_translation', 'translate_access', $comment)) { + $operations['translate'] = array( + 'title' => t('translate'), + 'href' => 'comment/' . $cid . '/translations', + 'query' => $destination, + ); + } + + $form['comments'][$cid]['operations'] = array(); + if (count($operations) > 1) { + // Render an unordered list of operations links. + $form['comments'][$cid]['operations'] = array( + '#type' => 'operations', + '#subtype' => 'comment', + '#links' => $operations, + ); + } + elseif (!empty($operations)) { + // Render the first and only operation as a link. + $link = reset($operations); + $form['comments'][$cid]['operations'] = array( + '#type' => 'link', + '#title' => $link['title'], + '#href' => $link['href'], + '#options' => array('query' => $link['query']), + ); + } + } + + $form['pager'] = array('#theme' => 'pager'); + return $form; +} diff --git a/core/modules/comment/comment.module b/core/modules/comment/comment.module index a7e43cb..475563c 100644 --- a/core/modules/comment/comment.module +++ b/core/modules/comment/comment.module @@ -184,7 +184,7 @@ function comment_menu() { $items['admin/content/comment'] = array( 'title' => 'Comments', 'description' => 'List and edit site comments and the comment approval queue.', - 'page callback' => 'comment_admin', + 'page callback' => 'comment_admin_comments', 'access arguments' => array('administer comments'), 'type' => MENU_LOCAL_TASK | MENU_NORMAL_ITEM, 'file' => 'comment.admin.inc', @@ -194,13 +194,6 @@ function comment_menu() { 'title' => 'Published comments', 'type' => MENU_DEFAULT_LOCAL_TASK, ); - $items['admin/content/comment/approval'] = array( - 'title' => 'Unapproved comments', - 'title callback' => 'comment_count_unpublished', - 'page arguments' => array('approval'), - 'access arguments' => array('administer comments'), - 'type' => MENU_LOCAL_TASK, - ); $items['comment/%comment'] = array( 'title' => 'Comment permalink', 'page callback' => 'comment_permalink', diff --git a/core/modules/comment/comment.routing.yml b/core/modules/comment/comment.routing.yml index eaaeba4..c8b9541 100644 --- a/core/modules/comment/comment.routing.yml +++ b/core/modules/comment/comment.routing.yml @@ -1,3 +1,10 @@ +comment_multiple_delete_confirm: + pattern: '/admin/content/comment/delete' + defaults: + _form: '\Drupal\comment\Form\DeleteMultiple' + requirements: + _permission: 'administer comments' + comment_edit_page: pattern: '/comment/{comment}/edit' defaults: diff --git a/core/modules/comment/comment.views.inc b/core/modules/comment/comment.views.inc index 66e2083..e77d22c 100644 --- a/core/modules/comment/comment.views.inc +++ b/core/modules/comment/comment.views.inc @@ -250,7 +250,7 @@ function comment_views_data() { $data['comment']['view_comment'] = array( 'field' => array( 'title' => t('Link to comment'), - 'help' => t('Provide a simple link to view the comment.'), + 'help' => t('Provide a simple link to the comment.'), 'id' => 'comment_link', ), ); diff --git a/core/modules/comment/config/action.action.comment_delete_action.yml b/core/modules/comment/config/action.action.comment_delete_action.yml new file mode 100644 index 0000000..eda1ce0 --- /dev/null +++ b/core/modules/comment/config/action.action.comment_delete_action.yml @@ -0,0 +1,6 @@ +id: comment_delete_action +label: 'Delete comment' +status: '1' +langcode: en +type: comment +plugin: comment_delete_action diff --git a/core/modules/comment/config/views.view.comments.yml b/core/modules/comment/config/views.view.comments.yml new file mode 100644 index 0000000..c5c57cd --- /dev/null +++ b/core/modules/comment/config/views.view.comments.yml @@ -0,0 +1,1487 @@ +base_field: cid +base_table: comment +core: 8.x +description: 'Find and manage comments.' +status: '1' +display: + page_1: + display_plugin: page + id: page_1 + display_title: Comments + position: '' + display_options: + path: admin/content/comment + menu: + type: tab + title: Comments + description: 'Comments published' + name: admin + weight: '0' + context: '0' + display_description: '' + filters: + status: + id: status + table: comment + field: status + relationship: none + group_type: group + admin_label: '' + operator: '=' + value: '1' + group: '1' + exposed: '0' + expose: + operator_id: '0' + label: '' + description: '' + use_operator: '0' + operator: '0' + identifier: '' + required: '0' + remember: '0' + multiple: '0' + remember_roles: + authenticated: authenticated + is_grouped: '0' + group_info: + label: '' + description: '' + identifier: '' + optional: '1' + widget: select + multiple: '0' + remember: '0' + default_group: All + default_group_multiple: { } + group_items: { } + defaults: + filters: '0' + filter_groups: '0' + fields: '0' + filter_groups: + operator: AND + groups: + 1: AND + fields: + action_bulk_form: + id: action_bulk_form + table: action + field: action_bulk_form + relationship: none + group_type: group + admin_label: '' + label: 'Bulk update' + exclude: '0' + alter: + alter_text: '0' + text: '' + make_link: '0' + path: '' + absolute: '0' + external: '0' + replace_spaces: '0' + path_case: none + trim_whitespace: '0' + alt: '' + rel: '' + link_class: '' + prefix: '' + suffix: '' + target: '' + nl2br: '0' + max_length: '' + word_boundary: '1' + ellipsis: '1' + more_link: '0' + more_link_text: '' + more_link_path: '' + strip_tags: '0' + trim: '0' + preserve_tags: '' + html: '0' + element_type: '' + element_class: '' + element_label_type: '' + element_label_class: '' + element_label_colon: '1' + element_wrapper_type: '' + element_wrapper_class: '' + element_default_classes: '1' + empty: '' + hide_empty: '0' + empty_zero: '0' + hide_alter_empty: '1' + include_exclude: include + selected_actions: + comment_delete_action: comment_delete_action + comment_unpublish_action: comment_unpublish_action + plugin_id: action_bulk_form + subject: + id: subject + table: comment + field: subject + relationship: none + group_type: group + admin_label: '' + label: Subject + exclude: '0' + alter: + alter_text: '0' + text: '' + make_link: '0' + path: '' + absolute: '0' + external: '0' + replace_spaces: '0' + path_case: none + trim_whitespace: '0' + alt: '' + rel: '' + link_class: '' + prefix: '' + suffix: '' + target: '' + nl2br: '0' + max_length: '' + word_boundary: '0' + ellipsis: '0' + more_link: '0' + more_link_text: '' + more_link_path: '' + strip_tags: '0' + trim: '0' + preserve_tags: '' + html: '0' + element_type: '' + element_class: '' + element_label_type: '' + element_label_class: '' + element_label_colon: '1' + element_wrapper_type: '' + element_wrapper_class: '' + element_default_classes: '1' + empty: '' + hide_empty: '0' + empty_zero: '0' + hide_alter_empty: '1' + link_to_comment: '1' + link_to_node: '0' + name: + id: name + table: comment + field: name + relationship: none + group_type: group + admin_label: '' + label: Author + exclude: '0' + alter: + alter_text: '0' + text: '' + make_link: '0' + path: '' + absolute: '0' + external: '0' + replace_spaces: '0' + path_case: none + trim_whitespace: '0' + alt: '' + rel: '' + link_class: '' + prefix: '' + suffix: '' + target: '' + nl2br: '0' + max_length: '' + word_boundary: '1' + ellipsis: '1' + more_link: '0' + more_link_text: '' + more_link_path: '' + strip_tags: '0' + trim: '0' + preserve_tags: '' + html: '0' + element_type: '' + element_class: '' + element_label_type: '' + element_label_class: '' + element_label_colon: '1' + element_wrapper_type: '' + element_wrapper_class: '' + element_default_classes: '1' + empty: '' + hide_empty: '0' + empty_zero: '0' + hide_alter_empty: '1' + link_to_user: '1' + plugin_id: comment_username + title: + id: title + table: node_field_data + field: title + relationship: nid + group_type: group + admin_label: '' + label: 'Posted in' + exclude: '0' + alter: + alter_text: '0' + text: '' + make_link: '0' + path: '' + absolute: '0' + external: '0' + replace_spaces: '0' + path_case: none + trim_whitespace: '0' + alt: '' + rel: '' + link_class: '' + prefix: '' + suffix: '' + target: '' + nl2br: '0' + max_length: '' + word_boundary: '1' + ellipsis: '1' + more_link: '0' + more_link_text: '' + more_link_path: '' + strip_tags: '0' + trim: '0' + preserve_tags: '' + html: '0' + element_type: '' + element_class: '' + element_label_type: '' + element_label_class: '' + element_label_colon: '1' + element_wrapper_type: '' + element_wrapper_class: '' + element_default_classes: '1' + empty: '' + hide_empty: '0' + empty_zero: '0' + hide_alter_empty: '1' + link_to_node: '1' + plugin_id: node + changed: + id: changed + table: comment + field: changed + relationship: none + group_type: group + admin_label: '' + label: Updated + exclude: '0' + alter: + alter_text: '0' + text: '' + make_link: '0' + path: '' + absolute: '0' + external: '0' + replace_spaces: '0' + path_case: none + trim_whitespace: '0' + alt: '' + rel: '' + link_class: '' + prefix: '' + suffix: '' + target: '' + nl2br: '0' + max_length: '' + word_boundary: '1' + ellipsis: '1' + more_link: '0' + more_link_text: '' + more_link_path: '' + strip_tags: '0' + trim: '0' + preserve_tags: '' + html: '0' + element_type: '' + element_class: '' + element_label_type: '' + element_label_class: '' + element_label_colon: '1' + element_wrapper_type: '' + element_wrapper_class: '' + element_default_classes: '1' + empty: '' + hide_empty: '0' + empty_zero: '0' + hide_alter_empty: '1' + date_format: short + custom_date_format: '' + timezone: '' + plugin_id: date + edit_comment: + id: edit_comment + table: comment + field: edit_comment + relationship: none + group_type: group + admin_label: '' + label: '' + exclude: '1' + alter: + alter_text: '0' + text: '' + make_link: '0' + path: '' + absolute: '0' + external: '0' + replace_spaces: '0' + path_case: none + trim_whitespace: '0' + alt: '' + rel: '' + link_class: '' + prefix: '' + suffix: '' + target: '' + nl2br: '0' + max_length: '' + word_boundary: '1' + ellipsis: '1' + more_link: '0' + more_link_text: '' + more_link_path: '' + strip_tags: '0' + trim: '0' + preserve_tags: '' + html: '0' + element_type: '' + element_class: '' + element_label_type: '' + element_label_class: '' + element_label_colon: '0' + element_wrapper_type: '' + element_wrapper_class: '' + element_default_classes: '1' + empty: '' + hide_empty: '0' + empty_zero: '0' + hide_alter_empty: '1' + text: Edit + link_to_node: '0' + destination: '0' + plugin_id: comment_link_edit + delete_comment: + id: delete_comment + table: comment + field: delete_comment + relationship: none + group_type: group + admin_label: '' + label: '' + exclude: '1' + alter: + alter_text: '0' + text: '' + make_link: '0' + path: '' + absolute: '0' + external: '0' + replace_spaces: '0' + path_case: none + trim_whitespace: '0' + alt: '' + rel: '' + link_class: '' + prefix: '' + suffix: '' + target: '' + nl2br: '0' + max_length: '' + word_boundary: '1' + ellipsis: '1' + more_link: '0' + more_link_text: '' + more_link_path: '' + strip_tags: '0' + trim: '0' + preserve_tags: '' + html: '0' + element_type: '' + element_class: '' + element_label_type: '' + element_label_class: '' + element_label_colon: '0' + element_wrapper_type: '' + element_wrapper_class: '' + element_default_classes: '1' + empty: '' + hide_empty: '0' + empty_zero: '0' + hide_alter_empty: '1' + text: Delete + link_to_node: '0' + plugin_id: comment_link_delete + dropbutton: + id: dropbutton + table: views + field: dropbutton + relationship: none + group_type: group + admin_label: '' + label: Operations + exclude: '0' + alter: + alter_text: '0' + text: '' + make_link: '0' + path: '' + absolute: '0' + external: '0' + replace_spaces: '0' + path_case: none + trim_whitespace: '0' + alt: '' + rel: '' + link_class: '' + prefix: '' + suffix: '' + target: '' + nl2br: '0' + max_length: '' + word_boundary: '1' + ellipsis: '1' + more_link: '0' + more_link_text: '' + more_link_path: '' + strip_tags: '0' + trim: '0' + preserve_tags: '' + html: '0' + element_type: '' + element_class: '' + element_label_type: '' + element_label_class: '' + element_label_colon: '0' + element_wrapper_type: '' + element_wrapper_class: '' + element_default_classes: '1' + empty: '' + hide_empty: '0' + empty_zero: '0' + hide_alter_empty: '1' + fields: + edit_comment: edit_comment + delete_comment: delete_comment + action_bulk_form: '0' + subject: '0' + name: '0' + title: '0' + changed: '0' + destination: '1' + plugin_id: dropbutton + page_2: + display_plugin: page + id: page_2 + display_title: 'Unapproved comments' + position: '' + display_options: + display_description: 'Comments pending to approval' + path: admin/content/comment/approval + menu: + type: tab + title: 'Unapproved comments' + description: '' + name: admin + weight: '0' + context: '0' + filters: + status: + id: status + table: comment + field: status + relationship: none + group_type: group + admin_label: '' + operator: '=' + value: '0' + group: '1' + exposed: '0' + expose: + operator_id: '0' + label: '' + description: '' + use_operator: '0' + operator: '0' + identifier: '' + required: '0' + remember: '0' + multiple: '0' + remember_roles: + authenticated: authenticated + is_grouped: '0' + group_info: + label: '' + description: '' + identifier: '' + optional: '1' + widget: select + multiple: '0' + remember: '0' + default_group: All + default_group_multiple: { } + group_items: { } + defaults: + filters: '0' + filter_groups: '0' + fields: '0' + filter_groups: + operator: AND + groups: + 1: AND + fields: + action_bulk_form: + id: action_bulk_form + table: action + field: action_bulk_form + relationship: none + group_type: group + admin_label: '' + label: 'Bulk update' + exclude: '0' + alter: + alter_text: '0' + text: '' + make_link: '0' + path: '' + absolute: '0' + external: '0' + replace_spaces: '0' + path_case: none + trim_whitespace: '0' + alt: '' + rel: '' + link_class: '' + prefix: '' + suffix: '' + target: '' + nl2br: '0' + max_length: '' + word_boundary: '1' + ellipsis: '1' + more_link: '0' + more_link_text: '' + more_link_path: '' + strip_tags: '0' + trim: '0' + preserve_tags: '' + html: '0' + element_type: '' + element_class: '' + element_label_type: '' + element_label_class: '' + element_label_colon: '1' + element_wrapper_type: '' + element_wrapper_class: '' + element_default_classes: '1' + empty: '' + hide_empty: '0' + empty_zero: '0' + hide_alter_empty: '1' + include_exclude: include + selected_actions: + comment_delete_action: comment_delete_action + comment_publish_action: comment_publish_action + plugin_id: action_bulk_form + subject: + id: subject + table: comment + field: subject + relationship: none + group_type: group + admin_label: '' + label: Subject + exclude: '0' + alter: + alter_text: '0' + text: '' + make_link: '0' + path: '' + absolute: '0' + external: '0' + replace_spaces: '0' + path_case: none + trim_whitespace: '0' + alt: '' + rel: '' + link_class: '' + prefix: '' + suffix: '' + target: '' + nl2br: '0' + max_length: '' + word_boundary: '0' + ellipsis: '0' + more_link: '0' + more_link_text: '' + more_link_path: '' + strip_tags: '0' + trim: '0' + preserve_tags: '' + html: '0' + element_type: '' + element_class: '' + element_label_type: '' + element_label_class: '' + element_label_colon: '1' + element_wrapper_type: '' + element_wrapper_class: '' + element_default_classes: '1' + empty: '' + hide_empty: '0' + empty_zero: '0' + hide_alter_empty: '1' + link_to_comment: '1' + link_to_node: '0' + name: + id: name + table: comment + field: name + relationship: none + group_type: group + admin_label: '' + label: Author + exclude: '0' + alter: + alter_text: '0' + text: '' + make_link: '0' + path: '' + absolute: '0' + external: '0' + replace_spaces: '0' + path_case: none + trim_whitespace: '0' + alt: '' + rel: '' + link_class: '' + prefix: '' + suffix: '' + target: '' + nl2br: '0' + max_length: '' + word_boundary: '1' + ellipsis: '1' + more_link: '0' + more_link_text: '' + more_link_path: '' + strip_tags: '0' + trim: '0' + preserve_tags: '' + html: '0' + element_type: '' + element_class: '' + element_label_type: '' + element_label_class: '' + element_label_colon: '1' + element_wrapper_type: '' + element_wrapper_class: '' + element_default_classes: '1' + empty: '' + hide_empty: '0' + empty_zero: '0' + hide_alter_empty: '1' + link_to_user: '1' + plugin_id: comment_username + title: + id: title + table: node_field_data + field: title + relationship: nid + group_type: group + admin_label: '' + label: 'Posted in' + exclude: '0' + alter: + alter_text: '0' + text: '' + make_link: '0' + path: '' + absolute: '0' + external: '0' + replace_spaces: '0' + path_case: none + trim_whitespace: '0' + alt: '' + rel: '' + link_class: '' + prefix: '' + suffix: '' + target: '' + nl2br: '0' + max_length: '' + word_boundary: '1' + ellipsis: '1' + more_link: '0' + more_link_text: '' + more_link_path: '' + strip_tags: '0' + trim: '0' + preserve_tags: '' + html: '0' + element_type: '' + element_class: '' + element_label_type: '' + element_label_class: '' + element_label_colon: '1' + element_wrapper_type: '' + element_wrapper_class: '' + element_default_classes: '1' + empty: '' + hide_empty: '0' + empty_zero: '0' + hide_alter_empty: '1' + link_to_node: '1' + plugin_id: node + changed: + id: changed + table: comment + field: changed + relationship: none + group_type: group + admin_label: '' + label: Updated + exclude: '0' + alter: + alter_text: '0' + text: '' + make_link: '0' + path: '' + absolute: '0' + external: '0' + replace_spaces: '0' + path_case: none + trim_whitespace: '0' + alt: '' + rel: '' + link_class: '' + prefix: '' + suffix: '' + target: '' + nl2br: '0' + max_length: '' + word_boundary: '1' + ellipsis: '1' + more_link: '0' + more_link_text: '' + more_link_path: '' + strip_tags: '0' + trim: '0' + preserve_tags: '' + html: '0' + element_type: '' + element_class: '' + element_label_type: '' + element_label_class: '' + element_label_colon: '1' + element_wrapper_type: '' + element_wrapper_class: '' + element_default_classes: '1' + empty: '' + hide_empty: '0' + empty_zero: '0' + hide_alter_empty: '1' + date_format: short + custom_date_format: '' + timezone: '' + plugin_id: date + approve_comment: + id: approve_comment + table: comment + field: approve_comment + relationship: none + group_type: group + admin_label: '' + label: '' + exclude: '1' + alter: + alter_text: '0' + text: '' + make_link: '0' + path: '' + absolute: '0' + external: '0' + replace_spaces: '0' + path_case: none + trim_whitespace: '0' + alt: '' + rel: '' + link_class: '' + prefix: '' + suffix: '' + target: '' + nl2br: '0' + max_length: '' + word_boundary: '1' + ellipsis: '1' + more_link: '0' + more_link_text: '' + more_link_path: '' + strip_tags: '0' + trim: '0' + preserve_tags: '' + html: '0' + element_type: '' + element_class: '' + element_label_type: '' + element_label_class: '' + element_label_colon: '0' + element_wrapper_type: '' + element_wrapper_class: '' + element_default_classes: '1' + empty: '' + hide_empty: '0' + empty_zero: '0' + hide_alter_empty: '1' + text: Approve + link_to_node: '0' + plugin_id: comment_link_approve + edit_comment: + id: edit_comment + table: comment + field: edit_comment + relationship: none + group_type: group + admin_label: '' + label: '' + exclude: '1' + alter: + alter_text: '0' + text: '' + make_link: '0' + path: '' + absolute: '0' + external: '0' + replace_spaces: '0' + path_case: none + trim_whitespace: '0' + alt: '' + rel: '' + link_class: '' + prefix: '' + suffix: '' + target: '' + nl2br: '0' + max_length: '' + word_boundary: '1' + ellipsis: '1' + more_link: '0' + more_link_text: '' + more_link_path: '' + strip_tags: '0' + trim: '0' + preserve_tags: '' + html: '0' + element_type: '' + element_class: '' + element_label_type: '' + element_label_class: '' + element_label_colon: '0' + element_wrapper_type: '' + element_wrapper_class: '' + element_default_classes: '1' + empty: '' + hide_empty: '0' + empty_zero: '0' + hide_alter_empty: '1' + text: Edit + link_to_node: '0' + destination: '0' + plugin_id: comment_link_edit + delete_comment: + id: delete_comment + table: comment + field: delete_comment + relationship: none + group_type: group + admin_label: '' + label: '' + exclude: '1' + alter: + alter_text: '0' + text: '' + make_link: '0' + path: '' + absolute: '0' + external: '0' + replace_spaces: '0' + path_case: none + trim_whitespace: '0' + alt: '' + rel: '' + link_class: '' + prefix: '' + suffix: '' + target: '' + nl2br: '0' + max_length: '' + word_boundary: '1' + ellipsis: '1' + more_link: '0' + more_link_text: '' + more_link_path: '' + strip_tags: '0' + trim: '0' + preserve_tags: '' + html: '0' + element_type: '' + element_class: '' + element_label_type: '' + element_label_class: '' + element_label_colon: '0' + element_wrapper_type: '' + element_wrapper_class: '' + element_default_classes: '1' + empty: '' + hide_empty: '0' + empty_zero: '0' + hide_alter_empty: '1' + text: Delete + link_to_node: '0' + plugin_id: comment_link_delete + dropbutton: + id: dropbutton + table: views + field: dropbutton + relationship: none + group_type: group + admin_label: '' + label: Operations + exclude: '0' + alter: + alter_text: '0' + text: '' + make_link: '0' + path: '' + absolute: '0' + external: '0' + replace_spaces: '0' + path_case: none + trim_whitespace: '0' + alt: '' + rel: '' + link_class: '' + prefix: '' + suffix: '' + target: '' + nl2br: '0' + max_length: '' + word_boundary: '1' + ellipsis: '1' + more_link: '0' + more_link_text: '' + more_link_path: '' + strip_tags: '0' + trim: '0' + preserve_tags: '' + html: '0' + element_type: '' + element_class: '' + element_label_type: '' + element_label_class: '' + element_label_colon: '0' + element_wrapper_type: '' + element_wrapper_class: '' + element_default_classes: '1' + empty: '' + hide_empty: '0' + empty_zero: '0' + hide_alter_empty: '1' + fields: + approve_comment: approve_comment + edit_comment: edit_comment + delete_comment: delete_comment + action_bulk_form: '0' + subject: '0' + name: '0' + title: '0' + changed: '0' + destination: '1' + plugin_id: dropbutton + default: + display_plugin: default + id: default + display_title: Master + position: '' + display_options: + access: + type: perm + options: + perm: 'administer comments' + cache: + type: none + options: { } + query: + type: views_query + options: + disable_sql_rewrite: '0' + distinct: '0' + slave: '0' + query_comment: '' + query_tags: { } + exposed_form: + type: basic + options: + submit_button: Apply + reset_button: '0' + reset_button_label: Reset + exposed_sorts_label: 'Sort by' + expose_sort_order: '1' + sort_asc_label: Asc + sort_desc_label: Desc + pager: + type: full + options: + items_per_page: '50' + offset: '0' + id: '0' + total_pages: '' + expose: + items_per_page: '0' + items_per_page_label: 'Items per page' + items_per_page_options: '5, 10, 20, 40, 60' + items_per_page_options_all: '0' + items_per_page_options_all_label: '- All -' + offset: '0' + offset_label: Offset + tags: + previous: '‹ previous' + next: 'next ›' + first: '« first' + last: 'last »' + quantity: '9' + style: + type: table + options: + grouping: { } + row_class: '' + default_row_class: '1' + row_class_special: '1' + override: '1' + sticky: '0' + caption: '' + summary: '' + description: '' + columns: + action_bulk_form: action_bulk_form + subject: subject + name: name + title: title + changed: changed + approve_comment: approve_comment + edit_comment: edit_comment + delete_comment: delete_comment + dropbutton: dropbutton + info: + action_bulk_form: + sortable: '0' + default_sort_order: asc + align: '' + separator: '' + empty_column: '1' + responsive: '' + subject: + sortable: '1' + default_sort_order: asc + align: '' + separator: '' + empty_column: '0' + responsive: '' + name: + sortable: '1' + default_sort_order: asc + align: '' + separator: '' + empty_column: '0' + responsive: '' + title: + sortable: '1' + default_sort_order: asc + align: '' + separator: '' + empty_column: '0' + responsive: '' + changed: + sortable: '1' + default_sort_order: desc + align: '' + separator: '' + empty_column: '0' + responsive: '' + approve_comment: + sortable: '0' + default_sort_order: asc + align: '' + separator: '' + empty_column: '0' + responsive: '' + edit_comment: + sortable: '0' + default_sort_order: asc + align: '' + separator: '' + empty_column: '0' + responsive: '' + delete_comment: + sortable: '0' + default_sort_order: asc + align: '' + separator: '' + empty_column: '0' + responsive: '' + dropbutton: + sortable: '0' + default_sort_order: asc + align: '' + separator: '' + empty_column: '0' + responsive: '' + default: changed + empty_table: '1' + row: + type: fields + relationships: + nid: + id: nid + table: comment + field: nid + required: '1' + relationship: none + group_type: group + admin_label: Content + fields: + action_bulk_form: + id: action_bulk_form + table: action + field: action_bulk_form + relationship: none + group_type: group + admin_label: '' + label: 'Bulk update' + exclude: '0' + alter: + alter_text: '0' + text: '' + make_link: '0' + path: '' + absolute: '0' + external: '0' + replace_spaces: '0' + path_case: none + trim_whitespace: '0' + alt: '' + rel: '' + link_class: '' + prefix: '' + suffix: '' + target: '' + nl2br: '0' + max_length: '' + word_boundary: '1' + ellipsis: '1' + more_link: '0' + more_link_text: '' + more_link_path: '' + strip_tags: '0' + trim: '0' + preserve_tags: '' + html: '0' + element_type: '' + element_class: '' + element_label_type: '' + element_label_class: '' + element_label_colon: '1' + element_wrapper_type: '' + element_wrapper_class: '' + element_default_classes: '1' + empty: '' + hide_empty: '0' + empty_zero: '0' + hide_alter_empty: '1' + include_exclude: include + selected_actions: + comment_unpublish_action: comment_unpublish_action + plugin_id: action_bulk_form + subject: + id: subject + table: comment + field: subject + relationship: none + group_type: group + admin_label: '' + label: Subject + exclude: '0' + alter: + alter_text: '0' + text: '' + make_link: '0' + path: '' + absolute: '0' + external: '0' + replace_spaces: '0' + path_case: none + trim_whitespace: '0' + alt: '' + rel: '' + link_class: '' + prefix: '' + suffix: '' + target: '' + nl2br: '0' + max_length: '' + word_boundary: '0' + ellipsis: '0' + more_link: '0' + more_link_text: '' + more_link_path: '' + strip_tags: '0' + trim: '0' + preserve_tags: '' + html: '0' + element_type: '' + element_class: '' + element_label_type: '' + element_label_class: '' + element_label_colon: '1' + element_wrapper_type: '' + element_wrapper_class: '' + element_default_classes: '1' + empty: '' + hide_empty: '0' + empty_zero: '0' + hide_alter_empty: '1' + link_to_comment: '1' + link_to_node: '0' + name: + id: name + table: comment + field: name + relationship: none + group_type: group + admin_label: '' + label: Author + exclude: '0' + alter: + alter_text: '0' + text: '' + make_link: '0' + path: '' + absolute: '0' + external: '0' + replace_spaces: '0' + path_case: none + trim_whitespace: '0' + alt: '' + rel: '' + link_class: '' + prefix: '' + suffix: '' + target: '' + nl2br: '0' + max_length: '' + word_boundary: '1' + ellipsis: '1' + more_link: '0' + more_link_text: '' + more_link_path: '' + strip_tags: '0' + trim: '0' + preserve_tags: '' + html: '0' + element_type: '' + element_class: '' + element_label_type: '' + element_label_class: '' + element_label_colon: '1' + element_wrapper_type: '' + element_wrapper_class: '' + element_default_classes: '1' + empty: '' + hide_empty: '0' + empty_zero: '0' + hide_alter_empty: '1' + link_to_user: '1' + plugin_id: comment_username + title: + id: title + table: node_field_data + field: title + relationship: nid + group_type: group + admin_label: '' + label: 'Posted in' + exclude: '0' + alter: + alter_text: '0' + text: '' + make_link: '0' + path: '' + absolute: '0' + external: '0' + replace_spaces: '0' + path_case: none + trim_whitespace: '0' + alt: '' + rel: '' + link_class: '' + prefix: '' + suffix: '' + target: '' + nl2br: '0' + max_length: '' + word_boundary: '1' + ellipsis: '1' + more_link: '0' + more_link_text: '' + more_link_path: '' + strip_tags: '0' + trim: '0' + preserve_tags: '' + html: '0' + element_type: '' + element_class: '' + element_label_type: '' + element_label_class: '' + element_label_colon: '1' + element_wrapper_type: '' + element_wrapper_class: '' + element_default_classes: '1' + empty: '' + hide_empty: '0' + empty_zero: '0' + hide_alter_empty: '1' + link_to_node: '1' + plugin_id: node + changed: + id: changed + table: comment + field: changed + relationship: none + group_type: group + admin_label: '' + label: Updated + exclude: '0' + alter: + alter_text: '0' + text: '' + make_link: '0' + path: '' + absolute: '0' + external: '0' + replace_spaces: '0' + path_case: none + trim_whitespace: '0' + alt: '' + rel: '' + link_class: '' + prefix: '' + suffix: '' + target: '' + nl2br: '0' + max_length: '' + word_boundary: '1' + ellipsis: '1' + more_link: '0' + more_link_text: '' + more_link_path: '' + strip_tags: '0' + trim: '0' + preserve_tags: '' + html: '0' + element_type: '' + element_class: '' + element_label_type: '' + element_label_class: '' + element_label_colon: '1' + element_wrapper_type: '' + element_wrapper_class: '' + element_default_classes: '1' + empty: '' + hide_empty: '0' + empty_zero: '0' + hide_alter_empty: '1' + date_format: short + custom_date_format: '' + timezone: '' + plugin_id: date + filters: + status: + id: status + table: comment + field: status + relationship: none + group_type: group + admin_label: '' + operator: '=' + value: '1' + group: '1' + exposed: '0' + expose: + operator_id: '0' + label: '' + description: '' + use_operator: '0' + operator: '0' + identifier: '' + required: '0' + remember: '0' + multiple: '0' + remember_roles: + authenticated: authenticated + is_grouped: '0' + group_info: + label: '' + description: '' + identifier: '' + optional: '1' + widget: select + multiple: '0' + remember: '0' + default_group: All + default_group_multiple: { } + group_items: { } + sorts: + created: + id: created + table: comment + field: created + order: DESC + relationship: none + group_type: group + admin_label: '' + exposed: '0' + expose: + label: '' + granularity: second + title: Comments + header: { } + footer: { } + empty: + area_text_custom: + id: area_text_custom + table: views + field: area_text_custom + relationship: none + group_type: group + admin_label: '' + empty: '1' + tokenize: '0' + content: 'No comments available.' + plugin_id: text_custom + arguments: { } +label: Comments +module: views +id: comments +tag: default +uuid: df052bd2-a90f-4632-811b-277cf6ef38eb +langcode: en diff --git a/core/modules/comment/lib/Drupal/comment/CommentStorageController.php b/core/modules/comment/lib/Drupal/comment/CommentStorageController.php index 4e6ca4c..0e0b5b2 100644 --- a/core/modules/comment/lib/Drupal/comment/CommentStorageController.php +++ b/core/modules/comment/lib/Drupal/comment/CommentStorageController.php @@ -232,4 +232,5 @@ public function getChildCids(array $comments) { ->execute() ->fetchCol(); } + } diff --git a/core/modules/comment/lib/Drupal/comment/Form/DeleteMultiple.php b/core/modules/comment/lib/Drupal/comment/Form/DeleteMultiple.php new file mode 100644 index 0000000..7895d8b --- /dev/null +++ b/core/modules/comment/lib/Drupal/comment/Form/DeleteMultiple.php @@ -0,0 +1,127 @@ +tempStoreFactory = $temp_store_factory; + $this->storageController = $manager->getStorageController('comment'); + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container) { + return new static( + $container->get('user.tempstore'), + $container->get('plugin.manager.entity') + ); + } + + /** + * {@inheritdoc} + */ + public function getFormID() { + return 'comment_multiple_delete_confirm'; + } + + /** + * {@inheritdoc} + */ + public function getQuestion() { + return format_plural(count($this->comments), 'Are you sure you want to delete this item?', 'Are you sure you want to delete these items?'); + } + + /** + * {@inheritdoc} + */ + public function getCancelPath() { + return 'admin/content/comment'; + } + + /** + * {@inheritdoc} + */ + public function getConfirmText() { + return t('Delete'); + } + + /** + * {@inheritdoc} + */ + public function buildForm(array $form, array &$form_state) { + $this->comments = $this->tempStoreFactory->get('comment_multiple_delete_confirm')->get($GLOBALS['user']->uid); + if (empty($this->comments)) { + return new RedirectResponse(url($this->getCancelPath(), array('absolute' => TRUE))); + } + + $form['comments'] = array( + '#theme' => 'item_list', + '#items' => array_map(function ($comment) { + return String::checkPlain($comment->label()); + }, $this->comments), + ); + return parent::buildForm($form, $form_state); + } + + /** + * {@inheritdoc} + */ + public function submitForm(array &$form, array &$form_state) { + if ($form_state['values']['confirm'] && !empty($this->comments)) { + $this->storageController->delete($this->comments); + $this->tempStoreFactory->get('comment_multiple_delete_confirm')->delete($GLOBALS['user']->uid); + $count = count($this->comments); + watchdog('content', 'Deleted @count posts.', array('@count' => $count)); + drupal_set_message(format_plural($count, 'Deleted 1 comment.', 'Deleted @count comments.')); + } + $form_state['redirect'] = 'admin/content/comment'; + } + +} diff --git a/core/modules/comment/lib/Drupal/comment/Plugin/Action/DeleteComment.php b/core/modules/comment/lib/Drupal/comment/Plugin/Action/DeleteComment.php new file mode 100644 index 0000000..832aa30 --- /dev/null +++ b/core/modules/comment/lib/Drupal/comment/Plugin/Action/DeleteComment.php @@ -0,0 +1,75 @@ +tempStore = $temp_store_factory->get('comment_multiple_delete_confirm'); + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container, array $configuration, $plugin_id, array $plugin_definition) { + return new static($configuration, $plugin_id, $plugin_definition, $container->get('user.tempstore')); + } + + /** + * {@inheritdoc} + */ + public function executeMultiple(array $entities) { + $this->tempStore->set($GLOBALS['user']->uid, $entities); + } + + /** + * {@inheritdoc} + */ + public function execute($object = NULL) { + $this->executeMultiple(array($object)); + } + +} diff --git a/core/modules/comment/lib/Drupal/comment/Plugin/views/field/Link.php b/core/modules/comment/lib/Drupal/comment/Plugin/views/field/Link.php index d1e19f5..9d7b222 100644 --- a/core/modules/comment/lib/Drupal/comment/Plugin/views/field/Link.php +++ b/core/modules/comment/lib/Drupal/comment/Plugin/views/field/Link.php @@ -9,7 +9,7 @@ use Drupal\views\Plugin\views\field\FieldPluginBase; use Drupal\Component\Annotation\PluginID; - +use Drupal\comment\CommentInterface; /** * Base field handler to present a link. * @@ -44,13 +44,24 @@ public function query() {} function render($values) { $comment = $this->getEntity($values); - return $this->render_link($comment, $values); + return $this->renderLink($comment, $values); } - function render_link($data, $values) { + /** + * Renders the comment action link in the view. + * + * @param \Drupal\comment\CommentInterface $comment + * Comment entity. + * @param array $values + * Array of values of the view row. + * + * @return string + * Rendered text to display. + * + */ + public function renderLink(CommentInterface $comment, $values) { $text = !empty($this->options['text']) ? $this->options['text'] : t('view'); - $comment = $data; - $nid = $comment->nid; + $nid = $comment->nid->value; $cid = $comment->id(); $this->options['alter']['make_link'] = TRUE; diff --git a/core/modules/comment/lib/Drupal/comment/Plugin/views/field/LinkApprove.php b/core/modules/comment/lib/Drupal/comment/Plugin/views/field/LinkApprove.php index 49bcb58..fb20cc5 100644 --- a/core/modules/comment/lib/Drupal/comment/Plugin/views/field/LinkApprove.php +++ b/core/modules/comment/lib/Drupal/comment/Plugin/views/field/LinkApprove.php @@ -8,6 +8,7 @@ namespace Drupal\comment\Plugin\views\field; use Drupal\Component\Annotation\PluginID; +use Drupal\comment\CommentInterface; /** * Provides a comment approve link. @@ -23,17 +24,17 @@ public function access() { return user_access('administer comments'); } - function render_link($data, $values) { - $status = $this->getValue($values, 'status'); - + /** + * {@inheritdoc} + */ + public function renderLink(CommentInterface $comment, $values) { // Don't show an approve link on published nodes. - if ($status == COMMENT_PUBLISHED) { - return; + if ($comment->status->value == COMMENT_PUBLISHED) { + return ''; } $text = !empty($this->options['text']) ? $this->options['text'] : t('approve'); - $cid = $this->getValue($values, 'cid'); - + $cid = $comment->id(); $this->options['alter']['make_link'] = TRUE; $this->options['alter']['path'] = "comment/" . $cid . "/approve"; $this->options['alter']['query'] = drupal_get_destination() + array('token' => drupal_get_token("comment/$cid/approve")); diff --git a/core/modules/comment/lib/Drupal/comment/Plugin/views/field/LinkDelete.php b/core/modules/comment/lib/Drupal/comment/Plugin/views/field/LinkDelete.php index 23c96de..d75ba03 100644 --- a/core/modules/comment/lib/Drupal/comment/Plugin/views/field/LinkDelete.php +++ b/core/modules/comment/lib/Drupal/comment/Plugin/views/field/LinkDelete.php @@ -8,6 +8,7 @@ namespace Drupal\comment\Plugin\views\field; use Drupal\Component\Annotation\PluginID; +use Drupal\comment\CommentInterface; /** * Field handler to present a link to delete a comment. @@ -19,16 +20,22 @@ class LinkDelete extends Link { public function access() { - //needs permission to administer comments in general + // Needs permission to administer comments in general. return user_access('administer comments'); } - function render_link($data, $values) { - $text = !empty($this->options['text']) ? $this->options['text'] : t('delete'); - $cid = $this->getValue($values, 'cid'); + /** + * {@inheritdoc} + */ + public function renderLink(CommentInterface $comment, $values) { + // Ensure user has access to edit this comment. + if (!$comment->access('delete')) { + return ''; + } + $text = !empty($this->options['text']) ? $this->options['text'] : t('delete'); $this->options['alter']['make_link'] = TRUE; - $this->options['alter']['path'] = "comment/" . $cid . "/delete"; + $this->options['alter']['path'] = "comment/" . $comment->id() . "/delete"; $this->options['alter']['query'] = drupal_get_destination(); return $text; diff --git a/core/modules/comment/lib/Drupal/comment/Plugin/views/field/LinkEdit.php b/core/modules/comment/lib/Drupal/comment/Plugin/views/field/LinkEdit.php index d77b824..8ea3624 100644 --- a/core/modules/comment/lib/Drupal/comment/Plugin/views/field/LinkEdit.php +++ b/core/modules/comment/lib/Drupal/comment/Plugin/views/field/LinkEdit.php @@ -8,6 +8,7 @@ namespace Drupal\comment\Plugin\views\field; use Drupal\Component\Annotation\PluginID; +use Drupal\comment\CommentInterface; /** * Field handler to present a link to edit a comment. @@ -37,12 +38,19 @@ public function buildOptionsForm(&$form, &$form_state) { ); } - function render_link($data, $values) { - parent::render_link($data, $values); + public function access() { + // Needs permission to administer comments in general. + return user_access('administer comments'); + } + + /** + * {@inheritdoc} + */ + public function renderLink(CommentInterface $comment, $values) { + parent::renderLink($comment, $values); // Ensure user has access to edit this comment. - $comment = $this->getValue($values); if (!$comment->access('update')) { - return; + return ''; } $text = !empty($this->options['text']) ? $this->options['text'] : t('edit'); diff --git a/core/modules/comment/lib/Drupal/comment/Plugin/views/field/LinkReply.php b/core/modules/comment/lib/Drupal/comment/Plugin/views/field/LinkReply.php index 112462f..b70073d 100644 --- a/core/modules/comment/lib/Drupal/comment/Plugin/views/field/LinkReply.php +++ b/core/modules/comment/lib/Drupal/comment/Plugin/views/field/LinkReply.php @@ -8,6 +8,7 @@ namespace Drupal\comment\Plugin\views\field; use Drupal\Component\Annotation\PluginID; +use Drupal\comment\CommentInterface; /** * Field handler to present a link to reply to a comment. @@ -19,17 +20,18 @@ class LinkReply extends Link { public function access() { - //check for permission to reply to comments + // Check for the permission to reply to comments. return user_access('post comments'); } - function render_link($data, $values) { + /** + * {@inheritdoc} + */ + public function renderLink(CommentInterface $comment, $values) { $text = !empty($this->options['text']) ? $this->options['text'] : t('reply'); - $nid = $this->getValue($values, 'nid'); - $cid = $this->getValue($values, 'cid'); $this->options['alter']['make_link'] = TRUE; - $this->options['alter']['path'] = "comment/reply/" . $nid . '/' . $cid; + $this->options['alter']['path'] = "comment/reply/" . $comment->nid->value . '/' . $comment->id(); return $text; } diff --git a/core/modules/comment/lib/Drupal/comment/Tests/CommentActionsTest.php b/core/modules/comment/lib/Drupal/comment/Tests/CommentActionsTest.php index 94a1651..24c12b2 100644 --- a/core/modules/comment/lib/Drupal/comment/Tests/CommentActionsTest.php +++ b/core/modules/comment/lib/Drupal/comment/Tests/CommentActionsTest.php @@ -19,6 +19,13 @@ class CommentActionsTest extends CommentTestBase { */ public static $modules = array('dblog', 'action'); + /** + * The entity manager. + * + * @var \Drupal\Core\Entity\EntityManager + */ + protected $manager; + public static function getInfo() { return array( 'name' => 'Comment actions', @@ -27,22 +34,30 @@ public static function getInfo() { ); } + function setUp() { + parent::setUp(); + + $this->manager = $this->container->get('plugin.manager.entity'); + } + /** * Tests comment publish and unpublish actions. */ - function testCommentPublishUnpublishActions() { + public function testCommentPublishUnpublishActions() { $this->drupalLogin($this->web_user); $comment_text = $this->randomName(); $subject = $this->randomName(); $comment = $this->postComment($this->node, $comment_text, $subject); // Unpublish a comment. - $action = entity_load('action', 'comment_unpublish_action'); + $actions = $this->manager->getStorageController('action')->load(array('comment_unpublish_action')); + $action = reset($actions); $action->execute(array($comment)); $this->assertEqual($comment->status->value, COMMENT_NOT_PUBLISHED, 'Comment was unpublished'); // Publish a comment. - $action = entity_load('action', 'comment_publish_action'); + $actions = $this->manager->getStorageController('action')->load(array('comment_publish_action')); + $action = reset($actions); $action->execute(array($comment)); $this->assertEqual($comment->status->value, COMMENT_PUBLISHED, 'Comment was published'); } @@ -50,11 +65,11 @@ function testCommentPublishUnpublishActions() { /** * Tests the unpublish comment by keyword action. */ - function testCommentUnpublishByKeyword() { + public function testCommentUnpublishByKeyword() { $this->drupalLogin($this->admin_user); $keyword_1 = $this->randomName(); $keyword_2 = $this->randomName(); - $action = entity_create('action', array( + $action = $this->manager->getStorageController('action')->create(array( 'id' => 'comment_unpublish_by_keyword_action', 'label' => $this->randomName(), 'type' => 'comment', @@ -68,7 +83,7 @@ function testCommentUnpublishByKeyword() { $comment = $this->postComment($this->node, $keyword_2, $this->randomName()); // Load the full comment so that status is available. - $comment = comment_load($comment->id()); + $this->manager->getStorageController('comment')->load(array($comment->id())); $this->assertTrue($comment->status->value == COMMENT_PUBLISHED, 'The comment status was set to published.'); @@ -76,4 +91,23 @@ function testCommentUnpublishByKeyword() { $this->assertTrue($comment->status->value == COMMENT_NOT_PUBLISHED, 'The comment status was set to not published.'); } + /** + * Tests comment delete action. + */ + public function testCommentDeleteAction() { + $this->drupalLogin($this->admin_user); + $comment_text = $this->randomName(); + $subject = $this->randomName(); + $comment = $this->postComment($this->node, $comment_text, $subject); + + // Delete a comment. + $actions = $this->manager->getStorageController('action')->load(array('comment_delete_action')); + $action = reset($actions); + $action->execute(array($comment)); + + // Try to load the comment again. + $comment = $this->manager->getStorageController('comment')->load(array($comment->id())); + $this->assertTrue(empty($comment), 'Comment was deleted'); + } + } diff --git a/core/modules/comment/lib/Drupal/comment/Tests/Views/CommentAdminView.php b/core/modules/comment/lib/Drupal/comment/Tests/Views/CommentAdminView.php new file mode 100644 index 0000000..d4aa11c --- /dev/null +++ b/core/modules/comment/lib/Drupal/comment/Tests/Views/CommentAdminView.php @@ -0,0 +1,145 @@ + 'Comment: Admin view', + 'description' => 'Tests the default comment admin screen provided by views.', + 'group' => 'Views module integration', + ); + } + + protected function setUp() { + parent::setUp(); + + $this->commentStorageController = $this->container->get('plugin.manager.entity')->getStorageController('comment'); + + // Create a node. + $this->node = $this->drupalCreateNode(); + } + + /** + * Add comments to the node. + */ + protected function createComments() { + $this->comments = array(); + for ($i = 0; $i < 20; $i++) { + $status = ($i % 2 == 0) ? FALSE : TRUE; + $comment = $this->commentStorageController->create(array( + 'nid' => $this->node->nid, + 'node_type' => 'node_type_' . $this->node->bundle(), + 'uid' => $this->node->uid, + 'status' => $status, + 'subject' => $this->randomName(), + 'language' => Language::LANGCODE_NOT_SPECIFIED, + 'comment_body' => array(Language::LANGCODE_NOT_SPECIFIED => array($this->randomName())), + 'created' => REQUEST_TIME - $i, + )); + $comment->save(); + $this->comments[$status][]['cid'] = $comment->id(); + } + } + + /** + * Tests the comment admin view. + */ + public function testCommentAdminView() { + // Create comments. + $this->createComments(); + $view = views_get_view('comments'); + $view->setDisplay('page_1'); + $this->executeView($view); + $view->preview(); + + $column_map = array('cid' => 'cid'); + + // Check if the view title is correct. + $this->assertEqual($view->getTitle(), 'Comments', 'Comment admin view title is correct.'); + + // Check the expected results for the approved comments display. + $this->assertIdenticalResultset($view, array_slice($this->comments[1], 0, 50), $column_map, 'Ensure that the approved comments are displayed on the published comments list.'); + $this->assertNotInResultSet($view, $this->comments[0], 'cid', 'Ensure no unexpected comment is in the result.'); + $view->destroy(); + + $view = views_get_view('comments'); + $view->setDisplay('page_2'); + $this->executeView($view); + $this->assertIdenticalResultset($view, array_slice($this->comments[0], 0, 50), $column_map, 'Ensure that the approved comments are displayed on the published comments list.'); + $this->assertNotInResultSet($view, $this->comments[1], 'cid', 'Ensure no unexpected comment is in the result.'); + } + + /** + * Tests the comment admin screen fields. + */ + public function testCommentAdminScreen() { + $user = $this->drupalCreateUser(array('administer comments')); + $this->drupalLogin($user); + + // Visit the comment page. + $this->drupalGet('admin/content/comment'); + $this->assertResponse(200); + $this->assertText('No comments available.', 'Empty text is displayed when there are no comments'); + + // Re visit when the comments are created. + $this->createComments(); + $this->drupalGet('admin/content/comment'); + // Check that the title and the links are present. + $this->assertTitle('Comments | Drupal'); + $this->assertLink('Published comments'); + $this->assertLink('Unapproved comments'); + + // Check for the fields and default links of the view. + $this->assertFieldByXPath('//td[contains(@class, "views-field-subject")]', NULL, 'Subject field is displayed'); + $this->assertFieldByXPath('//td[contains(@class, "views-field-name")]', NULL, 'Comment author field is displayed'); + $this->assertFieldByXPath('//td[contains(@class, "views-field-title")]', NULL, 'Node title field is displayed'); + $this->assertFieldByXPath('//td[contains(@class, "views-field-changed")]', NULL, 'Updated field is displayed'); + $this->assertFieldByXPath('//td[contains(@class, "views-field-dropbutton")]', NULL, 'Dropbutton is displayed'); + $this->assertFieldByXPath('//ul[@class="dropbutton"]/li[contains(@class, "edit-comment")]/a', 'Edit', 'Edit link is displayed'); + $this->assertFieldByXPath('//ul[@class="dropbutton"]/li[contains(@class, "delete-comment")]/a', 'Delete', 'Delete link is displayed'); + } + +} diff --git a/core/modules/node/lib/Drupal/node/Tests/Views/FrontpageTest.php b/core/modules/node/lib/Drupal/node/Tests/Views/FrontpageTest.php index f638dbe..5e3a1ce 100644 --- a/core/modules/node/lib/Drupal/node/Tests/Views/FrontpageTest.php +++ b/core/modules/node/lib/Drupal/node/Tests/Views/FrontpageTest.php @@ -121,32 +121,15 @@ public function testFrontPage() { $view->setDisplay('page_1'); $this->executeView($view); $this->assertIdenticalResultset($view, array_slice($expected, 0, 10), $column_map, 'Ensure that the right nodes are displayed on the frontpage.'); - $this->assertNotInResultSet($view, $not_expected_nids, 'Ensure no unexpected node is in the result.'); + $this->assertNotInResultSet($view, $not_expected_nids, 'nid', 'Ensure no unexpected node is in the result.'); $view->destroy(); $view->setDisplay('page_1'); $view->setCurrentPage(1); $this->executeView($view); $this->assertIdenticalResultset($view, array_slice($expected, 10, 10), $column_map, 'Ensure that the right nodes are displayed on second page of the frontpage.'); - $this->assertNotInResultSet($view, $not_expected_nids, 'Ensure no unexpected node is in the result.'); + $this->assertNotInResultSet($view, $not_expected_nids, 'nid', 'Ensure no unexpected node is in the result.'); $view->destroy(); } - /** - * Verifies that an amount of nids aren't in the result. - * - * @param \Drupal\views\ViewExecutable $view - * An executed View. - * @param array $not_expected_nids - * An array of nids which should not be part of the resultset. - * @param string $message - * (optional) A custom message to display with the assertion. - */ - protected function assertNotInResultSet(ViewExecutable $view, array $not_expected_nids, $message = '') { - $found_nids = array_filter($view->result, function ($row) use ($not_expected_nids) { - return in_array($row->nid, $not_expected_nids); - }); - $this->assertFalse($found_nids, $message); - } - } diff --git a/core/modules/views/lib/Drupal/views/Tests/DefaultViewsTest.php b/core/modules/views/lib/Drupal/views/Tests/DefaultViewsTest.php index cdbff1a..d797f3e 100644 --- a/core/modules/views/lib/Drupal/views/Tests/DefaultViewsTest.php +++ b/core/modules/views/lib/Drupal/views/Tests/DefaultViewsTest.php @@ -10,6 +10,7 @@ use Drupal\Core\Language\Language; use Drupal\simpletest\WebTestBase; use Drupal\views\ViewExecutable; +use Drupal\Component\Utility\Unicode; /** * Tests for views default views. @@ -24,6 +25,13 @@ class DefaultViewsTest extends ViewTestBase { public static $modules = array('views', 'node', 'search', 'comment', 'taxonomy', 'block'); /** + * The vocabulary used for creating terms. + * + * @var \Drupal\taxonomy\VocabularyInterface + */ + protected $vocabulary; + + /** * An array of argument arrays to use for default views. * * @var array @@ -51,7 +59,7 @@ protected function setUp() { $this->vocabulary = entity_create('taxonomy_vocabulary', array( 'name' => $this->randomName(), 'description' => $this->randomName(), - 'vid' => drupal_strtolower($this->randomName()), + 'vid' => Unicode::strtolower($this->randomName()), 'langcode' => Language::LANGCODE_NOT_SPECIFIED, 'help' => '', 'nodes' => array('page' => 'page'), @@ -60,9 +68,9 @@ protected function setUp() { $this->vocabulary->save(); // Setup a field and instance. - $this->field_name = drupal_strtolower($this->randomName()); + $field_name = Unicode::strtolower($this->randomName()); entity_create('field_entity', array( - 'field_name' => $this->field_name, + 'field_name' => $field_name, 'type' => 'taxonomy_term_reference', 'settings' => array( 'allowed_values' => array( @@ -74,7 +82,7 @@ protected function setUp() { ) ))->save(); entity_create('field_instance', array( - 'field_name' => $this->field_name, + 'field_name' => $field_name, 'entity_type' => 'node', 'bundle' => 'page', ))->save(); @@ -84,10 +92,10 @@ protected function setUp() { for ($i = 0; $i <= 10; $i++) { $user = $this->drupalCreateUser(); - $term = $this->createTerm($this->vocabulary); + $term = $this->createTerm(); $values = array('created' => $time, 'type' => 'page'); - $values[$this->field_name][]['target_id'] = $term->id(); + $values[$field_name][]['target_id'] = $term->id(); // Make every other node promoted. if ($i % 2) { @@ -105,10 +113,40 @@ protected function setUp() { 'node_type' => 'node_type_' . $node->bundle(), ); entity_create('comment', $comment)->save(); + + $comment = array( + 'uid' => $user->uid, + 'nid' => $node->nid, + 'node_type' => 'node_type_' . $node->bundle(), + 'status' => 0, + ); + entity_create('comment', $comment)->save(); + } } /** + * Returns a new term with random properties in vocabulary $vid. + * + * @return \Drupal\taxonomy\TermInterface + * Taxonomy term created. + */ + function createTerm() { + $filter_formats = filter_formats(); + $format = array_pop($filter_formats); + $term = entity_create('taxonomy_term', array( + 'name' => $this->randomName(), + 'description' => $this->randomName(), + // Use the first available text format. + 'format' => $format->format, + 'vid' => $this->vocabulary->id(), + 'langcode' => Language::LANGCODE_NOT_SPECIFIED, + )); + $term->save(); + return $term; + } + + /** * Test that all Default views work as expected. */ public function testDefaultViews() { @@ -141,24 +179,6 @@ public function testDefaultViews() { } /** - * Returns a new term with random properties in vocabulary $vid. - */ - function createTerm($vocabulary) { - $filter_formats = filter_formats(); - $format = array_pop($filter_formats); - $term = entity_create('taxonomy_term', array( - 'name' => $this->randomName(), - 'description' => $this->randomName(), - // Use the first available text format. - 'format' => $format->format, - 'vid' => $vocabulary->id(), - 'langcode' => Language::LANGCODE_NOT_SPECIFIED, - )); - $term->save(); - return $term; - } - - /** * Tests the archive view. */ public function testArchiveView() { diff --git a/core/modules/views/lib/Drupal/views/Tests/ViewTestBase.php b/core/modules/views/lib/Drupal/views/Tests/ViewTestBase.php index 5a00bd7..8feccf0 100644 --- a/core/modules/views/lib/Drupal/views/Tests/ViewTestBase.php +++ b/core/modules/views/lib/Drupal/views/Tests/ViewTestBase.php @@ -116,6 +116,25 @@ protected function assertNotIdenticalResultset($view, $expected_result, $column_ } /** + * Verifies that a set of elements aren't in the result. + * + * @param \Drupal\views\ViewExecutable $view + * An executed View. + * @param array $not_expected_elements + * An array of elements which should not be part of the resultset. + * @param string $column + * Name of the columnt to check the values. + * @param string $message + * (optional) A custom message to display with the assertion. + */ + protected function assertNotInResultSet(ViewExecutable $view, array $not_expected_elements, $column, $message = '') { + $found_elements = array_filter($view->result, function ($row) use ($not_expected_elements, $column) { + return in_array($row->{$column}, $not_expected_elements); + }); + $this->assertFalse($found_elements, $message); + } + + /** * Performs View result assertions. * * This is a helper method for ViewTestBase::assertIdenticalResultset() and