diff --git a/core/modules/forum/src/ForumManager.php b/core/modules/forum/src/ForumManager.php index aa7f2b19af..85f8c00761 100644 --- a/core/modules/forum/src/ForumManager.php +++ b/core/modules/forum/src/ForumManager.php @@ -327,48 +327,78 @@ protected function lastVisit($nid, AccountInterface $account) { * * @return \stdClass * The last post for the given forum. + * + * @deprecated in Drupal 8.0.0 and will be removed before Drupal 9.0.0. + * Use getLastPostData() instead */ protected function getLastPost($tid) { if (!empty($this->lastPostData[$tid])) { return $this->lastPostData[$tid]; } - // Query "Last Post" information for this forum. Only add the node table to - // the query if this is necessary for filtering access-restricted records. - if ($this->currentUserCanViewAllNodes()) { - $query = $this->connection->select('forum_index', 'f'); - } - else { - $query = $this->connection->select('node', 'n') - ->addTag('node_access'); - $query->join('forum_index', 'f', 'n.nid = f.nid'); - } - $query->join('comment_entity_statistics', 'ces', "f.nid = ces.entity_id AND ces.field_name = 'comment_forum' AND ces.entity_type = 'node'"); - $query->join('users_field_data', 'u', 'ces.last_comment_uid = u.uid AND u.default_langcode = 1'); - $query->addExpression('COALESCE(ces.last_comment_name, u.name)', 'last_comment_name'); + $data = $this->getLastPostData([$tid]); + return reset($data); + } - $topic = $query - ->fields('ces', ['last_comment_timestamp', 'last_comment_uid']) - ->condition('f.tid', $tid) - ->orderBy('f.last_comment_timestamp', 'DESC') - ->range(0, 1) - ->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; + /** + * Provides the last post information for the given forum tids. + * + * @param int[] $tids + * The forum tids. + * + * @return \stdClass[] + * The last post information for the given forums. + */ + protected function getLastPostData(array $tids) { + // Check if all tids already have post info. We assume no duplicate tids. + $tids_as_keys = array_flip($tids); + $known_data = array_intersect_key($this->lastPostData, $tids_as_keys); + if (count($known_data) < count($tids)) { + $unknown_tids = array_diff($tids, array_keys($this->lastPostData)); + + // Query "Last Post" information. Only add the node table to the query if + // this is necessary for filtering access-restricted records. + if ($this->currentUserCanViewAllNodes()) { + $query = $this->connection->select('forum_index', 'f'); + } + else { + $query = $this->connection->select('node', 'n') + ->addTag('node_access'); + $query->join('forum_index', 'f', 'n.nid = f.nid'); + } + $query->join('comment_entity_statistics', 'ces', "f.nid = ces.entity_id AND ces.field_name = 'comment_forum' AND ces.entity_type = 'node'"); + $query->join('users_field_data', 'u', 'ces.last_comment_uid = u.uid AND u.default_langcode = 1'); + $query->addField('f', 'tid'); + $query->addExpression('COALESCE(ces.last_comment_name, u.name)', 'last_comment_name'); + + $topics = $query + ->fields('ces', ['last_comment_timestamp', 'last_comment_uid']) + ->condition('f.tid', $unknown_tids, 'IN') + ->orderBy('f.last_comment_timestamp', 'DESC') + ->range(0, 1) + ->execute() + ->fetchAllAssoc('tid'); + + // Build the last post information. + foreach ($unknown_tids as $tid) { + $this->lastPostData[$tid] = new \stdClass(); + if (!empty($topics[$tid]->last_comment_timestamp)) { + $this->lastPostData[$tid]->created = $topics[$tid]->last_comment_timestamp; + $this->lastPostData[$tid]->name = $topics[$tid]->last_comment_name; + $this->lastPostData[$tid]->uid = $topics[$tid]->last_comment_uid; + } + } + + $known_data = array_intersect_key($this->lastPostData, $tids_as_keys); } - $this->lastPostData[$tid] = $last_post; - return $last_post; + return $known_data; } /** * Provides statistics for a forum. * + * This will prime statistics for all known forums, to minimize queries. + * * @param int $tid * The forum tid. * @@ -425,6 +455,15 @@ public function getChildren($vid, $tid) { } $forums = []; $_forums = $this->entityManager->getStorage('taxonomy_term')->loadTree($vid, $tid, NULL, TRUE); + + // Prime last post details for the forums. Unlike getForumStatistics() we + // only query data for the forums we actually need. + $tids = []; + foreach ($_forums as $forum) { + $tids[] = $forum->id(); + } + $last_post_data = $this->getLastPostData($tids); + foreach ($_forums as $forum) { // Merge in the topic and post counters. if (($count = $this->getForumStatistics($forum->id()))) { @@ -437,7 +476,7 @@ public function getChildren($vid, $tid) { } // Merge in last post details. - $forum->last_post = $this->getLastPost($forum->id()); + $forum->last_post = $last_post_data[$forum->id()]; $forums[$forum->id()] = $forum; }