CommentDeleteManager.php in Comment Delete 8
Namespace
Drupal\comment_deleteFile
src/CommentDeleteManager.phpView source
<?php
namespace Drupal\comment_delete;
use Drupal\comment\Entity\Comment;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Database\Connection;
use Drupal\Core\Entity\EntityStorageException;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\EventSubscriber\AjaxResponseSubscriber;
use Drupal\Core\EventSubscriber\MainContentViewSubscriber;
use Drupal\Core\Messenger\MessengerInterface;
use Drupal\Core\Session\AccountProxyInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Symfony\Component\HttpFoundation\RequestStack;
/**
* Service container for comment delete operations.
*
* @package Drupal\comment_delete
*/
class CommentDeleteManager {
use StringTranslationTrait;
/**
* The delete replies operation.
*
* @var int
*/
const DELETE_REPLIES = 0;
/**
* The move replies operation.
*
* @var int
*/
const MOVE_REPLIES = 1;
/**
* The keep replies operation.
*
* @var int
*/
const KEEP_REPLIES = 2;
/**
* The request stack.
*
* @var \Symfony\Component\HttpFoundation\RequestStack
*/
protected $requestStack;
/**
* The database connection.
*
* @var \Drupal\Core\Database\Connection
*/
protected $connection;
/**
* The config.
*
* @var \Drupal\Core\Config\ImmutableConfig
*/
protected $config;
/**
* The comment storage.
*
* @var \Drupal\Core\Entity\EntityStorageInterface
*/
protected $commentStorage;
/**
* The current user.
*
* @var \Drupal\Core\Session\AccountProxyInterface
*/
protected $currentUser;
/**
* The messenger.
*
* @var \Drupal\Core\Messenger\MessengerInterface
*/
protected $messenger;
/**
* The comment thread ripper.
*
* @var \Drupal\comment_delete\CommentThread
*/
protected $thread;
/**
* CommentDelete constructor.
*
* @param \Symfony\Component\HttpFoundation\RequestStack $request_stack
* The request stack.
* @param \Drupal\Core\Database\Connection $connection
* The database connection.
* @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
* The config factory.
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
* The entity type manager.
* @param \Drupal\Core\Session\AccountProxyInterface $current_user
* The current user.
* @param \Drupal\Core\Messenger\MessengerInterface $messenger
* The messenger.
* @param \Drupal\comment_delete\CommentThread $comment_thread
* The comment thread ripper.
*
* @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
* @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
*/
public function __construct(RequestStack $request_stack, Connection $connection, ConfigFactoryInterface $config_factory, EntityTypeManagerInterface $entity_type_manager, AccountProxyInterface $current_user, MessengerInterface $messenger, CommentThread $comment_thread) {
$this->requestStack = $request_stack;
$this->connection = $connection;
$this->config = $config_factory
->get('comment_delete.config');
$this->commentStorage = $entity_type_manager
->getStorage('comment');
$this->currentUser = $current_user;
$this->messenger = $messenger;
$this->thread = $comment_thread;
}
/**
* Get the comment delete operations available to current user.
*
* @return array
* An array of available comment delete operations.
*/
public function getOperations() {
$options = [];
if ($this->currentUser
->hasPermission('delete comment replies')) {
$options[self::DELETE_REPLIES] = $this
->t('Delete the comment and its replies');
}
if (!$this->config
->get('soft') && $this->currentUser
->hasPermission('move comment replies')) {
$options[self::MOVE_REPLIES] = $this
->t('Delete the comment and move its replies up');
}
$options[self::KEEP_REPLIES] = $this
->t('Delete the comment and keep its replies');
return $options;
}
/**
* Delete a comment and do something with its replies.
*
* @param \Drupal\comment\Entity\Comment $comment
* The comment entity.
* @param int $op
* The operation type.
*/
public function delete(Comment $comment, $op = self::KEEP_REPLIES) {
switch ($op) {
case self::DELETE_REPLIES:
// Delete comment and replies. Default Drupal behavior.
$this
->deleteReplies($comment);
break;
case self::MOVE_REPLIES:
// Delete comment and move replies up one thread.
$this
->moveReplies($comment);
break;
case self::KEEP_REPLIES:
// Soft delete comment and keep replies at current thread.
$this
->keepReplies($comment);
break;
}
// Set translatable confirmation message.
$this->messenger
->addMessage($this->config
->get('message'));
}
/**
* Delete comment and replies.
*
* @param \Drupal\comment\Entity\Comment $comment
* The comment entity.
*/
protected function deleteReplies(Comment $comment) {
// Permanently delete comment and replies.
if (!$this->config
->get('soft')) {
try {
$comment
->delete();
} catch (EntityStorageException $e) {
// Unable to delete.
watchdog_exception('comment_delete', $e);
}
return;
}
// Soft delete comment and replies.
$thread = $comment
->get('thread')
->getString();
$query = $this->commentStorage
->getQuery()
->condition('entity_type', $comment
->get('entity_type')
->getString())
->condition('entity_id', $comment
->get('entity_id')
->getString());
$db_or = $query
->orConditionGroup()
->condition('thread', $thread)
->condition('thread', $this->connection
->escapeLike(str_replace('/', '.', $thread)) . '%', 'LIKE');
$query
->condition($db_or);
$comment_ids = $query
->execute();
if (!empty($comment_ids)) {
$comment_thread = $this->commentStorage
->loadMultiple($comment_ids);
foreach ($comment_thread as $_comment) {
/** @var \Drupal\comment\Entity\Comment $_comment */
$this
->softDelete($_comment);
}
}
}
/**
* Delete comment and move replies up one level.
*
* @param \Drupal\comment\Entity\Comment $comment
* The comment entity.
*/
protected function moveReplies(Comment $comment) {
// Get all direct replies to the comment. Each will be given to the next
// thread up if one is available or set as a top level thread.
$query = $this->commentStorage
->getQuery()
->condition('pid', $comment
->id());
$comment_ids = $query
->execute();
if (!empty($comment_ids)) {
$comments = $this->commentStorage
->loadMultiple($comment_ids);
foreach ($comments as $_comment) {
/** @var \Drupal\comment\Entity\Comment $_comment */
try {
$parent_comment = $comment
->getParentComment();
if ($parent_comment && ($pid = $comment
->getParentComment()
->id())) {
$_comment
->set('pid', $pid);
}
else {
$_comment
->set('pid', NULL);
}
$_comment
->save();
} catch (EntityStorageException $e) {
// Unable to save.
watchdog_exception('comment_delete', $e);
}
}
}
try {
$comment
->delete();
$this->thread
->thread($comment
->getCommentedEntity());
} catch (EntityStorageException $e) {
// Unable to delete.
watchdog_exception('comment_delete', $e);
}
}
/**
* Soft delete comment and keep replies at current level.
*
* @param \Drupal\comment\Entity\Comment $comment
* The comment entity.
*/
protected function keepReplies(Comment $comment) {
// Get the total number of replies to the comment. If the comment has
// no replies we can safely hard delete the comment.
$replies_count = $this->commentStorage
->getQuery()
->condition('pid', $comment
->id())
->count()
->execute();
if ($replies_count > 0) {
// Replies exist so do the soft delete boogie.
$this
->softDelete($comment);
}
else {
if (!$this->config
->get('soft')) {
try {
$comment
->delete();
} catch (EntityStorageException $e) {
// Unable to delete.
watchdog_exception('comment_delete', $e);
}
}
else {
$this
->softDelete($comment);
}
}
}
/**
* Soft delete comment.
*
* @param \Drupal\comment\Entity\Comment $comment
* The comment entity.
*/
protected function softDelete(Comment $comment) {
if ($this->config
->get('soft_mode') === 'unpublished') {
// Hiding a comment is the same as setting unpublished. This mode is not
// recommended because it can cause thread indentation to go out of whack
// (unpublished comments still count towards the thread). Mitigated by the
// fact an unpublished comment can be published to restore indentation.
try {
$comment
->setUnpublished();
$comment
->save();
} catch (EntityStorageException $e) {
// Unable to save.
watchdog_exception('comment_delete', $e);
}
}
else {
$unset_author = $this->config
->get('soft_user');
$fields = array_filter($comment
->getFields(), function ($field_machine_name) {
return $field_machine_name !== 'field_name' && preg_match('/^field_(.*)/i', $field_machine_name);
}, ARRAY_FILTER_USE_KEY);
try {
// Reset values on source and all translations.
foreach ($comment
->getTranslationLanguages() as $translation) {
$comment_translation = $comment
->getTranslation($translation
->getId());
if ($unset_author) {
$comment
->setOwnerId(0);
}
$comment_translation
->set('subject', NULL);
$comment_translation
->set('comment_body', NULL);
foreach ($fields as $field_machine_name => $field) {
$comment_translation
->set($field_machine_name, NULL);
}
$comment_translation
->save();
}
} catch (EntityStorageException $e) {
// Unable to save.
watchdog_exception('comment_delete', $e);
}
}
}
/**
* Check if current request is Ajax.
*
* @return bool
* A boolean indicating if current request is Ajax.
*/
public function isAjaxRequest() {
$request = $this->requestStack
->getCurrentRequest();
$has_ajax_parameter = $request->request
->has(AjaxResponseSubscriber::AJAX_REQUEST_PARAMETER);
$has_ajax_format = $request->query
->get(MainContentViewSubscriber::WRAPPER_FORMAT) == 'drupal_ajax';
return $has_ajax_parameter || $has_ajax_format;
}
}
Classes
Name | Description |
---|---|
CommentDeleteManager | Service container for comment delete operations. |