diff --git a/core/modules/forum/forum.module b/core/modules/forum/forum.module index c047865..4c03884 100644 --- a/core/modules/forum/forum.module +++ b/core/modules/forum/forum.module @@ -166,21 +166,25 @@ function forum_menu_local_tasks(&$data, $router_item, $root_path) { // Add action link to 'node/add/forum' on 'forum' sub-pages. if ($root_path == 'forum' || $root_path == 'forum/%') { - $tid = (isset($router_item['page_arguments'][0]) ? $router_item['page_arguments'][0]->id() : 0); - $forum_term = forum_forum_load($tid); - if ($forum_term) { - $links = array(); - // Loop through all bundles for forum taxonomy vocabulary field. - $field = field_info_field('taxonomy_forums'); - foreach ($field['bundles']['node'] as $type) { - if (node_access('create', $type)) { - $links[$type] = array( - '#theme' => 'menu_local_action', - '#link' => array( - 'title' => t('Add new @node_type', array('@node_type' => node_type_get_label($type))), - 'href' => 'node/add/' . $type . '/' . $forum_term->id(), - ), - ); + $request = Drupal::request(); + $forum_term = $request->attributes->get('taxonomy_term'); + $vid = config('forum.settings')->get('vocabulary'); + $links = array(); + // Loop through all bundles for forum taxonomy vocabulary field. + $field = field_info_field('taxonomy_forums'); + foreach ($field['bundles']['node'] as $type) { + if (node_access('create', $type)) { + $links[$type] = array( + '#theme' => 'menu_local_action', + '#link' => array( + 'title' => t('Add new @node_type', array('@node_type' => node_type_get_label($type))), + 'href' => 'node/add/' . $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']['href'] .= '/' . $forum_term->id(); } } } @@ -236,7 +240,7 @@ function forum_entity_bundle_info_alter(&$bundles) { } /** - * Entity URI callback used in forum_entity_info_alter(). + * Entity URI callback used in forum_entity_bundle_info_alter(). */ function forum_uri($forum) { return array( @@ -283,6 +287,29 @@ function forum_node_view(EntityInterface $node, EntityDisplay $display, $view_mo } /** + * Implements hook_taxonomy_term_load(). + * + * @param array $entities + * An array of taxonomy term entities, indexed by tid. + */ +function forum_taxonomy_term_load(array $entities) { + $config = config('forum.settings'); + $vid = $config->get('vocabulary'); + foreach ($entities as $tid => &$forum_term) { + if ($forum_term->bundle() != $vid) { + // Not a forum term. + continue; + } + + // Determine if the requested term is a container. + if (in_array($forum_term->id(), $config->get('containers'))) { + $forum_term->container = TRUE; + } + } + return $entities; +} + +/** * Implements hook_node_validate(). * * Checks in particular that the node is assigned only a "leaf" term in the @@ -716,147 +743,6 @@ function _forum_topics_unread($term, $uid) { } /** - * Gets all the topics in a forum. - * - * @param $tid - * The term ID of the forum. - * @param $sortby - * One of the following integers indicating the sort criteria: - * - 1: Date - newest first. - * - 2: Date - oldest first. - * - 3: Posts with the most comments first. - * - 4: Posts with the least comments first. - * @param $forum_per_page - * The maximum number of topics to display per page. - * - * @return - * A list of all the topics in a forum. - */ -function forum_get_topics($tid, $sortby, $forum_per_page) { - global $user, $forum_topic_list_header; - - $forum_topic_list_header = array( - array('data' => t('Topic'), 'field' => 'f.title'), - array('data' => t('Replies'), 'field' => 'f.comment_count'), - array('data' => t('Last reply'), 'field' => 'f.last_comment_timestamp'), - ); - - $order = _forum_get_topic_order($sortby); - for ($i = 0; $i < count($forum_topic_list_header); $i++) { - if ($forum_topic_list_header[$i]['field'] == $order['field']) { - $forum_topic_list_header[$i]['sort'] = $order['sort']; - } - } - - $query = db_select('forum_index', 'f') - ->extend('Drupal\Core\Database\Query\PagerSelectExtender') - ->extend('Drupal\Core\Database\Query\TableSortExtender'); - $query->fields('f'); - $query - ->condition('f.tid', $tid) - ->addTag('node_access') - ->addMetaData('base_table', 'forum_index') - ->orderBy('f.sticky', 'DESC') - ->orderByHeader($forum_topic_list_header) - ->limit($forum_per_page); - - $count_query = db_select('forum_index', 'f'); - $count_query->condition('f.tid', $tid); - $count_query->addExpression('COUNT(*)'); - $count_query->addTag('node_access'); - $count_query->addMetaData('base_table', 'forum_index'); - - $query->setCountQuery($count_query); - $result = $query->execute(); - $nids = array(); - foreach ($result as $record) { - $nids[] = $record->nid; - } - if ($nids) { - $nodes = node_load_multiple($nids); - - $query = db_select('node_field_data', 'n') - ->extend('Drupal\Core\Database\Query\TableSortExtender'); - $query->fields('n', array('nid')); - - $query->join('node_comment_statistics', 'ncs', 'n.nid = ncs.nid'); - $query->fields('ncs', array('cid', 'last_comment_uid', 'last_comment_timestamp', 'comment_count')); - - $query->join('forum_index', 'f', 'f.nid = ncs.nid'); - $query->addField('f', 'tid', 'forum_tid'); - - $query->join('users', 'u', 'n.uid = u.uid'); - $query->addField('u', 'name'); - - $query->join('users', 'u2', 'ncs.last_comment_uid = u2.uid'); - - $query->addExpression('CASE ncs.last_comment_uid WHEN 0 THEN ncs.last_comment_name ELSE u2.name END', 'last_comment_name'); - - $query - ->orderBy('f.sticky', 'DESC') - ->orderByHeader($forum_topic_list_header) - ->condition('n.nid', $nids) - // @todo This should be actually filtering on the desired node language - // and just fall back to the default language. - ->condition('n.default_langcode', 1); - - $result = array(); - foreach ($query->execute() as $row) { - $topic = $nodes[$row->nid]; - $topic->comment_mode = $topic->comment; - - foreach ($row as $key => $value) { - $topic->{$key} = $value; - } - $result[] = $topic; - } - } - else { - $result = array(); - } - - $topics = array(); - $first_new_found = FALSE; - foreach ($result as $topic) { - if ($user->uid) { - // A forum is new if the topic is new, or if there are new comments since - // the user's last visit. - if ($topic->forum_tid != $tid) { - $topic->new = 0; - } - else { - $history = _forum_user_last_visit($topic->nid); - $topic->new_replies = comment_num_new($topic->nid, $history); - $topic->new = $topic->new_replies || ($topic->last_comment_timestamp > $history); - } - } - else { - // Do not track "new replies" status for topics if the user is anonymous. - $topic->new_replies = 0; - $topic->new = 0; - } - - // Make sure only one topic is indicated as the first new topic. - $topic->first_new = FALSE; - if ($topic->new != 0 && !$first_new_found) { - $topic->first_new = TRUE; - $first_new_found = TRUE; - } - - if ($topic->comment_count > 0) { - $last_reply = new stdClass(); - $last_reply->created = $topic->last_comment_timestamp; - $last_reply->name = $topic->last_comment_name; - $last_reply->uid = $topic->last_comment_uid; - $topic->last_reply = $last_reply; - } - $topics[$topic->nid] = $topic; - } - - return $topics; -} - -/** * Implements hook_preprocess_HOOK() for block.html.twig. */ function forum_preprocess_block(&$variables) { @@ -1122,61 +1008,6 @@ function template_preprocess_forum_submitted(&$variables) { } /** - * Gets the last time the user viewed a node. - * - * @param $nid - * The node ID. - * - * @return - * The timestamp when the user last viewed this node, if the user has - * previously viewed the node; otherwise HISTORY_READ_LIMIT. - */ -function _forum_user_last_visit($nid) { - global $user; - $history = &drupal_static(__FUNCTION__, array()); - - if (empty($history)) { - $result = db_query('SELECT nid, timestamp FROM {history} WHERE uid = :uid', array(':uid' => $user->uid)); - foreach ($result as $t) { - $history[$t->nid] = $t->timestamp > HISTORY_READ_LIMIT ? $t->timestamp : HISTORY_READ_LIMIT; - } - } - return isset($history[$nid]) ? $history[$nid] : HISTORY_READ_LIMIT; -} - -/** - * Gets topic sorting information based on an integer code. - * - * @param $sortby - * One of the following integers indicating the sort criteria: - * - 1: Date - newest first. - * - 2: Date - oldest first. - * - 3: Posts with the most comments first. - * - 4: Posts with the least comments first. - * - * @return - * An array with the following values: - * - field: A field for an SQL query. - * - sort: 'asc' or 'desc'. - */ -function _forum_get_topic_order($sortby) { - switch ($sortby) { - case 1: - return array('field' => 'f.last_comment_timestamp', 'sort' => 'desc'); - break; - case 2: - return array('field' => 'f.last_comment_timestamp', 'sort' => 'asc'); - break; - case 3: - return array('field' => 'f.comment_count', 'sort' => 'desc'); - break; - case 4: - return array('field' => 'f.comment_count', 'sort' => 'asc'); - break; - } -} - -/** * Updates the taxonomy index for a given node. * * @param $nid diff --git a/core/modules/forum/forum.routing.yml b/core/modules/forum/forum.routing.yml index 8a48097..2c3178d 100644 --- a/core/modules/forum/forum.routing.yml +++ b/core/modules/forum/forum.routing.yml @@ -17,7 +17,7 @@ forum_page: requirements: _permission: 'access content' forum_forum_page: - pattern: 'forum/{forum}' + pattern: 'forum/{taxonomy_term}' defaults: _content: 'Drupal\forum\Controller\ForumController::forumPage' requirements: diff --git a/core/modules/forum/forum.services.yml b/core/modules/forum/forum.services.yml new file mode 100644 index 0000000..5ecc619 --- /dev/null +++ b/core/modules/forum/forum.services.yml @@ -0,0 +1,4 @@ +services: + forum_manager: + class: Drupal\forum\ForumManager + arguments: ['@config.factory', '@plugin.manager.entity', '@database'] diff --git a/core/modules/forum/lib/Drupal/forum/Controller/ForumController.php b/core/modules/forum/lib/Drupal/forum/Controller/ForumController.php index 1e33923..f10c8c8 100644 --- a/core/modules/forum/lib/Drupal/forum/Controller/ForumController.php +++ b/core/modules/forum/lib/Drupal/forum/Controller/ForumController.php @@ -9,9 +9,9 @@ use Drupal\Core\ControllerInterface; use Drupal\Core\Config\ConfigFactory; -use Drupal\taxonomy\Plugin\Core\Entity\Term; -use Drupal\forum\Plugin\Core\Entity\Forum; use Drupal\Core\Entity\EntityManager; +use Drupal\forum\ForumManager; +use Drupal\taxonomy\Plugin\Core\Entity\Term; use Symfony\Component\DependencyInjection\ContainerInterface; class ForumController implements ControllerInterface { @@ -24,17 +24,28 @@ class ForumController implements ControllerInterface { protected $config; /** - * Forum storage controller. + * Forum manager service. + * + * @var Drupal\forum\ForumManager + */ + protected $forumManager; + + /** + * Entity manager service. * - * @var Drupal\Core\Entity\EntityStorageControllerInterface + * @var Drupal\Core\Entity\EntityManager */ - protected $storageController; + protected $entityManager; /** * Injects the ConfigFactory service to allow access to the forum settings. */ public static function create(ContainerInterface $container) { - return new static($container->get('config.factory'), $container->get('plugin.manager.entity')); + return new static( + $container->get('config.factory'), + $container->get('forum_manager'), + $container->get('plugin.manager.entity') + ); } /** @@ -42,22 +53,30 @@ public static function create(ContainerInterface $container) { * * @param \Drupal\Core\Config\ConfigFactory $config_factory * The config factory. + * @param \Drupal\forum\ForumManager $forum_manager + * The forum manager service. + * @param \Drupal\Core\Entity\EntityManager $entity_manager + * The entity manager service. */ - public function __construct(ConfigFactory $config_factory, EntityManager $entity_manager) { + public function __construct(ConfigFactory $config_factory, ForumManager $forum_manager, EntityManager $entity_manager) { $this->config = $config_factory->get('forum.settings'); - $this->storageController = $entity_manager->getStorageController('forum'); + $this->forumManager = $forum_manager; + $this->entityManager = $entity_manager; } /** * Returns a forum page. * - * @param \Drupal\forum\Plugin\Core\Entity\Forum $forum + * @param \Drupal\forum\Plugin\Core\Entity\Forum $taxonomy_term * (optional) The forum to render the page for. If empty, the forum index is * rendered instead. Defaults to NULL. + * + * @return array + * A render array. */ - public function forumPage(Forum $forum = NULL) { - if ($forum) { - return $this->forumForumPage($forum); + public function forumPage(Term $taxonomy_term = NULL) { + if ($taxonomy_term) { + return $this->forumForumPage($taxonomy_term); } // Index page. return $this->forumIndex(); @@ -66,34 +85,36 @@ public function forumPage(Forum $forum = NULL) { /** * Returns forum page for a given forum. * - * @param \Drupal\forum\Plugin\Core\Entity\Forum $forum + * @param \Drupal\forum\Plugin\Core\Entity\Forum $taxonomy_term * The forum to render the page for. * * @return array * A render array. */ - protected function forumForumPage(Forum $forum) { + protected function forumForumPage(Term $taxonomy_term) { + // Get forum details + $taxonomy_term->forums = $this->forumManager->getChildren($this->config->get('vocabulary'), $taxonomy_term->id()); + $taxonomy_term->parents = $this->forumManager->getParents($taxonomy_term->id()); // Page title. - drupal_set_title($forum->label()); + drupal_set_title($taxonomy_term->label()); // Breadcrumb navigation. - $vocabulary = entity_load('taxonomy_vocabulary', $this->config->get('vocabulary')); + $vocabularies = $this->entityManager->getStorageController('taxonomy_vocabulary')->load(array($this->config->get('vocabulary'))); + $vocabulary = reset($vocabularies); $breadcrumb[] = l(t('Home'), NULL); $breadcrumb[] = l($vocabulary->label(), 'forum'); - foreach (array_reverse($forum->parents) as $parent) { - if ($parent->id() != $forum->id()) { + foreach (array_reverse($taxonomy_term->parents) as $parent) { + if ($parent->id() != $taxonomy_term->id()) { $breadcrumb[] = l($parent->label(), 'forum/' . $parent->id()); } } drupal_set_breadcrumb($breadcrumb); - if ($forum->container) { + if ($taxonomy_term->container) { // Add RSS feed for forums. - drupal_add_feed('taxonomy/term/' . $forum->id() . '/feed', 'RSS - ' . $forum->label()); + drupal_add_feed('taxonomy/term/' . $taxonomy_term->id() . '/feed', 'RSS - ' . $taxonomy_term->label()); } - $forum_per_page = $this->config->get('topics.page_limit'); - $sort_by = $this->config->get('topics.order'); - if (!$forum->container) { - $topics = forum_get_topics($forum->id(), $sort_by, $forum_per_page); + if (!$taxonomy_term->container) { + $topics = $this->forumManager->getTopics($taxonomy_term->id()); } else { $topics = ''; @@ -101,12 +122,12 @@ protected function forumForumPage(Forum $forum) { $build = array( '#theme' => 'forums', - '#forums' => $forum->forums, + '#forums' => $taxonomy_term->forums, '#topics' => $topics, - '#parents' => $forum->parents, - '#tid' => $forum->id(), - '#sortby' => $sort_by, - '#forums_per_page' => $forum_per_page, + '#parents' => $taxonomy_term->parents, + '#tid' => $taxonomy_term->id(), + '#sortby' => $this->config->get('topics.order'), + '#forums_per_page' => $this->config->get('topics.page_limit'), ); $build['#attached']['css'][] = drupal_get_path('module', 'forum') . '/forum.css'; return $build; @@ -119,8 +140,9 @@ protected function forumForumPage(Forum $forum) { * A render array. */ protected function forumIndex() { - $vocabulary = entity_load('taxonomy_vocabulary', $this->config->get('vocabulary')); - $index = $this->storageController->forumIndex(); + $vocabularies = $this->entityManager->getStorageController('taxonomy_vocabulary')->load(array($this->config->get('vocabulary'))); + $vocabulary = reset($vocabularies); + $index = $this->forumManager->getIndex(); // Set the page title to forum's vocabulary name. drupal_set_title($vocabulary->label()); if (empty($index->forums)) { diff --git a/core/modules/forum/lib/Drupal/forum/ForumFormController.php b/core/modules/forum/lib/Drupal/forum/ForumFormController.php deleted file mode 100644 index 17419c7..0000000 --- a/core/modules/forum/lib/Drupal/forum/ForumFormController.php +++ /dev/null @@ -1,27 +0,0 @@ -config = $config_factory->get('forum.settings'); + $this->entityManager = $entity_manager; + $this->database = $database; + } + + /** + * Gets list of forum topics. + * + * @param int $tid + * Term id. + * + * @return array + * Array of topics. + */ + public function getTopics($tid) { + $forum_per_page = $this->config->get('topics.page_limit'); + $sortby = $this->config->get('topics.order'); + + global $user, $forum_topic_list_header; + + $forum_topic_list_header = array( + array('data' => t('Topic'), 'field' => 'f.title'), + array('data' => t('Replies'), 'field' => 'f.comment_count'), + array('data' => t('Last reply'), 'field' => 'f.last_comment_timestamp'), + ); + + $order = $this->getTopicOrder($sortby); + for ($i = 0; $i < count($forum_topic_list_header); $i++) { + if ($forum_topic_list_header[$i]['field'] == $order['field']) { + $forum_topic_list_header[$i]['sort'] = $order['sort']; + } + } + + $query = $this->database->select('forum_index', 'f') + ->extend('Drupal\Core\Database\Query\PagerSelectExtender') + ->extend('Drupal\Core\Database\Query\TableSortExtender'); + $query->fields('f'); + $query + ->condition('f.tid', $tid) + ->addTag('node_access') + ->addMetaData('base_table', 'forum_index') + ->orderBy('f.sticky', 'DESC') + ->orderByHeader($forum_topic_list_header) + ->limit($forum_per_page); + + $count_query = $this->database->select('forum_index', 'f'); + $count_query->condition('f.tid', $tid); + $count_query->addExpression('COUNT(*)'); + $count_query->addTag('node_access'); + $count_query->addMetaData('base_table', 'forum_index'); + + $query->setCountQuery($count_query); + $result = $query->execute(); + $nids = array(); + foreach ($result as $record) { + $nids[] = $record->nid; + } + if ($nids) { + $nodes = $this->entityManager->getStorageController('node')->load($nids); + + $query = $this->database->select('node_field_data', 'n') + ->extend('Drupal\Core\Database\Query\TableSortExtender'); + $query->fields('n', array('nid')); + + $query->join('node_comment_statistics', 'ncs', 'n.nid = ncs.nid'); + $query->fields('ncs', array('cid', 'last_comment_uid', 'last_comment_timestamp', 'comment_count')); + + $query->join('forum_index', 'f', 'f.nid = ncs.nid'); + $query->addField('f', 'tid', 'forum_tid'); + + $query->join('users', 'u', 'n.uid = u.uid'); + $query->addField('u', 'name'); + + $query->join('users', 'u2', 'ncs.last_comment_uid = u2.uid'); + + $query->addExpression('CASE ncs.last_comment_uid WHEN 0 THEN ncs.last_comment_name ELSE u2.name END', 'last_comment_name'); + + $query + ->orderBy('f.sticky', 'DESC') + ->orderByHeader($forum_topic_list_header) + ->condition('n.nid', $nids) + // @todo This should be actually filtering on the desired node language + // and just fall back to the default language. + ->condition('n.default_langcode', 1); + + $result = array(); + foreach ($query->execute() as $row) { + $topic = $nodes[$row->nid]; + $topic->comment_mode = $topic->comment; + + foreach ($row as $key => $value) { + $topic->{$key} = $value; + } + $result[] = $topic; + } + } + else { + $result = array(); + } + + $topics = array(); + $first_new_found = FALSE; + foreach ($result as $topic) { + if ($user->uid) { + // A forum is new if the topic is new, or if there are new comments since + // the user's last visit. + if ($topic->forum_tid != $tid) { + $topic->new = 0; + } + else { + $history = $this->lastVisit($topic->nid); + // @todo move use comment service. + $topic->new_replies = $this->numberNew($topic->nid, $history); + $topic->new = $topic->new_replies || ($topic->last_comment_timestamp > $history); + } + } + else { + // Do not track "new replies" status for topics if the user is anonymous. + $topic->new_replies = 0; + $topic->new = 0; + } + + // Make sure only one topic is indicated as the first new topic. + $topic->first_new = FALSE; + if ($topic->new != 0 && !$first_new_found) { + $topic->first_new = TRUE; + $first_new_found = TRUE; + } + + if ($topic->comment_count > 0) { + $last_reply = new stdClass(); + $last_reply->created = $topic->last_comment_timestamp; + $last_reply->name = $topic->last_comment_name; + $last_reply->uid = $topic->last_comment_uid; + $topic->last_reply = $last_reply; + } + $topics[$topic->nid] = $topic; + } + + return $topics; + + } + + /** + * Gets topic sorting information based on an integer code. + * + * @param int $sortby + * One of the following integers indicating the sort criteria: + * - 1: Date - newest first. + * - 2: Date - oldest first. + * - 3: Posts with the most comments first. + * - 4: Posts with the least comments first. + * + * @return array + * An array with the following values: + * - field: A field for an SQL query. + * - sort: 'asc' or 'desc'. + */ + protected function getTopicOrder($sortby) { + switch ($sortby) { + case 1: + return array('field' => 'f.last_comment_timestamp', 'sort' => 'desc'); + break; + case 2: + return array('field' => 'f.last_comment_timestamp', 'sort' => 'asc'); + break; + case 3: + return array('field' => 'f.comment_count', 'sort' => 'desc'); + break; + case 4: + return array('field' => 'f.comment_count', 'sort' => 'asc'); + break; + } + } + + /** + * Util method to ensure comment_num_new is behind a method. + * + * @param int $nid + * Node id. + * @param int $timestamp + * Timestamp of last read. + * + * @return int + * Number of new comments. + */ + protected function numberNew($nid, $timestamp) { + return comment_num_new($nid, $timestamp); + } + + /** + * Gets the last time the user viewed a node. + * + * @param int $nid + * The node ID. + * + * @return int + * The timestamp when the user last viewed this node, if the user has + * previously viewed the node; otherwise HISTORY_READ_LIMIT. + */ + function lastVisit($nid) { + global $user; + + if (empty($this->history[$nid])) { + $result = $this->database->select('history', 'h') + ->fields('h', array('nid', 'timestamp')) + ->condition('uid', $user->uid) + ->execute(); + foreach ($result as $t) { + $this->history[$t->nid] = $t->timestamp > HISTORY_READ_LIMIT ? $t->timestamp : HISTORY_READ_LIMIT; + } + } + return isset($this->history[$nid]) ? $this->history[$nid] : HISTORY_READ_LIMIT; + } + + /** + * Utility method to get the last post information for the given forum tid. + * + * @param int $tid + * The forum tid. + * + * @return \stdClass + * The last post for the given forum. + */ + protected function getLastPost($tid) { + if (!empty($this->lastPostData[$tid])) { + return $this->lastPostData[$tid]; + } + // Query "Last Post" information for this forum. + $query = $this->database->select('node_field_data', 'n'); + $query->join('forum', 'f', 'n.vid = f.vid AND f.tid = :tid', array(':tid' => $tid)); + $query->join('node_comment_statistics', 'ncs', 'n.nid = ncs.nid'); + $query->join('users', 'u', 'ncs.last_comment_uid = u.uid'); + $query->addExpression('CASE ncs.last_comment_uid WHEN 0 THEN ncs.last_comment_name ELSE u.name END', 'last_comment_name'); + + $topic = $query + ->fields('ncs', array('last_comment_timestamp', 'last_comment_uid')) + ->condition('n.status', 1) + ->orderBy('last_comment_timestamp', 'DESC') + ->range(0, 1) + ->addTag('node_access') + ->execute() + ->fetchObject(); + + // Build the last post information. + $last_post = new \stdClass(); + if (!empty($topic->last_comment_timestamp)) { + $last_post->created = $topic->last_comment_timestamp; + $last_post->name = $topic->last_comment_name; + $last_post->uid = $topic->last_comment_uid; + } + + $this->lastPostData[$tid] = $last_post; + return $last_post; + } + + /** + * Utility method to fetch statistics for a forum. + * + * @param int $tid + * The forum tid. + * + * @return \stdClass|NULL + * Statistics for the given forum if statistics exist, else NULL + */ + protected function getForumStatistics($tid) { + if (empty($this->forumStatistics)) { + // Prime the statistics. + $query = $this->database->select('node_field_data', 'n'); + $query->join('node_comment_statistics', 'ncs', 'n.nid = ncs.nid'); + $query->join('forum', 'f', 'n.vid = f.vid'); + $query->addExpression('COUNT(n.nid)', 'topic_count'); + $query->addExpression('SUM(ncs.comment_count)', 'comment_count'); + $this->forumStatistics = $query + ->fields('f', array('tid')) + ->condition('n.status', 1) + ->condition('n.default_langcode', 1) + ->groupBy('tid') + ->addTag('node_access') + ->execute() + ->fetchAllAssoc('tid'); + } + + if (!empty($this->forumStatistics[$tid])) { + return $this->forumStatistics[$tid]; + } + } + + /** + * Utility method to fetch the child forums for a given forum. + * + * @param int $vid + * The forum vocabulary id. + * @param int $tid + * The forum id to fetch the children for. + * + * @return array + * Array of children. + */ + public function getChildren($vid, $tid) { + if (!empty($this->forumChildren[$tid])) { + return $this->forumChildren[$tid]; + } + $forums = array(); + $_forums = taxonomy_get_tree($vid, $tid, NULL, TRUE); + foreach ($_forums as $forum) { + // Determine if the child term is a container. + if (in_array($forum->id(), $this->config->get('containers'))) { + $forum->container = TRUE; + } + + // Merge in the topic and post counters. + if (($count = $this->getForumStatistics($forum->id()))) { + $forum->num_topics = $count->topic_count; + $forum->num_posts = $count->topic_count + $count->comment_count; + } + else { + $forum->num_topics = 0; + $forum->num_posts = 0; + } + + // Merge in last post details. + $forum->last_post = $this->getLastPost($forum->id()); + $forums[$forum->id()] = $forum; + } + + $this->forumChildren[$tid] = $forums; + return $forums; + } + + /** + * Generates and returns the forum index. + * + * The forum index is a psuedo term that provides an overview of all forums. + * + * @return \Drupal\taxonomy\Plugin\Core\Entity\Term + * A psuedo term representing the overview of all forums. + */ + public function getIndex() { + if ($this->index) { + return $index; + } + + $vid = $this->config->get('vocabulary'); + $index = $this->entityManager->getStorageController('taxonomy_term')->create(array( + 'tid' => 0, + 'container' => TRUE, + 'parents' => array(), + 'isIndex' => TRUE, + 'vid' => $vid + )); + + // Load the tree below. + $index->forums = $this->getChildren($vid, 0); + $this->index = $index; + return $index; + } + + /** + * Overrides \Drupal\Core\Entity\DatabaseStorageController::resetCache(). + */ + public function resetCache(array $ids = NULL) { + parent::resetCache($ids); + // Reset the index. + $this->index = NULL; + // Reset history. + $this->history = NULL; + } + + /** + * Protected function to wrap call to taxonomy_term_load_parents_all. + * + * @param int $tid + * Term id. + * + * @return array + * Array of parent terms. + * + * @todo remove an inject a service when taxonomy_term_get_parents_all has an + * object-oriented equivalent. + */ + public function getParents($tid) { + return taxonomy_term_load_parents_all($tid); + } + +} diff --git a/core/modules/forum/lib/Drupal/forum/ForumStorageController.php b/core/modules/forum/lib/Drupal/forum/ForumStorageController.php deleted file mode 100644 index 6e7a1c6..0000000 --- a/core/modules/forum/lib/Drupal/forum/ForumStorageController.php +++ /dev/null @@ -1,261 +0,0 @@ -config = config('forum.settings'); - } - - /** - * Overrides \Drupal\Core\Entity\DatabaseStorageController::delete(). - */ - public function delete(array $entities) { - parent::delete($entities); - // For containers, remove the tid from the forum_containers variable. - $containers = $this->config->get('containers'); - foreach (array_keys($entities) as $tid) { - if (!empty($containser[$tid])) { - unset($containers[$tid]); - } - } - $this->config->set('containers', $containers)->save(); - } - - /** - * Overrides \Drupal\Core\Entity\DatabaseStorageController::load(). - */ - public function load(array $ids = NULL) { - $entities = parent::load($ids); - $vid = $this->config->get('vocabulary'); - foreach ($entities as $tid => &$forum_term) { - if ($forum_term->bundle() != $vid) { - // Not a forum term. - unset($entities[$tid]); - } - - // Determine if the requested term is a container. - if (in_array($forum_term->id(), $this->config->get('containers'))) { - $forum_term->container = TRUE; - } - - // Load parent terms. - // @todo - is this still needed? - $forum_term->parents = taxonomy_term_load_parents_all($forum_term->id()); - - // Load the tree below. - $forum_term->forums = $this->getChildren($vid, $tid); - } - return $entities; - } - - /** - * Utility method to get the last post information for the given forum tid. - * - * @param int $tid - * The forum tid. - * - * @return \stdClass - * The last post for the given forum. - */ - protected function getLastPost($tid) { - if (!empty($this->lastPostData[$tid])) { - return $this->lastPostData[$tid]; - } - // Query "Last Post" information for this forum. - $query = db_select('node', 'n'); - $query->join('forum', 'f', 'n.vid = f.vid AND f.tid = :tid', array(':tid' => $tid)); - $query->join('node_comment_statistics', 'ncs', 'n.nid = ncs.nid'); - $query->join('users', 'u', 'ncs.last_comment_uid = u.uid'); - $query->addExpression('CASE ncs.last_comment_uid WHEN 0 THEN ncs.last_comment_name ELSE u.name END', 'last_comment_name'); - - $topic = $query - ->fields('ncs', array('last_comment_timestamp', 'last_comment_uid')) - ->condition('n.status', 1) - ->orderBy('last_comment_timestamp', 'DESC') - ->range(0, 1) - ->addTag('node_access') - ->execute() - ->fetchObject(); - - // Build the last post information. - $last_post = new \stdClass(); - if (!empty($topic->last_comment_timestamp)) { - $last_post->created = $topic->last_comment_timestamp; - $last_post->name = $topic->last_comment_name; - $last_post->uid = $topic->last_comment_uid; - } - - $this->lastPostData[$tid] = $last_post; - return $last_post; - } - - /** - * Utility method to fetch statistics for a forum. - * - * @param int $tid - * The forum tid. - * - * @return \stdClass|NULL - * Statistics for the given forum if statistics exist, else NULL - */ - protected function getForumStatistics($tid) { - if (empty($this->forumStatistics)) { - // Prime the statistics. - $query = db_select('node', 'n'); - $query->join('node_comment_statistics', 'ncs', 'n.nid = ncs.nid'); - $query->join('forum', 'f', 'n.vid = f.vid'); - $query->addExpression('COUNT(n.nid)', 'topic_count'); - $query->addExpression('SUM(ncs.comment_count)', 'comment_count'); - $this->forumStatistics = $query - ->fields('f', array('tid')) - ->condition('n.status', 1) - ->groupBy('tid') - ->addTag('node_access') - ->execute() - ->fetchAllAssoc('tid'); - } - - if (!empty($this->forumStatistics[$tid])) { - return $this->forumStatistics[$tid]; - } - } - - /** - * Utility method to fetch the child forums for a given forum. - * - * @param int $vid - * The forum vocabulary id. - * @param int $tid - * The forum id to fetch the children for. - * - * @return array - * Array of children. - */ - protected function getChildren($vid, $tid) { - if (!empty($this->forumChildren[$tid])) { - return $this->forumChildren[$tid]; - } - $forums = array(); - $_forums = taxonomy_get_tree($vid, $tid, NULL, TRUE); - foreach ($_forums as $forum) { - // Determine if the child term is a container. - if (in_array($forum->tid, $this->config->get('containers'))) { - $forum->container = TRUE; - } - - // Merge in the topic and post counters. - if (($count = $this->getForumStatistics($forum->tid))) { - $forum->num_topics = $count->topic_count; - $forum->num_posts = $count->topic_count + $count->comment_count; - } - else { - $forum->num_topics = 0; - $forum->num_posts = 0; - } - - // Merge in last post details. - $forum->last_post = $this->getLastPost($forum->tid); - $forums[$forum->tid] = $forum; - } - - $this->forumChildren[$tid] = $forums; - return $forums; - } - - /** - * Generates and returns the forum index. - * - * The forum index is a psuedo term that provides an overview of all forums. - * - * @return \Drupal\taxonomy\Plugin\Core\Entity\Term - * A psuedo term representing the overview of all forums. - */ - public function forumIndex() { - if ($this->index) { - return $index; - } - - $index = $this->create(array( - 'tid' => 0, - 'container' => TRUE, - 'parents' => array(), - 'isIndex' => TRUE, - )); - - // Load the tree below. - $index->forums = $this->getChildren($this->config->get('vocabulary'), 0); - $this->index = $index; - return $index; - } - - /** - * Overrides \Drupal\Core\Entity\DatabaseStorageController::resetCache(). - */ - public function resetCache(array $ids = NULL) { - parent::resetCache($ids); - // Reset the index. - $this->index = NULL; - } - - /** - * Overrides \Drupal\Core\Entity\DatabaseStorageController::save(). - */ - public function save(EntityInterface $entity) { - if (!empty($entity->isIndex)) { - throw new Exception(t('The forum index cannot be saved')); - } - return parent::save($entity); - } -} diff --git a/core/modules/forum/lib/Drupal/forum/Plugin/Core/Entity/Forum.php b/core/modules/forum/lib/Drupal/forum/Plugin/Core/Entity/Forum.php deleted file mode 100644 index 759a94d..0000000 --- a/core/modules/forum/lib/Drupal/forum/Plugin/Core/Entity/Forum.php +++ /dev/null @@ -1,84 +0,0 @@ - 'forum/' . $this->id(), - ); - } -}