Commit a080a523 authored by alexpott's avatar alexpott

Issue #1978958 by jibran, disasm, kgoel, Pancho, vijaycs85, cosmicdreams,...

Issue #1978958 by jibran, disasm, kgoel, Pancho, vijaycs85, cosmicdreams, dawehner, wamilton: Convert comment_reply() to a Controller.
parent be312290
......@@ -228,14 +228,6 @@ function comment_menu() {
'route_name' => 'comment_confirm_delete',
'weight' => 20,
);
$items['comment/reply/%node'] = array(
'title' => 'Add new comment',
'page callback' => 'comment_reply',
'page arguments' => array(2),
'access callback' => 'node_access',
'access arguments' => array('view', 2),
'file' => 'comment.pages.inc',
);
return $items;
}
......
<?php
/**
* @file
* User page callbacks for the Comment module.
*/
use Drupal\Core\Entity\EntityInterface;
use Drupal\comment\Entity\Comment;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
/**
* Form constructor for the comment reply form.
*
* There are several cases that have to be handled, including:
* - replies to comments
* - replies to nodes
* - attempts to reply to nodes that can no longer accept comments
* - respecting access permissions ('access comments', 'post comments', etc.)
*
* The node or comment that is being replied to must appear above the comment
* form to provide the user context while authoring the comment.
*
* @param \Drupal\Core\Entity\EntityInterface $node
* Every comment belongs to a node. This is that node.
* @param $pid
* (optional) Some comments are replies to other comments. In those cases,
* $pid is the parent comment's comment ID. Defaults to NULL.
*
* @return array
* An associative array containing:
* - An array for rendering the node or parent comment.
* - comment_node: If the comment is a reply to the node.
* - comment_parent: If the comment is a reply to another comment.
* - comment_form: The comment form as a renderable array.
*/
function comment_reply(EntityInterface $node, $pid = NULL) {
// Set the breadcrumb trail.
drupal_set_breadcrumb(array(l(t('Home'), NULL), l($node->label(), 'node/' . $node->id())));
$op = Drupal::request()->request->get('op');
$build = array();
// The user is previewing a comment prior to submitting it.
if ($op == t('Preview')) {
if (user_access('post comments')) {
$build['comment_form'] = comment_add($node, $pid);
}
else {
drupal_set_message(t('You are not authorized to post comments.'), 'error');
return new RedirectResponse(url('node/' . $node->id(), array('absolute' => TRUE)));
}
}
else {
// $pid indicates that this is a reply to a comment.
if ($pid) {
if (user_access('access comments')) {
// Load the parent comment.
$comment = comment_load($pid);
if ($comment->status->value == COMMENT_PUBLISHED) {
// If that comment exists, make sure that the current comment and the
// parent comment both belong to the same parent node.
if ($comment->nid->target_id != $node->id()) {
// Attempting to reply to a comment not belonging to the current nid.
drupal_set_message(t('The comment you are replying to does not exist.'), 'error');
return new RedirectResponse(url('node/' . $node->id(), array('absolute' => TRUE)));
}
// Display the parent comment
$build['comment_parent'] = comment_view($comment);
}
else {
drupal_set_message(t('The comment you are replying to does not exist.'), 'error');
return new RedirectResponse(url('node/' . $node->id(), array('absolute' => TRUE)));
}
}
else {
drupal_set_message(t('You are not authorized to view comments.'), 'error');
return new RedirectResponse(url('node/' . $node->id(), array('absolute' => TRUE)));
}
}
// This is the case where the comment is in response to a node. Display the node.
elseif (user_access('access content')) {
$build['comment_node'] = node_view($node);
}
// Should we show the reply box?
if ($node->comment->value != COMMENT_NODE_OPEN) {
drupal_set_message(t("This discussion is closed: you can't post new comments."), 'error');
return new RedirectResponse(url('node/' . $node->id(), array('absolute' => TRUE)));
}
elseif (user_access('post comments')) {
$build['comment_form'] = comment_add($node, $pid);
}
else {
drupal_set_message(t('You are not authorized to post comments.'), 'error');
return new RedirectResponse(url('node/' . $node->id(), array('absolute' => TRUE)));
}
}
return $build;
}
......@@ -19,9 +19,18 @@ comment_permalink:
_controller: '\Drupal\comment\Controller\CommentController::commentPermalink'
requirements:
_entity_access: 'comment.view'
comment_confirm_delete:
pattern: '/comment/{comment}/delete'
defaults:
_entity_form: 'comment.delete'
requirements:
_entity_access: 'comment.delete'
comment_reply:
pattern: 'comment/reply/{node}/{pid}'
defaults:
_content: '\Drupal\comment\Controller\CommentController::getReplyForm'
pid: ~
requirements:
_entity_access: 'node.view'
services:
comment.breadcrumb:
class: Drupal\comment\CommentBreadcrumbBuilder
tags:
- { name: breadcrumb_builder, priority: 100 }
arguments: ['@string_translation']
<?php
/**
* @file
* Contains \Drupal\comment\CommentBreadcrumbBuilder.
*/
namespace Drupal\comment;
use Drupal\Core\Breadcrumb\BreadcrumbBuilderInterface;
use Drupal\Core\StringTranslation\TranslationManager;
use Symfony\Cmf\Component\Routing\RouteObjectInterface;
/**
* Class to define the comment breadcrumb builder.
*/
class CommentBreadcrumbBuilder implements BreadcrumbBuilderInterface {
/**
* The translation manager service.
*
* @var \Drupal\Core\StringTranslation\TranslationManager
*/
protected $translation;
/**
* Constructs a CommentBreadcrumbBuilder object.
*
* @param \Drupal\Core\StringTranslation\TranslationManager $translation
* The translation manager.
*/
public function __construct(TranslationManager $translation) {
$this->translation = $translation;
}
/**
* {@inheritdoc}
*/
public function build(array $attributes) {
if (isset($attributes[RouteObjectInterface::ROUTE_NAME]) && $attributes[RouteObjectInterface::ROUTE_NAME] == 'comment_reply' && isset($attributes['node'])) {
$node = $attributes['node'];
$uri = $node->uri();
$breadcrumb[] = l($this->t('Home'), NULL);
$breadcrumb[] = l($node->label(), $uri['path']);
return $breadcrumb;
}
}
/**
* Translates a string to the current language or to a given language.
*
* See the t() documentation for details.
*/
protected function t($string, array $args = array(), array $options = array()) {
return $this->translation->translate($string, $args, $options);
}
}
......@@ -9,8 +9,10 @@
use Drupal\comment\CommentInterface;
use Drupal\comment\Entity\Comment;
use Drupal\Core\Access\CsrfTokenGenerator;
use Drupal\Core\Controller\ControllerBase;
use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
use Drupal\Core\Routing\UrlGeneratorInterface;
use Drupal\Node\NodeInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
......@@ -23,41 +25,41 @@
*
* @see \Drupal\comment\Entity\Comment.
*/
class CommentController implements ContainerInjectionInterface {
class CommentController extends ControllerBase implements ContainerInjectionInterface {
/**
* The url generator service.
* The HTTP kernel.
*
* @var \Drupal\Core\Routing\UrlGeneratorInterface
* @var \Symfony\Component\HttpKernel\HttpKernelInterface
*/
protected $urlGenerator;
protected $httpKernel;
/**
* The HTTP kernel.
* The CSRF token manager service.
*
* @var \Symfony\Component\HttpKernel\HttpKernelInterface
* @var \Drupal\Core\Access\CsrfTokenGenerator
*/
protected $httpKernel;
protected $csrfToken;
/**
* Constructs a CommentController object.
*
* @param \Drupal\Core\Routing\UrlGeneratorInterface $url_generator
* The url generator service.
* @param \Symfony\Component\HttpKernel\HttpKernelInterface $httpKernel
* HTTP kernel to handle requests.
* @param \Drupal\Core\Access\CsrfTokenGenerator $csrf_token
* The CSRF token manager service.
*/
public function __construct(UrlGeneratorInterface $url_generator, HttpKernelInterface $httpKernel) {
$this->urlGenerator = $url_generator;
public function __construct(HttpKernelInterface $httpKernel, CsrfTokenGenerator $csrf_token) {
$this->httpKernel = $httpKernel;
$this->csrfToken = $csrf_token;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
return new static(
$container->get('url_generator'),
$container->get('http_kernel')
$container->get('http_kernel'),
$container->get('csrf_token')
);
}
......@@ -78,17 +80,17 @@ public function commentApprove(Request $request, CommentInterface $comment) {
// Integrate CSRF link token directly into routing system:
// https://drupal.org/node/1798296.
$token = $request->query->get('token');
if (!isset($token) || !drupal_valid_token($token, 'comment/' . $comment->id() . '/approve')) {
if (!isset($token) || !$this->csrfToken->validate($token, 'comment/' . $comment->id() . '/approve')) {
throw new AccessDeniedHttpException();
}
$comment->status->value = COMMENT_PUBLISHED;
$comment->save();
drupal_set_message(t('Comment approved.'));
drupal_set_message($this->t('Comment approved.'));
$permalink_uri = $comment->permalink();
$permalink_uri['options']['absolute'] = TRUE;
$url = $this->urlGenerator->generateFromPath($permalink_uri['path'], $permalink_uri['options']);
$url = $this->urlGenerator()->generateFromPath($permalink_uri['path'], $permalink_uri['options']);
return new RedirectResponse($url);
}
......@@ -132,4 +134,93 @@ public function commentPermalink(Request $request, CommentInterface $comment) {
throw new NotFoundHttpException();
}
/**
* Form constructor for the comment reply form.
*
* Both replies on the node itself and replies on other comments are
* supported. To provide context, the node or comment that is being replied on
* will be displayed along the comment reply form.
* The constructor takes care of access permissions and checks whether the
* node still accepts comments.
*
* @param \Symfony\Component\HttpFoundation\Request $request
* The current request object.
* @param \Drupal\node\NodeInterface $node
* Every comment belongs to a node. This is that node.
* @param int $pid
* (optional) Some comments are replies to other comments. In those cases,
* $pid is the parent comment's ID. Defaults to NULL.
*
* @return array|\Symfony\Component\HttpFoundation\RedirectResponse
* One of the following:
* - An associative array containing:
* - An array for rendering the node or parent comment.
* - comment_node: If the comment is a reply to the node.
* - comment_parent: If the comment is a reply to another comment.
* - comment_form: The comment form as a renderable array.
* - A redirect response to current node:
* - If user is not authorized to post comments.
* - If parent comment doesn't belong to current node.
* - If user is not authorized to view comments.
* - If current node comments are disable.
*/
public function getReplyForm(Request $request, NodeInterface $node, $pid = NULL) {
$uri = $node->uri();
$build = array();
$account = $this->currentUser();
$build['#title'] = $this->t('Add new comment');
// Check if the user has the proper permissions.
if (!$account->hasPermission('post comments')) {
drupal_set_message($this->t('You are not authorized to post comments.'), 'error');
return new RedirectResponse($this->urlGenerator()->generateFromPath($uri['path'], array('absolute' => TRUE)));
}
// The user is not just previewing a comment.
if ($request->request->get('op') != $this->t('Preview')) {
if ($node->comment->value != COMMENT_NODE_OPEN) {
drupal_set_message($this->t("This discussion is closed: you can't post new comments."), 'error');
return new RedirectResponse($this->urlGenerator()->generateFromPath($uri['path'], array('absolute' => TRUE)));
}
// $pid indicates that this is a reply to a comment.
if ($pid) {
// Check if the user has the proper permissions.
if (!$account->hasPermission('access comments')) {
drupal_set_message($this->t('You are not authorized to view comments.'), 'error');
return new RedirectResponse($this->urlGenerator()->generateFromPath($uri['path'], array('absolute' => TRUE)));
}
// Load the parent comment.
$comment = $this->entityManager()->getStorageController('comment')->load($pid);
// Check if the parent comment is published and belongs to the current nid.
if (($comment->status->value == COMMENT_NOT_PUBLISHED) || ($comment->nid->target_id != $node->id())) {
drupal_set_message($this->t('The comment you are replying to does not exist.'), 'error');
return new RedirectResponse($this->urlGenerator()->generateFromPath($uri['path'], array('absolute' => TRUE)));
}
// Display the parent comment.
$build['comment_parent'] = $this->entityManager()->getRenderController('comment')->view($comment);
}
// The comment is in response to a node.
elseif ($account->hasPermission('access content')) {
// Display the node.
$build['comment_node'] = $this->entityManager()->getRenderController('node')->view($node);
}
}
else {
$build['#title'] = $this->t('Preview comment');
}
// Show the actual reply box.
$comment = $this->entityManager()->getStorageController('comment')->create(array(
'nid' => $node->id(),
'pid' => $pid,
'node_type' => 'comment_node_' . $node->getType(),
));
$build['comment_form'] = $this->entityManager()->getForm($comment);
return $build;
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment