/**
	 * Return a clause with the list of disambiguation templates.
	 * This function was copied verbatim from specials/SpecialDisambiguations.php
	 */
	function disambiguation_templates( $dbr ) {
		$dMsgText = wfMsgForContent('disambiguationspage');

		$linkBatch = new LinkBatch;

		# If the text can be treated as a title, use it verbatim.
		# Otherwise, pull the titles from the links table
		$dp = Title::newFromText($dMsgText);
		if( $dp ) {
			if($dp->getNamespace() != NS_TEMPLATE) {
				# FIXME we assume the disambiguation message is a template but
				# the page can potentially be from another namespace :/
				wfDebug("Mediawiki:disambiguationspage message does not refer to a template!\n");
			}
			$linkBatch->addObj( $dp );
		} else {
			# Get all the templates linked from the Mediawiki:Disambiguationspage
			$disPageObj = Title::makeTitleSafe( NS_MEDIAWIKI, 'disambiguationspage' );
			$res = $dbr->select(
				array('pagelinks', 'page'),
				'pl_title',
				array('page_id = pl_from', 'pl_namespace' => NS_TEMPLATE,
					'page_namespace' => $disPageObj->getNamespace(), 'page_title' => $disPageObj->getDBkey()),
				__METHOD__ );

			foreach ( $res as $row ) {
				$linkBatch->addObj( Title::makeTitle( NS_TEMPLATE, $row->pl_title ));
			}
		}
		return $linkBatch->constructSet( 'tl', $dbr );
	}
 function getQueryInfo()
 {
     $dbr = wfGetDB(DB_SLAVE);
     $dMsgText = wfMsgForContent('disambiguationspage');
     $linkBatch = new LinkBatch();
     # If the text can be treated as a title, use it verbatim.
     # Otherwise, pull the titles from the links table
     $dp = Title::newFromText($dMsgText);
     if ($dp) {
         if ($dp->getNamespace() != NS_TEMPLATE) {
             # @todo FIXME: We assume the disambiguation message is a template but
             # the page can potentially be from another namespace :/
             wfDebug("Mediawiki:disambiguationspage message does not refer to a template!\n");
         }
         $linkBatch->addObj($dp);
     } else {
         # Get all the templates linked from the Mediawiki:Disambiguationspage
         $disPageObj = Title::makeTitleSafe(NS_MEDIAWIKI, 'disambiguationspage');
         $res = $dbr->select(array('pagelinks', 'page'), 'pl_title', array('page_id = pl_from', 'pl_namespace' => NS_TEMPLATE, 'page_namespace' => $disPageObj->getNamespace(), 'page_title' => $disPageObj->getDBkey()), __METHOD__);
         foreach ($res as $row) {
             $linkBatch->addObj(Title::makeTitle(NS_TEMPLATE, $row->pl_title));
         }
     }
     $set = $linkBatch->constructSet('tl', $dbr);
     if ($set === false) {
         # We must always return a valid SQL query, but this way
         # the DB will always quickly return an empty result
         $set = 'FALSE';
         wfDebug("Mediawiki:disambiguationspage message does not link to any templates!\n");
     }
     // @todo FIXME: What are pagelinks and p2 doing here?
     return array('tables' => array('templatelinks', 'p1' => 'page', 'pagelinks', 'p2' => 'page'), 'fields' => array('p1.page_namespace AS namespace', 'p1.page_title AS title', 'pl_from AS value'), 'conds' => array($set, 'p1.page_id = tl_from', 'pl_namespace = p1.page_namespace', 'pl_title = p1.page_title', 'p2.page_id = pl_from', 'p2.page_namespace' => MWNamespace::getContentNamespaces()));
 }
 function getSQL()
 {
     $dbr =& wfGetDB(DB_SLAVE);
     list($page, $pagelinks, $templatelinks) = $dbr->tableNamesN('page', 'pagelinks', 'templatelinks');
     $dMsgText = wfMsgForContent('disambiguationspage');
     $linkBatch = new LinkBatch();
     # If the text can be treated as a title, use it verbatim.
     # Otherwise, pull the titles from the links table
     $dp = Title::newFromText($dMsgText);
     if ($dp) {
         if ($dp->getNamespace() != NS_TEMPLATE) {
             # FIXME we assume the disambiguation message is a template but
             # the page can potentially be from another namespace :/
             wfDebug("Mediawiki:disambiguationspage message does not refer to a template!\n");
         }
         $linkBatch->addObj($dp);
     } else {
         # Get all the templates linked from the Mediawiki:Disambiguationspage
         $disPageObj = $this->getDisambiguationPageObj();
         $res = $dbr->select(array('pagelinks', 'page'), 'pl_title', array('page_id = pl_from', 'pl_namespace' => NS_TEMPLATE, 'page_namespace' => $disPageObj->getNamespace(), 'page_title' => $disPageObj->getDBkey()), 'DisambiguationsPage::getSQL');
         while ($row = $dbr->fetchObject($res)) {
             $linkBatch->addObj(Title::makeTitle(NS_TEMPLATE, $row->pl_title));
         }
         $dbr->freeResult($res);
     }
     $set = $linkBatch->constructSet('lb.tl', $dbr);
     if ($set === false) {
         $set = 'FALSE';
         # We must always return a valid sql query, but this way DB will always quicly return an empty result
         wfDebug("Mediawiki:disambiguationspage message does not link to any templates!\n");
     }
     $sql = "SELECT 'Disambiguations' AS \"type\", pb.page_namespace AS namespace," . " pb.page_title AS title, la.pl_from AS value" . " FROM {$templatelinks} AS lb, {$page} AS pb, {$pagelinks} AS la, {$page} AS pa" . " WHERE {$set}" . ' AND pa.page_id = la.pl_from' . ' AND pa.page_namespace = ' . NS_MAIN . ' AND pb.page_id = lb.tl_from' . ' AND pb.page_namespace = la.pl_namespace' . ' AND pb.page_title = la.pl_title' . ' ORDER BY lb.tl_namespace, lb.tl_title';
     return $sql;
 }
 function preprocessResults(&$dbo, &$res)
 {
     # Do a batch existence check on the user and talk pages
     $linkBatch = new LinkBatch();
     while ($row = $dbo->fetchObject($res)) {
         $linkBatch->addObj(Title::makeTitleSafe(NS_USER, $row->user_text));
         $linkBatch->addObj(Title::makeTitleSafe(NS_USER_TALK, $row->user_text));
     }
     $linkBatch->execute();
     # Seek to start
     if ($dbo->numRows($res) > 0) {
         $dbo->dataSeek($res, 0);
     }
 }
 /**
  * Main execution point
  *
  * @param string $subpage
  */
 public function execute($subpage)
 {
     $this->rcSubpage = $subpage;
     $this->setHeaders();
     $this->outputHeader();
     $this->addModules();
     $rows = $this->getRows();
     $opts = $this->getOptions();
     if ($rows === false) {
         if (!$this->including()) {
             $this->doHeader($opts, 0);
             $this->getOutput()->setStatusCode(404);
         }
         return;
     }
     $batch = new LinkBatch();
     foreach ($rows as $row) {
         $batch->add(NS_USER, $row->rc_user_text);
         $batch->add(NS_USER_TALK, $row->rc_user_text);
         $batch->add($row->rc_namespace, $row->rc_title);
         if ($row->rc_source === RecentChange::SRC_LOG) {
             $formatter = LogFormatter::newFromRow($row);
             foreach ($formatter->getPreloadTitles() as $title) {
                 $batch->addObj($title);
             }
         }
     }
     $batch->execute();
     $this->webOutput($rows, $opts);
     $rows->free();
 }
 protected function preprocessResults($results)
 {
     $names = array();
     foreach ($results as $result) {
         $names[] = $result->utr_name;
     }
     if (!$names) {
         return;
     }
     $dbr = wfGetDB(DB_SLAVE);
     $res = $dbr->select(array('user', 'ipblocks'), User::selectFields(), array('user_name' => array_unique($names), 'ipb_deleted IS NULL OR ipb_deleted = 0'), __METHOD__, array(), array('ipblocks' => array('LEFT JOIN', 'user_id = ipb_user')));
     $userArray = UserArray::newFromResult($res);
     $lb = new LinkBatch();
     foreach ($userArray as $user) {
         $this->users[$user->getName()] = $user;
         $lb->addObj($user->getUserPage());
         $lb->addObj($user->getTalkPage());
     }
     $lb->execute();
 }
 public function getBody()
 {
     $batch = new LinkBatch();
     $this->mResult->rewind();
     while ($row = $this->mResult->fetchObject()) {
         $batch->addObj(Title::makeTitleSafe(NS_CATEGORY, $row->cat_title));
     }
     $batch->execute();
     $this->mResult->rewind();
     return parent::getBody();
 }
 /**
  * Pre-fill the link cache
  */
 function preprocessResults(&$db, &$res)
 {
     if ($db->numRows($res) > 0) {
         $linkBatch = new LinkBatch();
         while ($row = $db->fetchObject($res)) {
             $linkBatch->addObj(Title::makeTitleSafe($row->namespace, $row->title));
         }
         $db->dataSeek($res, 0);
         $linkBatch->execute();
     }
 }
 public function getBody()
 {
     $batch = new LinkBatch();
     $this->mResult->rewind();
     foreach ($this->mResult as $row) {
         $batch->addObj(Title::makeTitleSafe(NS_CATEGORY, $row->cat_title));
     }
     $batch->execute();
     $this->mResult->rewind();
     return parent::getBody();
 }
 /**
  * Pre-cache page existence to speed up link generation
  *
  * @param Database $dbr Database connection
  * @param int $res Result pointer
  */
 public function preprocessResults($dbr, $res)
 {
     $batch = new LinkBatch();
     while ($row = $dbr->fetchObject($res)) {
         $title = Title::makeTitleSafe($row->namespace, $row->title);
         $batch->addObj($title);
     }
     $batch->execute();
     if ($dbr->numRows($res) > 0) {
         $dbr->dataSeek($res, 0);
     }
 }
 /**
  * Fetch user page links and cache their existence
  */
 function preprocessResults(&$db, &$res)
 {
     $batch = new LinkBatch();
     while ($row = $db->fetchObject($res)) {
         $batch->addObj(Title::makeTitleSafe($row->namespace, $row->title));
     }
     $batch->execute();
     // Back to start for display
     if ($db->numRows($res) > 0) {
         // If there are no rows we get an error seeking.
         $db->dataSeek($res, 0);
     }
 }
 function getStartBody()
 {
     # Do a link batch query
     $this->mResult->seek(0);
     $batch = new LinkBatch();
     # Give some pointers to make (last) links
     $this->mForm->prevId = [];
     foreach ($this->mResult as $row) {
         $batch->addObj(Title::makeTitleSafe(NS_USER, $row->user_name));
         $batch->addObj(Title::makeTitleSafe(NS_USER_TALK, $row->user_name));
         $rev_id = isset($rev_id) ? $rev_id : $row->rev_id;
         if ($rev_id > $row->rev_id) {
             $this->mForm->prevId[$rev_id] = $row->rev_id;
         } elseif ($rev_id < $row->rev_id) {
             $this->mForm->prevId[$row->rev_id] = $rev_id;
         }
         $rev_id = $row->rev_id;
     }
     $batch->execute();
     $this->mResult->seek(0);
     return '';
 }
 function execute($par)
 {
     $this->setHeaders();
     $this->outputHeader();
     $this->getOutput()->allowClickjacking();
     $this->getOutput()->addHTML(Html::openElement('table', ['class' => 'mw-datatable', 'id' => 'mw-trackingcategories-table']) . "\n" . "<thead><tr>\n\t\t\t<th>" . $this->msg('trackingcategories-msg')->escaped() . "\n\t\t\t</th>\n\t\t\t<th>" . $this->msg('trackingcategories-name')->escaped() . "</th>\n\t\t\t<th>" . $this->msg('trackingcategories-desc')->escaped() . "\n\t\t\t</th>\n\t\t\t</tr></thead>");
     $trackingCategories = $this->prepareTrackingCategoriesData();
     $batch = new LinkBatch();
     foreach ($trackingCategories as $catMsg => $data) {
         $batch->addObj($data['msg']);
         foreach ($data['cats'] as $catTitle) {
             $batch->addObj($catTitle);
         }
     }
     $batch->execute();
     foreach ($trackingCategories as $catMsg => $data) {
         $allMsgs = [];
         $catDesc = $catMsg . '-desc';
         $catMsgTitleText = Linker::link($data['msg'], htmlspecialchars($catMsg));
         foreach ($data['cats'] as $catTitle) {
             $catTitleText = Linker::link($catTitle, htmlspecialchars($catTitle->getText()));
             $allMsgs[] = $catTitleText;
         }
         # Extra message, when no category was found
         if (!count($allMsgs)) {
             $allMsgs[] = $this->msg('trackingcategories-disabled')->parse();
         }
         /*
          * Show category description if it exists as a system message
          * as category-name-desc
          */
         $descMsg = $this->msg($catDesc);
         if ($descMsg->isBlank()) {
             $descMsg = $this->msg('trackingcategories-nodesc');
         }
         $this->getOutput()->addHTML(Html::openElement('tr') . Html::openElement('td', ['class' => 'mw-trackingcategories-name']) . $this->getLanguage()->commaList(array_unique($allMsgs)) . Html::closeElement('td') . Html::openElement('td', ['class' => 'mw-trackingcategories-msg']) . $catMsgTitleText . Html::closeElement('td') . Html::openElement('td', ['class' => 'mw-trackingcategories-desc']) . $descMsg->parse() . Html::closeElement('td') . Html::closeElement('tr'));
     }
     $this->getOutput()->addHTML(Html::closeElement('table'));
 }
 /**
  * Cache page existence for performance
  *
  * @param IDatabase $db
  * @param ResultWrapper $res
  */
 function preprocessResults($db, $res)
 {
     if (!$res->numRows()) {
         return;
     }
     $batch = new LinkBatch();
     foreach ($res as $row) {
         $batch->add($row->namespace, $row->title);
         $batch->addObj($this->getRedirectTarget($row));
     }
     $batch->execute();
     // Back to start for display
     $res->seek(0);
 }
 function getBody()
 {
     if (!$this->mQueryDone) {
         $this->doQuery();
     }
     $batch = new LinkBatch();
     $this->mResult->rewind();
     while ($row = $this->mResult->fetchObject()) {
         $batch->addObj(Title::makeTitleSafe(NS_CATEGORY, $row->cl_to));
     }
     $batch->execute();
     $this->mResult->rewind();
     return parent::getBody();
 }
 /**
  * Cache page existence for performance
  *
  * @param $db DatabaseBase
  * @param $res ResultWrapper
  */
 function preprocessResults($db, $res)
 {
     $batch = new LinkBatch();
     foreach ($res as $row) {
         $batch->add($row->namespace, $row->title);
         $batch->addObj($this->getRedirectTarget($row));
     }
     $batch->execute();
     // Back to start for display
     if ($db->numRows($res) > 0) {
         // If there are no rows we get an error seeking.
         $db->dataSeek($res, 0);
     }
 }
 function preprocessResults(&$db, &$res)
 {
     # There's no point doing a batch check if we aren't caching results;
     # the page must exist for it to have been pulled out of the table
     if ($this->isCached()) {
         $batch = new LinkBatch();
         while ($row = $db->fetchObject($res)) {
             $batch->addObj(Title::makeTitleSafe($row->namespace, $row->title));
         }
         $batch->execute();
         if ($db->numRows($res) > 0) {
             $db->dataSeek($res, 0);
         }
     }
 }
Exemple #18
0
 /**
  * Cache page existence for performance
  */
 function preprocessResults(&$db, &$res)
 {
     global $wgUser;
     $batch = new LinkBatch();
     while ($row = $db->fetchObject($res)) {
         # <jld>
         $ns = $row->pl_namespace;
         if (!$wgUser->isAllowedEx($ns, "~", "browse")) {
             continue;
         }
         #if (! $wgUser->isAllowed( hnpClass::buildPermissionKey($ns,"~","browse") ))				continue;
         # </jld>
         $batch->addObj(Title::makeTitleSafe($row->namespace, $row->title));
     }
     $batch->execute();
     // Back to start for display
     if ($db->numRows($res) > 0) {
         // If there are no rows we get an error seeking.
         $db->dataSeek($res, 0);
     }
 }
 /**
  * Make an HTML list of templates, and then add a "More..." link at
  * the bottom. If $more is null, do not add a "More..." link. If $more
  * is a LinkTarget, make a link to that title and use it. If $more is a string,
  * directly paste it in as the link (escaping needs to be done manually).
  *
  * @param LinkTarget[] $templates
  * @param string|bool $type 'preview' if a preview, 'section' if a section edit, false if neither
  * @param LinkTarget|string|null $more An escaped link for "More..." of the templates
  * @return string HTML output
  */
 public function format(array $templates, $type = false, $more = null)
 {
     if (!$templates) {
         // No templates
         return '';
     }
     # Do a batch existence check
     $batch = new LinkBatch();
     foreach ($templates as $title) {
         $batch->addObj($title);
     }
     $batch->execute();
     # Construct the HTML
     $outText = '<div class="mw-templatesUsedExplanation">';
     $count = count($templates);
     if ($type === 'preview') {
         $outText .= $this->context->msg('templatesusedpreview')->numParams($count)->parseAsBlock();
     } elseif ($type === 'section') {
         $outText .= $this->context->msg('templatesusedsection')->numParams($count)->parseAsBlock();
     } else {
         $outText .= $this->context->msg('templatesused')->numParams($count)->parseAsBlock();
     }
     $outText .= "</div><ul>\n";
     usort($templates, 'Title::compare');
     foreach ($templates as $template) {
         $outText .= $this->formatTemplate($template);
     }
     if ($more instanceof LinkTarget) {
         $outText .= Html::rawElement('li', [], $this->linkRenderer->makeLink($more, $this->context->msg('moredotdotdot')->text()));
     } elseif ($more) {
         // Documented as should already be escaped
         $outText .= Html::rawElement('li', [], $more);
     }
     $outText .= '</ul>';
     return $outText;
 }
 public function getStartBody()
 {
     # Do a link batch query
     if ($this->getNumRows() > 0) {
         $lb = new LinkBatch();
         foreach ($this->mResult as $row) {
             $lb->add($row->log_namespace, $row->log_title);
             $lb->addObj(Title::makeTitleSafe(NS_USER, $row->user_name));
             $lb->addObj(Title::makeTitleSafe(NS_USER_TALK, $row->user_name));
             $formatter = LogFormatter::newFromRow($row);
             foreach ($formatter->getPreloadTitles() as $title) {
                 $lb->addObj($title);
             }
         }
         $lb->execute();
         $this->mResult->seek(0);
     }
     return '';
 }
 /**
  * If a language supports multiple variants, it is possible that
  * non-existing link in one variant actually exists in another variant.
  * This function tries to find it. See e.g. LanguageZh.php
  * The input parameters may be modified upon return
  *
  * @param string &$link The name of the link
  * @param Title &$nt The title object of the link
  * @param bool $ignoreOtherCond To disable other conditions when
  *   we need to transclude a template or update a category's link
  */
 public function findVariantLink(&$link, &$nt, $ignoreOtherCond = false)
 {
     # If the article has already existed, there is no need to
     # check it again, otherwise it may cause a fault.
     if (is_object($nt) && $nt->exists()) {
         return;
     }
     global $wgDisableLangConversion, $wgDisableTitleConversion, $wgRequest;
     $isredir = $wgRequest->getText('redirect', 'yes');
     $action = $wgRequest->getText('action');
     if ($action == 'edit' && $wgRequest->getBool('redlink')) {
         $action = 'view';
     }
     $linkconvert = $wgRequest->getText('linkconvert', 'yes');
     $disableLinkConversion = $wgDisableLangConversion || $wgDisableTitleConversion;
     $linkBatch = new LinkBatch();
     $ns = NS_MAIN;
     if ($disableLinkConversion || !$ignoreOtherCond && ($isredir == 'no' || $action == 'edit' || $action == 'submit' || $linkconvert == 'no')) {
         return;
     }
     if (is_object($nt)) {
         $ns = $nt->getNamespace();
     }
     $variants = $this->autoConvertToAllVariants($link);
     if (!$variants) {
         // give up
         return;
     }
     $titles = [];
     foreach ($variants as $v) {
         if ($v != $link) {
             $varnt = Title::newFromText($v, $ns);
             if (!is_null($varnt)) {
                 $linkBatch->addObj($varnt);
                 $titles[] = $varnt;
             }
         }
     }
     // fetch all variants in single query
     $linkBatch->execute();
     foreach ($titles as $varnt) {
         if ($varnt->getArticleID() > 0) {
             $nt = $varnt;
             $link = $varnt->getText();
             break;
         }
     }
 }
Exemple #22
0
 /**
  * Returns HTML for the "templates used on this page" list.
  *
  * @param $templates Array of templates from Article::getUsedTemplate
  * or similar
  * @param $preview Boolean: whether this is for a preview
  * @param $section Boolean: whether this is for a section edit
  * @return String: HTML output
  */
 public static function formatTemplates($templates, $preview = false, $section = false)
 {
     wfProfileIn(__METHOD__);
     $outText = '';
     if (count($templates) > 0) {
         # Do a batch existence check
         $batch = new LinkBatch();
         foreach ($templates as $title) {
             $batch->addObj($title);
         }
         $batch->execute();
         # Construct the HTML
         $outText = '<div class="mw-templatesUsedExplanation">';
         if ($preview) {
             $outText .= wfMsgExt('templatesusedpreview', array('parse'), count($templates));
         } elseif ($section) {
             $outText .= wfMsgExt('templatesusedsection', array('parse'), count($templates));
         } else {
             $outText .= wfMsgExt('templatesused', array('parse'), count($templates));
         }
         $outText .= "</div><ul>\n";
         usort($templates, array('Title', 'compare'));
         foreach ($templates as $titleObj) {
             $r = $titleObj->getRestrictions('edit');
             if (in_array('sysop', $r)) {
                 $protected = wfMsgExt('template-protected', array('parseinline'));
             } elseif (in_array('autoconfirmed', $r)) {
                 $protected = wfMsgExt('template-semiprotected', array('parseinline'));
             } else {
                 $protected = '';
             }
             if ($titleObj->quickUserCan('edit')) {
                 $editLink = self::link($titleObj, wfMsg('editlink'), array(), array('action' => 'edit'));
             } else {
                 $editLink = self::link($titleObj, wfMsg('viewsourcelink'), array(), array('action' => 'edit'));
             }
             $outText .= '<li>' . self::link($titleObj) . ' (' . $editLink . ') ' . $protected . '</li>';
         }
         $outText .= '</ul>';
     }
     wfProfileOut(__METHOD__);
     return $outText;
 }
 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;
 }
 /**
  * Print out a list of linked titles
  *
  * $titles can be an array of strings or Title objects; the former
  * is preferred, since Titles are very memory-heavy
  *
  * @param $titles array of strings, or Title objects
  * @param $output String
  */
 private function showTitles($titles, &$output)
 {
     $talk = $this->msg('talkpagelinktext')->escaped();
     // Do a batch existence check
     $batch = new LinkBatch();
     foreach ($titles as $title) {
         if (!$title instanceof Title) {
             $title = Title::newFromText($title);
         }
         if ($title instanceof Title) {
             $batch->addObj($title);
             $batch->addObj($title->getTalkPage());
         }
     }
     $batch->execute();
     // Print out the list
     $output .= "<ul>\n";
     foreach ($titles as $title) {
         if (!$title instanceof Title) {
             $title = Title::newFromText($title);
         }
         if ($title instanceof Title) {
             $output .= "<li>" . Linker::link($title) . ' (' . Linker::link($title->getTalkPage(), $talk) . ")</li>\n";
         }
     }
     $output .= "</ul>\n";
 }
 /**
  * Get the modification times of all titles that would be loaded for
  * a given context.
  * @param $context ResourceLoaderContext: Context object
  * @return array( prefixed DB key => UNIX timestamp ), nonexistent titles are dropped
  */
 protected function getTitleMtimes(ResourceLoaderContext $context)
 {
     $dbr = $this->getDB();
     if (!$dbr) {
         // We're dealing with a subclass that doesn't have a DB
         return array();
     }
     $hash = $context->getHash();
     if (isset($this->titleMtimes[$hash])) {
         return $this->titleMtimes[$hash];
     }
     $this->titleMtimes[$hash] = array();
     $batch = new LinkBatch();
     foreach ($this->getPages($context) as $titleText => $options) {
         $batch->addObj(Title::newFromText($titleText));
     }
     if (!$batch->isEmpty()) {
         $res = $dbr->select('page', array('page_namespace', 'page_title', 'page_touched'), $batch->constructSet('page', $dbr), __METHOD__);
         foreach ($res as $row) {
             $title = Title::makeTitle($row->page_namespace, $row->page_title);
             $this->titleMtimes[$hash][$title->getPrefixedDBkey()] = wfTimestamp(TS_UNIX, $row->page_touched);
         }
     }
     return $this->titleMtimes[$hash];
 }
 /**
  * Return a HTML representation of the image gallery
  *
  * For each image in the gallery, display
  * - a thumbnail
  * - the image name
  * - the additional text provided when adding the image
  * - the size of the image
  *
  * @return string
  */
 function toHTML()
 {
     if ($this->mPerRow > 0) {
         $maxwidth = $this->mPerRow * ($this->mWidths + $this->getAllPadding());
         $oldStyle = isset($this->mAttribs['style']) ? $this->mAttribs['style'] : '';
         # _width is ignored by any sane browser. IE6 doesn't know max-width
         # so it uses _width instead
         $this->mAttribs['style'] = "max-width: {$maxwidth}px;_width: {$maxwidth}px;" . $oldStyle;
     }
     $attribs = Sanitizer::mergeAttributes(['class' => 'gallery mw-gallery-' . $this->mMode], $this->mAttribs);
     $modules = $this->getModules();
     if ($this->mParser) {
         $this->mParser->getOutput()->addModules($modules);
         $this->mParser->getOutput()->addModuleStyles('mediawiki.page.gallery.styles');
     } else {
         $this->getOutput()->addModules($modules);
         $this->getOutput()->addModuleStyles('mediawiki.page.gallery.styles');
     }
     $output = Xml::openElement('ul', $attribs);
     if ($this->mCaption) {
         $output .= "\n\t<li class='gallerycaption'>{$this->mCaption}</li>";
     }
     if ($this->mShowFilename) {
         // Preload LinkCache info for when generating links
         // of the filename below
         $lb = new LinkBatch();
         foreach ($this->mImages as $img) {
             $lb->addObj($img[0]);
         }
         $lb->execute();
     }
     $lang = $this->getRenderLang();
     # Output each image...
     foreach ($this->mImages as $pair) {
         /** @var Title $nt */
         $nt = $pair[0];
         $text = $pair[1];
         # "text" means "caption" here
         $alt = $pair[2];
         $link = $pair[3];
         $descQuery = false;
         if ($nt->getNamespace() === NS_FILE) {
             # Get the file...
             if ($this->mParser instanceof Parser) {
                 # Give extensions a chance to select the file revision for us
                 $options = [];
                 Hooks::run('BeforeParserFetchFileAndTitle', [$this->mParser, $nt, &$options, &$descQuery]);
                 # Fetch and register the file (file title may be different via hooks)
                 list($img, $nt) = $this->mParser->fetchFileAndTitle($nt, $options);
             } else {
                 $img = wfFindFile($nt);
             }
         } else {
             $img = false;
         }
         $params = $this->getThumbParams($img);
         // $pair[4] is per image handler options
         $transformOptions = $params + $pair[4];
         $thumb = false;
         if (!$img) {
             # We're dealing with a non-image, spit out the name and be done with it.
             $thumbhtml = "\n\t\t\t" . '<div class="thumb" style="height: ' . ($this->getThumbPadding() + $this->mHeights) . 'px;">' . htmlspecialchars($nt->getText()) . '</div>';
             if ($this->mParser instanceof Parser) {
                 $this->mParser->addTrackingCategory('broken-file-category');
             }
         } elseif ($this->mHideBadImages && wfIsBadImage($nt->getDBkey(), $this->getContextTitle())) {
             # The image is blacklisted, just show it as a text link.
             $thumbhtml = "\n\t\t\t" . '<div class="thumb" style="height: ' . ($this->getThumbPadding() + $this->mHeights) . 'px;">' . Linker::linkKnown($nt, htmlspecialchars($nt->getText())) . '</div>';
         } else {
             $thumb = $img->transform($transformOptions);
             if (!$thumb) {
                 # Error generating thumbnail.
                 $thumbhtml = "\n\t\t\t" . '<div class="thumb" style="height: ' . ($this->getThumbPadding() + $this->mHeights) . 'px;">' . htmlspecialchars($img->getLastError()) . '</div>';
             } else {
                 /** @var MediaTransformOutput $thumb */
                 $vpad = $this->getVPad($this->mHeights, $thumb->getHeight());
                 $imageParameters = ['desc-link' => true, 'desc-query' => $descQuery, 'alt' => $alt, 'custom-url-link' => $link];
                 // In the absence of both alt text and caption, fall back on
                 // providing screen readers with the filename as alt text
                 if ($alt == '' && $text == '') {
                     $imageParameters['alt'] = $nt->getText();
                 }
                 $this->adjustImageParameters($thumb, $imageParameters);
                 Linker::processResponsiveImages($img, $thumb, $transformOptions);
                 # Set both fixed width and min-height.
                 $thumbhtml = "\n\t\t\t" . '<div class="thumb" style="width: ' . $this->getThumbDivWidth($thumb->getWidth()) . 'px;">' . '<div style="margin:' . $vpad . 'px auto;">' . $thumb->toHtml($imageParameters) . '</div></div>';
                 // Call parser transform hook
                 /** @var MediaHandler $handler */
                 $handler = $img->getHandler();
                 if ($this->mParser && $handler) {
                     $handler->parserTransformHook($this->mParser, $img);
                 }
             }
         }
         // @todo Code is incomplete.
         // $linkTarget = Title::newFromText( $wgContLang->getNsText( MWNamespace::getUser() ) .
         // ":{$ut}" );
         // $ul = Linker::link( $linkTarget, $ut );
         if ($this->mShowBytes) {
             if ($img) {
                 $fileSize = htmlspecialchars($lang->formatSize($img->getSize()));
             } else {
                 $fileSize = $this->msg('filemissing')->escaped();
             }
             $fileSize = "{$fileSize}<br />\n";
         } else {
             $fileSize = '';
         }
         $textlink = $this->mShowFilename ? Linker::linkKnown($nt, htmlspecialchars($lang->truncate($nt->getText(), $this->mCaptionLength))) . "<br />\n" : '';
         $galleryText = $textlink . $text . $fileSize;
         $galleryText = $this->wrapGalleryText($galleryText, $thumb);
         # Weird double wrapping (the extra div inside the li) needed due to FF2 bug
         # Can be safely removed if FF2 falls completely out of existence
         $output .= "\n\t\t" . '<li class="gallerybox" style="width: ' . $this->getGBWidth($thumb) . 'px">' . '<div style="width: ' . $this->getGBWidth($thumb) . 'px">' . $thumbhtml . $galleryText . "\n\t\t</div></li>";
     }
     $output .= "\n</ul>";
     return $output;
 }
Exemple #27
0
function wfPolyglotGetLanguages($title)
{
    global $wgPolyglotLanguages;
    if (!$wgPolyglotLanguages) {
        return null;
    }
    $n = $title->getDBkey();
    $ns = $title->getNamespace();
    $titles = array();
    $batch = new LinkBatch();
    foreach ($wgPolyglotLanguages as $lang) {
        $obj = Title::makeTitle($ns, $n . '/' . $lang);
        $batch->addObj($obj);
        $titles[] = array($obj, $lang);
    }
    $batch->execute();
    $links = array();
    foreach ($titles as $parts) {
        list($t, $lang) = $parts;
        if ($t->exists()) {
            $links[$lang] = $t->getFullText();
        }
    }
    return $links;
}
 /**
  * Print out a list of linked titles
  *
  * $titles can be an array of strings or Title objects; the former
  * is preferred, since Titles are very memory-heavy
  *
  * @param array $titles Array of strings, or Title objects
  * @param string $output
  */
 private function showTitles($titles, &$output)
 {
     $talk = $this->msg('talkpagelinktext')->escaped();
     // Do a batch existence check
     $batch = new LinkBatch();
     if (count($titles) >= 100) {
         $output = $this->msg('watchlistedit-too-many')->parse();
         return;
     }
     foreach ($titles as $title) {
         if (!$title instanceof Title) {
             $title = Title::newFromText($title);
         }
         if ($title instanceof Title) {
             $batch->addObj($title);
             $batch->addObj($title->getTalkPage());
         }
     }
     $batch->execute();
     // Print out the list
     $output .= "<ul>\n";
     foreach ($titles as $title) {
         if (!$title instanceof Title) {
             $title = Title::newFromText($title);
         }
         if ($title instanceof Title) {
             $output .= '<li>' . Linker::link($title) . ' ' . $this->msg('parentheses')->rawParams(Linker::link($title->getTalkPage(), $talk))->escaped() . "</li>\n";
         }
     }
     $output .= "</ul>\n";
 }
/**
 * Constructor
 */
function wfSpecialRecentchanges($par, $specialPage)
{
    global $wgUser, $wgOut, $wgRequest, $wgUseRCPatrol;
    global $wgRCShowWatchingUsers, $wgShowUpdatedMarker;
    global $wgAllowCategorizedRecentChanges;
    $fname = 'wfSpecialRecentchanges';
    # Get query parameters
    $feedFormat = $wgRequest->getVal('feed');
    /* Checkbox values can't be true by default, because
     * we cannot differentiate between unset and not set at all
     */
    $defaults = array('days' => $wgUser->getDefaultOption('rcdays'), 'limit' => $wgUser->getDefaultOption('rclimit'), 'hideminor' => false, 'hidebots' => true, 'hideanons' => false, 'hideliu' => false, 'hidepatrolled' => false, 'hidemyself' => false, 'from' => '', 'namespace' => null, 'invert' => false, 'categories_any' => false);
    extract($defaults);
    $days = $wgUser->getOption('rcdays', $defaults['days']);
    $days = $wgRequest->getInt('days', $days);
    $limit = $wgUser->getOption('rclimit', $defaults['limit']);
    #	list( $limit, $offset ) = wfCheckLimits( 100, 'rclimit' );
    $limit = $wgRequest->getInt('limit', $limit);
    /* order of selection: url > preferences > default */
    $hideminor = $wgRequest->getBool('hideminor', $wgUser->getOption('hideminor') ? true : $defaults['hideminor']);
    # As a feed, use limited settings only
    if ($feedFormat) {
        global $wgFeedLimit;
        if ($limit > $wgFeedLimit) {
            $limit = $wgFeedLimit;
        }
    } else {
        $namespace = $wgRequest->getIntOrNull('namespace');
        $invert = $wgRequest->getBool('invert', $defaults['invert']);
        $hidebots = $wgRequest->getBool('hidebots', $defaults['hidebots']);
        $hideanons = $wgRequest->getBool('hideanons', $defaults['hideanons']);
        $hideliu = $wgRequest->getBool('hideliu', $defaults['hideliu']);
        $hidepatrolled = $wgRequest->getBool('hidepatrolled', $defaults['hidepatrolled']);
        $hidemyself = $wgRequest->getBool('hidemyself', $defaults['hidemyself']);
        $from = $wgRequest->getVal('from', $defaults['from']);
        # Get query parameters from path
        if ($par) {
            $bits = preg_split('/\\s*,\\s*/', trim($par));
            foreach ($bits as $bit) {
                if ('hidebots' == $bit) {
                    $hidebots = 1;
                }
                if ('bots' == $bit) {
                    $hidebots = 0;
                }
                if ('hideminor' == $bit) {
                    $hideminor = 1;
                }
                if ('minor' == $bit) {
                    $hideminor = 0;
                }
                if ('hideliu' == $bit) {
                    $hideliu = 1;
                }
                if ('hidepatrolled' == $bit) {
                    $hidepatrolled = 1;
                }
                if ('hideanons' == $bit) {
                    $hideanons = 1;
                }
                if ('hidemyself' == $bit) {
                    $hidemyself = 1;
                }
                if (is_numeric($bit)) {
                    $limit = $bit;
                }
                $m = array();
                if (preg_match('/^limit=(\\d+)$/', $bit, $m)) {
                    $limit = $m[1];
                }
                if (preg_match('/^days=(\\d+)$/', $bit, $m)) {
                    $days = $m[1];
                }
            }
        }
    }
    if ($limit < 0 || $limit > 5000) {
        $limit = $defaults['limit'];
    }
    # Database connection and caching
    $dbr = wfGetDB(DB_SLAVE);
    list($recentchanges, $watchlist) = $dbr->tableNamesN('recentchanges', 'watchlist');
    $cutoff_unixtime = time() - $days * 86400;
    $cutoff_unixtime = $cutoff_unixtime - $cutoff_unixtime % 86400;
    $cutoff = $dbr->timestamp($cutoff_unixtime);
    if (preg_match('/^[0-9]{14}$/', $from) and $from > wfTimestamp(TS_MW, $cutoff)) {
        $cutoff = $dbr->timestamp($from);
    } else {
        $from = $defaults['from'];
    }
    # 10 seconds server-side caching max
    $wgOut->setSquidMaxage(10);
    # Get last modified date, for client caching
    # Don't use this if we are using the patrol feature, patrol changes don't update the timestamp
    $lastmod = $dbr->selectField('recentchanges', 'MAX(rc_timestamp)', false, $fname);
    if ($feedFormat || !$wgUseRCPatrol) {
        if ($lastmod && $wgOut->checkLastModified($lastmod)) {
            # Client cache fresh and headers sent, nothing more to do.
            return;
        }
    }
    # It makes no sense to hide both anons and logged-in users
    # Where this occurs, force anons to be shown
    if ($hideanons && $hideliu) {
        $hideanons = false;
    }
    # Form WHERE fragments for all the options
    $hidem = $hideminor ? 'AND rc_minor = 0' : '';
    $hidem .= $hidebots ? ' AND rc_bot = 0' : '';
    $hidem .= $hideliu ? ' AND rc_user = 0' : '';
    $hidem .= $wgUseRCPatrol && $hidepatrolled ? ' AND rc_patrolled = 0' : '';
    $hidem .= $hideanons ? ' AND rc_user != 0' : '';
    if ($hidemyself) {
        if ($wgUser->getID()) {
            $hidem .= ' AND rc_user != ' . $wgUser->getID();
        } else {
            $hidem .= ' AND rc_user_text != ' . $dbr->addQuotes($wgUser->getName());
        }
    }
    # Namespace filtering
    $hidem .= is_null($namespace) ? '' : ' AND rc_namespace' . ($invert ? '!=' : '=') . $namespace;
    // This is the big thing!
    $uid = $wgUser->getID();
    // Perform query
    $forceclause = $dbr->useIndexClause("rc_timestamp");
    $sql2 = "SELECT * FROM {$recentchanges} {$forceclause}" . ($uid ? "LEFT OUTER JOIN {$watchlist} ON wl_user={$uid} AND wl_title=rc_title AND wl_namespace=rc_namespace " : "") . "WHERE rc_timestamp >= '{$cutoff}' {$hidem} " . "ORDER BY rc_timestamp DESC";
    $sql2 = $dbr->limitResult($sql2, $limit, 0);
    $res = $dbr->query($sql2, $fname);
    // Fetch results, prepare a batch link existence check query
    $rows = array();
    $batch = new LinkBatch();
    while ($row = $dbr->fetchObject($res)) {
        $rows[] = $row;
        if (!$feedFormat) {
            // User page link
            $title = Title::makeTitleSafe(NS_USER, $row->rc_user_text);
            $batch->addObj($title);
            // User talk
            $title = Title::makeTitleSafe(NS_USER_TALK, $row->rc_user_text);
            $batch->addObj($title);
        }
    }
    $dbr->freeResult($res);
    if ($feedFormat) {
        rcOutputFeed($rows, $feedFormat, $limit, $hideminor, $lastmod);
    } else {
        # Web output...
        // Run existence checks
        $batch->execute();
        $any = $wgRequest->getBool('categories_any', $defaults['categories_any']);
        // Output header
        if (!$specialPage->including()) {
            $wgOut->addWikiText(wfMsgForContentNoTrans("recentchangestext"));
            // Dump everything here
            $nondefaults = array();
            wfAppendToArrayIfNotDefault('days', $days, $defaults, $nondefaults);
            wfAppendToArrayIfNotDefault('limit', $limit, $defaults, $nondefaults);
            wfAppendToArrayIfNotDefault('hideminor', $hideminor, $defaults, $nondefaults);
            wfAppendToArrayIfNotDefault('hidebots', $hidebots, $defaults, $nondefaults);
            wfAppendToArrayIfNotDefault('hideanons', $hideanons, $defaults, $nondefaults);
            wfAppendToArrayIfNotDefault('hideliu', $hideliu, $defaults, $nondefaults);
            wfAppendToArrayIfNotDefault('hidepatrolled', $hidepatrolled, $defaults, $nondefaults);
            wfAppendToArrayIfNotDefault('hidemyself', $hidemyself, $defaults, $nondefaults);
            wfAppendToArrayIfNotDefault('from', $from, $defaults, $nondefaults);
            wfAppendToArrayIfNotDefault('namespace', $namespace, $defaults, $nondefaults);
            wfAppendToArrayIfNotDefault('invert', $invert, $defaults, $nondefaults);
            wfAppendToArrayIfNotDefault('categories_any', $any, $defaults, $nondefaults);
            // Add end of the texts
            $wgOut->addHTML('<div class="rcoptions">' . rcOptionsPanel($defaults, $nondefaults) . "\n");
            $wgOut->addHTML(rcNamespaceForm($namespace, $invert, $nondefaults, $any) . '</div>' . "\n");
        }
        // And now for the content
        $list = ChangesList::newFromUser($wgUser);
        if ($wgAllowCategorizedRecentChanges) {
            $categories = trim($wgRequest->getVal('categories', ""));
            $categories = str_replace("|", "\n", $categories);
            $categories = explode("\n", $categories);
            rcFilterByCategories($rows, $categories, $any);
        }
        $s = $list->beginRecentChangesList();
        $counter = 1;
        foreach ($rows as $obj) {
            if ($limit == 0) {
                break;
            }
            if (!($hideminor && $obj->rc_minor) && !($hidepatrolled && $obj->rc_patrolled)) {
                $rc = RecentChange::newFromRow($obj);
                $rc->counter = $counter++;
                if ($wgShowUpdatedMarker && !empty($obj->wl_notificationtimestamp) && $obj->rc_timestamp >= $obj->wl_notificationtimestamp) {
                    $rc->notificationtimestamp = true;
                } else {
                    $rc->notificationtimestamp = false;
                }
                if ($wgRCShowWatchingUsers && $wgUser->getOption('shownumberswatching')) {
                    $sql3 = "SELECT COUNT(*) AS n FROM {$watchlist} WHERE wl_title='" . $dbr->strencode($obj->rc_title) . "' AND wl_namespace={$obj->rc_namespace}";
                    $res3 = $dbr->query($sql3, 'wfSpecialRecentChanges');
                    $x = $dbr->fetchObject($res3);
                    $rc->numberofWatchingusers = $x->n;
                } else {
                    $rc->numberofWatchingusers = 0;
                }
                $s .= $list->recentChangesLine($rc, !empty($obj->wl_user));
                --$limit;
            }
        }
        $s .= $list->endRecentChangesList();
        $wgOut->addHTML($s);
    }
}
 protected function showHistory()
 {
     $this->checkReadOnly();
     $out = $this->getOutput();
     if ($this->mAllowed) {
         $out->addModules('mediawiki.special.undelete');
     }
     $out->wrapWikiMsg("<div class='mw-undelete-pagetitle'>\n\$1\n</div>\n", array('undeletepagetitle', wfEscapeWikiText($this->mTargetObj->getPrefixedText())));
     $archive = new PageArchive($this->mTargetObj, $this->getConfig());
     Hooks::run('UndeleteForm::showHistory', array(&$archive, $this->mTargetObj));
     /*
     $text = $archive->getLastRevisionText();
     if( is_null( $text ) ) {
     	$out->addWikiMsg( 'nohistory' );
     	return;
     }
     */
     $out->addHTML('<div class="mw-undelete-history">');
     if ($this->mAllowed) {
         $out->addWikiMsg('undeletehistory');
         $out->addWikiMsg('undeleterevdel');
     } else {
         $out->addWikiMsg('undeletehistorynoadmin');
     }
     $out->addHTML('</div>');
     # List all stored revisions
     $revisions = $archive->listRevisions();
     $files = $archive->listFiles();
     $haveRevisions = $revisions && $revisions->numRows() > 0;
     $haveFiles = $files && $files->numRows() > 0;
     # Batch existence check on user and talk pages
     if ($haveRevisions) {
         $batch = new LinkBatch();
         foreach ($revisions as $row) {
             $batch->addObj(Title::makeTitleSafe(NS_USER, $row->ar_user_text));
             $batch->addObj(Title::makeTitleSafe(NS_USER_TALK, $row->ar_user_text));
         }
         $batch->execute();
         $revisions->seek(0);
     }
     if ($haveFiles) {
         $batch = new LinkBatch();
         foreach ($files as $row) {
             $batch->addObj(Title::makeTitleSafe(NS_USER, $row->fa_user_text));
             $batch->addObj(Title::makeTitleSafe(NS_USER_TALK, $row->fa_user_text));
         }
         $batch->execute();
         $files->seek(0);
     }
     if ($this->mAllowed) {
         $action = $this->getPageTitle()->getLocalURL(array('action' => 'submit'));
         # Start the form here
         $top = Xml::openElement('form', array('method' => 'post', 'action' => $action, 'id' => 'undelete'));
         $out->addHTML($top);
     }
     # Show relevant lines from the deletion log:
     $deleteLogPage = new LogPage('delete');
     $out->addHTML(Xml::element('h2', null, $deleteLogPage->getName()->text()) . "\n");
     LogEventsList::showLogExtract($out, 'delete', $this->mTargetObj);
     # Show relevant lines from the suppression log:
     $suppressLogPage = new LogPage('suppress');
     if ($this->getUser()->isAllowed('suppressionlog')) {
         $out->addHTML(Xml::element('h2', null, $suppressLogPage->getName()->text()) . "\n");
         LogEventsList::showLogExtract($out, 'suppress', $this->mTargetObj);
     }
     if ($this->mAllowed && ($haveRevisions || $haveFiles)) {
         # Format the user-visible controls (comment field, submission button)
         # in a nice little table
         if ($this->getUser()->isAllowed('suppressrevision')) {
             $unsuppressBox = "<tr>\n\t\t\t\t\t\t<td>&#160;</td>\n\t\t\t\t\t\t<td class='mw-input'>" . Xml::checkLabel($this->msg('revdelete-unsuppress')->text(), 'wpUnsuppress', 'mw-undelete-unsuppress', $this->mUnsuppress) . "</td>\n\t\t\t\t\t</tr>";
         } else {
             $unsuppressBox = '';
         }
         $table = Xml::fieldset($this->msg('undelete-fieldset-title')->text()) . Xml::openElement('table', array('id' => 'mw-undelete-table')) . "<tr>\n\t\t\t\t\t<td colspan='2' class='mw-undelete-extrahelp'>" . $this->msg('undeleteextrahelp')->parseAsBlock() . "</td>\n\t\t\t</tr>\n\t\t\t<tr>\n\t\t\t\t<td class='mw-label'>" . Xml::label($this->msg('undeletecomment')->text(), 'wpComment') . "</td>\n\t\t\t\t<td class='mw-input'>" . Xml::input('wpComment', 50, $this->mComment, array('id' => 'wpComment', 'autofocus' => '')) . "</td>\n\t\t\t</tr>\n\t\t\t<tr>\n\t\t\t\t<td>&#160;</td>\n\t\t\t\t<td class='mw-submit'>" . Xml::submitButton($this->msg('undeletebtn')->text(), array('name' => 'restore', 'id' => 'mw-undelete-submit')) . ' ' . Xml::submitButton($this->msg('undeleteinvert')->text(), array('name' => 'invert', 'id' => 'mw-undelete-invert')) . "</td>\n\t\t\t</tr>" . $unsuppressBox . Xml::closeElement('table') . Xml::closeElement('fieldset');
         $out->addHTML($table);
     }
     $out->addHTML(Xml::element('h2', null, $this->msg('history')->text()) . "\n");
     if ($haveRevisions) {
         # The page's stored (deleted) history:
         $out->addHTML('<ul>');
         $remaining = $revisions->numRows();
         $earliestLiveTime = $this->mTargetObj->getEarliestRevTime();
         foreach ($revisions as $row) {
             $remaining--;
             $out->addHTML($this->formatRevisionRow($row, $earliestLiveTime, $remaining));
         }
         $revisions->free();
         $out->addHTML('</ul>');
     } else {
         $out->addWikiMsg('nohistory');
     }
     if ($haveFiles) {
         $out->addHTML(Xml::element('h2', null, $this->msg('filehist')->text()) . "\n");
         $out->addHTML('<ul>');
         foreach ($files as $row) {
             $out->addHTML($this->formatFileRow($row));
         }
         $files->free();
         $out->addHTML('</ul>');
     }
     if ($this->mAllowed) {
         # Slip in the hidden controls here
         $misc = Html::hidden('target', $this->mTarget);
         $misc .= Html::hidden('wpEditToken', $this->getUser()->getEditToken());
         $misc .= Xml::closeElement('form');
         $out->addHTML($misc);
     }
     return true;
 }