/** * 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(array('nosuchrcid', $params['rcid'])); } } else { $rev = Revision::newFromId($params['revid']); if (!$rev) { $this->dieUsageMsg(array('nosuchrevid', $params['revid'])); } $rc = $rev->getRecentChange(); if (!$rc) { $this->dieUsage('The revision ' . $params['revid'] . " can't be patrolled as it's too old", 'notpatrollable'); } } $retval = $rc->doMarkPatrolled($this->getUser()); if ($retval) { $this->dieUsageMsg(reset($retval)); } $result = array('rcid' => intval($rc->getAttribute('rc_id'))); ApiQueryBase::addTitleInfo($result, $rc->getTitle()); $this->getResult()->addValue(null, $this->getModuleName(), $result); }
/** * Purges the cache of a page */ public function execute() { global $wgUser; $params = $this->extractRequestParams(); if (!$wgUser->isAllowed('purge')) { $this->dieUsageMsg(array('cantpurge')); } if (!isset($params['titles'])) { $this->dieUsageMsg(array('missingparam', 'titles')); } $result = array(); foreach ($params['titles'] as $t) { $r = array(); $title = Title::newFromText($t); if (!$title instanceof Title) { $r['title'] = $t; $r['invalid'] = ''; $result[] = $r; continue; } ApiQueryBase::addTitleInfo($r, $title); if (!$title->exists()) { $r['missing'] = ''; $result[] = $r; continue; } $article = new Article($title); $article->doPurge(); // Directly purge and skip the UI part of purge(). $r['purged'] = ''; $result[] = $r; } $this->getResult()->setIndexedTagName($result, 'page'); $this->getResult()->addValue(null, $this->getModuleName(), $result); }
/** * Patrols the article or provides the reason the patrol failed. */ public function execute() { global $wgUser, $wgUseRCPatrol, $wgUseNPPatrol; $this->getMain()->requestWriteMode(); $params = $this->extractRequestParams(); if (!isset($params['token'])) { $this->dieUsageMsg(array('missingparam', 'token')); } if (!isset($params['rcid'])) { $this->dieUsageMsg(array('missingparam', 'rcid')); } if (!$wgUser->matchEditToken($params['token'])) { $this->dieUsageMsg(array('sessionfailure')); } $rc = RecentChange::newFromID($params['rcid']); if (!$rc instanceof RecentChange) { $this->dieUsageMsg(array('nosuchrcid', $params['rcid'])); } $retval = RecentChange::markPatrolled($params['rcid']); if ($retval) { $this->dieUsageMsg(current($retval)); } $result = array('rcid' => $rc->getAttribute('rc_id')); ApiQueryBase::addTitleInfo($result, $rc->getTitle()); $this->getResult()->addValue(null, $this->getModuleName(), $result); }
/** * Purges the cache of a page */ public function execute() { $params = $this->extractRequestParams(); $forceLinkUpdate = $params['forcelinkupdate']; $pageSet = $this->getPageSet(); $pageSet->execute(); $result = array(); self::addValues($result, $pageSet->getInvalidTitles(), 'invalid', 'title'); self::addValues($result, $pageSet->getSpecialTitles(), 'special', 'title'); self::addValues($result, $pageSet->getMissingPageIDs(), 'missing', 'pageid'); self::addValues($result, $pageSet->getMissingRevisionIDs(), 'missing', 'revid'); self::addValues($result, $pageSet->getMissingTitles(), 'missing'); self::addValues($result, $pageSet->getInterwikiTitlesAsResult()); foreach ($pageSet->getGoodTitles() as $title) { $r = array(); ApiQueryBase::addTitleInfo($r, $title); $page = WikiPage::factory($title); $page->doPurge(); // Directly purge and skip the UI part of purge(). $r['purged'] = ''; if ($forceLinkUpdate) { if (!$this->getUser()->pingLimiter()) { global $wgEnableParserCache; $popts = $page->makeParserOptions('canonical'); # Parse content; note that HTML generation is only needed if we want to cache the result. $content = $page->getContent(Revision::RAW); $p_result = $content->getParserOutput($title, $page->getLatest(), $popts, $wgEnableParserCache); # Update the links tables $updates = $content->getSecondaryDataUpdates($title, null, true, $p_result); DataUpdate::runUpdates($updates); $r['linkupdate'] = ''; if ($wgEnableParserCache) { $pcache = ParserCache::singleton(); $pcache->save($p_result, $page, $popts); } } else { $error = $this->parseMsg(array('actionthrottledtext')); $this->setWarning($error['info']); $forceLinkUpdate = false; } } $result[] = $r; } $apiResult = $this->getResult(); $apiResult->setIndexedTagName($result, 'page'); $apiResult->addValue(null, $this->getModuleName(), $result); $values = $pageSet->getNormalizedTitlesAsResult($apiResult); if ($values) { $apiResult->addValue(null, 'normalized', $values); } $values = $pageSet->getConvertedTitlesAsResult($apiResult); if ($values) { $apiResult->addValue(null, 'converted', $values); } $values = $pageSet->getRedirectTitlesAsResult($apiResult); if ($values) { $apiResult->addValue(null, 'redirects', $values); } }
public function __construct(ApiQuery $query, $moduleName, $prefix = 'ii') { // We allow a subclass to override the prefix, to create a related API // module. Some other parts of MediaWiki construct this with a null // $prefix, which used to be ignored when this only took two arguments if (is_null($prefix)) { $prefix = 'ii'; } parent::__construct($query, $moduleName, $prefix); }
private function run($resultPageSet = null) { wfProfileIn($this->getModuleProfileName() . '-getDB'); $db =& $this->getDB(); wfProfileOut($this->getModuleProfileName() . '-getDB'); wfProfileIn($this->getModuleProfileName() . '-parseParams'); $limit = $from = $namespace = $filterredir = $prefix = null; extract($this->extractRequestParams()); $this->addTables('page'); if (!$this->addWhereIf('page_is_redirect = 1', $filterredir === 'redirects')) { $this->addWhereIf('page_is_redirect = 0', $filterredir === 'nonredirects'); } $this->addWhereFld('page_namespace', $namespace); if (isset($from)) { $this->addWhere('page_title>=' . $db->addQuotes(ApiQueryBase::titleToKey($from))); } if (isset($prefix)) { $this->addWhere("page_title LIKE '{$db->strencode(ApiQueryBase::titleToKey($prefix))}%'"); } if (is_null($resultPageSet)) { $this->addFields(array('page_id', 'page_namespace', 'page_title')); } else { $this->addFields($resultPageSet->getPageTableFields()); } $this->addOption('USE INDEX', 'name_title'); $this->addOption('LIMIT', $limit + 1); $this->addOption('ORDER BY', 'page_namespace, page_title'); wfProfileOut($this->getModuleProfileName() . '-parseParams'); $res = $this->select(__METHOD__); wfProfileIn($this->getModuleProfileName() . '-saveResults'); $data = array(); $count = 0; while ($row = $db->fetchObject($res)) { if (++$count > $limit) { // We've reached the one extra which shows that there are additional pages to be had. Stop here... $this->setContinueEnumParameter('from', ApiQueryBase::keyToTitle($row->page_title)); break; } if (is_null($resultPageSet)) { $vals = $this->addRowInfo('page', $row); if ($vals) { $data[intval($row->page_id)] = $vals; } } else { $resultPageSet->processDbRow($row); } } $db->freeResult($res); if (is_null($resultPageSet)) { $result = $this->getResult(); $result->setIndexedTagName($data, 'p'); $result->addValue('query', $this->getModuleName(), $data); } wfProfileOut($this->getModuleProfileName() . '-saveResults'); }
/** * Purges the cache of a page */ public function execute() { global $wgUser; $params = $this->extractRequestParams(); if (!$wgUser->isAllowed('purge') && !$this->getMain()->isInternalMode() && !$this->getMain()->getRequest()->wasPosted()) { $this->dieUsageMsg(array('mustbeposted', $this->getModuleName())); } $forceLinkUpdate = $params['forcelinkupdate']; $result = array(); foreach ($params['titles'] as $t) { $r = array(); $title = Title::newFromText($t); if (!$title instanceof Title) { $r['title'] = $t; $r['invalid'] = ''; $result[] = $r; continue; } ApiQueryBase::addTitleInfo($r, $title); if (!$title->exists()) { $r['missing'] = ''; $result[] = $r; continue; } $context = $this->createContext(); $context->setTitle($title); $article = Article::newFromTitle($title, $context); $article->doPurge(); // Directly purge and skip the UI part of purge(). $r['purged'] = ''; if ($forceLinkUpdate) { if (!$wgUser->pingLimiter()) { global $wgParser, $wgEnableParserCache; $popts = new ParserOptions(); $p_result = $wgParser->parse($article->getContent(), $title, $popts); # Update the links tables $u = new LinksUpdate($title, $p_result); $u->doUpdate(); $r['linkupdate'] = ''; if ($wgEnableParserCache) { $pcache = ParserCache::singleton(); $pcache->save($p_result, $article, $popts); } } else { $this->setWarning($this->parseMsg(array('actionthrottledtext'))); $forceLinkUpdate = false; } } $result[] = $r; } $apiResult = $this->getResult(); $apiResult->setIndexedTagName($result, 'page'); $apiResult->addValue(null, $this->getModuleName(), $result); }
private function run($resultPageSet = null) { $limit = $from = $namespace = $filterredir = null; extract($this->extractRequestParams()); $db = $this->getDB(); $where = array('page_namespace' => $namespace); if (isset($from)) { $where[] = 'page_title>=' . $db->addQuotes(ApiQueryBase::titleToKey($from)); } if ($filterredir === 'redirects') { $where['page_is_redirect'] = 1; } elseif ($filterredir === 'nonredirects') { $where['page_is_redirect'] = 0; } if (is_null($resultPageSet)) { $fields = array('page_id', 'page_namespace', 'page_title'); } else { $fields = $resultPageSet->getPageTableFields(); } $this->profileDBIn(); $res = $db->select('page', $fields, $where, __CLASS__ . '::' . __METHOD__, array('USE INDEX' => 'name_title', 'LIMIT' => $limit + 1, 'ORDER BY' => 'page_namespace, page_title')); $this->profileDBOut(); $data = array(); $count = 0; while ($row = $db->fetchObject($res)) { if (++$count > $limit) { // We've reached the one extra which shows that there are additional pages to be had. Stop here... $msg = array('continue' => $this->encodeParamName('from') . '=' . ApiQueryBase::keyToTitle($row->page_title)); $this->getResult()->addValue('query-status', 'allpages', $msg); break; } $title = Title::makeTitle($row->page_namespace, $row->page_title); // skip any pages that user has no rights to read if ($title->userCanRead()) { if (is_null($resultPageSet)) { $id = intval($row->page_id); $data[] = $id; // in generator mode, just assemble a list of page IDs. } else { $resultPageSet->processDbRow($row); } } } $db->freeResult($res); if (is_null($resultPageSet)) { ApiResult::setIndexedTagName($data, 'p'); $this->getResult()->addValue('query', 'allpages', $data); } }
/** * Patrols the article or provides the reason the patrol failed. */ public function execute() { $params = $this->extractRequestParams(); $rc = RecentChange::newFromID($params['rcid']); if (!$rc instanceof RecentChange) { $this->dieUsageMsg(array('nosuchrcid', $params['rcid'])); } $retval = $rc->doMarkPatrolled($this->getUser()); if ($retval) { $this->dieUsageMsg(reset($retval)); } $result = array('rcid' => intval($rc->getAttribute('rc_id'))); ApiQueryBase::addTitleInfo($result, $rc->getTitle()); $this->getResult()->addValue(null, $this->getModuleName(), $result); }
public function __construct($query, $resolveRedirects = false) { parent::__construct($query, __CLASS__); $this->mAllPages = array(); $this->mGoodTitles = array(); $this->mMissingTitles = array(); $this->mMissingPageIDs = array(); $this->mRedirectTitles = array(); $this->mNormalizedTitles = array(); $this->mRequestedPageFields = array(); $this->mResolveRedirects = $resolveRedirects; if ($resolveRedirects) { $this->mPendingRedirectIDs = array(); } }
private function run($resultPageSet = null) { $db = $this->getDB(); $params = $this->extractRequestParams(); $this->addTables('page'); if (!$this->addWhereIf('page_is_redirect = 1', $params['filterredir'] === 'redirects')) { $this->addWhereIf('page_is_redirect = 0', $params['filterredir'] === 'nonredirects'); } $this->addWhereFld('page_namespace', $params['namespace']); if (!is_null($params['from'])) { $this->addWhere('page_title>=' . $db->addQuotes(ApiQueryBase::titleToKey($params['from']))); } if (isset($params['prefix'])) { $this->addWhere("page_title LIKE '" . $db->escapeLike(ApiQueryBase::titleToKey($params['prefix'])) . "%'"); } if (is_null($resultPageSet)) { $this->addFields(array('page_id', 'page_namespace', 'page_title')); } else { $this->addFields($resultPageSet->getPageTableFields()); } $this->addOption('USE INDEX', 'name_title'); $limit = $params['limit']; $this->addOption('LIMIT', $limit + 1); $this->addOption('ORDER BY', 'page_namespace, page_title'); $res = $this->select(__METHOD__); $data = array(); $count = 0; while ($row = $db->fetchObject($res)) { if (++$count > $limit) { // We've reached the one extra which shows that there are additional pages to be had. Stop here... // TODO: Security issue - if the user has no right to view next title, it will still be shown $this->setContinueEnumParameter('from', ApiQueryBase::keyToTitle($row->page_title)); break; } if (is_null($resultPageSet)) { $title = Title::makeTitle($row->page_namespace, $row->page_title); $data[] = array('pageid' => intval($row->page_id), 'ns' => intval($title->getNamespace()), 'title' => $title->getPrefixedText()); } else { $resultPageSet->processDbRow($row); } } $db->freeResult($res); if (is_null($resultPageSet)) { $result = $this->getResult(); $result->setIndexedTagName($data, 'p'); $result->addValue('query', $this->getModuleName(), $data); } }
/** * Add all items from $values into the result * @param array $result Output * @param array $values Values to add * @param string $flag The name of the boolean flag to mark this element * @param string $name If given, name of the value */ private static function addValues(array &$result, $values, $flag = null, $name = null) { foreach ($values as $val) { if ($val instanceof Title) { $v = array(); ApiQueryBase::addTitleInfo($v, $val); } elseif ($name !== null) { $v = array($name => $val); } else { $v = $val; } if ($flag !== null) { $v[$flag] = ''; } $result[] = $v; } }
function reportPage( $title, $origTitle, $revisionCount, $successCount, $pageInfo = '' ) { // Add a result entry $r = array(); ApiQueryBase::addTitleInfo($r, $title); $r['revisions'] = intval($successCount); $this->mResultArr[] = $r; # call the parent to do the logging # avoid bug in 1.15.4 Special:Import (new file page text without the file uploaded) # PHP Fatal error: Call to a member function insertOn() on a non-object in E:\www\psychologos\includes\specials\SpecialImport.php on line 334 // do not create informational null revisions // because they are placed on top of real user made revisions, // making the binary search algorithm used to compare local and remote revs to fail // TODO: change the binary search algorithm to two/three level hashes if ( WikiSyncSetup::$report_null_revisions && $title->getArticleId() !== 0 ) { parent::reportPage( $title, $origTitle, $revisionCount, $successCount, $pageInfo ); } }
private function run($resultPageSet = null) { $db = $this->getDB(); $params = $this->extractRequestParams(); $this->addTables('categorylinks'); $this->addFields('cl_to'); if (!is_null($params['from'])) { $this->addWhere('cl_to>=' . $db->addQuotes(ApiQueryBase::titleToKey($params['from']))); } if (isset($params['prefix'])) { $this->addWhere("cl_to LIKE '" . $db->escapeLike(ApiQueryBase::titleToKey($params['prefix'])) . "%'"); } $this->addOption('LIMIT', $params['limit'] + 1); $this->addOption('ORDER BY', 'cl_to' . ($params['dir'] == 'descending' ? ' DESC' : '')); $this->addOption('DISTINCT'); $res = $this->select(__METHOD__); $pages = array(); $count = 0; while ($row = $db->fetchObject($res)) { if (++$count > $params['limit']) { // We've reached the one extra which shows that there are additional cats to be had. Stop here... // TODO: Security issue - if the user has no right to view next title, it will still be shown $this->setContinueEnumParameter('from', ApiQueryBase::keyToTitle($row->cl_to)); break; } // Normalize titles $titleObj = Title::makeTitle(NS_CATEGORY, $row->cl_to); if (!is_null($resultPageSet)) { $pages[] = $titleObj->getPrefixedText(); } else { // Don't show "Category:" everywhere in non-generator mode $pages[] = $titleObj->getText(); } } $db->freeResult($res); if (is_null($resultPageSet)) { $result = $this->getResult(); $result->setIndexedTagName($pages, 'c'); $result->addValue('query', $this->getModuleName(), $pages); } else { $resultPageSet->populateFromTitles($pages); } }
/** * Constructor * @param $query ApiQuery * @param $resolveRedirects bool Whether redirects should be resolved */ public function __construct($query, $resolveRedirects = false) { parent::__construct($query, 'query'); $this->mAllPages = array(); $this->mTitles = array(); $this->mGoodTitles = array(); $this->mMissingTitles = array(); $this->mInvalidTitles = array(); $this->mMissingPageIDs = array(); $this->mRedirectTitles = array(); $this->mNormalizedTitles = array(); $this->mInterwikiTitles = array(); $this->mGoodRevIDs = array(); $this->mMissingRevIDs = array(); $this->mRequestedPageFields = array(); $this->mResolveRedirects = $resolveRedirects; if ($resolveRedirects) { $this->mPendingRedirectIDs = array(); } $this->mFakePageId = -1; }
private function run($resultPageSet = null) { if ($this->getPageSet()->getGoodTitleCount() == 0) { return; } // nothing to do $this->addFields(array('il_from', 'il_to')); $this->addTables('imagelinks'); $this->addWhereFld('il_from', array_keys($this->getPageSet()->getGoodTitles())); $this->addOption('ORDER BY', "il_from, il_to"); $db = $this->getDB(); $res = $this->select(__METHOD__); if (is_null($resultPageSet)) { $data = array(); $lastId = 0; // database has no ID 0 while ($row = $db->fetchObject($res)) { if ($lastId != $row->il_from) { if ($lastId != 0) { $this->addPageSubItems($lastId, $data); $data = array(); } $lastId = $row->il_from; } $vals = array(); ApiQueryBase::addTitleInfo($vals, Title::makeTitle(NS_IMAGE, $row->il_to)); $data[] = $vals; } if ($lastId != 0) { $this->addPageSubItems($lastId, $data); } } else { $titles = array(); while ($row = $db->fetchObject($res)) { $titles[] = Title::makeTitle(NS_IMAGE, $row->il_to); } $resultPageSet->populateFromTitles($titles); } $db->freeResult($res); }
/** * 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); }
/** * Overrides base class to prepend 'g' to every generator parameter * @param $paramName string Parameter name * @return string Prefixed parameter name */ public function encodeParamName($paramName) { if ($this->mIsGenerator) { return 'g' . parent::encodeParamName($paramName); } else { return parent::encodeParamName($paramName); } }
/** * @param $resultPageSet ApiPageSet * @return void */ private function run($resultPageSet = null) { $params = $this->extractRequestParams(); $this->addTables('protected_titles'); $this->addFields(array('pt_namespace', 'pt_title', 'pt_timestamp')); $prop = array_flip($params['prop']); $this->addFieldsIf('pt_user', isset($prop['user']) || isset($prop['userid'])); $this->addFieldsIf('pt_reason', isset($prop['comment']) || isset($prop['parsedcomment'])); $this->addFieldsIf('pt_expiry', isset($prop['expiry'])); $this->addFieldsIf('pt_create_perm', isset($prop['level'])); $this->addTimestampWhereRange('pt_timestamp', $params['dir'], $params['start'], $params['end']); $this->addWhereFld('pt_namespace', $params['namespace']); $this->addWhereFld('pt_create_perm', $params['level']); if (isset($prop['user'])) { $this->addTables('user'); $this->addFields('user_name'); $this->addJoinConds(array('user' => array('LEFT JOIN', 'user_id=pt_user'))); } $this->addOption('LIMIT', $params['limit'] + 1); $res = $this->select(__METHOD__); $count = 0; $result = $this->getResult(); $titles = array(); foreach ($res as $row) { if (++$count > $params['limit']) { // We've reached the one extra which shows that there are additional pages to be had. Stop here... $this->setContinueEnumParameter('start', wfTimestamp(TS_ISO_8601, $row->pt_timestamp)); break; } $title = Title::makeTitle($row->pt_namespace, $row->pt_title); if (is_null($resultPageSet)) { $vals = array(); ApiQueryBase::addTitleInfo($vals, $title); if (isset($prop['timestamp'])) { $vals['timestamp'] = wfTimestamp(TS_ISO_8601, $row->pt_timestamp); } if (isset($prop['user']) && !is_null($row->user_name)) { $vals['user'] = $row->user_name; } if (isset($prop['user'])) { $vals['userid'] = $row->pt_user; } if (isset($prop['comment'])) { $vals['comment'] = $row->pt_reason; } if (isset($prop['parsedcomment'])) { global $wgUser; $vals['parsedcomment'] = $wgUser->getSkin()->formatComment($row->pt_reason, $title); } if (isset($prop['expiry'])) { global $wgContLang; $vals['expiry'] = $wgContLang->formatExpiry($row->pt_expiry, TS_ISO_8601); } if (isset($prop['level'])) { $vals['level'] = $row->pt_create_perm; } $fit = $result->addValue(array('query', $this->getModuleName()), null, $vals); if (!$fit) { $this->setContinueEnumParameter('start', wfTimestamp(TS_ISO_8601, $row->pt_timestamp)); break; } } else { $titles[] = $title; } } if (is_null($resultPageSet)) { $result->setIndexedTagName_internal(array('query', $this->getModuleName()), $this->getModulePrefix()); } else { $resultPageSet->populateFromTitles($titles); } }
private function run($resultPageSet = null) { if ($this->getPageSet()->getGoodTitleCount() == 0) { return; } // nothing to do $params = $this->extractRequestParams(); $prop = array_flip((array) $params['prop']); $show = array_flip((array) $params['show']); $this->addFields(array('cl_from', 'cl_to')); $this->addFieldsIf('cl_sortkey', isset($prop['sortkey'])); $this->addFieldsIf('cl_timestamp', isset($prop['timestamp'])); $this->addTables('categorylinks'); $this->addWhereFld('cl_from', array_keys($this->getPageSet()->getGoodTitles())); if (!is_null($params['categories'])) { $cats = array(); foreach ($params['categories'] as $cat) { $title = Title::newFromText($cat); if (!$title || $title->getNamespace() != NS_CATEGORY) { $this->setWarning("``{$cat}'' is not a category"); } else { $cats[] = $title->getDBkey(); } } $this->addWhereFld('cl_to', $cats); } if (!is_null($params['continue'])) { $cont = explode('|', $params['continue']); if (count($cont) != 2) { $this->dieUsage("Invalid continue param. You should pass the " . "original value returned by the previous query", "_badcontinue"); } $clfrom = intval($cont[0]); $clto = $this->getDB()->strencode($this->titleToKey($cont[1])); $this->addWhere("cl_from > {$clfrom} OR " . "(cl_from = {$clfrom} AND " . "cl_to >= '{$clto}')"); } if (isset($show['hidden']) && isset($show['!hidden'])) { $this->dieUsageMsg(array('show')); } if (isset($show['hidden']) || isset($show['!hidden']) || isset($prop['hidden'])) { $this->addOption('STRAIGHT_JOIN'); $this->addTables(array('page', 'page_props')); $this->addFieldsIf('pp_propname', isset($prop['hidden'])); $this->addJoinConds(array('page' => array('LEFT JOIN', array('page_namespace' => NS_CATEGORY, 'page_title = cl_to')), 'page_props' => array('LEFT JOIN', array('pp_page=page_id', 'pp_propname' => 'hiddencat')))); if (isset($show['hidden'])) { $this->addWhere(array('pp_propname IS NOT NULL')); } else { if (isset($show['!hidden'])) { $this->addWhere(array('pp_propname IS NULL')); } } } $this->addOption('USE INDEX', array('categorylinks' => 'cl_from')); // Don't order by cl_from if it's constant in the WHERE clause if (count($this->getPageSet()->getGoodTitles()) == 1) { $this->addOption('ORDER BY', 'cl_to'); } else { $this->addOption('ORDER BY', "cl_from, cl_to"); } $db = $this->getDB(); $res = $this->select(__METHOD__); if (is_null($resultPageSet)) { $count = 0; while ($row = $db->fetchObject($res)) { if (++$count > $params['limit']) { // We've reached the one extra which shows that // there are additional pages to be had. Stop here... $this->setContinueEnumParameter('continue', $row->cl_from . '|' . $this->keyToTitle($row->cl_to)); break; } $title = Title::makeTitle(NS_CATEGORY, $row->cl_to); $vals = array(); ApiQueryBase::addTitleInfo($vals, $title); if (isset($prop['sortkey'])) { $vals['sortkey'] = $row->cl_sortkey; } if (isset($prop['timestamp'])) { $vals['timestamp'] = wfTimestamp(TS_ISO_8601, $row->cl_timestamp); } if (isset($prop['hidden']) && !is_null($row->pp_propname)) { $vals['hidden'] = ''; } $fit = $this->addPageSubItem($row->cl_from, $vals); if (!$fit) { $this->setContinueEnumParameter('continue', $row->cl_from . '|' . $this->keyToTitle($row->cl_to)); break; } } } else { $titles = array(); while ($row = $db->fetchObject($res)) { if (++$count > $params['limit']) { // We've reached the one extra which shows that // there are additional pages to be had. Stop here... $this->setContinueEnumParameter('continue', $row->cl_from . '|' . $this->keyToTitle($row->cl_to)); break; } $titles[] = Title::makeTitle(NS_CATEGORY, $row->cl_to); } $resultPageSet->populateFromTitles($titles); } $db->freeResult($res); }
public function __construct(ApiQuery $query, $moduleName) { parent::__construct($query, $moduleName, 'fri'); }
private function extractRowInfo($row) { $vals = array(); $type = intval($row->rc_type); /* Determine what kind of change this was. */ switch ($type) { case RC_EDIT: $vals['type'] = 'edit'; break; case RC_NEW: $vals['type'] = 'new'; break; case RC_MOVE: $vals['type'] = 'move'; break; case RC_LOG: $vals['type'] = 'log'; break; case RC_EXTERNAL: $vals['type'] = 'external'; break; case RC_MOVE_OVER_REDIRECT: $vals['type'] = 'move over redirect'; break; default: $vals['type'] = $type; } if ($this->fld_ids) { $vals['pageid'] = intval($row->rc_cur_id); $vals['revid'] = intval($row->rc_this_oldid); $vals['old_revid'] = intval($row->rc_last_oldid); } $title = Title::makeTitle($row->rc_namespace, $row->rc_title); if ($this->fld_title) { ApiQueryBase::addTitleInfo($vals, $title); } if ($this->fld_user || $this->fld_userid) { if ($this->fld_userid) { $vals['userid'] = $row->rc_user; // for backwards compatibility $vals['user'] = $row->rc_user; } if ($this->fld_user) { $vals['user'] = $row->rc_user_text; } if (!$row->rc_user) { $vals['anon'] = ''; } } if ($this->fld_flags) { if ($row->rc_type == RC_NEW) { $vals['new'] = ''; } if ($row->rc_minor) { $vals['minor'] = ''; } if ($row->rc_bot) { $vals['bot'] = ''; } } if ($this->fld_patrol && isset($row->rc_patrolled)) { $vals['patrolled'] = ''; } if ($this->fld_timestamp) { $vals['timestamp'] = wfTimestamp(TS_ISO_8601, $row->rc_timestamp); } if ($this->fld_sizes) { $vals['oldlen'] = intval($row->rc_old_len); $vals['newlen'] = intval($row->rc_new_len); } if ($this->fld_notificationtimestamp) { $vals['notificationtimestamp'] = $row->wl_notificationtimestamp == null ? '' : wfTimestamp(TS_ISO_8601, $row->wl_notificationtimestamp); } if ($this->fld_comment && isset($row->rc_comment)) { $vals['comment'] = $row->rc_comment; } if ($this->fld_parsedcomment && isset($row->rc_comment)) { $vals['parsedcomment'] = Linker::formatComment($row->rc_comment, $title); } if ($this->fld_loginfo && $row->rc_type == RC_LOG) { $vals['logid'] = intval($row->rc_logid); $vals['logtype'] = $row->rc_log_type; $vals['logaction'] = $row->rc_log_action; $logEntry = DatabaseLogEntry::newFromRow((array) $row); ApiQueryLogEvents::addLogParams($this->getResult(), $vals, $logEntry->getParameters(), $logEntry->getType(), $logEntry->getSubtype(), $logEntry->getTimestamp()); } return $vals; }
/** * Extracts from a single sql row the data needed to describe one recent change. * * @param stdClass $row The row from which to extract the data. * @return array An array mapping strings (descriptors) to their respective string values. * @access public */ public function extractRowInfo($row) { /* Determine the title of the page that has been changed. */ $title = Title::makeTitle($row->rc_namespace, $row->rc_title); $user = $this->getUser(); /* Our output data. */ $vals = array(); $type = intval($row->rc_type); $vals['type'] = RecentChange::parseFromRCType($type); $anyHidden = false; /* Create a new entry in the result for the title. */ if ($this->fld_title || $this->fld_ids) { if ($type === RC_LOG && $row->rc_deleted & LogPage::DELETED_ACTION) { $vals['actionhidden'] = true; $anyHidden = true; } if ($type !== RC_LOG || LogEventsList::userCanBitfield($row->rc_deleted, LogPage::DELETED_ACTION, $user)) { if ($this->fld_title) { ApiQueryBase::addTitleInfo($vals, $title); } if ($this->fld_ids) { $vals['pageid'] = intval($row->rc_cur_id); $vals['revid'] = intval($row->rc_this_oldid); $vals['old_revid'] = intval($row->rc_last_oldid); } } } if ($this->fld_ids) { $vals['rcid'] = intval($row->rc_id); } /* Add user data and 'anon' flag, if user is anonymous. */ if ($this->fld_user || $this->fld_userid) { if ($row->rc_deleted & Revision::DELETED_USER) { $vals['userhidden'] = true; $anyHidden = true; } if (Revision::userCanBitfield($row->rc_deleted, Revision::DELETED_USER, $user)) { if ($this->fld_user) { $vals['user'] = $row->rc_user_text; } if ($this->fld_userid) { $vals['userid'] = $row->rc_user; } if (!$row->rc_user) { $vals['anon'] = true; } } } /* Add flags, such as new, minor, bot. */ if ($this->fld_flags) { $vals['bot'] = (bool) $row->rc_bot; $vals['new'] = $row->rc_type == RC_NEW; $vals['minor'] = (bool) $row->rc_minor; } /* Add sizes of each revision. (Only available on 1.10+) */ if ($this->fld_sizes) { $vals['oldlen'] = intval($row->rc_old_len); $vals['newlen'] = intval($row->rc_new_len); } /* Add the timestamp. */ if ($this->fld_timestamp) { $vals['timestamp'] = wfTimestamp(TS_ISO_8601, $row->rc_timestamp); } /* Add edit summary / log summary. */ if ($this->fld_comment || $this->fld_parsedcomment) { if ($row->rc_deleted & Revision::DELETED_COMMENT) { $vals['commenthidden'] = true; $anyHidden = true; } if (Revision::userCanBitfield($row->rc_deleted, Revision::DELETED_COMMENT, $user)) { if ($this->fld_comment && isset($row->rc_comment)) { $vals['comment'] = $row->rc_comment; } if ($this->fld_parsedcomment && isset($row->rc_comment)) { $vals['parsedcomment'] = Linker::formatComment($row->rc_comment, $title); } } } if ($this->fld_redirect) { $vals['redirect'] = (bool) $row->page_is_redirect; } /* Add the patrolled flag */ if ($this->fld_patrolled) { $vals['patrolled'] = $row->rc_patrolled == 1; $vals['unpatrolled'] = ChangesList::isUnpatrolled($row, $user); } if ($this->fld_loginfo && $row->rc_type == RC_LOG) { if ($row->rc_deleted & LogPage::DELETED_ACTION) { $vals['actionhidden'] = true; $anyHidden = true; } if (LogEventsList::userCanBitfield($row->rc_deleted, LogPage::DELETED_ACTION, $user)) { $vals['logid'] = intval($row->rc_logid); $vals['logtype'] = $row->rc_log_type; $vals['logaction'] = $row->rc_log_action; $vals['logparams'] = LogFormatter::newFromRow($row)->formatParametersForApi(); } } if ($this->fld_tags) { if ($row->ts_tags) { $tags = explode(',', $row->ts_tags); ApiResult::setIndexedTagName($tags, 'tag'); $vals['tags'] = $tags; } else { $vals['tags'] = array(); } } if ($this->fld_sha1 && $row->rev_sha1 !== null) { if ($row->rev_deleted & Revision::DELETED_TEXT) { $vals['sha1hidden'] = true; $anyHidden = true; } if (Revision::userCanBitfield($row->rev_deleted, Revision::DELETED_TEXT, $user)) { if ($row->rev_sha1 !== '') { $vals['sha1'] = wfBaseConvert($row->rev_sha1, 36, 16, 40); } else { $vals['sha1'] = ''; } } } if (!is_null($this->token)) { $tokenFunctions = $this->getTokenFunctions(); foreach ($this->token as $t) { $val = call_user_func($tokenFunctions[$t], $row->rc_cur_id, $title, RecentChange::newFromRow($row)); if ($val === false) { $this->setWarning("Action '{$t}' is not allowed for the current user"); } else { $vals[$t . 'token'] = $val; } } } if ($anyHidden && $row->rc_deleted & Revision::DELETED_RESTRICTED) { $vals['suppressed'] = true; } return $vals; }
/** * @param $resultPageSet ApiPageSet * @return void */ private function run($resultPageSet = null) { $this->selectNamedDB('watchlist', DB_SLAVE, 'watchlist'); $params = $this->extractRequestParams(); $user = $this->getWatchlistUser($params); $prop = array_flip((array) $params['prop']); $show = array_flip((array) $params['show']); if (isset($show['changed']) && isset($show['!changed'])) { $this->dieUsageMsg('show'); } $this->addTables('watchlist'); $this->addFields(array('wl_namespace', 'wl_title')); $this->addFieldsIf('wl_notificationtimestamp', isset($prop['changed'])); $this->addWhereFld('wl_user', $user->getId()); $this->addWhereFld('wl_namespace', $params['namespace']); $this->addWhereIf('wl_notificationtimestamp IS NOT NULL', isset($show['changed'])); $this->addWhereIf('wl_notificationtimestamp IS NULL', isset($show['!changed'])); if (isset($params['continue'])) { $cont = explode('|', $params['continue']); $this->dieContinueUsageIf(count($cont) != 2); $ns = intval($cont[0]); $this->dieContinueUsageIf(strval($ns) !== $cont[0]); $title = $this->getDB()->addQuotes($cont[1]); $op = $params['dir'] == 'ascending' ? '>' : '<'; $this->addWhere("wl_namespace {$op} {$ns} OR " . "(wl_namespace = {$ns} AND " . "wl_title {$op}= {$title})"); } $sort = $params['dir'] == 'descending' ? ' DESC' : ''; // Don't ORDER BY wl_namespace if it's constant in the WHERE clause if (count($params['namespace']) == 1) { $this->addOption('ORDER BY', 'wl_title' . $sort); } else { $this->addOption('ORDER BY', array('wl_namespace' . $sort, 'wl_title' . $sort)); } $this->addOption('LIMIT', $params['limit'] + 1); $res = $this->select(__METHOD__); $titles = array(); $count = 0; foreach ($res as $row) { if (++$count > $params['limit']) { // We've reached the one extra which shows that there are additional pages to be had. Stop here... $this->setContinueEnumParameter('continue', $row->wl_namespace . '|' . $row->wl_title); break; } $t = Title::makeTitle($row->wl_namespace, $row->wl_title); if (is_null($resultPageSet)) { $vals = array(); ApiQueryBase::addTitleInfo($vals, $t); if (isset($prop['changed']) && !is_null($row->wl_notificationtimestamp)) { $vals['changed'] = wfTimestamp(TS_ISO_8601, $row->wl_notificationtimestamp); } $fit = $this->getResult()->addValue($this->getModuleName(), null, $vals); if (!$fit) { $this->setContinueEnumParameter('continue', $row->wl_namespace . '|' . $row->wl_title); break; } } else { $titles[] = $t; } } if (is_null($resultPageSet)) { $this->getResult()->setIndexedTagName_internal($this->getModuleName(), 'wr'); } else { $resultPageSet->populateFromTitles($titles); } }
/** * Appends an element for each page in the current pageSet with the * most general information (id, title), plus any title normalizations * and missing or invalid title/pageids/revids. */ private function outputGeneralPageInfo() { $pageSet = $this->getPageSet(); $result = $this->getResult(); // We don't check for a full result set here because we can't be adding // more than 380K. The maximum revision size is in the megabyte range, // and the maximum result size must be even higher than that. $values = $pageSet->getNormalizedTitlesAsResult($result); if ($values) { $result->addValue('query', 'normalized', $values); } $values = $pageSet->getConvertedTitlesAsResult($result); if ($values) { $result->addValue('query', 'converted', $values); } $values = $pageSet->getInterwikiTitlesAsResult($result, $this->mParams['iwurl']); if ($values) { $result->addValue('query', 'interwiki', $values); } $values = $pageSet->getRedirectTitlesAsResult($result); if ($values) { $result->addValue('query', 'redirects', $values); } $values = $pageSet->getMissingRevisionIDsAsResult($result); if ($values) { $result->addValue('query', 'badrevids', $values); } // Page elements $pages = array(); // Report any missing titles foreach ($pageSet->getMissingTitles() as $fakeId => $title) { $vals = array(); ApiQueryBase::addTitleInfo($vals, $title); $vals['missing'] = ''; $pages[$fakeId] = $vals; } // Report any invalid titles foreach ($pageSet->getInvalidTitles() as $fakeId => $title) { $pages[$fakeId] = array('title' => $title, 'invalid' => ''); } // Report any missing page ids foreach ($pageSet->getMissingPageIDs() as $pageid) { $pages[$pageid] = array('pageid' => $pageid, 'missing' => ''); } // Report special pages /** @var $title Title */ foreach ($pageSet->getSpecialTitles() as $fakeId => $title) { $vals = array(); ApiQueryBase::addTitleInfo($vals, $title); $vals['special'] = ''; if ($title->isSpecialPage() && !SpecialPageFactory::exists($title->getDBkey())) { $vals['missing'] = ''; } elseif ($title->getNamespace() == NS_MEDIA && !wfFindFile($title)) { $vals['missing'] = ''; } $pages[$fakeId] = $vals; } // Output general page information for found titles foreach ($pageSet->getGoodTitles() as $pageid => $title) { $vals = array(); $vals['pageid'] = $pageid; ApiQueryBase::addTitleInfo($vals, $title); $pages[$pageid] = $vals; } if (count($pages)) { if ($this->mParams['indexpageids']) { $pageIDs = array_keys($pages); // json treats all map keys as strings - converting to match $pageIDs = array_map('strval', $pageIDs); $result->setIndexedTagName($pageIDs, 'id'); $result->addValue('query', 'pageids', $pageIDs); } $result->setIndexedTagName($pages, 'page'); $result->addValue('query', 'pages', $pages); } if ($this->mParams['export']) { $this->doExport($pageSet, $result); } }
/** * @param ApiPageSet $resultPageSet */ private function run($resultPageSet = null) { if ($this->getPageSet()->getGoodTitleCount() == 0) { return; // nothing to do } $params = $this->extractRequestParams(); $prop = array_flip((array) $params['prop']); $show = array_flip((array) $params['show']); $this->addFields(array('cl_from', 'cl_to')); $this->addFieldsIf(array('cl_sortkey', 'cl_sortkey_prefix'), isset($prop['sortkey'])); $this->addFieldsIf('cl_timestamp', isset($prop['timestamp'])); $this->addTables('categorylinks'); $this->addWhereFld('cl_from', array_keys($this->getPageSet()->getGoodTitles())); if (!is_null($params['categories'])) { $cats = array(); foreach ($params['categories'] as $cat) { $title = Title::newFromText($cat); if (!$title || $title->getNamespace() != NS_CATEGORY) { $this->setWarning("\"{$cat}\" is not a category"); } else { $cats[] = $title->getDBkey(); } } $this->addWhereFld('cl_to', $cats); } if (!is_null($params['continue'])) { $cont = explode('|', $params['continue']); $this->dieContinueUsageIf(count($cont) != 2); $op = $params['dir'] == 'descending' ? '<' : '>'; $clfrom = intval($cont[0]); $clto = $this->getDB()->addQuotes($cont[1]); $this->addWhere("cl_from {$op} {$clfrom} OR " . "(cl_from = {$clfrom} AND " . "cl_to {$op}= {$clto})"); } if (isset($show['hidden']) && isset($show['!hidden'])) { $this->dieUsageMsg('show'); } if (isset($show['hidden']) || isset($show['!hidden']) || isset($prop['hidden'])) { $this->addOption('STRAIGHT_JOIN'); $this->addTables(array('page', 'page_props')); $this->addFieldsIf('pp_propname', isset($prop['hidden'])); $this->addJoinConds(array('page' => array('LEFT JOIN', array('page_namespace' => NS_CATEGORY, 'page_title = cl_to')), 'page_props' => array('LEFT JOIN', array('pp_page=page_id', 'pp_propname' => 'hiddencat')))); if (isset($show['hidden'])) { $this->addWhere(array('pp_propname IS NOT NULL')); } elseif (isset($show['!hidden'])) { $this->addWhere(array('pp_propname IS NULL')); } } $sort = $params['dir'] == 'descending' ? ' DESC' : ''; // Don't order by cl_from if it's constant in the WHERE clause if (count($this->getPageSet()->getGoodTitles()) == 1) { $this->addOption('ORDER BY', 'cl_to' . $sort); } else { $this->addOption('ORDER BY', array('cl_from' . $sort, 'cl_to' . $sort)); } $res = $this->select(__METHOD__); $count = 0; if (is_null($resultPageSet)) { foreach ($res as $row) { if (++$count > $params['limit']) { // We've reached the one extra which shows that // there are additional pages to be had. Stop here... $this->setContinueEnumParameter('continue', $row->cl_from . '|' . $row->cl_to); break; } $title = Title::makeTitle(NS_CATEGORY, $row->cl_to); $vals = array(); ApiQueryBase::addTitleInfo($vals, $title); if (isset($prop['sortkey'])) { $vals['sortkey'] = bin2hex($row->cl_sortkey); $vals['sortkeyprefix'] = $row->cl_sortkey_prefix; } if (isset($prop['timestamp'])) { $vals['timestamp'] = wfTimestamp(TS_ISO_8601, $row->cl_timestamp); } if (isset($prop['hidden'])) { $vals['hidden'] = !is_null($row->pp_propname); } $fit = $this->addPageSubItem($row->cl_from, $vals); if (!$fit) { $this->setContinueEnumParameter('continue', $row->cl_from . '|' . $row->cl_to); break; } } } else { $titles = array(); foreach ($res as $row) { if (++$count > $params['limit']) { // We've reached the one extra which shows that // there are additional pages to be had. Stop here... $this->setContinueEnumParameter('continue', $row->cl_from . '|' . $row->cl_to); break; } $titles[] = Title::makeTitle(NS_CATEGORY, $row->cl_to); } $resultPageSet->populateFromTitles($titles); } }
public function __construct($query, $moduleName) { parent::__construct($query, $moduleName, 'mt'); }
/** * @param ApiPageSet $resultPageSet * @return void */ protected function run(ApiPageSet $resultPageSet = null) { $db = $this->getDB(); $params = $this->extractRequestParams(false); $result = $this->getResult(); $this->requireMaxOneParameter($params, 'user', 'excludeuser'); // Namespace check is likely to be desired, but can't be done // efficiently in SQL. $miser_ns = null; $needPageTable = false; if ($params['namespace'] !== null) { $params['namespace'] = array_unique($params['namespace']); sort($params['namespace']); if ($params['namespace'] != MWNamespace::getValidNamespaces()) { $needPageTable = true; if ($this->getConfig()->get('MiserMode')) { $miser_ns = $params['namespace']; } else { $this->addWhere(array('page_namespace' => $params['namespace'])); } } } $this->addTables('revision'); if ($resultPageSet === null) { $this->parseParameters($params); $this->addTables('page'); $this->addJoinConds(array('page' => array('INNER JOIN', array('rev_page = page_id')))); $this->addFields(Revision::selectFields()); $this->addFields(Revision::selectPageFields()); // Review this depeneding on the outcome of T113901 $this->addOption('STRAIGHT_JOIN'); } else { $this->limit = $this->getParameter('limit') ?: 10; $this->addFields(array('rev_timestamp', 'rev_id')); if ($params['generatetitles']) { $this->addFields(array('rev_page')); } if ($needPageTable) { $this->addTables('page'); $this->addJoinConds(array('page' => array('INNER JOIN', array('rev_page = page_id')))); $this->addFieldsIf(array('page_namespace'), (bool) $miser_ns); // Review this depeneding on the outcome of T113901 $this->addOption('STRAIGHT_JOIN'); } } if ($this->fld_tags) { $this->addTables('tag_summary'); $this->addJoinConds(array('tag_summary' => array('LEFT JOIN', array('rev_id=ts_rev_id')))); $this->addFields('ts_tags'); } if ($this->fetchContent) { $this->addTables('text'); $this->addJoinConds(array('text' => array('INNER JOIN', array('rev_text_id=old_id')))); $this->addFields('old_id'); $this->addFields(Revision::selectTextFields()); } if ($params['user'] !== null) { $id = User::idFromName($params['user']); if ($id) { $this->addWhereFld('rev_user', $id); } else { $this->addWhereFld('rev_user_text', $params['user']); } } elseif ($params['excludeuser'] !== null) { $id = User::idFromName($params['excludeuser']); if ($id) { $this->addWhere('rev_user != ' . $id); } else { $this->addWhere('rev_user_text != ' . $db->addQuotes($params['excludeuser'])); } } if ($params['user'] !== null || $params['excludeuser'] !== null) { // Paranoia: avoid brute force searches (bug 17342) if (!$this->getUser()->isAllowed('deletedhistory')) { $bitmask = Revision::DELETED_USER; } elseif (!$this->getUser()->isAllowedAny('suppressrevision', 'viewsuppressed')) { $bitmask = Revision::DELETED_USER | Revision::DELETED_RESTRICTED; } else { $bitmask = 0; } if ($bitmask) { $this->addWhere($db->bitAnd('rev_deleted', $bitmask) . " != {$bitmask}"); } } $dir = $params['dir']; if ($params['continue'] !== null) { $op = $dir == 'newer' ? '>' : '<'; $cont = explode('|', $params['continue']); $this->dieContinueUsageIf(count($cont) != 2); $ts = $db->addQuotes($db->timestamp($cont[0])); $rev_id = (int) $cont[1]; $this->dieContinueUsageIf(strval($rev_id) !== $cont[1]); $this->addWhere("rev_timestamp {$op} {$ts} OR " . "(rev_timestamp = {$ts} AND " . "rev_id {$op}= {$rev_id})"); } $this->addOption('LIMIT', $this->limit + 1); $sort = $dir == 'newer' ? '' : ' DESC'; $orderby = array(); // Targeting index rev_timestamp, user_timestamp, or usertext_timestamp // But 'user' is always constant for the latter two, so it doesn't matter here. $orderby[] = "rev_timestamp {$sort}"; $orderby[] = "rev_id {$sort}"; $this->addOption('ORDER BY', $orderby); $res = $this->select(__METHOD__); $pageMap = array(); // Maps rev_page to array index $count = 0; $nextIndex = 0; $generated = array(); foreach ($res as $row) { if (++$count > $this->limit) { // We've had enough $this->setContinueEnumParameter('continue', "{$row->rev_timestamp}|{$row->rev_id}"); break; } // Miser mode namespace check if ($miser_ns !== null && !in_array($row->page_namespace, $miser_ns)) { continue; } if ($resultPageSet !== null) { if ($params['generatetitles']) { $generated[$row->rev_page] = $row->rev_page; } else { $generated[] = $row->rev_id; } } else { $revision = Revision::newFromRow($row); $rev = $this->extractRevisionInfo($revision, $row); if (!isset($pageMap[$row->rev_page])) { $index = $nextIndex++; $pageMap[$row->rev_page] = $index; $title = $revision->getTitle(); $a = array('pageid' => $title->getArticleID(), 'revisions' => array($rev)); ApiResult::setIndexedTagName($a['revisions'], 'rev'); ApiQueryBase::addTitleInfo($a, $title); $fit = $result->addValue(array('query', $this->getModuleName()), $index, $a); } else { $index = $pageMap[$row->rev_page]; $fit = $result->addValue(array('query', $this->getModuleName(), $index, 'revisions'), null, $rev); } if (!$fit) { $this->setContinueEnumParameter('continue', "{$row->rev_timestamp}|{$row->rev_id}"); break; } } } if ($resultPageSet !== null) { if ($params['generatetitles']) { $resultPageSet->populateFromPageIDs($generated); } else { $resultPageSet->populateFromRevisionIDs($generated); } } else { $result->addIndexedTagName(array('query', $this->getModuleName()), 'page'); } }
/** * @param ApiPageSet $resultPageSet * @return void */ private function run($resultPageSet = null) { $params = $this->extractRequestParams(); $this->addTables('protected_titles'); $this->addFields(array('pt_namespace', 'pt_title', 'pt_timestamp')); $prop = array_flip($params['prop']); $this->addFieldsIf('pt_user', isset($prop['user']) || isset($prop['userid'])); $this->addFieldsIf('pt_reason', isset($prop['comment']) || isset($prop['parsedcomment'])); $this->addFieldsIf('pt_expiry', isset($prop['expiry'])); $this->addFieldsIf('pt_create_perm', isset($prop['level'])); $this->addTimestampWhereRange('pt_timestamp', $params['dir'], $params['start'], $params['end']); $this->addWhereFld('pt_namespace', $params['namespace']); $this->addWhereFld('pt_create_perm', $params['level']); // Include in ORDER BY for uniqueness $this->addWhereRange('pt_namespace', $params['dir'], null, null); $this->addWhereRange('pt_title', $params['dir'], null, null); if (!is_null($params['continue'])) { $cont = explode('|', $params['continue']); $this->dieContinueUsageIf(count($cont) != 3); $op = $params['dir'] === 'newer' ? '>' : '<'; $db = $this->getDB(); $continueTimestamp = $db->addQuotes($db->timestamp($cont[0])); $continueNs = (int) $cont[1]; $this->dieContinueUsageIf($continueNs != $cont[1]); $continueTitle = $db->addQuotes($cont[2]); $this->addWhere("pt_timestamp {$op} {$continueTimestamp} OR " . "(pt_timestamp = {$continueTimestamp} AND " . "(pt_namespace {$op} {$continueNs} OR " . "(pt_namespace = {$continueNs} AND " . "pt_title {$op}= {$continueTitle})))"); } if (isset($prop['user'])) { $this->addTables('user'); $this->addFields('user_name'); $this->addJoinConds(array('user' => array('LEFT JOIN', 'user_id=pt_user'))); } $this->addOption('LIMIT', $params['limit'] + 1); $res = $this->select(__METHOD__); $count = 0; $result = $this->getResult(); $titles = array(); foreach ($res as $row) { if (++$count > $params['limit']) { // We've reached the one extra which shows that there are // additional pages to be had. Stop here... $this->setContinueEnumParameter('continue', "{$row->pt_timestamp}|{$row->pt_namespace}|{$row->pt_title}"); break; } $title = Title::makeTitle($row->pt_namespace, $row->pt_title); if (is_null($resultPageSet)) { $vals = array(); ApiQueryBase::addTitleInfo($vals, $title); if (isset($prop['timestamp'])) { $vals['timestamp'] = wfTimestamp(TS_ISO_8601, $row->pt_timestamp); } if (isset($prop['user']) && !is_null($row->user_name)) { $vals['user'] = $row->user_name; } if (isset($prop['userid']) || isset($prop['user'])) { $vals['userid'] = (int) $row->pt_user; } if (isset($prop['comment'])) { $vals['comment'] = $row->pt_reason; } if (isset($prop['parsedcomment'])) { $vals['parsedcomment'] = Linker::formatComment($row->pt_reason, $title); } if (isset($prop['expiry'])) { global $wgContLang; $vals['expiry'] = $wgContLang->formatExpiry($row->pt_expiry, TS_ISO_8601); } if (isset($prop['level'])) { $vals['level'] = $row->pt_create_perm; } $fit = $result->addValue(array('query', $this->getModuleName()), null, $vals); if (!$fit) { $this->setContinueEnumParameter('continue', "{$row->pt_timestamp}|{$row->pt_namespace}|{$row->pt_title}"); break; } } else { $titles[] = $title; } } if (is_null($resultPageSet)) { $result->addIndexedTagName(array('query', $this->getModuleName()), $this->getModulePrefix()); } else { $resultPageSet->populateFromTitles($titles); } }
/** * @param Title $title * @param Title $origTitle * @param int $revisionCount * @param int $successCount * @param array $pageInfo * @return void */ function reportPage($title, $origTitle, $revisionCount, $successCount, $pageInfo) { // Add a result entry $r = array(); if ($title === null) { # Invalid or non-importable title $r['title'] = $pageInfo['title']; $r['invalid'] = true; } else { ApiQueryBase::addTitleInfo($r, $title); $r['revisions'] = intval($successCount); } $this->mResultArr[] = $r; // Piggyback on the parent to do the logging parent::reportPage($title, $origTitle, $revisionCount, $successCount, $pageInfo); }