Version 1
[yaffs-website] / web / core / modules / forum / src / Controller / ForumController.php
1 <?php
2
3 namespace Drupal\forum\Controller;
4
5 use Drupal\Core\Cache\Cache;
6 use Drupal\Core\Controller\ControllerBase;
7 use Drupal\Core\Entity\EntityAccessControlHandlerInterface;
8 use Drupal\Core\Entity\EntityStorageInterface;
9 use Drupal\Core\Entity\EntityTypeInterface;
10 use Drupal\Core\Render\RendererInterface;
11 use Drupal\Core\Session\AccountInterface;
12 use Drupal\Core\Url;
13 use Drupal\forum\ForumManagerInterface;
14 use Drupal\taxonomy\TermInterface;
15 use Drupal\taxonomy\TermStorageInterface;
16 use Drupal\taxonomy\VocabularyStorageInterface;
17 use Symfony\Component\DependencyInjection\ContainerInterface;
18
19 /**
20  * Controller routines for forum routes.
21  */
22 class ForumController extends ControllerBase {
23
24   /**
25    * Forum manager service.
26    *
27    * @var \Drupal\forum\ForumManagerInterface
28    */
29   protected $forumManager;
30
31   /**
32    * Vocabulary storage.
33    *
34    * @var \Drupal\taxonomy\VocabularyStorageInterface
35    */
36   protected $vocabularyStorage;
37
38   /**
39    * Term storage.
40    *
41    * @var \Drupal\taxonomy\TermStorageInterface
42    */
43   protected $termStorage;
44
45   /**
46    * Node access control handler.
47    *
48    * @var \Drupal\Core\Entity\EntityAccessControlHandlerInterface
49    */
50   protected $nodeAccess;
51
52   /**
53    * Field map of existing fields on the site.
54    *
55    * @var array
56    */
57   protected $fieldMap;
58
59   /**
60    * Node type storage handler.
61    *
62    * @var \Drupal\Core\Entity\EntityStorageInterface
63    */
64   protected $nodeTypeStorage;
65
66   /**
67    * The renderer.
68    *
69    * @var \Drupal\Core\Render\RendererInterface
70    */
71   protected $renderer;
72
73   /**
74    * Node entity type, we need to get cache tags from here.
75    *
76    * @var \Drupal\Core\Entity\EntityTypeInterface
77    */
78   protected $nodeEntityTypeDefinition;
79
80   /**
81    * Comment entity type, we need to get cache tags from here.
82    *
83    * @var \Drupal\Core\Entity\EntityTypeInterface
84    */
85   protected $commentEntityTypeDefinition;
86
87   /**
88    * Constructs a ForumController object.
89    *
90    * @param \Drupal\forum\ForumManagerInterface $forum_manager
91    *   The forum manager service.
92    * @param \Drupal\taxonomy\VocabularyStorageInterface $vocabulary_storage
93    *   Vocabulary storage.
94    * @param \Drupal\taxonomy\TermStorageInterface $term_storage
95    *   Term storage.
96    * @param \Drupal\Core\Session\AccountInterface $current_user
97    *   The current logged in user.
98    * @param \Drupal\Core\Entity\EntityAccessControlHandlerInterface $node_access
99    *   Node access control handler.
100    * @param array $field_map
101    *   Array of active fields on the site.
102    * @param \Drupal\Core\Entity\EntityStorageInterface $node_type_storage
103    *   Node type storage handler.
104    * @param \Drupal\Core\Render\RendererInterface $renderer
105    *   The renderer.
106    * @param \Drupal\Core\Entity\EntityTypeInterface $node_entity_type_definition
107    *   Node entity type definition object
108    * @param \Drupal\Core\Entity\EntityTypeInterface $comment_entity_type_definition
109    *   Comment entity type definition object
110    */
111   public function __construct(ForumManagerInterface $forum_manager, VocabularyStorageInterface $vocabulary_storage, TermStorageInterface $term_storage, AccountInterface $current_user, EntityAccessControlHandlerInterface $node_access, array $field_map, EntityStorageInterface $node_type_storage, RendererInterface $renderer, EntityTypeInterface $node_entity_type_definition, EntityTypeInterface $comment_entity_type_definition) {
112     $this->forumManager = $forum_manager;
113     $this->vocabularyStorage = $vocabulary_storage;
114     $this->termStorage = $term_storage;
115     $this->currentUser = $current_user;
116     $this->nodeAccess = $node_access;
117     $this->fieldMap = $field_map;
118     $this->nodeTypeStorage = $node_type_storage;
119     $this->renderer = $renderer;
120     $this->nodeEntityTypeDefinition = $node_entity_type_definition;
121     $this->commentEntityTypeDefinition = $comment_entity_type_definition;
122   }
123
124   /**
125    * {@inheritdoc}
126    */
127   public static function create(ContainerInterface $container) {
128     /** @var \Drupal\Core\Entity\EntityManagerInterface $entity_manager */
129     $entity_manager = $container->get('entity.manager');
130
131     return new static(
132       $container->get('forum_manager'),
133       $entity_manager->getStorage('taxonomy_vocabulary'),
134       $entity_manager->getStorage('taxonomy_term'),
135       $container->get('current_user'),
136       $entity_manager->getAccessControlHandler('node'),
137       $entity_manager->getFieldMap(),
138       $entity_manager->getStorage('node_type'),
139       $container->get('renderer'),
140       $entity_manager->getDefinition('node'),
141       $entity_manager->getDefinition('comment')
142     );
143   }
144
145   /**
146    * Returns forum page for a given forum.
147    *
148    * @param \Drupal\taxonomy\TermInterface $taxonomy_term
149    *   The forum to render the page for.
150    *
151    * @return array
152    *   A render array.
153    */
154   public function forumPage(TermInterface $taxonomy_term) {
155     // Get forum details.
156     $taxonomy_term->forums = $this->forumManager->getChildren($this->config('forum.settings')->get('vocabulary'), $taxonomy_term->id());
157     $taxonomy_term->parents = $this->forumManager->getParents($taxonomy_term->id());
158
159     if (empty($taxonomy_term->forum_container->value)) {
160       $build = $this->forumManager->getTopics($taxonomy_term->id(), $this->currentUser());
161       $topics = $build['topics'];
162       $header = $build['header'];
163     }
164     else {
165       $topics = [];
166       $header = [];
167     }
168     return $this->build($taxonomy_term->forums, $taxonomy_term, $topics, $taxonomy_term->parents, $header);
169   }
170
171   /**
172    * Returns forum index page.
173    *
174    * @return array
175    *   A render array.
176    */
177   public function forumIndex() {
178     $vocabulary = $this->vocabularyStorage->load($this->config('forum.settings')->get('vocabulary'));
179     $index = $this->forumManager->getIndex();
180     $build = $this->build($index->forums, $index);
181     if (empty($index->forums)) {
182       // Root of empty forum.
183       $build['#title'] = $this->t('No forums defined');
184     }
185     else {
186       // Set the page title to forum's vocabulary name.
187       $build['#title'] = $vocabulary->label();
188       $this->renderer->addCacheableDependency($build, $vocabulary);
189     }
190     return $build;
191   }
192
193   /**
194    * Returns a renderable forum index page array.
195    *
196    * @param array $forums
197    *   A list of forums.
198    * @param \Drupal\taxonomy\TermInterface $term
199    *   The taxonomy term of the forum.
200    * @param array $topics
201    *   The topics of this forum.
202    * @param array $parents
203    *   The parent forums in relation this forum.
204    * @param array $header
205    *   Array of header cells.
206    *
207    * @return array
208    *   A render array.
209    */
210   protected function build($forums, TermInterface $term, $topics = [], $parents = [], $header = []) {
211     $config = $this->config('forum.settings');
212     $build = [
213       '#theme' => 'forums',
214       '#forums' => $forums,
215       '#topics' => $topics,
216       '#parents' => $parents,
217       '#header' => $header,
218       '#term' => $term,
219       '#sortby' => $config->get('topics.order'),
220       '#forums_per_page' => $config->get('topics.page_limit'),
221     ];
222     if (empty($term->forum_container->value)) {
223       $build['#attached']['feed'][] = ['taxonomy/term/' . $term->id() . '/feed', 'RSS - ' . $term->getName()];
224     }
225     $this->renderer->addCacheableDependency($build, $config);
226
227     foreach ($forums as $forum) {
228       $this->renderer->addCacheableDependency($build, $forum);
229     }
230     foreach ($topics as $topic) {
231       $this->renderer->addCacheableDependency($build, $topic);
232     }
233     foreach ($parents as $parent) {
234       $this->renderer->addCacheableDependency($build, $parent);
235     }
236     $this->renderer->addCacheableDependency($build, $term);
237
238     return [
239       'action' => $this->buildActionLinks($config->get('vocabulary'), $term),
240       'forum' => $build,
241       '#cache' => [
242         'tags' => Cache::mergeTags($this->nodeEntityTypeDefinition->getListCacheTags(), $this->commentEntityTypeDefinition->getListCacheTags()),
243       ],
244     ];
245   }
246
247   /**
248    * Returns add forum entity form.
249    *
250    * @return array
251    *   Render array for the add form.
252    */
253   public function addForum() {
254     $vid = $this->config('forum.settings')->get('vocabulary');
255     $taxonomy_term = $this->termStorage->create([
256       'vid' => $vid,
257       'forum_controller' => 0,
258     ]);
259     return $this->entityFormBuilder()->getForm($taxonomy_term, 'forum');
260   }
261
262   /**
263    * Returns add container entity form.
264    *
265    * @return array
266    *   Render array for the add form.
267    */
268   public function addContainer() {
269     $vid = $this->config('forum.settings')->get('vocabulary');
270     $taxonomy_term = $this->termStorage->create([
271       'vid' => $vid,
272       'forum_container' => 1,
273     ]);
274     return $this->entityFormBuilder()->getForm($taxonomy_term, 'container');
275   }
276
277   /**
278    * Generates an action link to display at the top of the forum listing.
279    *
280    * @param string $vid
281    *   Vocabulary ID.
282    * @param \Drupal\taxonomy\TermInterface $forum_term
283    *   The term for which the links are to be built.
284    *
285    * @return array
286    *   Render array containing the links.
287    */
288   protected function buildActionLinks($vid, TermInterface $forum_term = NULL) {
289     $user = $this->currentUser();
290
291     $links = [];
292     // Loop through all bundles for forum taxonomy vocabulary field.
293     foreach ($this->fieldMap['node']['taxonomy_forums']['bundles'] as $type) {
294       if ($this->nodeAccess->createAccess($type)) {
295         $node_type = $this->nodeTypeStorage->load($type);
296         $links[$type] = [
297           '#attributes' => ['class' => ['action-links']],
298           '#theme' => 'menu_local_action',
299           '#link' => [
300             'title' => $this->t('Add new @node_type', [
301               '@node_type' => $this->nodeTypeStorage->load($type)->label(),
302             ]),
303             'url' => Url::fromRoute('node.add', ['node_type' => $type]),
304           ],
305           '#cache' => [
306             'tags' => $node_type->getCacheTags(),
307           ],
308         ];
309         if ($forum_term && $forum_term->bundle() == $vid) {
310           // We are viewing a forum term (specific forum), append the tid to
311           // the url.
312           $links[$type]['#link']['localized_options']['query']['forum_id'] = $forum_term->id();
313         }
314       }
315     }
316     if (empty($links)) {
317       // Authenticated user does not have access to create new topics.
318       if ($user->isAuthenticated()) {
319         $links['disallowed'] = [
320           '#markup' => $this->t('You are not allowed to post new content in the forum.'),
321         ];
322       }
323       // Anonymous user does not have access to create new topics.
324       else {
325         $links['login'] = [
326           '#attributes' => ['class' => ['action-links']],
327           '#theme' => 'menu_local_action',
328           '#link' => [
329             'title' => $this->t('Log in to post new content in the forum.'),
330             'url' => Url::fromRoute('user.login', [], ['query' => $this->getDestinationArray()]),
331           ],
332         ];
333       }
334     }
335     return $links;
336   }
337
338 }