Issue #1986606 by jibran, pcambra, vijaycs85, dawehner, andypost, mbovan, Arla, adnen, vprocessor, tkuldeep17, xjm, kim.pepper, dobe, snig, larowlan, miro_dietiker, tim.plunkett, Berdir, Lendude, plach, olli, damiankloip: Convert the comments administration screen to a view
parent
bcc7d03859
commit
04d69926b4
|
@ -2,6 +2,7 @@
|
|||
|
||||
namespace Drupal\Core\Field\Plugin\Field\FieldFormatter;
|
||||
|
||||
use Drupal\Core\Entity\EntityInterface;
|
||||
use Drupal\Core\Entity\EntityManagerInterface;
|
||||
use Drupal\Core\Field\FieldDefinitionInterface;
|
||||
use Drupal\Core\Field\FieldItemInterface;
|
||||
|
@ -116,8 +117,8 @@ class StringFormatter extends FormatterBase implements ContainerFactoryPluginInt
|
|||
$elements = [];
|
||||
$url = NULL;
|
||||
if ($this->getSetting('link_to_entity')) {
|
||||
// For the default revision this falls back to 'canonical'
|
||||
$url = $items->getEntity()->urlInfo('revision');
|
||||
// For the default revision this falls back to 'canonical'.
|
||||
$url = $this->getEntityUrl($items->getEntity());
|
||||
}
|
||||
|
||||
foreach ($items as $delta => $item) {
|
||||
|
@ -155,4 +156,18 @@ class StringFormatter extends FormatterBase implements ContainerFactoryPluginInt
|
|||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the URI elements of the entity.
|
||||
*
|
||||
* @param \Drupal\Core\Entity\EntityInterface $entity
|
||||
* The entity object.
|
||||
*
|
||||
* @return \Drupal\Core\Url
|
||||
* The URI elements of the entity.
|
||||
*/
|
||||
protected function getEntityUrl(EntityInterface $entity) {
|
||||
// For the default revision this falls back to 'canonical'.
|
||||
return $entity->toUrl('revision');
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Post update functions for the comment module.
|
||||
*/
|
||||
|
||||
use Drupal\Core\Config\FileStorage;
|
||||
use Drupal\Core\Config\InstallStorage;
|
||||
|
||||
/**
|
||||
* Enable the comment admin view.
|
||||
*/
|
||||
function comment_post_update_enable_comment_admin_view() {
|
||||
$module_handler = \Drupal::moduleHandler();
|
||||
$entity_type_manager = \Drupal::entityTypeManager();
|
||||
|
||||
// Save the comment delete action to config.
|
||||
$config_install_path = $module_handler->getModule('comment')->getPath() . '/' . InstallStorage::CONFIG_INSTALL_DIRECTORY;
|
||||
$storage = new FileStorage($config_install_path);
|
||||
$entity_type_manager
|
||||
->getStorage('action')
|
||||
->create($storage->read('system.action.comment_delete_action'))
|
||||
->save();
|
||||
|
||||
// Only create if the views module is enabled.
|
||||
if (!$module_handler->moduleExists('views')) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Save the comment admin view to config.
|
||||
$optional_install_path = $module_handler->getModule('comment')->getPath() . '/' . InstallStorage::CONFIG_OPTIONAL_DIRECTORY;
|
||||
$storage = new FileStorage($optional_install_path);
|
||||
$entity_type_manager
|
||||
->getStorage('view')
|
||||
->create($storage->read('views.view.comment'))
|
||||
->save();
|
||||
}
|
|
@ -2,7 +2,7 @@ comment.admin:
|
|||
path: '/admin/content/comment'
|
||||
defaults:
|
||||
_title: 'Comments'
|
||||
_controller: '\Drupal\comment\Controller\AdminController::adminPage'
|
||||
_form: '\Drupal\comment\Form\CommentAdminOverview'
|
||||
type: 'new'
|
||||
requirements:
|
||||
_permission: 'administer comments'
|
||||
|
@ -11,7 +11,7 @@ comment.admin_approval:
|
|||
path: '/admin/content/comment/approval'
|
||||
defaults:
|
||||
_title: 'Unapproved comments'
|
||||
_controller: '\Drupal\comment\Controller\AdminController::adminPage'
|
||||
_form: '\Drupal\comment\Form\CommentAdminOverview'
|
||||
type: 'approval'
|
||||
requirements:
|
||||
_permission: 'administer comments'
|
||||
|
@ -54,6 +54,14 @@ entity.comment.delete_form:
|
|||
_entity_access: 'comment.delete'
|
||||
comment: \d+
|
||||
|
||||
comment.multiple_delete_confirm:
|
||||
path: '/admin/content/comment/delete'
|
||||
defaults:
|
||||
_title: 'Delete'
|
||||
_form: '\Drupal\comment\Form\ConfirmDeleteMultiple'
|
||||
requirements:
|
||||
_permission: 'administer comments'
|
||||
|
||||
comment.reply:
|
||||
path: '/comment/reply/{entity_type}/{entity}/{field_name}/{pid}'
|
||||
defaults:
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
langcode: en
|
||||
status: true
|
||||
dependencies:
|
||||
module:
|
||||
- comment
|
||||
id: comment_delete_action
|
||||
label: 'Delete comment'
|
||||
type: comment
|
||||
plugin: comment_delete_action
|
||||
configuration: { }
|
File diff suppressed because it is too large
Load Diff
|
@ -38,6 +38,10 @@ action.configuration.comment_unpublish_action:
|
|||
type: action_configuration_default
|
||||
label: 'Unpublish comment configuration'
|
||||
|
||||
action.configuration.comment_delete_action:
|
||||
type: action_configuration_default
|
||||
label: 'Delete comment configuration'
|
||||
|
||||
comment.type.*:
|
||||
type: config_entity
|
||||
label: 'Comment type settings'
|
||||
|
@ -105,3 +109,6 @@ field.field_settings.comment:
|
|||
preview:
|
||||
type: integer
|
||||
label: 'Preview comment'
|
||||
|
||||
field.formatter.settings.comment_permalink:
|
||||
type: field.formatter.settings.string
|
||||
|
|
|
@ -16,6 +16,14 @@ views.field.comment_entity_link:
|
|||
type: boolean
|
||||
label: 'Show teaser-style link'
|
||||
|
||||
views.field.comment_bulk_form:
|
||||
type: views_field_bulk_form
|
||||
label: 'Comment bulk form'
|
||||
|
||||
views.field.commented_entity:
|
||||
type: views.field.field
|
||||
label: 'Commented entity'
|
||||
|
||||
views.field.comment_last_timestamp:
|
||||
type: views.field.date
|
||||
label: 'Last comment date'
|
||||
|
|
|
@ -23,6 +23,7 @@ class CommentViewsData extends EntityViewsData {
|
|||
|
||||
$data['comment_field_data']['subject']['title'] = $this->t('Title');
|
||||
$data['comment_field_data']['subject']['help'] = $this->t('The title of the comment.');
|
||||
$data['comment_field_data']['subject']['field']['default_formatter'] = 'comment_permalink';
|
||||
|
||||
$data['comment_field_data']['name']['title'] = $this->t('Author');
|
||||
$data['comment_field_data']['name']['help'] = $this->t("The name of the comment's author. Can be rendered as a link to the author's homepage.");
|
||||
|
@ -168,6 +169,17 @@ class CommentViewsData extends EntityViewsData {
|
|||
],
|
||||
];
|
||||
|
||||
$data['comment_field_data']['entity_id']['field']['id'] = 'commented_entity';
|
||||
unset($data['comment_field_data']['entity_id']['relationship']);
|
||||
|
||||
$data['comment']['comment_bulk_form'] = [
|
||||
'title' => $this->t('Comment operations bulk form'),
|
||||
'help' => $this->t('Add a form element that lets you run operations on multiple comments.'),
|
||||
'field' => [
|
||||
'id' => 'comment_bulk_form',
|
||||
],
|
||||
];
|
||||
|
||||
$data['comment_field_data']['thread']['field'] = [
|
||||
'title' => $this->t('Depth'),
|
||||
'help' => $this->t('Display the depth of the comment if it is threaded.'),
|
||||
|
|
|
@ -1,62 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\comment\Controller;
|
||||
|
||||
use Drupal\Core\Controller\ControllerBase;
|
||||
use Drupal\Core\Form\FormBuilderInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
* Returns responses for comment module administrative routes.
|
||||
*/
|
||||
class AdminController extends ControllerBase {
|
||||
|
||||
/**
|
||||
* The form builder.
|
||||
*
|
||||
* @var \Drupal\Core\Form\FormBuilderInterface
|
||||
*/
|
||||
protected $formBuilder;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function create(ContainerInterface $container) {
|
||||
return new static(
|
||||
$container->get('form_builder')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an AdminController object.
|
||||
*
|
||||
* @param \Drupal\Core\Form\FormBuilderInterface $form_builder
|
||||
* The form builder.
|
||||
*/
|
||||
public function __construct(FormBuilderInterface $form_builder) {
|
||||
$this->formBuilder = $form_builder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Presents an administrative comment listing.
|
||||
*
|
||||
* @param \Symfony\Component\HttpFoundation\Request $request
|
||||
* The request of the page.
|
||||
* @param string $type
|
||||
* The type of the overview form ('approval' or 'new') default to 'new'.
|
||||
*
|
||||
* @return array
|
||||
* Then comment multiple delete confirmation form or the comments overview
|
||||
* administration form.
|
||||
*/
|
||||
public function adminPage(Request $request, $type = 'new') {
|
||||
if ($request->request->get('operation') == 'delete' && $request->request->get('comments')) {
|
||||
return $this->formBuilder->getForm('\Drupal\comment\Form\ConfirmDeleteMultiple', $request);
|
||||
}
|
||||
else {
|
||||
return $this->formBuilder->getForm('\Drupal\comment\Form\CommentAdminOverview', $type);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -3,13 +3,13 @@
|
|||
namespace Drupal\comment\Form;
|
||||
|
||||
use Drupal\comment\CommentInterface;
|
||||
use Drupal\comment\CommentStorageInterface;
|
||||
use Drupal\Component\Utility\Unicode;
|
||||
use Drupal\Core\Datetime\DateFormatterInterface;
|
||||
use Drupal\Core\Entity\EntityManagerInterface;
|
||||
use Drupal\Core\Entity\EntityTypeManagerInterface;
|
||||
use Drupal\Core\Extension\ModuleHandlerInterface;
|
||||
use Drupal\Core\Form\FormBase;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
use Drupal\user\PrivateTempStoreFactory;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
|
@ -18,11 +18,11 @@ use Symfony\Component\DependencyInjection\ContainerInterface;
|
|||
class CommentAdminOverview extends FormBase {
|
||||
|
||||
/**
|
||||
* The entity storage.
|
||||
* The entity type manager.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityManagerInterface
|
||||
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
|
||||
*/
|
||||
protected $entityManager;
|
||||
protected $entityTypeManager;
|
||||
|
||||
/**
|
||||
* The comment storage.
|
||||
|
@ -45,23 +45,31 @@ class CommentAdminOverview extends FormBase {
|
|||
*/
|
||||
protected $moduleHandler;
|
||||
|
||||
/**
|
||||
* The tempstore factory.
|
||||
*
|
||||
* @var \Drupal\user\PrivateTempStoreFactory
|
||||
*/
|
||||
protected $tempStoreFactory;
|
||||
|
||||
/**
|
||||
* Creates a CommentAdminOverview form.
|
||||
*
|
||||
* @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
|
||||
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
|
||||
* The entity manager service.
|
||||
* @param \Drupal\comment\CommentStorageInterface $comment_storage
|
||||
* The comment storage.
|
||||
* @param \Drupal\Core\Datetime\DateFormatterInterface $date_formatter
|
||||
* The date formatter service.
|
||||
* @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
|
||||
* The module handler.
|
||||
* @param \Drupal\user\PrivateTempStoreFactory $temp_store_factory
|
||||
* The tempstore factory.
|
||||
*/
|
||||
public function __construct(EntityManagerInterface $entity_manager, CommentStorageInterface $comment_storage, DateFormatterInterface $date_formatter, ModuleHandlerInterface $module_handler) {
|
||||
$this->entityManager = $entity_manager;
|
||||
$this->commentStorage = $comment_storage;
|
||||
public function __construct(EntityTypeManagerInterface $entity_type_manager, DateFormatterInterface $date_formatter, ModuleHandlerInterface $module_handler, PrivateTempStoreFactory $temp_store_factory) {
|
||||
$this->entityTypeManager = $entity_type_manager;
|
||||
$this->commentStorage = $entity_type_manager->getStorage('comment');
|
||||
$this->dateFormatter = $date_formatter;
|
||||
$this->moduleHandler = $module_handler;
|
||||
$this->tempStoreFactory = $temp_store_factory;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -69,10 +77,10 @@ class CommentAdminOverview extends FormBase {
|
|||
*/
|
||||
public static function create(ContainerInterface $container) {
|
||||
return new static(
|
||||
$container->get('entity.manager'),
|
||||
$container->get('entity.manager')->getStorage('comment'),
|
||||
$container->get('entity_type.manager'),
|
||||
$container->get('date.formatter'),
|
||||
$container->get('module_handler')
|
||||
$container->get('module_handler'),
|
||||
$container->get('user.private_tempstore')
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -171,7 +179,9 @@ class CommentAdminOverview extends FormBase {
|
|||
}
|
||||
|
||||
foreach ($commented_entity_ids as $entity_type => $ids) {
|
||||
$commented_entities[$entity_type] = $this->entityManager->getStorage($entity_type)->loadMultiple($ids);
|
||||
$commented_entities[$entity_type] = $this->entityTypeManager
|
||||
->getStorage($entity_type)
|
||||
->loadMultiple($ids);
|
||||
}
|
||||
|
||||
foreach ($comments as $comment) {
|
||||
|
@ -255,23 +265,33 @@ class CommentAdminOverview extends FormBase {
|
|||
public function submitForm(array &$form, FormStateInterface $form_state) {
|
||||
$operation = $form_state->getValue('operation');
|
||||
$cids = $form_state->getValue('comments');
|
||||
|
||||
foreach ($cids as $cid) {
|
||||
// Delete operation handled in \Drupal\comment\Form\ConfirmDeleteMultiple
|
||||
// see \Drupal\comment\Controller\AdminController::adminPage().
|
||||
if ($operation == 'unpublish') {
|
||||
$comment = $this->commentStorage->load($cid);
|
||||
$comment->setPublished(FALSE);
|
||||
$comment->save();
|
||||
}
|
||||
elseif ($operation == 'publish') {
|
||||
$comment = $this->commentStorage->load($cid);
|
||||
$comment->setPublished(TRUE);
|
||||
/** @var \Drupal\comment\CommentInterface[] $comments */
|
||||
$comments = $this->commentStorage->loadMultiple($cids);
|
||||
if ($operation != 'delete') {
|
||||
foreach ($comments as $comment) {
|
||||
if ($operation == 'unpublish') {
|
||||
$comment->setUnpublished();
|
||||
}
|
||||
elseif ($operation == 'publish') {
|
||||
$comment->setPublished();
|
||||
}
|
||||
$comment->save();
|
||||
}
|
||||
drupal_set_message($this->t('The update has been performed.'));
|
||||
$form_state->setRedirect('comment.admin');
|
||||
}
|
||||
else {
|
||||
$info = [];
|
||||
/** @var \Drupal\comment\CommentInterface $comment */
|
||||
foreach ($comments as $comment) {
|
||||
$langcode = $comment->language()->getId();
|
||||
$info[$comment->id()][$langcode] = $langcode;
|
||||
}
|
||||
$this->tempStoreFactory
|
||||
->get('comment_multiple_delete_confirm')
|
||||
->set($this->currentUser()->id(), $info);
|
||||
$form_state->setRedirect('comment.multiple_delete_confirm');
|
||||
}
|
||||
drupal_set_message($this->t('The update has been performed.'));
|
||||
$form_state->setRedirect('comment.admin');
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
namespace Drupal\comment\Form;
|
||||
|
||||
use Drupal\comment\CommentStorageInterface;
|
||||
use Drupal\Component\Utility\Html;
|
||||
use Drupal\user\PrivateTempStoreFactory;
|
||||
use Drupal\Core\Form\ConfirmFormBase;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
use Drupal\Core\Url;
|
||||
|
@ -14,6 +14,13 @@ use Symfony\Component\DependencyInjection\ContainerInterface;
|
|||
*/
|
||||
class ConfirmDeleteMultiple extends ConfirmFormBase {
|
||||
|
||||
/**
|
||||
* The tempstore factory.
|
||||
*
|
||||
* @var \Drupal\user\PrivateTempStoreFactory
|
||||
*/
|
||||
protected $tempStoreFactory;
|
||||
|
||||
/**
|
||||
* The comment storage.
|
||||
*
|
||||
|
@ -24,18 +31,21 @@ class ConfirmDeleteMultiple extends ConfirmFormBase {
|
|||
/**
|
||||
* An array of comments to be deleted.
|
||||
*
|
||||
* @var \Drupal\comment\CommentInterface[]
|
||||
* @var string[][]
|
||||
*/
|
||||
protected $comments;
|
||||
protected $commentInfo;
|
||||
|
||||
/**
|
||||
* Creates an new ConfirmDeleteMultiple form.
|
||||
*
|
||||
* @param \Drupal\comment\CommentStorageInterface $comment_storage
|
||||
* The comment storage.
|
||||
* @param \Drupal\user\PrivateTempStoreFactory $temp_store_factory
|
||||
* The tempstore factory.
|
||||
*/
|
||||
public function __construct(CommentStorageInterface $comment_storage) {
|
||||
public function __construct(CommentStorageInterface $comment_storage, PrivateTempStoreFactory $temp_store_factory) {
|
||||
$this->commentStorage = $comment_storage;
|
||||
$this->tempStoreFactory = $temp_store_factory;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -43,7 +53,8 @@ class ConfirmDeleteMultiple extends ConfirmFormBase {
|
|||
*/
|
||||
public static function create(ContainerInterface $container) {
|
||||
return new static(
|
||||
$container->get('entity.manager')->getStorage('comment')
|
||||
$container->get('entity.manager')->getStorage('comment'),
|
||||
$container->get('user.private_tempstore')
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -58,7 +69,7 @@ class ConfirmDeleteMultiple extends ConfirmFormBase {
|
|||
* {@inheritdoc}
|
||||
*/
|
||||
public function getQuestion() {
|
||||
return $this->t('Are you sure you want to delete these comments and all their children?');
|
||||
return $this->formatPlural(count($this->commentInfo), 'Are you sure you want to delete this comment and all its children?', 'Are you sure you want to delete these comments and all their children?');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -72,39 +83,56 @@ class ConfirmDeleteMultiple extends ConfirmFormBase {
|
|||
* {@inheritdoc}
|
||||
*/
|
||||
public function getConfirmText() {
|
||||
return $this->t('Delete comments');
|
||||
return $this->t('Delete');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function buildForm(array $form, FormStateInterface $form_state) {
|
||||
$edit = $form_state->getUserInput();
|
||||
$this->commentInfo = $this->tempStoreFactory->get('comment_multiple_delete_confirm')->get($this->currentUser()->id());
|
||||
if (empty($this->commentInfo)) {
|
||||
return $this->redirect('comment.admin');
|
||||
}
|
||||
/** @var \Drupal\comment\CommentInterface[] $comments */
|
||||
$comments = $this->commentStorage->loadMultiple(array_keys($this->commentInfo));
|
||||
|
||||
$items = [];
|
||||
foreach ($this->commentInfo as $id => $langcodes) {
|
||||
foreach ($langcodes as $langcode) {
|
||||
$comment = $comments[$id]->getTranslation($langcode);
|
||||
$key = $id . ':' . $langcode;
|
||||
$default_key = $id . ':' . $comment->getUntranslated()->language()->getId();
|
||||
|
||||
// If we have a translated entity we build a nested list of translations
|
||||
// that will be deleted.
|
||||
$languages = $comment->getTranslationLanguages();
|
||||
if (count($languages) > 1 && $comment->isDefaultTranslation()) {
|
||||
$names = [];
|
||||
foreach ($languages as $translation_langcode => $language) {
|
||||
$names[] = $language->getName();
|
||||
unset($items[$id . ':' . $translation_langcode]);
|
||||
}
|
||||
$items[$default_key] = [
|
||||
'label' => [
|
||||
'#markup' => $this->t('@label (Original translation) - <em>The following comment translations will be deleted:</em>', ['@label' => $comment->label()]),
|
||||
],
|
||||
'deleted_translations' => [
|
||||
'#theme' => 'item_list',
|
||||
'#items' => $names,
|
||||
],
|
||||
];
|
||||
}
|
||||
elseif (!isset($items[$default_key])) {
|
||||
$items[$key] = $comment->label();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$form['comments'] = [
|
||||
'#prefix' => '<ul>',
|
||||
'#suffix' => '</ul>',
|
||||
'#tree' => TRUE,
|
||||
'#theme' => 'item_list',
|
||||
'#items' => $items,
|
||||
];
|
||||
// array_filter() returns only elements with actual values.
|
||||
$comment_counter = 0;
|
||||
$this->comments = $this->commentStorage->loadMultiple(array_keys(array_filter($edit['comments'])));
|
||||
foreach ($this->comments as $comment) {
|
||||
$cid = $comment->id();
|
||||
$form['comments'][$cid] = [
|
||||
'#type' => 'hidden',
|
||||
'#value' => $cid,
|
||||
'#prefix' => '<li>',
|
||||
'#suffix' => Html::escape($comment->label()) . '</li>'
|
||||
];
|
||||
$comment_counter++;
|
||||
}
|
||||
$form['operation'] = ['#type' => 'hidden', '#value' => 'delete'];
|
||||
|
||||
if (!$comment_counter) {
|
||||
drupal_set_message($this->t('There do not appear to be any comments to delete, or your selected comment was deleted by another administrator.'));
|
||||
$form_state->setRedirect('comment.admin');
|
||||
}
|
||||
|
||||
return parent::buildForm($form, $form_state);
|
||||
}
|
||||
|
@ -113,12 +141,56 @@ class ConfirmDeleteMultiple extends ConfirmFormBase {
|
|||
* {@inheritdoc}
|
||||
*/
|
||||
public function submitForm(array &$form, FormStateInterface $form_state) {
|
||||
if ($form_state->getValue('confirm')) {
|
||||
$this->commentStorage->delete($this->comments);
|
||||
$count = count($form_state->getValue('comments'));
|
||||
$this->logger('comment')->notice('Deleted @count comments.', ['@count' => $count]);
|
||||
drupal_set_message($this->formatPlural($count, 'Deleted 1 comment.', 'Deleted @count comments.'));
|
||||
if ($form_state->getValue('confirm') && !empty($this->commentInfo)) {
|
||||
$total_count = 0;
|
||||
$delete_comments = [];
|
||||
/** @var \Drupal\Core\Entity\ContentEntityInterface[][] $delete_translations */
|
||||
$delete_translations = [];
|
||||
/** @var \Drupal\comment\CommentInterface[] $comments */
|
||||
$comments = $this->commentStorage->loadMultiple(array_keys($this->commentInfo));
|
||||
|
||||
foreach ($this->commentInfo as $id => $langcodes) {
|
||||
foreach ($langcodes as $langcode) {
|
||||
$comment = $comments[$id]->getTranslation($langcode);
|
||||
if ($comment->isDefaultTranslation()) {
|
||||
$delete_comments[$id] = $comment;
|
||||
unset($delete_translations[$id]);
|
||||
$total_count += count($comment->getTranslationLanguages());
|
||||
}
|
||||
elseif (!isset($delete_comments[$id])) {
|
||||
$delete_translations[$id][] = $comment;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($delete_comments) {
|
||||
$this->commentStorage->delete($delete_comments);
|
||||
$this->logger('content')->notice('Deleted @count comments.', ['@count' => count($delete_comments)]);
|
||||
}
|
||||
|
||||
if ($delete_translations) {
|
||||
$count = 0;
|
||||
foreach ($delete_translations as $id => $translations) {
|
||||
$comment = $comments[$id]->getUntranslated();
|
||||
foreach ($translations as $translation) {
|
||||
$comment->removeTranslation($translation->language()->getId());
|
||||
}
|
||||
$comment->save();
|
||||
$count += count($translations);
|
||||
}
|
||||
if ($count) {
|
||||
$total_count += $count;
|
||||
$this->logger('content')->notice('Deleted @count comment translations.', ['@count' => $count]);
|
||||
}
|
||||
}
|
||||
|
||||
if ($total_count) {
|
||||
drupal_set_message($this->formatPlural($total_count, 'Deleted 1 comment.', 'Deleted @count comments.'));
|
||||
}
|
||||
|
||||
$this->tempStoreFactory->get('comment_multiple_delete_confirm')->delete($this->currentUser()->id());
|
||||
}
|
||||
|
||||
$form_state->setRedirectUrl($this->getCancelUrl());
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,98 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\comment\Plugin\Action;
|
||||
|
||||
use Drupal\Core\Action\ActionBase;
|
||||
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
|
||||
use Drupal\Core\Session\AccountInterface;
|
||||
use Drupal\user\PrivateTempStoreFactory;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
* Deletes a comment.
|
||||
*
|
||||
* @Action(
|
||||
* id = "comment_delete_action",
|
||||
* label = @Translation("Delete comment"),
|
||||
* type = "comment",
|
||||
* confirm_form_route_name = "comment.multiple_delete_confirm"
|
||||
* )
|
||||
*/
|
||||
class DeleteComment extends ActionBase implements ContainerFactoryPluginInterface {
|
||||
|
||||
/**
|
||||
* The tempstore object.
|
||||
*
|
||||
* @var \Drupal\user\PrivateTempStore
|
||||
*/
|
||||
protected $tempStore;
|
||||
|
||||
/**
|
||||
* The current user.
|
||||
*
|
||||
* @var \Drupal\Core\Session\AccountInterface
|
||||
*/
|
||||
protected $currentUser;
|
||||
|
||||
/**
|
||||
* Constructs a new DeleteComment object.
|
||||
*
|
||||
* @param array $configuration
|
||||
* A configuration array containing information about the plugin instance.
|
||||
* @param string $plugin_id
|
||||
* The plugin ID for the plugin instance.
|
||||
* @param array $plugin_definition
|
||||
* The plugin implementation definition.
|
||||
* @param \Drupal\user\PrivateTempStoreFactory $temp_store_factory
|
||||
* The tempstore factory.
|
||||
* @param \Drupal\Core\Session\AccountInterface $current_user
|
||||
* The current user.
|
||||
*/
|
||||
public function __construct(array $configuration, $plugin_id, array $plugin_definition, PrivateTempStoreFactory $temp_store_factory, AccountInterface $current_user) {
|
||||
$this->currentUser = $current_user;
|
||||
$this->tempStore = $temp_store_factory->get('comment_multiple_delete_confirm');
|
||||
parent::__construct($configuration, $plugin_id, $plugin_definition);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
|
||||
return new static(
|
||||
$configuration,
|
||||
$plugin_id,
|
||||
$plugin_definition,
|
||||
$container->get('user.private_tempstore'),
|
||||
$container->get('current_user')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function executeMultiple(array $entities) {
|
||||
$info = [];
|
||||
/** @var \Drupal\comment\CommentInterface $comment */
|
||||
foreach ($entities as $comment) {
|
||||
$langcode = $comment->language()->getId();
|
||||
$info[$comment->id()][$langcode] = $langcode;
|
||||
}
|
||||
$this->tempStore->set($this->currentUser->id(), $info);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function execute($entity = NULL) {
|
||||
$this->executeMultiple([$entity]);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function access($comment, AccountInterface $account = NULL, $return_as_object = FALSE) {
|
||||
/** @var \Drupal\comment\CommentInterface $comment */
|
||||
return $comment->access('delete', $account, $return_as_object);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\comment\Plugin\Field\FieldFormatter;
|
||||
|
||||
use Drupal\Component\Utility\Unicode;
|
||||
use Drupal\Core\Entity\EntityInterface;
|
||||
use Drupal\Core\Field\FieldDefinitionInterface;
|
||||
use Drupal\Core\Field\Plugin\Field\FieldFormatter\StringFormatter;
|
||||
|
||||
/**
|
||||
* Plugin implementation of the 'comment_permalink' formatter.
|
||||
*
|
||||
* All the other entities use 'canonical' or 'revision' links to link the entity
|
||||
* to itself but comments use permalink URL.
|
||||
*
|
||||
* @FieldFormatter(
|
||||
* id = "comment_permalink",
|
||||
* label = @Translation("Comment Permalink"),
|
||||
* field_types = {
|
||||
* "string",
|
||||
* "uri",
|
||||
* },
|
||||
* quickedit = {
|
||||
* "editor" = "plain_text"
|
||||
* }
|
||||
* )
|
||||
*/
|
||||
class CommentPermalinkFormatter extends StringFormatter {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getEntityUrl(EntityInterface $comment) {
|
||||
/* @var $comment \Drupal\comment\CommentInterface */
|
||||
$comment_permalink = $comment->permalink();
|
||||
if ($comment->hasField('comment_body') && ($body = $comment->get('comment_body')->value)) {
|
||||
$attributes = $comment_permalink->getOption('attributes') ?: [];
|
||||
$attributes += ['title' => Unicode::truncate($body, 128)];
|
||||
$comment_permalink->setOption('attributes', $attributes);
|
||||
}
|
||||
return $comment_permalink;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function isApplicable(FieldDefinitionInterface $field_definition) {
|
||||
return parent::isApplicable($field_definition) && $field_definition->getTargetEntityTypeId() === 'comment' && $field_definition->getName() === 'subject';
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\comment\Plugin\views\field;
|
||||
|
||||
use Drupal\system\Plugin\views\field\BulkForm;
|
||||
|
||||
/**
|
||||
* Defines a comment operations bulk form element.
|
||||
*
|
||||
* @ViewsField("comment_bulk_form")
|
||||
*/
|
||||
class CommentBulkForm extends BulkForm {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function emptySelectedMessage() {
|
||||
return $this->t('Select one or more comments to perform the update on.');
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\comment\Plugin\views\field;
|
||||
|
||||
use Drupal\views\Plugin\views\field\EntityField;
|
||||
use Drupal\views\ResultRow;
|
||||
|
||||
/**
|
||||
* Views field display for commented entity.
|
||||
*
|
||||
* @ViewsField("commented_entity")
|
||||
*/
|
||||
class CommentedEntity extends EntityField {
|
||||
|
||||
/**
|
||||
* Array of entities that has comments.
|
||||
*
|
||||
* We use this to load all the commented entities of same entity type at once
|
||||
* to the EntityStorageController static cache.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $loadedCommentedEntities = [];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getItems(ResultRow $values) {
|
||||
if (empty($this->loadedCommentedEntities)) {
|
||||
$result = $this->view->result;
|
||||
|
||||
$entity_ids_per_type = [];
|
||||
foreach ($result as $value) {
|
||||
/** @var \Drupal\comment\CommentInterface $comment */
|
||||
if ($comment = $this->getEntity($value)) {
|
||||
$entity_ids_per_type[$comment->getCommentedEntityTypeId()][] = $comment->getCommentedEntityId();
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($entity_ids_per_type as $type => $ids) {
|
||||
$this->loadedCommentedEntities[$type] = $this->entityManager->getStorage($type)->loadMultiple($ids);
|
||||
}
|
||||
}
|
||||
|
||||
return parent::getItems($values);
|
||||
}
|
||||
|
||||
}
|
|
@ -2,6 +2,9 @@
|
|||
|
||||
namespace Drupal\comment\Tests;
|
||||
|
||||
use Drupal\Component\Render\FormattableMarkup;
|
||||
use Drupal\Component\Utility\Html;
|
||||
use Drupal\language\Entity\ConfigurableLanguage;
|
||||
use Drupal\user\RoleInterface;
|
||||
use Drupal\comment\Entity\Comment;
|
||||
|
||||
|
@ -90,7 +93,7 @@ class CommentAdminTest extends CommentTestBase {
|
|||
];
|
||||
$this->drupalPostForm(NULL, $edit, t('Update'));
|
||||
$this->assertText(t('Are you sure you want to delete these comments and all their children?'), 'Confirmation required.');
|
||||
$this->drupalPostForm(NULL, $edit, t('Delete comments'));
|
||||
$this->drupalPostForm(NULL, [], t('Delete'));
|
||||
$this->assertText(t('No comments available.'), 'All comments were deleted.');
|
||||
// Test message when no comments selected.
|
||||
$edit = [
|
||||
|
@ -98,6 +101,15 @@ class CommentAdminTest extends CommentTestBase {
|
|||
];
|
||||
$this->drupalPostForm(NULL, $edit, t('Update'));
|
||||
$this->assertText(t('Select one or more comments to perform the update on.'));
|
||||
|
||||
// Make sure the label of unpublished node is not visible on listing page.
|
||||
$this->drupalGet('admin/content/comment');
|
||||
$this->postComment($this->node, $this->randomMachineName());
|
||||
$this->drupalGet('admin/content/comment');
|
||||
$this->assertText(Html::escape($this->node->label()));
|
||||
$this->node->setUnpublished()->save();
|
||||
$this->drupalGet('admin/content/comment');
|
||||
$this->assertNoText(Html::escape($this->node->label()));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -215,4 +227,51 @@ class CommentAdminTest extends CommentTestBase {
|
|||
$this->assertFieldById('edit-mail', $anonymous_comment->getAuthorEmail());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests commented translation deletion admin view.
|
||||
*/
|
||||
public function testCommentedTranslationDeletion() {
|
||||
\Drupal::service('module_installer')->install([
|
||||
'language',
|
||||
'locale',
|
||||
]);
|
||||
\Drupal::service('router.builder')->rebuildIfNeeded();
|
||||
|
||||
ConfigurableLanguage::createFromLangcode('ur')->save();
|
||||
// Rebuild the container to update the default language container variable.
|
||||
$this->rebuildContainer();
|
||||
// Ensure that doesn't require contact info.
|
||||
$this->setCommentAnonymous('0');
|
||||
$this->drupalLogin($this->webUser);
|
||||
$count_query = \Drupal::entityTypeManager()
|
||||
->getStorage('comment')
|
||||
->getQuery()
|
||||
->count();
|
||||
$before_count = $count_query->execute();
|
||||
// Post 2 anonymous comments without contact info.
|
||||
$comment1 = $this->postComment($this->node, $this->randomMachineName(), $this->randomMachineName(), TRUE);
|
||||
$comment2 = $this->postComment($this->node, $this->randomMachineName(), $this->randomMachineName(), TRUE);
|
||||
|
||||
$comment1->addTranslation('ur', ['subject' => 'ur ' . $comment1->label()])
|
||||
->save();
|
||||
$comment2->addTranslation('ur', ['subject' => 'ur ' . $comment1->label()])
|
||||
->save();
|
||||
$this->drupalLogout();
|
||||
$this->drupalLogin($this->adminUser);
|
||||
// Delete multiple comments in one operation.
|
||||
$edit = [
|
||||
'operation' => 'delete',
|
||||
"comments[{$comment1->id()}]" => 1,
|
||||
"comments[{$comment2->id()}]" => 1,
|
||||
];
|
||||
$this->drupalPostForm('admin/content/comment', $edit, t('Update'));
|
||||
$this->assertRaw(new FormattableMarkup('@label (Original translation) - <em>The following comment translations will be deleted:</em>', ['@label' => $comment1->label()]));
|
||||
$this->assertRaw(new FormattableMarkup('@label (Original translation) - <em>The following comment translations will be deleted:</em>', ['@label' => $comment2->label()]));
|
||||
$this->assertText('English');
|
||||
$this->assertText('Urdu');
|
||||
$this->drupalPostForm(NULL, [], t('Delete'));
|
||||
$after_count = $count_query->execute();
|
||||
$this->assertEqual($after_count, $before_count, 'No comment or translation found.');
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -222,7 +222,7 @@ class CommentNonNodeTest extends WebTestBase {
|
|||
$this->drupalPostForm('admin/content/comment' . ($approval ? '/approval' : ''), $edit, t('Update'));
|
||||
|
||||
if ($operation == 'delete') {
|
||||
$this->drupalPostForm(NULL, [], t('Delete comments'));
|
||||
$this->drupalPostForm(NULL, [], t('Delete'));
|
||||
$this->assertRaw(\Drupal::translation()->formatPlural(1, 'Deleted 1 comment.', 'Deleted @count comments.'), format_string('Operation "@operation" was performed on comment.', ['@operation' => $operation]));
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -354,7 +354,7 @@ abstract class CommentTestBase extends WebTestBase {
|
|||
$this->drupalPostForm('admin/content/comment' . ($approval ? '/approval' : ''), $edit, t('Update'));
|
||||
|
||||
if ($operation == 'delete') {
|
||||
$this->drupalPostForm(NULL, [], t('Delete comments'));
|
||||
$this->drupalPostForm(NULL, [], t('Delete'));
|
||||
$this->assertRaw(\Drupal::translation()->formatPlural(1, 'Deleted 1 comment.', 'Deleted @count comments.'), format_string('Operation "@operation" was performed on comment.', ['@operation' => $operation]));
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\comment\Tests\Update;
|
||||
|
||||
use Drupal\system\Tests\Update\UpdatePathTestBase;
|
||||
|
||||
/**
|
||||
* Tests that comment admin view is enabled after update.
|
||||
*
|
||||
* @see comment_post_update_enable_comment_admin_view()
|
||||
*
|
||||
* @group Update
|
||||
*/
|
||||
class CommentAdminViewUpdateTest extends UpdatePathTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = ['comment', 'views'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setDatabaseDumpFiles() {
|
||||
$this->databaseDumpFiles = [
|
||||
__DIR__ . '/../../../../system/tests/fixtures/update/drupal-8.bare.standard.php.gz',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that comment admin view is enabled after update.
|
||||
*/
|
||||
public function testCommentAdminPostUpdateHook() {
|
||||
$this->runUpdates();
|
||||
// Ensure we can load the view from the storage after the update and it's
|
||||
// enabled.
|
||||
$entity_type_manager = \Drupal::entityTypeManager();
|
||||
/** @var \Drupal\views\ViewEntityInterface $comment_admin_view */
|
||||
$comment_admin_view = $entity_type_manager->getStorage('view')->load('comment');
|
||||
$this->assertNotNull($comment_admin_view, 'Comment admin view exist in storage.');
|
||||
$this->assertTrue($comment_admin_view->enable(), 'Comment admin view is enabled.');
|
||||
$comment_delete_action = $entity_type_manager->getStorage('action')->load('comment_delete_action');
|
||||
$this->assertNotNull($comment_delete_action, 'Comment delete action imported');
|
||||
// Verify comment admin page is working after updates.
|
||||
$account = $this->drupalCreateUser(['administer comments']);
|
||||
$this->drupalLogin($account);
|
||||
$this->drupalGet('admin/content/comment');
|
||||
$this->assertText(t('No comments available.'));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,211 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\comment\Tests\Views;
|
||||
|
||||
use Drupal\block_content\Entity\BlockContent;
|
||||
use Drupal\block_content\Entity\BlockContentType;
|
||||
use Drupal\comment\Entity\Comment;
|
||||
use Drupal\comment\Plugin\Field\FieldType\CommentItemInterface;
|
||||
use Drupal\Component\Render\FormattableMarkup;
|
||||
use Drupal\comment\Tests\CommentTestBase as CommentWebTestBase;
|
||||
use Drupal\Component\Utility\Html;
|
||||
use Drupal\Component\Utility\Unicode;
|
||||
use Drupal\user\RoleInterface;
|
||||
use Drupal\views\Views;
|
||||
|
||||
/**
|
||||
* Tests comment approval functionality.
|
||||
*
|
||||
* @group comment
|
||||
*/
|
||||
class CommentAdminTest extends CommentWebTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
\Drupal::service('module_installer')->install(['views']);
|
||||
$view = Views::getView('comment');
|
||||
$view->storage->enable()->save();
|
||||
\Drupal::service('router.builder')->rebuildIfNeeded();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test comment approval functionality through admin/content/comment.
|
||||
*/
|
||||
public function testApprovalAdminInterface() {
|
||||
// Set anonymous comments to require approval.
|
||||
user_role_change_permissions(RoleInterface::ANONYMOUS_ID, [
|
||||
'access comments' => TRUE,
|
||||
'post comments' => TRUE,
|
||||
'skip comment approval' => FALSE,
|
||||
]);
|
||||
$this->drupalPlaceBlock('page_title_block');
|
||||
$this->drupalLogin($this->adminUser);
|
||||
// Ensure that doesn't require contact info.
|
||||
$this->setCommentAnonymous('0');
|
||||
|
||||
// Test that the comments page loads correctly when there are no comments.
|
||||
$this->drupalGet('admin/content/comment');
|
||||
$this->assertText(t('No comments available.'));
|
||||
|
||||
$this->drupalLogout();
|
||||
|
||||
// Post anonymous comment without contact info.
|
||||
$body = $this->getRandomGenerator()->sentences(4);
|
||||
$subject = Unicode::truncate(trim(Html::decodeEntities(strip_tags($body))), 29, TRUE, TRUE);
|
||||
$author_name = $this->randomMachineName();
|
||||
$this->drupalPostForm('comment/reply/node/' . $this->node->id() . '/comment', [
|
||||
'name' => $author_name,
|
||||
'comment_body[0][value]' => $body,
|
||||
], t('Save'));
|
||||
$this->assertText(t('Your comment has been queued for review by site administrators and will be published after approval.'), 'Comment requires approval.');
|
||||
|
||||
// Get unapproved comment id.
|
||||
$this->drupalLogin($this->adminUser);
|
||||
$anonymous_comment4 = $this->getUnapprovedComment($subject);
|
||||
$anonymous_comment4 = Comment::create([
|
||||
'cid' => $anonymous_comment4,
|
||||
'subject' => $subject,
|
||||
'comment_body' => $body,
|
||||
'entity_id' => $this->node->id(),
|
||||
'entity_type' => 'node',
|
||||
'field_name' => 'comment',
|
||||
]);
|
||||
$this->drupalLogout();
|
||||
|
||||
$this->assertFalse($this->commentExists($anonymous_comment4), 'Anonymous comment was not published.');
|
||||
|
||||
// Approve comment.
|
||||
$this->drupalLogin($this->adminUser);
|
||||
$edit = [];
|
||||
$edit['action'] = 'comment_publish_action';
|
||||
$edit['comment_bulk_form[0]'] = $anonymous_comment4->id();
|
||||
$this->drupalPostForm('admin/content/comment/approval', $edit, t('Apply to selected items'));
|
||||
|
||||
$this->assertText('Publish comment was applied to 1 item.', new FormattableMarkup('Operation "@operation" was performed on comment.', ['@operation' => 'publish']));
|
||||
$this->drupalLogout();
|
||||
|
||||
$this->drupalGet('node/' . $this->node->id());
|
||||
$this->assertTrue($this->commentExists($anonymous_comment4), 'Anonymous comment visible.');
|
||||
|
||||
// Post 2 anonymous comments without contact info.
|
||||
$comments[] = $this->postComment($this->node, $this->randomMachineName(), $this->randomMachineName(), TRUE);
|
||||
$comments[] = $this->postComment($this->node, $this->randomMachineName(), $this->randomMachineName(), TRUE);
|
||||
|
||||
// Publish multiple comments in one operation.
|
||||
$this->drupalLogin($this->adminUser);
|
||||
$this->drupalGet('admin/content/comment/approval');
|
||||
$this->assertText(t('Unapproved comments (@count)', ['@count' => 2]), 'Two unapproved comments waiting for approval.');
|
||||
$edit = [
|
||||
"action" => 'comment_publish_action',
|
||||
"comment_bulk_form[1]" => $comments[0]->id(),
|
||||
"comment_bulk_form[0]" => $comments[1]->id(),
|
||||
];
|
||||
$this->drupalPostForm(NULL, $edit, t('Apply to selected items'));
|
||||
$this->assertText(t('Unapproved comments (@count)', ['@count' => 0]), 'All comments were approved.');
|
||||
|
||||
// Test message when no comments selected.
|
||||
$this->drupalPostForm('admin/content/comment', [], t('Apply to selected items'));
|
||||
$this->assertText(t('Select one or more comments to perform the update on.'));
|
||||
|
||||
$subject_link = $this->xpath('//table/tbody/tr/td/a[contains(@href, :href) and contains(@title, :title) and text()=:text]', [
|
||||
':href' => $comments[0]->permalink()->toString(),
|
||||
':title' => Unicode::truncate($comments[0]->get('comment_body')->value, 128),
|
||||
':text' => $comments[0]->getSubject(),
|
||||
]);
|
||||
$this->assertTrue(!empty($subject_link), 'Comment listing shows the correct subject link.');
|
||||
$this->assertText($author_name . ' (not verified)', 'Anonymous author name is displayed correctly.');
|
||||
|
||||
$subject_link = $this->xpath('//table/tbody/tr/td/a[contains(@href, :href) and contains(@title, :title) and text()=:text]', [
|
||||
':href' => $anonymous_comment4->permalink()->toString(),
|
||||
':title' => Unicode::truncate($body, 128),
|
||||
':text' => $subject,
|
||||
]);
|
||||
$this->assertTrue(!empty($subject_link), 'Comment listing shows the correct subject link.');
|
||||
$this->assertText($author_name . ' (not verified)', 'Anonymous author name is displayed correctly.');
|
||||
|
||||
// Delete multiple comments in one operation.
|
||||
$edit = [
|
||||
'action' => 'comment_delete_action',
|
||||
"comment_bulk_form[1]" => $comments[0]->id(),
|
||||
"comment_bulk_form[0]" => $comments[1]->id(),
|
||||
"comment_bulk_form[2]" => $anonymous_comment4->id(),
|
||||
];
|
||||
$this->drupalPostForm(NULL, $edit, t('Apply to selected items'));
|
||||
$this->assertText(t('Are you sure you want to delete these comments and all their children?'), 'Confirmation required.');
|
||||
$this->drupalPostForm(NULL, [], t('Delete'));
|
||||
$this->assertText(t('No comments available.'), 'All comments were deleted.');
|
||||
|
||||
// Make sure the label of unpublished node is not visible on listing page.
|
||||
$this->drupalGet('admin/content/comment');
|
||||
$this->postComment($this->node, $this->randomMachineName());
|
||||
$this->drupalLogout();
|
||||
$this->drupalLogin($this->adminUser);
|
||||
$this->drupalGet('admin/content/comment');
|
||||
$this->assertText(Html::escape($this->node->label()), 'Comment admin can see the title of a published node');
|
||||
$this->node->setUnpublished()->save();
|
||||
$this->assertFalse($this->node->isPublished(), 'Node is unpublished now.');
|
||||
$this->drupalGet('admin/content/comment');
|
||||
$this->assertNoText(Html::escape($this->node->label()), 'Comment admin cannot see the title of an unpublished node');
|
||||
$this->drupalLogout();
|
||||
$node_access_user = $this->drupalCreateUser([
|
||||
'administer comments',
|
||||
'bypass node access',
|
||||
]);
|
||||
$this->drupalLogin($node_access_user);
|
||||
$this->drupalGet('admin/content/comment');
|
||||
$this->assertText(Html::escape($this->node->label()), 'Comment admin with bypass node access permissions can still see the title of a published node');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests commented entity label of admin view.
|
||||
*/
|
||||
public function testCommentedEntityLabel() {
|
||||
\Drupal::service('module_installer')->install(['block_content']);
|
||||
\Drupal::service('router.builder')->rebuildIfNeeded();
|
||||
$bundle = BlockContentType::create([
|
||||
'id' => 'basic',
|
||||
'label' => 'basic',
|
||||
'revision' => FALSE,
|
||||
]);
|
||||
$bundle->save();
|
||||
$block_content = BlockContent::create([
|
||||
'type' => 'basic',
|
||||
'label' => 'Some block title',
|
||||
'info' => 'Test block',
|
||||
]);
|
||||
$block_content->save();
|
||||
|
||||
// Create comment field on block_content.
|
||||
$this->addDefaultCommentField('block_content', 'basic', 'block_comment', CommentItemInterface::OPEN, 'block_comment');
|
||||
$this->drupalLogin($this->webUser);
|
||||
// Post a comment to node.
|
||||
$node_comment = $this->postComment($this->node, $this->randomMachineName(), $this->randomMachineName(), TRUE);
|
||||
// Post a comment to block content.
|
||||
$block_content_comment = $this->postComment($block_content, $this->randomMachineName(), $this->randomMachineName(), TRUE, 'block_comment');
|
||||
$this->drupalLogout();
|
||||
// Login as admin to test the admin comment page.
|
||||
$this->drupalLogin($this->adminUser);
|
||||
$this->drupalGet('admin/content/comment');
|
||||
|
||||
$comment_author_link = $this->xpath('//table/tbody/tr[1]/td/a[contains(@href, :href) and text()=:text]', [
|
||||
':href' => $this->webUser->toUrl()->toString(),
|
||||
':text' => $this->webUser->label(),
|
||||
]);
|
||||
$this->assertTrue(!empty($comment_author_link), 'Comment listing links to comment author.');
|
||||
$comment_author_link = $this->xpath('//table/tbody/tr[2]/td/a[contains(@href, :href) and text()=:text]', [
|
||||
':href' => $this->webUser->toUrl()->toString(),
|
||||
':text' => $this->webUser->label(),
|
||||
]);
|
||||
$this->assertTrue(!empty($comment_author_link), 'Comment listing links to comment author.');
|
||||
// Admin page contains label of both entities.
|
||||
$this->assertText(Html::escape($this->node->label()), 'Node title is visible.');
|
||||
$this->assertText(Html::escape($block_content->label()), 'Block content label is visible.');
|
||||
// Admin page contains subject of both entities.
|
||||
$this->assertText(Html::escape($node_comment->label()), 'Node comment is visible.');
|
||||
$this->assertText(Html::escape($block_content_comment->label()), 'Block content comment is visible.');
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\comment\Tests\Views;
|
||||
|
||||
use Drupal\comment\Tests\CommentTestBase as CommentWebTestBase;
|
||||
|
||||
/**
|
||||
* Tests comment edit functionality.
|
||||
*
|
||||
* @group comment
|
||||
*/
|
||||
class CommentEditTest extends CommentWebTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected $profile = 'standard';
|
||||
|
||||
/**
|
||||
* Tests comment label in admin view.
|
||||
*/
|
||||
public function testCommentEdit() {
|
||||
$this->drupalLogin($this->adminUser);
|
||||
// Post a comment to node.
|
||||
$node_comment = $this->postComment($this->node, $this->randomMachineName(), $this->randomMachineName(), TRUE);
|
||||
$this->drupalGet('admin/content/comment');
|
||||
$this->assertText($this->adminUser->label());
|
||||
$this->drupalGet($node_comment->toUrl('edit-form')->toString());
|
||||
$edit = [
|
||||
'comment_body[0][value]' => $this->randomMachineName(),
|
||||
];
|
||||
$this->drupalPostForm(NULL, $edit, t('Save'));
|
||||
$this->drupalGet('admin/content/comment');
|
||||
$this->assertText($this->adminUser->label());
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,93 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\comment\Unit\Plugin\views\field;
|
||||
|
||||
use Drupal\Core\DependencyInjection\ContainerBuilder;
|
||||
use Drupal\comment\Plugin\views\field\CommentBulkForm;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \Drupal\comment\Plugin\views\field\CommentBulkForm
|
||||
* @group comment
|
||||
*/
|
||||
class CommentBulkFormTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function tearDown() {
|
||||
parent::tearDown();
|
||||
$container = new ContainerBuilder();
|
||||
\Drupal::setContainer($container);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the constructor assignment of actions.
|
||||
*/
|
||||
public function testConstructor() {
|
||||
$actions = [];
|
||||
|
||||
for ($i = 1; $i <= 2; $i++) {
|
||||
$action = $this->getMock('\Drupal\system\ActionConfigEntityInterface');
|
||||
$action->expects($this->any())
|
||||
->method('getType')
|
||||
->will($this->returnValue('comment'));
|
||||
$actions[$i] = $action;
|
||||
}
|
||||
|
||||
$action = $this->getMock('\Drupal\system\ActionConfigEntityInterface');
|
||||
$action->expects($this->any())
|
||||
->method('getType')
|
||||
->will($this->returnValue('user'));
|
||||
$actions[] = $action;
|
||||
|
||||
$entity_storage = $this->getMock('Drupal\Core\Entity\EntityStorageInterface');
|
||||
$entity_storage->expects($this->any())
|
||||
->method('loadMultiple')
|
||||
->will($this->returnValue($actions));
|
||||
|
||||
$entity_manager = $this->getMock('Drupal\Core\Entity\EntityManagerInterface');
|
||||
$entity_manager->expects($this->once())
|
||||
->method('getStorage')
|
||||
->with('action')
|
||||
->will($this->returnValue($entity_storage));
|
||||
|
||||
$language_manager = $this->getMock('Drupal\Core\Language\LanguageManagerInterface');
|
||||
|
||||
$views_data = $this->getMockBuilder('Drupal\views\ViewsData')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$views_data->expects($this->any())
|
||||
->method('get')
|
||||
->with('comment')
|
||||
->will($this->returnValue(['table' => ['entity type' => 'comment']]));
|
||||
$container = new ContainerBuilder();
|
||||
$container->set('views.views_data', $views_data);
|
||||
$container->set('string_translation', $this->getStringTranslationStub());
|
||||
\Drupal::setContainer($container);
|
||||
|
||||
$storage = $this->getMock('Drupal\views\ViewEntityInterface');
|
||||
$storage->expects($this->any())
|
||||
->method('get')
|
||||
->with('base_table')
|
||||
->will($this->returnValue('comment'));
|
||||
|
||||
$executable = $this->getMockBuilder('Drupal\views\ViewExecutable')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$executable->storage = $storage;
|
||||
|
||||
$display = $this->getMockBuilder('Drupal\views\Plugin\views\display\DisplayPluginBase')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
|
||||
$definition['title'] = '';
|
||||
$options = [];
|
||||
|
||||
$comment_bulk_form = new CommentBulkForm([], 'comment_bulk_form', $definition, $entity_manager, $language_manager);
|
||||
$comment_bulk_form->init($executable, $display, $options);
|
||||
|
||||
$this->assertAttributeEquals(array_slice($actions, 0, -1, TRUE), 'actions', $comment_bulk_form);
|
||||
}
|
||||
|
||||
}
|
|
@ -57,7 +57,7 @@ class MigrateUpgrade6Test extends MigrateUpgradeTestBase {
|
|||
'search_page' => 2,
|
||||
'shortcut' => 2,
|
||||
'shortcut_set' => 1,
|
||||
'action' => 22,
|
||||
'action' => 23,
|
||||
'menu' => 8,
|
||||
'taxonomy_term' => 7,
|
||||
'taxonomy_vocabulary' => 6,
|
||||
|
@ -65,7 +65,7 @@ class MigrateUpgrade6Test extends MigrateUpgradeTestBase {
|
|||
'user' => 7,
|
||||
'user_role' => 6,
|
||||
'menu_link_content' => 4,
|
||||
'view' => 15,
|
||||
'view' => 16,
|
||||
'date_format' => 11,
|
||||
'entity_form_display' => 19,
|
||||
'entity_form_mode' => 1,
|
||||
|
|
|
@ -63,7 +63,7 @@ class MigrateUpgrade7Test extends MigrateUpgradeTestBase {
|
|||
'search_page' => 2,
|
||||
'shortcut' => 6,
|
||||
'shortcut_set' => 2,
|
||||
'action' => 16,
|
||||
'action' => 17,
|
||||
'menu' => 6,
|
||||
'taxonomy_term' => 18,
|
||||
'taxonomy_vocabulary' => 4,
|
||||
|
@ -71,7 +71,7 @@ class MigrateUpgrade7Test extends MigrateUpgradeTestBase {
|
|||
'user' => 4,
|
||||
'user_role' => 3,
|
||||
'menu_link_content' => 7,
|
||||
'view' => 15,
|
||||
'view' => 16,
|
||||
'date_format' => 11,
|
||||
'entity_form_display' => 18,
|
||||
'entity_form_mode' => 1,
|
||||
|
|
|
@ -100,6 +100,15 @@ class DefaultViewsTest extends ViewTestBase {
|
|||
'field_name' => 'comment'
|
||||
];
|
||||
Comment::create($comment)->save();
|
||||
|
||||
$unpublished_comment = [
|
||||
'uid' => $user->id(),
|
||||
'status' => CommentInterface::NOT_PUBLISHED,
|
||||
'entity_id' => $node->id(),
|
||||
'entity_type' => 'node',
|
||||
'field_name' => 'comment',
|
||||
];
|
||||
Comment::create($unpublished_comment)->save();
|
||||
}
|
||||
|
||||
// Some views, such as the "Who's Online" view, only return results if at
|
||||
|
|
Loading…
Reference in New Issue