diff --git a/core/modules/forum/css/forum.module.css b/core/modules/forum/css/forum.module.css index 6334ae31988..e7490f2a059 100644 --- a/core/modules/forum/css/forum.module.css +++ b/core/modules/forum/css/forum.module.css @@ -65,3 +65,6 @@ text-align: right; float: left; } +.action--forum { + list-style: none; +} diff --git a/core/modules/forum/forum.module b/core/modules/forum/forum.module index 6b99955acf6..d4be4f5547a 100644 --- a/core/modules/forum/forum.module +++ b/core/modules/forum/forum.module @@ -99,38 +99,6 @@ function forum_theme() { ); } -/** - * Implements hook_menu_local_tasks(). - */ -function forum_menu_local_tasks(&$data, $route_name) { - // Add action link to 'node/add/forum' on 'forum' sub-pages. - if (in_array($route_name, array('forum.index', 'forum.page'))) { - $forum_term = \Drupal::routeMatch()->getParameter('taxonomy_term'); - $vid = \Drupal::config('forum.settings')->get('vocabulary'); - $links = array(); - // Loop through all bundles for forum taxonomy vocabulary field. - $field_map = \Drupal::entityManager()->getFieldMap(); - foreach ($field_map['node']['taxonomy_forums']['bundles'] as $type) { - if (\Drupal::entityManager()->getAccessControlHandler('node')->createAccess($type)) { - $links[$type] = array( - '#theme' => 'menu_local_action', - '#link' => array( - 'title' => t('Add new @node_type', array('@node_type' => entity_load('node_type', $type)->label())), - 'url' => Url::fromRoute('node.add', ['node_type' => $type]), - ), - ); - if ($forum_term && $forum_term->bundle() == $vid) { - // We are viewing a forum term (specific forum), append the tid to the - // url. - $links[$type]['#link']['localized_options']['query']['forum_id'] = $forum_term->id(); - } - } - } - $data['actions'] += $links; - } - // @todo Bring back functionality in https://www.drupal.org/node/1853072. -} - /** * Implements hook_entity_type_build(). */ diff --git a/core/modules/forum/src/Controller/ForumController.php b/core/modules/forum/src/Controller/ForumController.php index 2ca2e8eb5bc..951e254861a 100644 --- a/core/modules/forum/src/Controller/ForumController.php +++ b/core/modules/forum/src/Controller/ForumController.php @@ -8,6 +8,10 @@ namespace Drupal\forum\Controller; use Drupal\Core\Controller\ControllerBase; +use Drupal\Core\Entity\EntityAccessControlHandlerInterface; +use Drupal\Core\Entity\EntityStorageInterface; +use Drupal\Core\Session\AccountInterface; +use Drupal\Core\Url; use Drupal\forum\ForumManagerInterface; use Drupal\taxonomy\TermInterface; use Drupal\taxonomy\TermStorageInterface; @@ -40,6 +44,27 @@ class ForumController extends ControllerBase { */ protected $termStorage; + /** + * Node access control handler. + * + * @var \Drupal\Core\Entity\EntityAccessControlHandlerInterface + */ + protected $nodeAccess; + + /** + * Field map of existing fields on the site. + * + * @var array + */ + protected $fieldMap; + + /** + * Node type storage handler. + * + * @var \Drupal\Core\Entity\EntityStorageInterface + */ + protected $nodeTypeStorage; + /** * Constructs a ForumController object. * @@ -49,21 +74,39 @@ class ForumController extends ControllerBase { * Vocabulary storage. * @param \Drupal\taxonomy\TermStorageInterface $term_storage * Term storage. + * @param \Drupal\Core\Session\AccountInterface $current_user + * The current logged in user. + * @param \Drupal\Core\Entity\EntityAccessControlHandlerInterface $node_access + * Node access control handler. + * @param array $field_map + * Array of active fields on the site. + * @param \Drupal\Core\Entity\EntityStorageInterface $node_type_storage + * Node type storage handler. */ - public function __construct(ForumManagerInterface $forum_manager, VocabularyStorageInterface $vocabulary_storage, TermStorageInterface $term_storage) { + 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) { $this->forumManager = $forum_manager; $this->vocabularyStorage = $vocabulary_storage; $this->termStorage = $term_storage; + $this->currentUser = $current_user; + $this->nodeAccess = $node_access; + $this->fieldMap = $field_map; + $this->nodeTypeStorage = $node_type_storage; } /** * {@inheritdoc} */ public static function create(ContainerInterface $container) { + /** @var \Drupal\Core\Entity\EntityManagerInterface $entity_manager */ + $entity_manager = $container->get('entity.manager'); return new static( $container->get('forum_manager'), - $container->get('entity.manager')->getStorage('taxonomy_vocabulary'), - $container->get('entity.manager')->getStorage('taxonomy_term') + $entity_manager->getStorage('taxonomy_vocabulary'), + $entity_manager->getStorage('taxonomy_term'), + $container->get('current_user'), + $entity_manager->getAccessControlHandler('node'), + $entity_manager->getFieldMap(), + $entity_manager->getStorage('node_type') ); } @@ -148,7 +191,10 @@ class ForumController extends ControllerBase { $build['#attached']['feed'][] = array('taxonomy/term/' . $term->id() . '/feed', 'RSS - ' . $term->getName()); } - return $build; + return [ + 'action' => $this->buildActionLinks($config->get('vocabulary'), $term), + 'forum' => $build, + ]; } /** @@ -181,4 +227,68 @@ class ForumController extends ControllerBase { return $this->entityFormBuilder()->getForm($taxonomy_term, 'container'); } + /** + * Generates an action link to display at the top of the forum listing. + * + * @param string $vid + * Vocabulary ID. + * @param \Drupal\taxonomy\TermInterface $forum_term + * The term for which the links are to be built. + * + * @return array + * Render array containing the links. + */ + protected function buildActionLinks($vid, TermInterface $forum_term = NULL) { + $user = $this->currentUser(); + + $links = []; + // Loop through all bundles for forum taxonomy vocabulary field. + foreach ($this->fieldMap['node']['taxonomy_forums']['bundles'] as $type) { + if ($this->nodeAccess->createAccess($type)) { + $links[$type] = [ + '#attributes' => ['class' => ['action--forum']], + '#theme' => 'menu_local_action', + '#link' => [ + 'title' => $this->t('Add new @node_type', [ + '@node_type' => $this->nodeTypeStorage->load($type)->label(), + ]), + 'url' => Url::fromRoute('node.add', ['node_type' => $type]), + ], + ]; + if ($forum_term && $forum_term->bundle() == $vid) { + // We are viewing a forum term (specific forum), append the tid to + // the url. + $links[$type]['#link']['localized_options']['query']['forum_id'] = $forum_term->id(); + } + } + } + if (empty($links)) { + // Authenticated user does not have access to create new topics. + if ($user->isAuthenticated()) { + $links['disallowed'] = [ + '#markup' => $this->t('You are not allowed to post new content in the forum.'), + ]; + } + // Anonymous user does not have access to create new topics. + else { + $links['login'] = [ + '#attributes' => ['class' => ['action--forum']], + '#theme' => 'menu_local_action', + '#link' => array( + 'title' => $this->t('Log in to post new content in the forum.'), + 'url' => Url::fromRoute('user.login', [], ['query' => $this->getDestination()]), + ), + ]; + } + } + return $links; + } + + /** + * Wraps drupal_get_destination(). + */ + protected function getDestination() { + return drupal_get_destination(); + } + } diff --git a/core/modules/forum/src/Tests/ForumTest.php b/core/modules/forum/src/Tests/ForumTest.php index 8ebdb81a451..95c61ed149f 100644 --- a/core/modules/forum/src/Tests/ForumTest.php +++ b/core/modules/forum/src/Tests/ForumTest.php @@ -121,9 +121,7 @@ class ForumTest extends WebTestBase { $this->drupalLogin($this->web_user); // Verify that this user is shown a message that they may not post content. $this->drupalGet('forum/' . $this->forum['tid']); - // @todo Restore test coverage in https://www.drupal.org/node/1853072. - //$this->assertText(t('You are not allowed to post new content in the forum'), "Authenticated user without permission to post forum content is shown message in local tasks to that effect."); - + $this->assertText(t('You are not allowed to post new content in the forum'), "Authenticated user without permission to post forum content is shown message in local tasks to that effect."); // Log in, and do basic tests for a user with permission to edit any forum // content.