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"; }
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"; }
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"; }
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) . ' ' . ($tagSelector ? implode(' ', $tagSelector) . ' ' : '') . $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; }
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); }
/** * 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); }
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); }
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') . ' ' . 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); }
/** * 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); }
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); }
/** * 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 = '   ' . $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 = ' '; } 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 = ' '; } 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; }