function doTagRow($tag, $hitcount)
 {
     $user = $this->getUser();
     $newRow = '';
     $newRow .= Xml::tags('td', null, Xml::element('code', null, $tag));
     $disp = ChangeTags::tagDescription($tag);
     if ($user->isAllowed('editinterface')) {
         $disp .= ' ';
         $editLink = Linker::link(Title::makeTitle(NS_MEDIAWIKI, "Tag-{$tag}"), $this->msg('tags-edit')->escaped());
         $disp .= $this->msg('parentheses')->rawParams($editLink)->escaped();
     }
     $newRow .= Xml::tags('td', null, $disp);
     $msg = $this->msg("tag-{$tag}-description");
     $desc = !$msg->exists() ? '' : $msg->parse();
     if ($user->isAllowed('editinterface')) {
         $desc .= ' ';
         $editDescLink = Linker::link(Title::makeTitle(NS_MEDIAWIKI, "Tag-{$tag}-description"), $this->msg('tags-edit')->escaped());
         $desc .= $this->msg('parentheses')->rawParams($editDescLink)->escaped();
     }
     $newRow .= Xml::tags('td', null, $desc);
     $active = isset($this->definedTags[$tag]) ? 'tags-active-yes' : 'tags-active-no';
     $active = $this->msg($active)->escaped();
     $newRow .= Xml::tags('td', null, $active);
     $hitcountLabel = $this->msg('tags-hitcount')->numParams($hitcount)->escaped();
     $hitcountLink = Linker::link(SpecialPage::getTitleFor('Recentchanges'), $hitcountLabel, array(), array('tagfilter' => $tag));
     // add raw $hitcount for sorting, because tags-hitcount contains numbers and letters
     $newRow .= Xml::tags('td', array('data-sort-value' => $hitcount), $hitcountLink);
     return Xml::tags('tr', null, $newRow) . "\n";
 }
Exemple #2
0
 function doTagRow($tag, $hitcount)
 {
     static $doneTags = array();
     if (in_array($tag, $doneTags)) {
         return '';
     }
     $newRow = '';
     $newRow .= Xml::tags('td', null, Xml::element('code', null, $tag));
     $disp = ChangeTags::tagDescription($tag);
     $disp .= ' ';
     $editLink = Linker::link(Title::makeTitle(NS_MEDIAWIKI, "Tag-{$tag}"), $this->msg('tags-edit')->escaped());
     $disp .= $this->msg('parentheses')->rawParams($editLink)->escaped();
     $newRow .= Xml::tags('td', null, $disp);
     $msg = $this->msg("tag-{$tag}-description");
     $desc = !$msg->exists() ? '' : $msg->parse();
     $desc .= ' ';
     $editDescLink = Linker::link(Title::makeTitle(NS_MEDIAWIKI, "Tag-{$tag}-description"), $this->msg('tags-edit')->escaped());
     $desc .= $this->msg('parentheses')->rawParams($editDescLink)->escaped();
     $newRow .= Xml::tags('td', null, $desc);
     $hitcount = $this->msg('tags-hitcount')->numParams($hitcount)->escaped();
     $hitcount = Linker::link(SpecialPage::getTitleFor('Recentchanges'), $hitcount, array(), array('tagfilter' => $tag));
     $newRow .= Xml::tags('td', null, $hitcount);
     $doneTags[] = $tag;
     return Xml::tags('tr', null, $newRow) . "\n";
 }
Exemple #3
0
 function doTagRow($tag, $hitcount)
 {
     static $sk = null, $doneTags = array();
     if (!$sk) {
         $sk = $this->getSkin();
     }
     if (in_array($tag, $doneTags)) {
         return '';
     }
     global $wgLang;
     $newRow = '';
     $newRow .= Xml::tags('td', null, Xml::element('tt', null, $tag));
     $disp = ChangeTags::tagDescription($tag);
     $disp .= ' (' . $sk->link(Title::makeTitle(NS_MEDIAWIKI, "Tag-{$tag}"), wfMsgHtml('tags-edit')) . ')';
     $newRow .= Xml::tags('td', null, $disp);
     $msg = wfMessage("tag-{$tag}-description");
     $desc = !$msg->exists() ? '' : $msg->parse();
     $desc .= ' (' . $sk->link(Title::makeTitle(NS_MEDIAWIKI, "Tag-{$tag}-description"), wfMsgHtml('tags-edit')) . ')';
     $newRow .= Xml::tags('td', null, $desc);
     $hitcount = wfMsgExt('tags-hitcount', array('parsemag'), $wgLang->formatNum($hitcount));
     $hitcount = $sk->link(SpecialPage::getTitleFor('Recentchanges'), $hitcount, array(), array('tagfilter' => $tag));
     $newRow .= Xml::tags('td', null, $hitcount);
     $doneTags[] = $tag;
     return Xml::tags('tr', null, $newRow) . "\n";
 }
Exemple #4
0
 function doTagRow($tag, $hitcount)
 {
     static $sk = null, $doneTags = array();
     if (!$sk) {
         global $wgUser;
         $sk = $wgUser->getSkin();
     }
     if (in_array($tag, $doneTags)) {
         return '';
     }
     $newRow = '';
     $newRow .= Xml::tags('td', null, Xml::element('tt', null, $tag));
     $disp = ChangeTags::tagDescription($tag);
     $disp .= ' (' . $sk->link(Title::makeTitle(NS_MEDIAWIKI, "Tag-{$tag}"), wfMsg('tags-edit')) . ')';
     $newRow .= Xml::tags('td', null, $disp);
     $desc = wfMsgExt("tag-{$tag}-description", 'parseinline');
     $desc = wfEmptyMsg("tag-{$tag}-description", $desc) ? '' : $desc;
     $desc .= ' (' . $sk->link(Title::makeTitle(NS_MEDIAWIKI, "Tag-{$tag}-description"), wfMsg('tags-edit')) . ')';
     $newRow .= Xml::tags('td', null, $desc);
     $hitcount = wfMsg('tags-hitcount', $hitcount);
     $hitcount = $sk->link(SpecialPage::getTitleFor('RecentChanges'), $hitcount, array(), array('tagfilter' => $tag));
     $newRow .= Xml::tags('td', null, $hitcount);
     $doneTags[] = $tag;
     return Xml::tags('tr', null, $newRow) . "\n";
 }
 /**
  * @param IDatabase $db
  * @return mixed
  */
 public function doQuery($db)
 {
     $ids = array_map('intval', $this->ids);
     $queryInfo = ['tables' => ['revision', 'user'], 'fields' => array_merge(Revision::selectFields(), Revision::selectUserFields()), 'conds' => ['rev_page' => $this->title->getArticleID(), 'rev_id' => $ids], 'options' => ['ORDER BY' => 'rev_id DESC'], 'join_conds' => ['page' => Revision::pageJoinCond(), 'user' => Revision::userJoinCond()]];
     ChangeTags::modifyDisplayQuery($queryInfo['tables'], $queryInfo['fields'], $queryInfo['conds'], $queryInfo['join_conds'], $queryInfo['options'], '');
     $live = $db->select($queryInfo['tables'], $queryInfo['fields'], $queryInfo['conds'], __METHOD__, $queryInfo['options'], $queryInfo['join_conds']);
     if ($live->numRows() >= count($ids)) {
         // All requested revisions are live, keeps things simple!
         return $live;
     }
     $archiveQueryInfo = ['tables' => ['archive'], 'fields' => Revision::selectArchiveFields(), 'conds' => ['ar_rev_id' => $ids], 'options' => ['ORDER BY' => 'ar_rev_id DESC'], 'join_conds' => []];
     ChangeTags::modifyDisplayQuery($archiveQueryInfo['tables'], $archiveQueryInfo['fields'], $archiveQueryInfo['conds'], $archiveQueryInfo['join_conds'], $archiveQueryInfo['options'], '');
     // Check if any requested revisions are available fully deleted.
     $archived = $db->select($archiveQueryInfo['tables'], $archiveQueryInfo['fields'], $archiveQueryInfo['conds'], __METHOD__, $archiveQueryInfo['options'], $archiveQueryInfo['join_conds']);
     if ($archived->numRows() == 0) {
         return $live;
     } elseif ($live->numRows() == 0) {
         return $archived;
     } else {
         // Combine the two! Whee
         $rows = [];
         foreach ($live as $row) {
             $rows[$row->rev_id] = $row;
         }
         foreach ($archived as $row) {
             $rows[$row->ar_rev_id] = $row;
         }
         krsort($rows);
         return new FakeResultWrapper(array_values($rows));
     }
 }
 /**
  * Display a list with the passed revisions.
  *
  * @since 0.1
  *
  * @param EPPageObject $object
  */
 protected function displayRevisions(EPPageObject $object)
 {
     $conditions = array('type' => get_class($object));
     if ($object->hasIdField()) {
         $conditions['object_id'] = $object->getId();
     }
     $action = htmlspecialchars($GLOBALS['wgScript']);
     $request = $this->getRequest();
     $out = $this->getOutput();
     /**
      * Add date selector to quickly get to a certain time
      */
     $year = $request->getInt('year');
     $month = $request->getInt('month');
     $tagFilter = $request->getVal('tagfilter');
     $tagSelector = ChangeTags::buildTagFilterSelector($tagFilter);
     /**
      * Option to show only revisions that have been (partially) hidden via RevisionDelete
      */
     if ($request->getBool('deleted')) {
         $conditions['deleted'] = true;
     }
     $checkDeleted = Xml::checkLabel($this->msg('history-show-deleted')->text(), 'deleted', 'mw-show-deleted-only', $request->getBool('deleted')) . "\n";
     $out->addHTML("<form action=\"{$action}\" method=\"get\" id=\"mw-history-searchform\">" . Xml::fieldset($this->msg('history-fieldset-title')->text(), false, array('id' => 'mw-history-search')) . Html::hidden('title', $this->getTitle()->getPrefixedDBKey()) . "\n" . Html::hidden('action', 'history') . "\n" . Xml::dateMenu($year, $month) . '&#160;' . ($tagSelector ? implode('&#160;', $tagSelector) . '&#160;' : '') . $checkDeleted . Xml::submitButton($this->msg('allpagessubmit')->text()) . "\n" . '</fieldset></form>');
     $pager = new EPRevisionPager($this->getContext(), $conditions);
     if ($pager->getNumRows()) {
         $out->addHTML($pager->getNavigationBar() . $pager->getBody() . $pager->getNavigationBar());
     } else {
         // TODO
     }
 }
 function getDiv($value)
 {
     $this->tagFilter = ChangeTags::buildTagFilterSelector($value);
     if ($this->tagFilter) {
         return parent::getDiv($value);
     }
     return '';
 }
 function tagProxyChange($recentChange)
 {
     global $wgTagProxyActions, $wgUser;
     if ($wgTagProxyActions && self::isProxy(wfGetIP()) && !$wgUser->isAllowed('notagproxychanges')) {
         ChangeTags::addTags('proxy', $recentChange->mAttribs['rc_id'], $recentChange->mAttribs['rc_this_oldid'], $recentChange->mAttribs['rc_logid']);
     }
     return true;
 }
 public function execute()
 {
     global $wgVisualEditorNamespaces, $wgVisualEditorUseChangeTagging;
     $user = $this->getUser();
     $params = $this->extractRequestParams();
     $page = Title::newFromText($params['page']);
     if (!$page) {
         $this->dieUsageMsg('invalidtitle', $params['page']);
     }
     if (!in_array($page->getNamespace(), $wgVisualEditorNamespaces)) {
         $this->dieUsage("VisualEditor is not enabled in namespace " . $page->getNamespace(), 'novenamespace');
     }
     $parserParams = array();
     if (isset($params['oldwt'])) {
         $parserParams['oldwt'] = $params['oldwt'];
     } else {
         if (isset($params['oldid'])) {
             $parserParams['oldid'] = $params['oldid'];
         }
     }
     if ($params['cachekey'] !== null) {
         $wikitext = $this->trySerializationCache($params['cachekey']);
         if (!is_string($wikitext)) {
             $this->dieUsage('No cached serialization found with that key', 'badcachekey');
         }
     } else {
         $wikitext = $this->postHTML($page, $params['html'], $parserParams);
         if ($wikitext === false) {
             $this->dieUsage('Error contacting the Parsoid server', 'parsoidserver');
         }
     }
     $saveresult = $this->saveWikitext($page, $wikitext, $params);
     $editStatus = $saveresult['edit']['result'];
     // Error
     if ($editStatus !== 'Success') {
         $result = array('result' => 'error', 'edit' => $saveresult['edit']);
         // Success
     } else {
         if (isset($saveresult['edit']['newrevid']) && $wgVisualEditorUseChangeTagging) {
             ChangeTags::addTags('visualeditor', null, intval($saveresult['edit']['newrevid']), null);
             if ($params['needcheck']) {
                 ChangeTags::addTags('visualeditor-needcheck', null, intval($saveresult['edit']['newrevid']), null);
             }
         }
         // Return result of parseWikitext instead of saveWikitext so that the
         // frontend can update the page rendering without a refresh.
         $result = $this->parseWikitext($page, $params['useskin']);
         if ($result === false) {
             $this->dieUsage('Error contacting the Parsoid server', 'parsoidserver');
         }
         $result['isRedirect'] = $page->isRedirect();
         if (isset($saveresult['edit']['newrevid'])) {
             $result['newrevid'] = intval($saveresult['edit']['newrevid']);
         }
         $result['result'] = 'success';
     }
     $this->getResult()->addValue(null, $this->getModuleName(), $result);
 }
 /**
  * @desc Mark all edits made via mobile skin with a mobileedit tag
  *
  * @param $article
  * @param $user
  * @param $text
  * @param $summary
  * @param $minoredit
  * @param $watchthis
  * @param $sectionanchor
  * @param $flags
  * @param $revision Revision
  * @param $status
  * @param $baseRevId
  */
 public static function onArticleSaveComplete(&$article, &$user, $text, $summary, $minoredit, $watchthis, $sectionanchor, &$flags, $revision, &$status, $baseRevId)
 {
     $app = F::app();
     //Add Mobile Edit tag when an article was saved via mobile skin
     if ($app->checkSkin('wikiamobile') && !is_null($revision)) {
         ChangeTags::addTags('mobileedit', null, $revision->getId(), null);
     }
     return true;
 }
 /**
  * @param IDatabase $db
  * @return mixed
  */
 public function doQuery($db)
 {
     $timestamps = [];
     foreach ($this->ids as $id) {
         $timestamps[] = $db->timestamp($id);
     }
     $tables = ['archive'];
     $fields = Revision::selectArchiveFields();
     $conds = ['ar_namespace' => $this->title->getNamespace(), 'ar_title' => $this->title->getDBkey(), 'ar_timestamp' => $timestamps];
     $join_conds = [];
     $options = ['ORDER BY' => 'ar_timestamp DESC'];
     ChangeTags::modifyDisplayQuery($tables, $fields, $conds, $join_conds, $options, '');
     return $db->select($tables, $fields, $conds, __METHOD__, $options, $join_conds);
 }
 /**
  * Add/remove change tags from all the revisions in the list.
  *
  * @param array $tagsToAdd
  * @param array $tagsToRemove
  * @param array $params
  * @param string $reason
  * @param User $user
  * @return Status
  */
 public function updateChangeTagsOnAll($tagsToAdd, $tagsToRemove, $params, $reason, $user)
 {
     // @codingStandardsIgnoreStart Generic.CodeAnalysis.ForLoopWithTestFunctionCall.NotAllowed
     for ($this->reset(); $this->current(); $this->next()) {
         // @codingStandardsIgnoreEnd
         $item = $this->current();
         $status = ChangeTags::updateTagsWithChecks($tagsToAdd, $tagsToRemove, null, $item->getId(), null, $params, $reason, $user);
         // Should only fail on second and subsequent times if the user trips
         // the rate limiter
         if (!$status->isOK()) {
             break;
         }
     }
     return $status;
 }
Exemple #13
0
 public function execute()
 {
     $this->useTransactionalTimeLimit();
     $params = $this->extractRequestParams();
     $user = $this->getUser();
     if (!$user->isAllowed('undelete')) {
         $this->dieUsageMsg('permdenied-undelete');
     }
     if ($user->isBlocked()) {
         $this->dieBlocked($user->getBlock());
     }
     $titleObj = Title::newFromText($params['title']);
     if (!$titleObj || $titleObj->isExternal()) {
         $this->dieUsageMsg(['invalidtitle', $params['title']]);
     }
     // Check if user can add tags
     if (!is_null($params['tags'])) {
         $ableToTag = ChangeTags::canAddTagsAccompanyingChange($params['tags'], $user);
         if (!$ableToTag->isOK()) {
             $this->dieStatus($ableToTag);
         }
     }
     // Convert timestamps
     if (!isset($params['timestamps'])) {
         $params['timestamps'] = [];
     }
     if (!is_array($params['timestamps'])) {
         $params['timestamps'] = [$params['timestamps']];
     }
     foreach ($params['timestamps'] as $i => $ts) {
         $params['timestamps'][$i] = wfTimestamp(TS_MW, $ts);
     }
     $pa = new PageArchive($titleObj, $this->getConfig());
     $retval = $pa->undelete(isset($params['timestamps']) ? $params['timestamps'] : [], $params['reason'], $params['fileids'], false, $user, $params['tags']);
     if (!is_array($retval)) {
         $this->dieUsageMsg('cannotundelete');
     }
     if ($retval[1]) {
         Hooks::run('FileUndeleteComplete', [$titleObj, $params['fileids'], $this->getUser(), $params['reason']]);
     }
     $this->setWatch($params['watchlist'], $titleObj);
     $info['title'] = $titleObj->getPrefixedText();
     $info['revisions'] = intval($retval[0]);
     $info['fileversions'] = intval($retval[1]);
     $info['reason'] = $retval[2];
     $this->getResult()->addValue(null, $this->getModuleName(), $info);
 }
Exemple #14
0
 /**
  * Extracts the title and reason from the request parameters and invokes
  * the local delete() function with these as arguments. It does not make use of
  * the delete function specified by Article.php. If the deletion succeeds, the
  * details of the article deleted and the reason for deletion are added to the
  * result object.
  */
 public function execute()
 {
     $this->useTransactionalTimeLimit();
     $params = $this->extractRequestParams();
     $pageObj = $this->getTitleOrPageId($params, 'fromdbmaster');
     if (!$pageObj->exists()) {
         $this->dieUsageMsg('notanarticle');
     }
     $titleObj = $pageObj->getTitle();
     $reason = $params['reason'];
     $user = $this->getUser();
     // Check that the user is allowed to carry out the deletion
     $errors = $titleObj->getUserPermissionsErrors('delete', $user);
     if (count($errors)) {
         $this->dieUsageMsg($errors[0]);
     }
     // If change tagging was requested, check that the user is allowed to tag,
     // and the tags are valid
     if (count($params['tags'])) {
         $tagStatus = ChangeTags::canAddTagsAccompanyingChange($params['tags'], $user);
         if (!$tagStatus->isOK()) {
             $this->dieStatus($tagStatus);
         }
     }
     if ($titleObj->getNamespace() == NS_FILE) {
         $status = self::deleteFile($pageObj, $user, $params['oldimage'], $reason, false, $params['tags']);
     } else {
         $status = self::delete($pageObj, $user, $reason, $params['tags']);
     }
     if (is_array($status)) {
         $this->dieUsageMsg($status[0]);
     }
     if (!$status->isGood()) {
         $this->dieStatus($status);
     }
     // Deprecated parameters
     if ($params['watch']) {
         $watch = 'watch';
     } elseif ($params['unwatch']) {
         $watch = 'unwatch';
     } else {
         $watch = $params['watchlist'];
     }
     $this->setWatch($watch, $titleObj, 'watchdeletion');
     $r = ['title' => $titleObj->getPrefixedText(), 'reason' => $reason, 'logid' => $status->value];
     $this->getResult()->addValue(null, $this->getModuleName(), $r);
 }
 function getQueryInfo()
 {
     $conds = [];
     $conds['rc_new'] = 1;
     $namespace = $this->opts->getValue('namespace');
     $namespace = $namespace === 'all' ? false : intval($namespace);
     $username = $this->opts->getValue('username');
     $user = Title::makeTitleSafe(NS_USER, $username);
     $rcIndexes = [];
     if ($namespace !== false) {
         if ($this->opts->getValue('invert')) {
             $conds[] = 'rc_namespace != ' . $this->mDb->addQuotes($namespace);
         } else {
             $conds['rc_namespace'] = $namespace;
         }
     }
     if ($user) {
         $conds['rc_user_text'] = $user->getText();
         $rcIndexes = 'rc_user_text';
     } elseif (User::groupHasPermission('*', 'createpage') && $this->opts->getValue('hideliu')) {
         # If anons cannot make new pages, don't "exclude logged in users"!
         $conds['rc_user'] = 0;
     }
     # If this user cannot see patrolled edits or they are off, don't do dumb queries!
     if ($this->opts->getValue('hidepatrolled') && $this->getUser()->useNPPatrol()) {
         $conds['rc_patrolled'] = 0;
     }
     if ($this->opts->getValue('hidebots')) {
         $conds['rc_bot'] = 0;
     }
     if ($this->opts->getValue('hideredirs')) {
         $conds['page_is_redirect'] = 0;
     }
     // Allow changes to the New Pages query
     $tables = ['recentchanges', 'page'];
     $fields = ['rc_namespace', 'rc_title', 'rc_cur_id', 'rc_user', 'rc_user_text', 'rc_comment', 'rc_timestamp', 'rc_patrolled', 'rc_id', 'rc_deleted', 'length' => 'page_len', 'rev_id' => 'page_latest', 'rc_this_oldid', 'page_namespace', 'page_title'];
     $join_conds = ['page' => ['INNER JOIN', 'page_id=rc_cur_id']];
     Hooks::run('SpecialNewpagesConditions', [&$this, $this->opts, &$conds, &$tables, &$fields, &$join_conds]);
     $options = [];
     if ($rcIndexes) {
         $options = ['USE INDEX' => ['recentchanges' => $rcIndexes]];
     }
     $info = ['tables' => $tables, 'fields' => $fields, 'conds' => $conds, 'options' => $options, 'join_conds' => $join_conds];
     // Modify query for tags
     ChangeTags::modifyDisplayQuery($info['tables'], $info['fields'], $info['conds'], $info['join_conds'], $info['options'], $this->opts['tagfilter']);
     return $info;
 }
 protected function addTags($items, $dry)
 {
     $count = count($items);
     if (!$count) {
         $this->output("No revisions to tag\n");
         return;
     }
     if ($dry) {
         $this->output("{$count} revisions would be tagged\n");
         return;
     }
     $this->output("{$count} rows are tagged\n");
     foreach ($items as $item) {
         list($row, $revId) = $item;
         ChangeTags::addTags('contenttranslation', null, $revId, null, FormatJson::encode(array('from' => $row->translation_source_language, 'to' => $row->translation_target_language)));
     }
 }
 /**
  * @return string A HTML <li> element representing this revision, showing
  * change tags and everything
  */
 public function getHTML()
 {
     $difflink = $this->list->msg('parentheses')->rawParams($this->getDiffLink())->escaped();
     $revlink = $this->getRevisionLink();
     $userlink = Linker::revUserLink($this->revision);
     $comment = Linker::revComment($this->revision);
     if ($this->isDeleted()) {
         $revlink = "<span class=\"history-deleted\">{$revlink}</span>";
     }
     $content = "{$difflink} {$revlink} {$userlink} {$comment}";
     $attribs = array();
     $tags = $this->getTags();
     if ($tags) {
         list($tagSummary, $classes) = ChangeTags::formatSummaryRow($tags, 'edittags');
         $content .= " {$tagSummary}";
         $attribs['class'] = implode(' ', $classes);
     }
     return Xml::tags('li', $attribs, $content);
 }
Exemple #18
0
 public function execute()
 {
     $this->useTransactionalTimeLimit();
     $user = $this->getUser();
     $params = $this->extractRequestParams();
     $titleObj = $this->getRbTitle($params);
     $pageObj = WikiPage::factory($titleObj);
     $summary = $params['summary'];
     $details = [];
     // If change tagging was requested, check that the user is allowed to tag,
     // and the tags are valid
     if (count($params['tags'])) {
         $tagStatus = ChangeTags::canAddTagsAccompanyingChange($params['tags'], $user);
         if (!$tagStatus->isOK()) {
             $this->dieStatus($tagStatus);
         }
     }
     $retval = $pageObj->doRollback($this->getRbUser($params), $summary, $params['token'], $params['markbot'], $details, $user, $params['tags']);
     // We don't care about multiple errors, just report one of them
     if ($retval) {
         if (isset($retval[0][0]) && ($retval[0][0] == 'alreadyrolled' || $retval[0][0] == 'cantrollback')) {
             $error = $retval[0];
             $userMessage = $this->msg($error[0], array_slice($error, 1));
             // dieUsageMsg() doesn't support $extraData
             $errorCode = $error[0];
             $errorInfo = isset(ApiBase::$messageMap[$errorCode]) ? ApiBase::$messageMap[$errorCode]['info'] : $errorCode;
             $this->dieUsage($errorInfo, $errorCode, 0, ['messageHtml' => $userMessage->parseAsBlock()]);
         }
         $this->dieUsageMsg(reset($retval));
     }
     $watch = 'preferences';
     if (isset($params['watchlist'])) {
         $watch = $params['watchlist'];
     }
     // Watch pages
     $this->setWatch($watch, $titleObj, 'watchrollback');
     $info = ['title' => $titleObj->getPrefixedText(), 'pageid' => intval($details['current']->getPage()), 'summary' => $details['summary'], 'revid' => intval($details['newid']), 'old_revid' => intval($details['current']->getID()), 'last_revid' => intval($details['target']->getID())];
     $oldUser = $details['current']->getUserText(Revision::FOR_THIS_USER);
     $lastUser = $details['target']->getUserText(Revision::FOR_THIS_USER);
     $diffUrl = $titleObj->getFullURL(['diff' => $info['revid'], 'oldid' => $info['old_revid'], 'diffonly' => '1']);
     $info['messageHtml'] = $this->msg('rollback-success-notify')->params($oldUser, $lastUser, $diffUrl)->parseAsBlock();
     $this->getResult()->addValue(null, $this->getModuleName(), $info);
 }
Exemple #19
0
 protected function processIndividual($type, $params, $id)
 {
     $idResult = array($type => $id);
     // validate the ID
     $valid = false;
     switch ($type) {
         case 'rcid':
             $valid = RecentChange::newFromId($id);
             break;
         case 'revid':
             $valid = Revision::newFromId($id);
             break;
         case 'logid':
             $valid = self::validateLogId($id);
             break;
     }
     if (!$valid) {
         $idResult['status'] = 'error';
         $idResult += $this->parseMsg(array("nosuch{$type}", $id));
         return $idResult;
     }
     $status = ChangeTags::updateTagsWithChecks($params['add'], $params['remove'], $type === 'rcid' ? $id : null, $type === 'revid' ? $id : null, $type === 'logid' ? $id : null, null, $params['reason'], $this->getUser());
     if (!$status->isOK()) {
         if ($status->hasMessage('actionthrottledtext')) {
             $idResult['status'] = 'skipped';
         } else {
             $idResult['status'] = 'failure';
             $idResult['errors'] = $this->getErrorFormatter()->arrayFromStatus($status, 'error');
         }
     } else {
         $idResult['status'] = 'success';
         if (is_null($status->value->logId)) {
             $idResult['noop'] = '';
         } else {
             $idResult['actionlogid'] = $status->value->logId;
             $idResult['added'] = $status->value->addedTags;
             ApiResult::setIndexedTagName($idResult['added'], 't');
             $idResult['removed'] = $status->value->removedTags;
             ApiResult::setIndexedTagName($idResult['removed'], 't');
         }
     }
     return $idResult;
 }
 public function showForm()
 {
     global $wgScript;
     // Add explanatory text
     $this->getOutput()->addWikiMsg('problemchanges-list', $this->getLanguage()->formatNum($this->pager->getNumRows()));
     $form = Html::openElement('form', array('name' => 'problemchanges', 'action' => $wgScript, 'method' => 'get')) . "\n";
     $form .= "<fieldset><legend>" . $this->msg('problemchanges-legend')->escaped() . "</legend>\n";
     $form .= Html::hidden('title', $this->getPageTitle()->getPrefixedDBKey()) . "\n";
     $form .= FlaggedRevs::qualityVersions() ? "<span style='white-space: nowrap;'>" . FlaggedRevsXML::getLevelMenu($this->level, 'revreview-filter-stable') . '</span> ' : "";
     $tagForm = ChangeTags::buildTagFilterSelector($this->tag);
     if (count($tagForm)) {
         $form .= Xml::tags('td', array('class' => 'mw-label'), $tagForm[0]);
         $form .= Xml::tags('td', array('class' => 'mw-input'), $tagForm[1]);
     }
     $form .= '<br />' . Xml::label($this->msg("problemchanges-category")->text(), 'wpCategory') . '&#160;' . Xml::input('category', 30, $this->category, array('id' => 'wpCategory')) . ' ';
     $form .= Xml::submitButton($this->msg('allpagessubmit')->text()) . "\n";
     $form .= '</fieldset>';
     $form .= Html::closeElement('form') . "\n";
     $this->getOutput()->addHTML($form);
 }
Exemple #21
0
 /**
  * Unblocks the specified user or provides the reason the unblock failed.
  */
 public function execute()
 {
     $user = $this->getUser();
     $params = $this->extractRequestParams();
     if (is_null($params['id']) && is_null($params['user'])) {
         $this->dieUsageMsg('unblock-notarget');
     }
     if (!is_null($params['id']) && !is_null($params['user'])) {
         $this->dieUsageMsg('unblock-idanduser');
     }
     if (!$user->isAllowed('block')) {
         $this->dieUsageMsg('cantunblock');
     }
     # bug 15810: blocked admins should have limited access here
     if ($user->isBlocked()) {
         $status = SpecialBlock::checkUnblockSelf($params['user'], $user);
         if ($status !== true) {
             $msg = $this->parseMsg($status);
             $this->dieUsage($msg['info'], $msg['code'], 0, ['blockinfo' => ApiQueryUserInfo::getBlockInfo($user->getBlock())]);
         }
     }
     // Check if user can add tags
     if (!is_null($params['tags'])) {
         $ableToTag = ChangeTags::canAddTagsAccompanyingChange($params['tags'], $user);
         if (!$ableToTag->isOK()) {
             $this->dieStatus($ableToTag);
         }
     }
     $data = ['Target' => is_null($params['id']) ? $params['user'] : "******", 'Reason' => $params['reason'], 'Tags' => $params['tags']];
     $block = Block::newFromTarget($data['Target']);
     $retval = SpecialUnblock::processUnblock($data, $this->getContext());
     if ($retval !== true) {
         $this->dieUsageMsg($retval[0]);
     }
     $res['id'] = $block->getId();
     $target = $block->getType() == Block::TYPE_AUTO ? '' : $block->getTarget();
     $res['user'] = $target instanceof User ? $target->getName() : $target;
     $res['userid'] = $target instanceof User ? $target->getId() : 0;
     $res['reason'] = $params['reason'];
     $this->getResult()->addValue(null, $this->getModuleName(), $res);
 }
Exemple #22
0
 public function execute()
 {
     $this->useTransactionalTimeLimit();
     $user = $this->getUser();
     $params = $this->extractRequestParams();
     // WikiPage::doRollback needs a Web UI token, so get one of those if we
     // validated based on an API rollback token.
     $token = $params['token'];
     if ($user->matchEditToken($token, 'rollback', $this->getRequest())) {
         $token = $this->getUser()->getEditToken($this->getWebUITokenSalt($params), $this->getRequest());
     }
     $titleObj = $this->getRbTitle($params);
     $pageObj = WikiPage::factory($titleObj);
     $summary = $params['summary'];
     $details = array();
     // If change tagging was requested, check that the user is allowed to tag,
     // and the tags are valid
     if (count($params['tags'])) {
         $tagStatus = ChangeTags::canAddTagsAccompanyingChange($params['tags'], $user);
         if (!$tagStatus->isOK()) {
             $this->dieStatus($tagStatus);
         }
     }
     $retval = $pageObj->doRollback($this->getRbUser($params), $summary, $token, $params['markbot'], $details, $user, $params['tags']);
     if ($retval) {
         // We don't care about multiple errors, just report one of them
         $this->dieUsageMsg(reset($retval));
     }
     $watch = 'preferences';
     if (isset($params['watchlist'])) {
         $watch = $params['watchlist'];
     }
     // Watch pages
     $this->setWatch($watch, $titleObj, 'watchrollback');
     $info = array('title' => $titleObj->getPrefixedText(), 'pageid' => intval($details['current']->getPage()), 'summary' => $details['summary'], 'revid' => intval($details['newid']), 'old_revid' => intval($details['current']->getID()), 'last_revid' => intval($details['target']->getID()));
     $this->getResult()->addValue(null, $this->getModuleName(), $info);
 }
Exemple #23
0
 /**
  * Patrols the article or provides the reason the patrol failed.
  */
 public function execute()
 {
     $params = $this->extractRequestParams();
     $this->requireOnlyOneParameter($params, 'rcid', 'revid');
     if (isset($params['rcid'])) {
         $rc = RecentChange::newFromId($params['rcid']);
         if (!$rc) {
             $this->dieUsageMsg(['nosuchrcid', $params['rcid']]);
         }
     } else {
         $rev = Revision::newFromId($params['revid']);
         if (!$rev) {
             $this->dieUsageMsg(['nosuchrevid', $params['revid']]);
         }
         $rc = $rev->getRecentChange();
         if (!$rc) {
             $this->dieUsage('The revision ' . $params['revid'] . " can't be patrolled as it's too old", 'notpatrollable');
         }
     }
     $user = $this->getUser();
     $tags = $params['tags'];
     // Check if user can add tags
     if (!is_null($tags)) {
         $ableToTag = ChangeTags::canAddTagsAccompanyingChange($tags, $user);
         if (!$ableToTag->isOK()) {
             $this->dieStatus($ableToTag);
         }
     }
     $retval = $rc->doMarkPatrolled($user, false, $tags);
     if ($retval) {
         $this->dieUsageMsg(reset($retval));
     }
     $result = ['rcid' => intval($rc->getAttribute('rc_id'))];
     ApiQueryBase::addTitleInfo($result, $rc->getTitle());
     $this->getResult()->addValue(null, $this->getModuleName(), $result);
 }
 /**
  * Constructs the most part of the query. Extra conditions are sprinkled in
  * all over this class.
  * @return array
  */
 public function getQueryInfo()
 {
     $basic = DatabaseLogEntry::getSelectQueryData();
     $tables = $basic['tables'];
     $fields = $basic['fields'];
     $conds = $basic['conds'];
     $options = $basic['options'];
     $joins = $basic['join_conds'];
     $index = array();
     # Add log_search table if there are conditions on it.
     # This filters the results to only include log rows that have
     # log_search records with the specified ls_field and ls_value values.
     if (array_key_exists('ls_field', $this->mConds)) {
         $tables[] = 'log_search';
         $index['log_search'] = 'ls_field_val';
         $index['logging'] = 'PRIMARY';
         if (!$this->hasEqualsClause('ls_field') || !$this->hasEqualsClause('ls_value')) {
             # Since (ls_field,ls_value,ls_logid) is unique, if the condition is
             # to match a specific (ls_field,ls_value) tuple, then there will be
             # no duplicate log rows. Otherwise, we need to remove the duplicates.
             $options[] = 'DISTINCT';
         }
     }
     if (count($index)) {
         $options['USE INDEX'] = $index;
     }
     # Don't show duplicate rows when using log_search
     $joins['log_search'] = array('INNER JOIN', 'ls_log_id=log_id');
     $info = array('tables' => $tables, 'fields' => $fields, 'conds' => array_merge($conds, $this->mConds), 'options' => $options, 'join_conds' => $joins);
     # Add ChangeTags filter query
     ChangeTags::modifyDisplayQuery($info['tables'], $info['fields'], $info['conds'], $info['join_conds'], $info['options'], $this->mTagFilter);
     return $info;
 }
 /**
  * RecentChange_save hook handler that tags mobile changes
  * @see https://www.mediawiki.org/wiki/Manual:Hooks/RecentChange_save
  *
  * @param RecentChange $rc
  * @return bool
  */
 public static function onRecentChange_save(RecentChange $rc)
 {
     $context = MobileContext::singleton();
     $userAgent = $context->getRequest()->getHeader("User-agent");
     $logType = $rc->getAttribute('rc_log_type');
     // Only log edits and uploads
     if ($context->shouldDisplayMobileView() && ($logType === 'upload' || is_null($logType))) {
         $rcId = $rc->getAttribute('rc_id');
         $revId = $rc->getAttribute('rc_this_oldid');
         $logId = $rc->getAttribute('rc_logid');
         ChangeTags::addTags('mobile edit', $rcId, $revId, $logId);
         // Tag as mobile web edit specifically, if it isn't coming from the apps
         if (strpos($userAgent, 'WikipediaApp/') !== 0) {
             ChangeTags::addTags('mobile web edit', $rcId, $revId, $logId);
         }
     }
     return true;
 }
 /**
  * Process the query
  *
  * @param array $conds
  * @param FormOptions $opts
  * @return bool|ResultWrapper Result or false (for Recentchangeslinked only)
  */
 public function doMainQuery($conds, $opts)
 {
     $dbr = $this->getDB();
     $user = $this->getUser();
     # Toggle watchlist content (all recent edits or just the latest)
     if ($opts['extended']) {
         $limitWatchlist = $user->getIntOption('wllimit');
         $usePage = false;
     } else {
         # Top log Ids for a page are not stored
         $nonRevisionTypes = array(RC_LOG);
         Hooks::run('SpecialWatchlistGetNonRevisionTypes', array(&$nonRevisionTypes));
         if ($nonRevisionTypes) {
             $conds[] = $dbr->makeList(array('rc_this_oldid=page_latest', 'rc_type' => $nonRevisionTypes), LIST_OR);
         }
         $limitWatchlist = 0;
         $usePage = true;
     }
     $tables = array('recentchanges', 'watchlist');
     $fields = RecentChange::selectFields();
     $query_options = array('ORDER BY' => 'rc_timestamp DESC');
     $join_conds = array('watchlist' => array('INNER JOIN', array('wl_user' => $user->getId(), 'wl_namespace=rc_namespace', 'wl_title=rc_title')));
     if ($this->getConfig()->get('ShowUpdatedMarker')) {
         $fields[] = 'wl_notificationtimestamp';
     }
     if ($limitWatchlist) {
         $query_options['LIMIT'] = $limitWatchlist;
     }
     $rollbacker = $user->isAllowed('rollback');
     if ($usePage || $rollbacker) {
         $tables[] = 'page';
         $join_conds['page'] = array('LEFT JOIN', 'rc_cur_id=page_id');
         if ($rollbacker) {
             $fields[] = 'page_latest';
         }
     }
     // Log entries with DELETED_ACTION must not show up unless the user has
     // the necessary rights.
     if (!$user->isAllowed('deletedhistory')) {
         $bitmask = LogPage::DELETED_ACTION;
     } elseif (!$user->isAllowedAny('suppressrevision', 'viewsuppressed')) {
         $bitmask = LogPage::DELETED_ACTION | LogPage::DELETED_RESTRICTED;
     } else {
         $bitmask = 0;
     }
     if ($bitmask) {
         $conds[] = $dbr->makeList(array('rc_type != ' . RC_LOG, $dbr->bitAnd('rc_deleted', $bitmask) . " != {$bitmask}"), LIST_OR);
     }
     ChangeTags::modifyDisplayQuery($tables, $fields, $conds, $join_conds, $query_options, '');
     $this->runMainQueryHook($tables, $fields, $conds, $query_options, $join_conds, $opts);
     return $dbr->select($tables, $fields, $conds, __METHOD__, $query_options, $join_conds);
 }
 public function showDiffPage($diffOnly = false)
 {
     # Allow frames except in certain special cases
     $out = $this->getOutput();
     $out->allowClickjacking();
     $out->setRobotPolicy('noindex,nofollow');
     if (!$this->loadRevisionData()) {
         $this->showMissingRevision();
         return;
     }
     $user = $this->getUser();
     $permErrors = $this->mNewPage->getUserPermissionsErrors('read', $user);
     if ($this->mOldPage) {
         # mOldPage might not be set, see below.
         $permErrors = wfMergeErrorArrays($permErrors, $this->mOldPage->getUserPermissionsErrors('read', $user));
     }
     if (count($permErrors)) {
         throw new PermissionsError('read', $permErrors);
     }
     $rollback = '';
     $query = array();
     # Carry over 'diffonly' param via navigation links
     if ($diffOnly != $user->getBoolOption('diffonly')) {
         $query['diffonly'] = $diffOnly;
     }
     # Cascade unhide param in links for easy deletion browsing
     if ($this->unhide) {
         $query['unhide'] = 1;
     }
     # Check if one of the revisions is deleted/suppressed
     $deleted = $suppressed = false;
     $allowed = $this->mNewRev->userCan(Revision::DELETED_TEXT, $user);
     $revisionTools = array();
     # mOldRev is false if the difference engine is called with a "vague" query for
     # a diff between a version V and its previous version V' AND the version V
     # is the first version of that article. In that case, V' does not exist.
     if ($this->mOldRev === false) {
         $out->setPageTitle($this->msg('difference-title', $this->mNewPage->getPrefixedText()));
         $samePage = true;
         $oldHeader = '';
     } else {
         Hooks::run('DiffViewHeader', array($this, $this->mOldRev, $this->mNewRev));
         if ($this->mNewPage->equals($this->mOldPage)) {
             $out->setPageTitle($this->msg('difference-title', $this->mNewPage->getPrefixedText()));
             $samePage = true;
         } else {
             $out->setPageTitle($this->msg('difference-title-multipage', $this->mOldPage->getPrefixedText(), $this->mNewPage->getPrefixedText()));
             $out->addSubtitle($this->msg('difference-multipage'));
             $samePage = false;
         }
         if ($samePage && $this->mNewPage->quickUserCan('edit', $user)) {
             if ($this->mNewRev->isCurrent() && $this->mNewPage->userCan('rollback', $user)) {
                 $rollbackLink = Linker::generateRollback($this->mNewRev, $this->getContext());
                 if ($rollbackLink) {
                     $out->preventClickjacking();
                     $rollback = '&#160;&#160;&#160;' . $rollbackLink;
                 }
             }
             if (!$this->mOldRev->isDeleted(Revision::DELETED_TEXT) && !$this->mNewRev->isDeleted(Revision::DELETED_TEXT)) {
                 $undoLink = Html::element('a', array('href' => $this->mNewPage->getLocalURL(array('action' => 'edit', 'undoafter' => $this->mOldid, 'undo' => $this->mNewid)), 'title' => Linker::titleAttrib('undo')), $this->msg('editundo')->text());
                 $revisionTools['mw-diff-undo'] = $undoLink;
             }
         }
         # Make "previous revision link"
         if ($samePage && $this->mOldRev->getPrevious()) {
             $prevlink = Linker::linkKnown($this->mOldPage, $this->msg('previousdiff')->escaped(), array('id' => 'differences-prevlink'), array('diff' => 'prev', 'oldid' => $this->mOldid) + $query);
         } else {
             $prevlink = '&#160;';
         }
         if ($this->mOldRev->isMinor()) {
             $oldminor = ChangesList::flag('minor');
         } else {
             $oldminor = '';
         }
         $ldel = $this->revisionDeleteLink($this->mOldRev);
         $oldRevisionHeader = $this->getRevisionHeader($this->mOldRev, 'complete');
         $oldChangeTags = ChangeTags::formatSummaryRow($this->mOldTags, 'diff');
         $oldHeader = '<div id="mw-diff-otitle1"><strong>' . $oldRevisionHeader . '</strong></div>' . '<div id="mw-diff-otitle2">' . Linker::revUserTools($this->mOldRev, !$this->unhide) . '</div>' . '<div id="mw-diff-otitle3">' . $oldminor . Linker::revComment($this->mOldRev, !$diffOnly, !$this->unhide) . $ldel . '</div>' . '<div id="mw-diff-otitle5">' . $oldChangeTags[0] . '</div>' . '<div id="mw-diff-otitle4">' . $prevlink . '</div>';
         if ($this->mOldRev->isDeleted(Revision::DELETED_TEXT)) {
             $deleted = true;
             // old revisions text is hidden
             if ($this->mOldRev->isDeleted(Revision::DELETED_RESTRICTED)) {
                 $suppressed = true;
                 // also suppressed
             }
         }
         # Check if this user can see the revisions
         if (!$this->mOldRev->userCan(Revision::DELETED_TEXT, $user)) {
             $allowed = false;
         }
     }
     # Make "next revision link"
     # Skip next link on the top revision
     if ($samePage && !$this->mNewRev->isCurrent()) {
         $nextlink = Linker::linkKnown($this->mNewPage, $this->msg('nextdiff')->escaped(), array('id' => 'differences-nextlink'), array('diff' => 'next', 'oldid' => $this->mNewid) + $query);
     } else {
         $nextlink = '&#160;';
     }
     if ($this->mNewRev->isMinor()) {
         $newminor = ChangesList::flag('minor');
     } else {
         $newminor = '';
     }
     # Handle RevisionDelete links...
     $rdel = $this->revisionDeleteLink($this->mNewRev);
     # Allow extensions to define their own revision tools
     Hooks::run('DiffRevisionTools', array($this->mNewRev, &$revisionTools, $this->mOldRev, $user));
     $formattedRevisionTools = array();
     // Put each one in parentheses (poor man's button)
     foreach ($revisionTools as $key => $tool) {
         $toolClass = is_string($key) ? $key : 'mw-diff-tool';
         $element = Html::rawElement('span', array('class' => $toolClass), $this->msg('parentheses')->rawParams($tool)->escaped());
         $formattedRevisionTools[] = $element;
     }
     $newRevisionHeader = $this->getRevisionHeader($this->mNewRev, 'complete') . ' ' . implode(' ', $formattedRevisionTools);
     $newChangeTags = ChangeTags::formatSummaryRow($this->mNewTags, 'diff');
     $newHeader = '<div id="mw-diff-ntitle1"><strong>' . $newRevisionHeader . '</strong></div>' . '<div id="mw-diff-ntitle2">' . Linker::revUserTools($this->mNewRev, !$this->unhide) . " {$rollback}</div>" . '<div id="mw-diff-ntitle3">' . $newminor . Linker::revComment($this->mNewRev, !$diffOnly, !$this->unhide) . $rdel . '</div>' . '<div id="mw-diff-ntitle5">' . $newChangeTags[0] . '</div>' . '<div id="mw-diff-ntitle4">' . $nextlink . $this->markPatrolledLink() . '</div>';
     if ($this->mNewRev->isDeleted(Revision::DELETED_TEXT)) {
         $deleted = true;
         // new revisions text is hidden
         if ($this->mNewRev->isDeleted(Revision::DELETED_RESTRICTED)) {
             $suppressed = true;
             // also suppressed
         }
     }
     # If the diff cannot be shown due to a deleted revision, then output
     # the diff header and links to unhide (if available)...
     if ($deleted && (!$this->unhide || !$allowed)) {
         $this->showDiffStyle();
         $multi = $this->getMultiNotice();
         $out->addHTML($this->addHeader('', $oldHeader, $newHeader, $multi));
         if (!$allowed) {
             $msg = $suppressed ? 'rev-suppressed-no-diff' : 'rev-deleted-no-diff';
             # Give explanation for why revision is not visible
             $out->wrapWikiMsg("<div id='mw-{$msg}' class='mw-warning plainlinks'>\n\$1\n</div>\n", array($msg));
         } else {
             # Give explanation and add a link to view the diff...
             $query = $this->getRequest()->appendQueryValue('unhide', '1');
             $link = $this->getTitle()->getFullURL($query);
             $msg = $suppressed ? 'rev-suppressed-unhide-diff' : 'rev-deleted-unhide-diff';
             $out->wrapWikiMsg("<div id='mw-{$msg}' class='mw-warning plainlinks'>\n\$1\n</div>\n", array($msg, $link));
         }
         # Otherwise, output a regular diff...
     } else {
         # Add deletion notice if the user is viewing deleted content
         $notice = '';
         if ($deleted) {
             $msg = $suppressed ? 'rev-suppressed-diff-view' : 'rev-deleted-diff-view';
             $notice = "<div id='mw-{$msg}' class='mw-warning plainlinks'>\n" . $this->msg($msg)->parse() . "</div>\n";
         }
         $this->showDiff($oldHeader, $newHeader, $notice);
         if (!$diffOnly) {
             $this->renderNewRevision();
         }
     }
 }
 /**
  * @param $s string
  * @param $rc RecentChange
  * @param $classes
  */
 public function insertTags(&$s, &$rc, &$classes)
 {
     if (empty($rc->mAttribs['ts_tags'])) {
         return;
     }
     list($tagSummary, $newClasses) = ChangeTags::formatSummaryRow($rc->mAttribs['ts_tags'], 'changeslist');
     $classes = array_merge($classes, $newClasses);
     $s .= ' ' . $tagSummary;
 }
 /**
  * Process the query
  *
  * @param array $conds
  * @param FormOptions $opts
  * @return bool|ResultWrapper Result or false
  */
 public function doMainQuery($conds, $opts)
 {
     $tables = ['recentchanges'];
     $fields = RecentChange::selectFields();
     $query_options = [];
     $join_conds = [];
     ChangeTags::modifyDisplayQuery($tables, $fields, $conds, $join_conds, $query_options, '');
     if (!$this->runMainQueryHook($tables, $fields, $conds, $query_options, $join_conds, $opts)) {
         return false;
     }
     $dbr = $this->getDB();
     return $dbr->select($tables, $fields, $conds, __METHOD__, $query_options, $join_conds);
 }
 private function doTag($tagName, $hitcount)
 {
     static $count = 0;
     static $doneTags = array();
     if (in_array($tagName, $doneTags)) {
         return true;
     }
     if (++$count > $this->limit) {
         $this->setContinueEnumParameter('continue', $tagName);
         return false;
     }
     $tag = array();
     $tag['name'] = $tagName;
     if ($this->fld_displayname) {
         $tag['displayname'] = ChangeTags::tagDescription($tagName);
     }
     if ($this->fld_description) {
         $msg = wfMessage("tag-{$tagName}-description");
         $tag['description'] = $msg->exists() ? $msg->text() : '';
     }
     if ($this->fld_hitcount) {
         $tag['hitcount'] = $hitcount;
     }
     $doneTags[] = $tagName;
     $fit = $this->result->addValue(array('query', $this->getModuleName()), null, $tag);
     if (!$fit) {
         $this->setContinueEnumParameter('continue', $tagName);
         return false;
     }
     return true;
 }