MediaWiki
REL1_24
|
00001 <?php 00032 class ApiQueryAllPages extends ApiQueryGeneratorBase { 00033 00034 public function __construct( ApiQuery $query, $moduleName ) { 00035 parent::__construct( $query, $moduleName, 'ap' ); 00036 } 00037 00038 public function execute() { 00039 $this->run(); 00040 } 00041 00042 public function getCacheMode( $params ) { 00043 return 'public'; 00044 } 00045 00050 public function executeGenerator( $resultPageSet ) { 00051 if ( $resultPageSet->isResolvingRedirects() ) { 00052 $this->dieUsage( 00053 'Use "gapfilterredir=nonredirects" option instead of "redirects" ' . 00054 'when using allpages as a generator', 00055 'params' 00056 ); 00057 } 00058 00059 $this->run( $resultPageSet ); 00060 } 00061 00066 private function run( $resultPageSet = null ) { 00067 $db = $this->getDB(); 00068 00069 $params = $this->extractRequestParams(); 00070 00071 // Page filters 00072 $this->addTables( 'page' ); 00073 00074 if ( !is_null( $params['continue'] ) ) { 00075 $cont = explode( '|', $params['continue'] ); 00076 $this->dieContinueUsageIf( count( $cont ) != 1 ); 00077 $op = $params['dir'] == 'descending' ? '<' : '>'; 00078 $cont_from = $db->addQuotes( $cont[0] ); 00079 $this->addWhere( "page_title $op= $cont_from" ); 00080 } 00081 00082 if ( $params['filterredir'] == 'redirects' ) { 00083 $this->addWhereFld( 'page_is_redirect', 1 ); 00084 } elseif ( $params['filterredir'] == 'nonredirects' ) { 00085 $this->addWhereFld( 'page_is_redirect', 0 ); 00086 } 00087 00088 $this->addWhereFld( 'page_namespace', $params['namespace'] ); 00089 $dir = ( $params['dir'] == 'descending' ? 'older' : 'newer' ); 00090 $from = ( $params['from'] === null 00091 ? null 00092 : $this->titlePartToKey( $params['from'], $params['namespace'] ) ); 00093 $to = ( $params['to'] === null 00094 ? null 00095 : $this->titlePartToKey( $params['to'], $params['namespace'] ) ); 00096 $this->addWhereRange( 'page_title', $dir, $from, $to ); 00097 00098 if ( isset( $params['prefix'] ) ) { 00099 $this->addWhere( 'page_title' . $db->buildLike( 00100 $this->titlePartToKey( $params['prefix'], $params['namespace'] ), 00101 $db->anyString() ) ); 00102 } 00103 00104 if ( is_null( $resultPageSet ) ) { 00105 $selectFields = array( 00106 'page_namespace', 00107 'page_title', 00108 'page_id' 00109 ); 00110 } else { 00111 $selectFields = $resultPageSet->getPageTableFields(); 00112 } 00113 00114 $this->addFields( $selectFields ); 00115 $forceNameTitleIndex = true; 00116 if ( isset( $params['minsize'] ) ) { 00117 $this->addWhere( 'page_len>=' . intval( $params['minsize'] ) ); 00118 $forceNameTitleIndex = false; 00119 } 00120 00121 if ( isset( $params['maxsize'] ) ) { 00122 $this->addWhere( 'page_len<=' . intval( $params['maxsize'] ) ); 00123 $forceNameTitleIndex = false; 00124 } 00125 00126 // Page protection filtering 00127 if ( count( $params['prtype'] ) || $params['prexpiry'] != 'all' ) { 00128 $this->addTables( 'page_restrictions' ); 00129 $this->addWhere( 'page_id=pr_page' ); 00130 $this->addWhere( "pr_expiry > {$db->addQuotes( $db->timestamp() )} OR pr_expiry IS NULL" ); 00131 00132 if ( count( $params['prtype'] ) ) { 00133 $this->addWhereFld( 'pr_type', $params['prtype'] ); 00134 00135 if ( isset( $params['prlevel'] ) ) { 00136 // Remove the empty string and '*' from the prlevel array 00137 $prlevel = array_diff( $params['prlevel'], array( '', '*' ) ); 00138 00139 if ( count( $prlevel ) ) { 00140 $this->addWhereFld( 'pr_level', $prlevel ); 00141 } 00142 } 00143 if ( $params['prfiltercascade'] == 'cascading' ) { 00144 $this->addWhereFld( 'pr_cascade', 1 ); 00145 } elseif ( $params['prfiltercascade'] == 'noncascading' ) { 00146 $this->addWhereFld( 'pr_cascade', 0 ); 00147 } 00148 } 00149 $forceNameTitleIndex = false; 00150 00151 if ( $params['prexpiry'] == 'indefinite' ) { 00152 $this->addWhere( "pr_expiry = {$db->addQuotes( $db->getInfinity() )} OR pr_expiry IS NULL" ); 00153 } elseif ( $params['prexpiry'] == 'definite' ) { 00154 $this->addWhere( "pr_expiry != {$db->addQuotes( $db->getInfinity() )}" ); 00155 } 00156 00157 $this->addOption( 'DISTINCT' ); 00158 } elseif ( isset( $params['prlevel'] ) ) { 00159 $this->dieUsage( 'prlevel may not be used without prtype', 'params' ); 00160 } 00161 00162 if ( $params['filterlanglinks'] == 'withoutlanglinks' ) { 00163 $this->addTables( 'langlinks' ); 00164 $this->addJoinConds( array( 'langlinks' => array( 'LEFT JOIN', 'page_id=ll_from' ) ) ); 00165 $this->addWhere( 'll_from IS NULL' ); 00166 $forceNameTitleIndex = false; 00167 } elseif ( $params['filterlanglinks'] == 'withlanglinks' ) { 00168 $this->addTables( 'langlinks' ); 00169 $this->addWhere( 'page_id=ll_from' ); 00170 $this->addOption( 'STRAIGHT_JOIN' ); 00171 // We have to GROUP BY all selected fields to stop 00172 // PostgreSQL from whining 00173 $this->addOption( 'GROUP BY', $selectFields ); 00174 $forceNameTitleIndex = false; 00175 } 00176 00177 if ( $forceNameTitleIndex ) { 00178 $this->addOption( 'USE INDEX', 'name_title' ); 00179 } 00180 00181 $limit = $params['limit']; 00182 $this->addOption( 'LIMIT', $limit + 1 ); 00183 $res = $this->select( __METHOD__ ); 00184 00185 //Get gender information 00186 if ( MWNamespace::hasGenderDistinction( $params['namespace'] ) ) { 00187 $users = array(); 00188 foreach ( $res as $row ) { 00189 $users[] = $row->page_title; 00190 } 00191 GenderCache::singleton()->doQuery( $users, __METHOD__ ); 00192 $res->rewind(); //reset 00193 } 00194 00195 $count = 0; 00196 $result = $this->getResult(); 00197 foreach ( $res as $row ) { 00198 if ( ++$count > $limit ) { 00199 // We've reached the one extra which shows that there are 00200 // additional pages to be had. Stop here... 00201 $this->setContinueEnumParameter( 'continue', $row->page_title ); 00202 break; 00203 } 00204 00205 if ( is_null( $resultPageSet ) ) { 00206 $title = Title::makeTitle( $row->page_namespace, $row->page_title ); 00207 $vals = array( 00208 'pageid' => intval( $row->page_id ), 00209 'ns' => intval( $title->getNamespace() ), 00210 'title' => $title->getPrefixedText() 00211 ); 00212 $fit = $result->addValue( array( 'query', $this->getModuleName() ), null, $vals ); 00213 if ( !$fit ) { 00214 $this->setContinueEnumParameter( 'continue', $row->page_title ); 00215 break; 00216 } 00217 } else { 00218 $resultPageSet->processDbRow( $row ); 00219 } 00220 } 00221 00222 if ( is_null( $resultPageSet ) ) { 00223 $result->setIndexedTagName_internal( array( 'query', $this->getModuleName() ), 'p' ); 00224 } 00225 } 00226 00227 public function getAllowedParams() { 00228 return array( 00229 'from' => null, 00230 'continue' => null, 00231 'to' => null, 00232 'prefix' => null, 00233 'namespace' => array( 00234 ApiBase::PARAM_DFLT => NS_MAIN, 00235 ApiBase::PARAM_TYPE => 'namespace', 00236 ), 00237 'filterredir' => array( 00238 ApiBase::PARAM_DFLT => 'all', 00239 ApiBase::PARAM_TYPE => array( 00240 'all', 00241 'redirects', 00242 'nonredirects' 00243 ) 00244 ), 00245 'minsize' => array( 00246 ApiBase::PARAM_TYPE => 'integer', 00247 ), 00248 'maxsize' => array( 00249 ApiBase::PARAM_TYPE => 'integer', 00250 ), 00251 'prtype' => array( 00252 ApiBase::PARAM_TYPE => Title::getFilteredRestrictionTypes( true ), 00253 ApiBase::PARAM_ISMULTI => true 00254 ), 00255 'prlevel' => array( 00256 ApiBase::PARAM_TYPE => $this->getConfig()->get( 'RestrictionLevels' ), 00257 ApiBase::PARAM_ISMULTI => true 00258 ), 00259 'prfiltercascade' => array( 00260 ApiBase::PARAM_DFLT => 'all', 00261 ApiBase::PARAM_TYPE => array( 00262 'cascading', 00263 'noncascading', 00264 'all' 00265 ), 00266 ), 00267 'limit' => array( 00268 ApiBase::PARAM_DFLT => 10, 00269 ApiBase::PARAM_TYPE => 'limit', 00270 ApiBase::PARAM_MIN => 1, 00271 ApiBase::PARAM_MAX => ApiBase::LIMIT_BIG1, 00272 ApiBase::PARAM_MAX2 => ApiBase::LIMIT_BIG2 00273 ), 00274 'dir' => array( 00275 ApiBase::PARAM_DFLT => 'ascending', 00276 ApiBase::PARAM_TYPE => array( 00277 'ascending', 00278 'descending' 00279 ) 00280 ), 00281 'filterlanglinks' => array( 00282 ApiBase::PARAM_TYPE => array( 00283 'withlanglinks', 00284 'withoutlanglinks', 00285 'all' 00286 ), 00287 ApiBase::PARAM_DFLT => 'all' 00288 ), 00289 'prexpiry' => array( 00290 ApiBase::PARAM_TYPE => array( 00291 'indefinite', 00292 'definite', 00293 'all' 00294 ), 00295 ApiBase::PARAM_DFLT => 'all' 00296 ), 00297 ); 00298 } 00299 00300 public function getParamDescription() { 00301 $p = $this->getModulePrefix(); 00302 00303 return array( 00304 'from' => 'The page title to start enumerating from', 00305 'continue' => 'When more results are available, use this to continue', 00306 'to' => 'The page title to stop enumerating at', 00307 'prefix' => 'Search for all page titles that begin with this value', 00308 'namespace' => 'The namespace to enumerate', 00309 'filterredir' => 'Which pages to list', 00310 'dir' => 'The direction in which to list', 00311 'minsize' => 'Limit to pages with at least this many bytes', 00312 'maxsize' => 'Limit to pages with at most this many bytes', 00313 'prtype' => 'Limit to protected pages only', 00314 'prlevel' => "The protection level (must be used with {$p}prtype= parameter)", 00315 'prfiltercascade' 00316 => "Filter protections based on cascadingness (ignored when {$p}prtype isn't set)", 00317 'filterlanglinks' => array( 00318 'Filter based on whether a page has langlinks', 00319 'Note that this may not consider langlinks added by extensions.', 00320 ), 00321 'limit' => 'How many total pages to return.', 00322 'prexpiry' => array( 00323 'Which protection expiry to filter the page on', 00324 ' indefinite - Get only pages with indefinite protection expiry', 00325 ' definite - Get only pages with a definite (specific) protection expiry', 00326 ' all - Get pages with any protections expiry' 00327 ), 00328 ); 00329 } 00330 00331 public function getDescription() { 00332 return 'Enumerate all pages sequentially in a given namespace.'; 00333 } 00334 00335 public function getExamples() { 00336 return array( 00337 'api.php?action=query&list=allpages&apfrom=B' => array( 00338 'Simple Use', 00339 'Show a list of pages starting at the letter "B"', 00340 ), 00341 'api.php?action=query&generator=allpages&gaplimit=4&gapfrom=T&prop=info' => array( 00342 'Using as Generator', 00343 'Show info about 4 pages starting at the letter "T"', 00344 ), 00345 'api.php?action=query&generator=allpages&gaplimit=2&' . 00346 'gapfilterredir=nonredirects&gapfrom=Re&prop=revisions&rvprop=content' 00347 => array( 'Show content of first 2 non-redirect pages beginning at "Re"' ) 00348 ); 00349 } 00350 00351 public function getHelpUrls() { 00352 return 'https://www.mediawiki.org/wiki/API:Allpages'; 00353 } 00354 }