3 namespace Drupal\forum\Controller;
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;
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;
20 * Controller routines for forum routes.
22 class ForumController extends ControllerBase {
25 * Forum manager service.
27 * @var \Drupal\forum\ForumManagerInterface
29 protected $forumManager;
34 * @var \Drupal\taxonomy\VocabularyStorageInterface
36 protected $vocabularyStorage;
41 * @var \Drupal\taxonomy\TermStorageInterface
43 protected $termStorage;
46 * Node access control handler.
48 * @var \Drupal\Core\Entity\EntityAccessControlHandlerInterface
50 protected $nodeAccess;
53 * Field map of existing fields on the site.
60 * Node type storage handler.
62 * @var \Drupal\Core\Entity\EntityStorageInterface
64 protected $nodeTypeStorage;
69 * @var \Drupal\Core\Render\RendererInterface
74 * Node entity type, we need to get cache tags from here.
76 * @var \Drupal\Core\Entity\EntityTypeInterface
78 protected $nodeEntityTypeDefinition;
81 * Comment entity type, we need to get cache tags from here.
83 * @var \Drupal\Core\Entity\EntityTypeInterface
85 protected $commentEntityTypeDefinition;
88 * Constructs a ForumController object.
90 * @param \Drupal\forum\ForumManagerInterface $forum_manager
91 * The forum manager service.
92 * @param \Drupal\taxonomy\VocabularyStorageInterface $vocabulary_storage
94 * @param \Drupal\taxonomy\TermStorageInterface $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
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
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;
127 public static function create(ContainerInterface $container) {
128 /** @var \Drupal\Core\Entity\EntityManagerInterface $entity_manager */
129 $entity_manager = $container->get('entity.manager');
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')
146 * Returns forum page for a given forum.
148 * @param \Drupal\taxonomy\TermInterface $taxonomy_term
149 * The forum to render the page for.
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());
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'];
168 return $this->build($taxonomy_term->forums, $taxonomy_term, $topics, $taxonomy_term->parents, $header);
172 * Returns forum index page.
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');
186 // Set the page title to forum's vocabulary name.
187 $build['#title'] = $vocabulary->label();
188 $this->renderer->addCacheableDependency($build, $vocabulary);
194 * Returns a renderable forum index page array.
196 * @param array $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.
210 protected function build($forums, TermInterface $term, $topics = [], $parents = [], $header = []) {
211 $config = $this->config('forum.settings');
213 '#theme' => 'forums',
214 '#forums' => $forums,
215 '#topics' => $topics,
216 '#parents' => $parents,
217 '#header' => $header,
219 '#sortby' => $config->get('topics.order'),
220 '#forums_per_page' => $config->get('topics.page_limit'),
222 if (empty($term->forum_container->value)) {
223 $build['#attached']['feed'][] = ['taxonomy/term/' . $term->id() . '/feed', 'RSS - ' . $term->getName()];
225 $this->renderer->addCacheableDependency($build, $config);
227 foreach ($forums as $forum) {
228 $this->renderer->addCacheableDependency($build, $forum);
230 foreach ($topics as $topic) {
231 $this->renderer->addCacheableDependency($build, $topic);
233 foreach ($parents as $parent) {
234 $this->renderer->addCacheableDependency($build, $parent);
236 $this->renderer->addCacheableDependency($build, $term);
239 'action' => $this->buildActionLinks($config->get('vocabulary'), $term),
242 'tags' => Cache::mergeTags($this->nodeEntityTypeDefinition->getListCacheTags(), $this->commentEntityTypeDefinition->getListCacheTags()),
248 * Returns add forum entity form.
251 * Render array for the add form.
253 public function addForum() {
254 $vid = $this->config('forum.settings')->get('vocabulary');
255 $taxonomy_term = $this->termStorage->create([
257 'forum_controller' => 0,
259 return $this->entityFormBuilder()->getForm($taxonomy_term, 'forum');
263 * Returns add container entity form.
266 * Render array for the add form.
268 public function addContainer() {
269 $vid = $this->config('forum.settings')->get('vocabulary');
270 $taxonomy_term = $this->termStorage->create([
272 'forum_container' => 1,
274 return $this->entityFormBuilder()->getForm($taxonomy_term, 'container');
278 * Generates an action link to display at the top of the forum listing.
282 * @param \Drupal\taxonomy\TermInterface $forum_term
283 * The term for which the links are to be built.
286 * Render array containing the links.
288 protected function buildActionLinks($vid, TermInterface $forum_term = NULL) {
289 $user = $this->currentUser();
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);
297 '#attributes' => ['class' => ['action-links']],
298 '#theme' => 'menu_local_action',
300 'title' => $this->t('Add new @node_type', [
301 '@node_type' => $this->nodeTypeStorage->load($type)->label(),
303 'url' => Url::fromRoute('node.add', ['node_type' => $type]),
306 'tags' => $node_type->getCacheTags(),
309 if ($forum_term && $forum_term->bundle() == $vid) {
310 // We are viewing a forum term (specific forum), append the tid to
312 $links[$type]['#link']['localized_options']['query']['forum_id'] = $forum_term->id();
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.'),
323 // Anonymous user does not have access to create new topics.
326 '#attributes' => ['class' => ['action-links']],
327 '#theme' => 'menu_local_action',
329 'title' => $this->t('Log in to post new content in the forum.'),
330 'url' => Url::fromRoute('user.login', [], ['query' => $this->getDestinationArray()]),