Mercurial > hg > isophonics-drupal-site
comparison core/modules/comment/src/Controller/CommentController.php @ 0:4c8ae668cc8c
Initial import (non-working)
author | Chris Cannam |
---|---|
date | Wed, 29 Nov 2017 16:09:58 +0000 |
parents | |
children | 7a779792577d |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:4c8ae668cc8c |
---|---|
1 <?php | |
2 | |
3 namespace Drupal\comment\Controller; | |
4 | |
5 use Drupal\comment\CommentInterface; | |
6 use Drupal\comment\CommentManagerInterface; | |
7 use Drupal\comment\Plugin\Field\FieldType\CommentItemInterface; | |
8 use Drupal\Core\Access\AccessResult; | |
9 use Drupal\Core\Cache\CacheableResponseInterface; | |
10 use Drupal\Core\Controller\ControllerBase; | |
11 use Drupal\Core\Entity\EntityInterface; | |
12 use Drupal\Core\Entity\EntityManagerInterface; | |
13 use Symfony\Component\DependencyInjection\ContainerInterface; | |
14 use Symfony\Component\HttpFoundation\JsonResponse; | |
15 use Symfony\Component\HttpFoundation\RedirectResponse; | |
16 use Symfony\Component\HttpFoundation\Request; | |
17 use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; | |
18 use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; | |
19 use Symfony\Component\HttpKernel\HttpKernelInterface; | |
20 | |
21 /** | |
22 * Controller for the comment entity. | |
23 * | |
24 * @see \Drupal\comment\Entity\Comment. | |
25 */ | |
26 class CommentController extends ControllerBase { | |
27 | |
28 /** | |
29 * The HTTP kernel. | |
30 * | |
31 * @var \Symfony\Component\HttpKernel\HttpKernelInterface | |
32 */ | |
33 protected $httpKernel; | |
34 | |
35 /** | |
36 * The comment manager service. | |
37 * | |
38 * @var \Drupal\comment\CommentManagerInterface | |
39 */ | |
40 protected $commentManager; | |
41 | |
42 /** | |
43 * The entity manager. | |
44 * | |
45 * @var \Drupal\Core\Entity\EntityStorageInterface | |
46 */ | |
47 protected $entityManager; | |
48 | |
49 /** | |
50 * Constructs a CommentController object. | |
51 * | |
52 * @param \Symfony\Component\HttpKernel\HttpKernelInterface $http_kernel | |
53 * HTTP kernel to handle requests. | |
54 * @param \Drupal\comment\CommentManagerInterface $comment_manager | |
55 * The comment manager service. | |
56 * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager | |
57 * The entity manager service. | |
58 */ | |
59 public function __construct(HttpKernelInterface $http_kernel, CommentManagerInterface $comment_manager, EntityManagerInterface $entity_manager) { | |
60 $this->httpKernel = $http_kernel; | |
61 $this->commentManager = $comment_manager; | |
62 $this->entityManager = $entity_manager; | |
63 } | |
64 | |
65 /** | |
66 * {@inheritdoc} | |
67 */ | |
68 public static function create(ContainerInterface $container) { | |
69 return new static( | |
70 $container->get('http_kernel'), | |
71 $container->get('comment.manager'), | |
72 $container->get('entity.manager') | |
73 ); | |
74 } | |
75 | |
76 /** | |
77 * Publishes the specified comment. | |
78 * | |
79 * @param \Drupal\comment\CommentInterface $comment | |
80 * A comment entity. | |
81 * | |
82 * @return \Symfony\Component\HttpFoundation\RedirectResponse | |
83 */ | |
84 public function commentApprove(CommentInterface $comment) { | |
85 $comment->setPublished(TRUE); | |
86 $comment->save(); | |
87 | |
88 drupal_set_message($this->t('Comment approved.')); | |
89 $permalink_uri = $comment->permalink(); | |
90 $permalink_uri->setAbsolute(); | |
91 return new RedirectResponse($permalink_uri->toString()); | |
92 } | |
93 | |
94 /** | |
95 * Redirects comment links to the correct page depending on comment settings. | |
96 * | |
97 * Since comments are paged there is no way to guarantee which page a comment | |
98 * appears on. Comment paging and threading settings may be changed at any | |
99 * time. With threaded comments, an individual comment may move between pages | |
100 * as comments can be added either before or after it in the overall | |
101 * discussion. Therefore we use a central routing function for comment links, | |
102 * which calculates the page number based on current comment settings and | |
103 * returns the full comment view with the pager set dynamically. | |
104 * | |
105 * @param \Symfony\Component\HttpFoundation\Request $request | |
106 * The request of the page. | |
107 * @param \Drupal\comment\CommentInterface $comment | |
108 * A comment entity. | |
109 * | |
110 * @return \Symfony\Component\HttpFoundation\Response | |
111 * The comment listing set to the page on which the comment appears. | |
112 * | |
113 * @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException | |
114 * @throws \Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException | |
115 */ | |
116 public function commentPermalink(Request $request, CommentInterface $comment) { | |
117 if ($entity = $comment->getCommentedEntity()) { | |
118 // Check access permissions for the entity. | |
119 if (!$entity->access('view')) { | |
120 throw new AccessDeniedHttpException(); | |
121 } | |
122 $field_definition = $this->entityManager()->getFieldDefinitions($entity->getEntityTypeId(), $entity->bundle())[$comment->getFieldName()]; | |
123 | |
124 // Find the current display page for this comment. | |
125 $page = $this->entityManager()->getStorage('comment')->getDisplayOrdinal($comment, $field_definition->getSetting('default_mode'), $field_definition->getSetting('per_page')); | |
126 // @todo: Cleaner sub request handling. | |
127 $subrequest_url = $entity->urlInfo()->setOption('query', ['page' => $page])->toString(TRUE); | |
128 $redirect_request = Request::create($subrequest_url->getGeneratedUrl(), 'GET', $request->query->all(), $request->cookies->all(), [], $request->server->all()); | |
129 // Carry over the session to the subrequest. | |
130 if ($session = $request->getSession()) { | |
131 $redirect_request->setSession($session); | |
132 } | |
133 $request->query->set('page', $page); | |
134 $response = $this->httpKernel->handle($redirect_request, HttpKernelInterface::SUB_REQUEST); | |
135 if ($response instanceof CacheableResponseInterface) { | |
136 // @todo Once path aliases have cache tags (see | |
137 // https://www.drupal.org/node/2480077), add test coverage that | |
138 // the cache tag for a commented entity's path alias is added to the | |
139 // comment's permalink response, because there can be blocks or | |
140 // other content whose renderings depend on the subrequest's URL. | |
141 $response->addCacheableDependency($subrequest_url); | |
142 } | |
143 return $response; | |
144 } | |
145 throw new NotFoundHttpException(); | |
146 } | |
147 | |
148 /** | |
149 * The _title_callback for the page that renders the comment permalink. | |
150 * | |
151 * @param \Drupal\comment\CommentInterface $comment | |
152 * The current comment. | |
153 * | |
154 * @return string | |
155 * The translated comment subject. | |
156 */ | |
157 public function commentPermalinkTitle(CommentInterface $comment) { | |
158 return $this->entityManager()->getTranslationFromContext($comment)->label(); | |
159 } | |
160 | |
161 /** | |
162 * Redirects legacy node links to the new path. | |
163 * | |
164 * @param \Drupal\Core\Entity\EntityInterface $node | |
165 * The node object identified by the legacy URL. | |
166 * | |
167 * @return \Symfony\Component\HttpFoundation\RedirectResponse | |
168 * Redirects user to new url. | |
169 * | |
170 * @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException | |
171 */ | |
172 public function redirectNode(EntityInterface $node) { | |
173 $fields = $this->commentManager->getFields('node'); | |
174 // Legacy nodes only had a single comment field, so use the first comment | |
175 // field on the entity. | |
176 if (!empty($fields) && ($field_names = array_keys($fields)) && ($field_name = reset($field_names))) { | |
177 return $this->redirect('comment.reply', [ | |
178 'entity_type' => 'node', | |
179 'entity' => $node->id(), | |
180 'field_name' => $field_name, | |
181 ]); | |
182 } | |
183 throw new NotFoundHttpException(); | |
184 } | |
185 | |
186 /** | |
187 * Form constructor for the comment reply form. | |
188 * | |
189 * There are several cases that have to be handled, including: | |
190 * - replies to comments | |
191 * - replies to entities | |
192 * | |
193 * @param \Symfony\Component\HttpFoundation\Request $request | |
194 * The current request object. | |
195 * @param \Drupal\Core\Entity\EntityInterface $entity | |
196 * The entity this comment belongs to. | |
197 * @param string $field_name | |
198 * The field_name to which the comment belongs. | |
199 * @param int $pid | |
200 * (optional) Some comments are replies to other comments. In those cases, | |
201 * $pid is the parent comment's comment ID. Defaults to NULL. | |
202 * | |
203 * @return array|\Symfony\Component\HttpFoundation\RedirectResponse | |
204 * An associative array containing: | |
205 * - An array for rendering the entity or parent comment. | |
206 * - comment_entity: If the comment is a reply to the entity. | |
207 * - comment_parent: If the comment is a reply to another comment. | |
208 * - comment_form: The comment form as a renderable array. | |
209 * | |
210 * @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException | |
211 */ | |
212 public function getReplyForm(Request $request, EntityInterface $entity, $field_name, $pid = NULL) { | |
213 $account = $this->currentUser(); | |
214 $build = []; | |
215 | |
216 // The user is not just previewing a comment. | |
217 if ($request->request->get('op') != $this->t('Preview')) { | |
218 | |
219 // $pid indicates that this is a reply to a comment. | |
220 if ($pid) { | |
221 // Load the parent comment. | |
222 $comment = $this->entityManager()->getStorage('comment')->load($pid); | |
223 // Display the parent comment. | |
224 $build['comment_parent'] = $this->entityManager()->getViewBuilder('comment')->view($comment); | |
225 } | |
226 | |
227 // The comment is in response to a entity. | |
228 elseif ($entity->access('view', $account)) { | |
229 // We make sure the field value isn't set so we don't end up with a | |
230 // redirect loop. | |
231 $entity = clone $entity; | |
232 $entity->{$field_name}->status = CommentItemInterface::HIDDEN; | |
233 // Render array of the entity full view mode. | |
234 $build['commented_entity'] = $this->entityManager()->getViewBuilder($entity->getEntityTypeId())->view($entity, 'full'); | |
235 unset($build['commented_entity']['#cache']); | |
236 } | |
237 } | |
238 else { | |
239 $build['#title'] = $this->t('Preview comment'); | |
240 } | |
241 | |
242 // Show the actual reply box. | |
243 $comment = $this->entityManager()->getStorage('comment')->create([ | |
244 'entity_id' => $entity->id(), | |
245 'pid' => $pid, | |
246 'entity_type' => $entity->getEntityTypeId(), | |
247 'field_name' => $field_name, | |
248 ]); | |
249 $build['comment_form'] = $this->entityFormBuilder()->getForm($comment); | |
250 | |
251 return $build; | |
252 } | |
253 | |
254 /** | |
255 * Access check for the reply form. | |
256 * | |
257 * @param \Drupal\Core\Entity\EntityInterface $entity | |
258 * The entity this comment belongs to. | |
259 * @param string $field_name | |
260 * The field_name to which the comment belongs. | |
261 * @param int $pid | |
262 * (optional) Some comments are replies to other comments. In those cases, | |
263 * $pid is the parent comment's comment ID. Defaults to NULL. | |
264 * | |
265 * @return \Drupal\Core\Access\AccessResultInterface | |
266 * An access result | |
267 * | |
268 * @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException | |
269 */ | |
270 public function replyFormAccess(EntityInterface $entity, $field_name, $pid = NULL) { | |
271 // Check if entity and field exists. | |
272 $fields = $this->commentManager->getFields($entity->getEntityTypeId()); | |
273 if (empty($fields[$field_name])) { | |
274 throw new NotFoundHttpException(); | |
275 } | |
276 | |
277 $account = $this->currentUser(); | |
278 | |
279 // Check if the user has the proper permissions. | |
280 $access = AccessResult::allowedIfHasPermission($account, 'post comments'); | |
281 | |
282 $status = $entity->{$field_name}->status; | |
283 $access = $access->andIf(AccessResult::allowedIf($status == CommentItemInterface::OPEN) | |
284 ->addCacheableDependency($entity)); | |
285 | |
286 // $pid indicates that this is a reply to a comment. | |
287 if ($pid) { | |
288 // Check if the user has the proper permissions. | |
289 $access = $access->andIf(AccessResult::allowedIfHasPermission($account, 'access comments')); | |
290 | |
291 // Load the parent comment. | |
292 $comment = $this->entityManager()->getStorage('comment')->load($pid); | |
293 // Check if the parent comment is published and belongs to the entity. | |
294 $access = $access->andIf(AccessResult::allowedIf($comment && $comment->isPublished() && $comment->getCommentedEntityId() == $entity->id())); | |
295 if ($comment) { | |
296 $access->addCacheableDependency($comment); | |
297 } | |
298 } | |
299 return $access; | |
300 } | |
301 | |
302 /** | |
303 * Returns a set of nodes' last read timestamps. | |
304 * | |
305 * @param \Symfony\Component\HttpFoundation\Request $request | |
306 * The request of the page. | |
307 * | |
308 * @return \Symfony\Component\HttpFoundation\JsonResponse | |
309 * The JSON response. | |
310 * | |
311 * @throws \Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException | |
312 * @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException | |
313 */ | |
314 public function renderNewCommentsNodeLinks(Request $request) { | |
315 if ($this->currentUser()->isAnonymous()) { | |
316 throw new AccessDeniedHttpException(); | |
317 } | |
318 | |
319 $nids = $request->request->get('node_ids'); | |
320 $field_name = $request->request->get('field_name'); | |
321 if (!isset($nids)) { | |
322 throw new NotFoundHttpException(); | |
323 } | |
324 // Only handle up to 100 nodes. | |
325 $nids = array_slice($nids, 0, 100); | |
326 | |
327 $links = []; | |
328 foreach ($nids as $nid) { | |
329 $node = $this->entityManager->getStorage('node')->load($nid); | |
330 $new = $this->commentManager->getCountNewComments($node); | |
331 $page_number = $this->entityManager()->getStorage('comment') | |
332 ->getNewCommentPageNumber($node->{$field_name}->comment_count, $new, $node, $field_name); | |
333 $query = $page_number ? ['page' => $page_number] : NULL; | |
334 $links[$nid] = [ | |
335 'new_comment_count' => (int) $new, | |
336 'first_new_comment_link' => $this->getUrlGenerator()->generateFromRoute('entity.node.canonical', ['node' => $node->id()], ['query' => $query, 'fragment' => 'new']), | |
337 ]; | |
338 } | |
339 | |
340 return new JsonResponse($links); | |
341 } | |
342 | |
343 } |