static function bulkLoad($rows) { // Preload subthreads $top_thread_ids = array(); $all_thread_rows = $rows; $pageIds = array(); $linkBatch = new LinkBatch(); $userIds = array(); $loadEditorsFor = array(); $dbr = wfGetDB(DB_SLAVE); if (!is_array(self::$replyCacheById)) { self::$replyCacheById = array(); } // Build a list of threads for which to pull replies, and page IDs to pull data for. // Also, pre-initialise the reply cache. foreach ($rows as $row) { if ($row->thread_ancestor) { $top_thread_ids[] = $row->thread_ancestor; } else { $top_thread_ids[] = $row->thread_id; } // Grab page data while we're here. if ($row->thread_root) { $pageIds[] = $row->thread_root; } if ($row->thread_summary_page) { $pageIds[] = $row->thread_summary_page; } if (!isset(self::$replyCacheById[$row->thread_id])) { self::$replyCacheById[$row->thread_id] = array(); } } $all_thread_ids = $top_thread_ids; // Pull replies to the threads provided, and as above, pull page IDs to pull data for, // pre-initialise the reply cache, and stash the row object for later use. if (count($top_thread_ids)) { $res = $dbr->select('thread', '*', array('thread_ancestor' => $top_thread_ids, 'thread_type != ' . $dbr->addQuotes(Threads::TYPE_DELETED)), __METHOD__); foreach ($res as $row) { // Grab page data while we're here. if ($row->thread_root) { $pageIds[] = $row->thread_root; } if ($row->thread_summary_page) { $pageIds[] = $row->thread_summary_page; } $all_thread_rows[] = $row; $all_thread_ids[$row->thread_id] = $row->thread_id; } } // Pull thread reactions if (count($all_thread_ids)) { $res = $dbr->select('thread_reaction', '*', array('tr_thread' => $all_thread_ids), __METHOD__); foreach ($res as $row) { $thread_id = $row->tr_thread; $user = $row->tr_user_text; $info = array('type' => $row->tr_type, 'user-id' => $row->tr_user, 'user-name' => $row->tr_user_text, 'value' => $row->tr_value); $type = $info['type']; $user = $info['user-name']; if (!isset(self::$reactionCacheById[$thread_id])) { self::$reactionCacheById[$thread_id] = array(); } if (!isset(self::$reactionCacheById[$thread_id][$type])) { self::$reactionCacheById[$thread_id][$type] = array(); } self::$reactionCacheById[$thread_id][$type][$user] = $info; } } // Preload page data (restrictions, and preload Article object with everything from // the page table. Also, precache the title and article objects for pulling later. $articlesById = array(); if (count($pageIds)) { // Pull restriction info. Needs to come first because otherwise it's done per // page by loadPageData. $restrictionRows = array_fill_keys($pageIds, array()); $res = $dbr->select('page_restrictions', '*', array('pr_page' => $pageIds), __METHOD__); foreach ($res as $row) { $restrictionRows[$row->pr_page][] = $row; } $res = $dbr->select('page', '*', array('page_id' => $pageIds), __METHOD__); foreach ($res as $row) { $t = Title::newFromRow($row); if (isset($restrictionRows[$t->getArticleId()])) { $t->loadRestrictionsFromRows($restrictionRows[$t->getArticleId()], $row->page_restrictions); } $article = new Article($t); $article->loadPageData($row); self::$titleCacheById[$t->getArticleId()] = $t; $articlesById[$article->getId()] = $article; if (count(self::$titleCacheById) > 10000) { self::$titleCacheById = array(); } } } // For every thread we have a row object for, load a Thread object, add the user and // user talk pages to a link batch, cache the relevant user id/name pair, and // populate the reply cache. foreach ($all_thread_rows as $row) { $thread = Thread::newFromRow($row, null); if (isset($articlesById[$thread->rootId])) { $thread->root = $articlesById[$thread->rootId]; } // User cache data $t = Title::makeTitleSafe(NS_USER, $row->thread_author_name); $linkBatch->addObj($t); $t = Title::makeTitleSafe(NS_USER_TALK, $row->thread_author_name); $linkBatch->addObj($t); User::$idCacheByName[$row->thread_author_name] = $row->thread_author_id; $userIds[$row->thread_author_id] = true; if ($row->thread_editedness > Threads::EDITED_BY_AUTHOR) { $loadEditorsFor[$row->thread_root] = $thread; $thread->setEditors(array()); } } // Pull list of users who have edited if (count($loadEditorsFor)) { $res = $dbr->select('revision', array('rev_user_text', 'rev_page'), array('rev_page' => array_keys($loadEditorsFor), 'rev_parent_id != ' . $dbr->addQuotes(0)), __METHOD__); foreach ($res as $row) { $pageid = $row->rev_page; $editor = $row->rev_user_text; $t = $loadEditorsFor[$pageid]; $t->addEditor($editor); } } // Pull link batch data. $linkBatch->execute(); $threads = array(); // Fill and return an array with the threads that were actually requested. foreach ($rows as $row) { $threads[$row->thread_id] = Threads::$cache_by_id[$row->thread_id]; } return $threads; }