MediaWiki REL1_34
ApiQueryAllPages.php
Go to the documentation of this file.
1<?php
23
30
31 public function __construct( ApiQuery $query, $moduleName ) {
32 parent::__construct( $query, $moduleName, 'ap' );
33 }
34
35 public function execute() {
36 $this->run();
37 }
38
39 public function getCacheMode( $params ) {
40 return 'public';
41 }
42
47 public function executeGenerator( $resultPageSet ) {
48 if ( $resultPageSet->isResolvingRedirects() ) {
49 $this->dieWithError( 'apierror-allpages-generator-redirects', 'params' );
50 }
51
52 $this->run( $resultPageSet );
53 }
54
59 private function run( $resultPageSet = null ) {
60 $db = $this->getDB();
61
62 $params = $this->extractRequestParams();
63
64 // Page filters
65 $this->addTables( 'page' );
66
67 if ( !is_null( $params['continue'] ) ) {
68 $cont = explode( '|', $params['continue'] );
69 $this->dieContinueUsageIf( count( $cont ) != 1 );
70 $op = $params['dir'] == 'descending' ? '<' : '>';
71 $cont_from = $db->addQuotes( $cont[0] );
72 $this->addWhere( "page_title $op= $cont_from" );
73 }
74
75 $miserMode = $this->getConfig()->get( 'MiserMode' );
76 if ( !$miserMode ) {
77 if ( $params['filterredir'] == 'redirects' ) {
78 $this->addWhereFld( 'page_is_redirect', 1 );
79 } elseif ( $params['filterredir'] == 'nonredirects' ) {
80 $this->addWhereFld( 'page_is_redirect', 0 );
81 }
82 }
83
84 $this->addWhereFld( 'page_namespace', $params['namespace'] );
85 $dir = ( $params['dir'] == 'descending' ? 'older' : 'newer' );
86 $from = ( $params['from'] === null
87 ? null
88 : $this->titlePartToKey( $params['from'], $params['namespace'] ) );
89 $to = ( $params['to'] === null
90 ? null
91 : $this->titlePartToKey( $params['to'], $params['namespace'] ) );
92 $this->addWhereRange( 'page_title', $dir, $from, $to );
93
94 if ( isset( $params['prefix'] ) ) {
95 $this->addWhere( 'page_title' . $db->buildLike(
96 $this->titlePartToKey( $params['prefix'], $params['namespace'] ),
97 $db->anyString() ) );
98 }
99
100 if ( is_null( $resultPageSet ) ) {
101 $selectFields = [
102 'page_namespace',
103 'page_title',
104 'page_id'
105 ];
106 } else {
107 $selectFields = $resultPageSet->getPageTableFields();
108 }
109
110 $miserModeFilterRedirValue = null;
111 $miserModeFilterRedir = $miserMode && $params['filterredir'] !== 'all';
112 if ( $miserModeFilterRedir ) {
113 $selectFields[] = 'page_is_redirect';
114
115 if ( $params['filterredir'] == 'redirects' ) {
116 $miserModeFilterRedirValue = 1;
117 } elseif ( $params['filterredir'] == 'nonredirects' ) {
118 $miserModeFilterRedirValue = 0;
119 }
120 }
121
122 $this->addFields( $selectFields );
123 $forceNameTitleIndex = true;
124 if ( isset( $params['minsize'] ) ) {
125 $this->addWhere( 'page_len>=' . (int)$params['minsize'] );
126 $forceNameTitleIndex = false;
127 }
128
129 if ( isset( $params['maxsize'] ) ) {
130 $this->addWhere( 'page_len<=' . (int)$params['maxsize'] );
131 $forceNameTitleIndex = false;
132 }
133
134 // Page protection filtering
135 if ( $params['prtype'] || $params['prexpiry'] != 'all' ) {
136 $this->addTables( 'page_restrictions' );
137 $this->addWhere( 'page_id=pr_page' );
138 $this->addWhere( "pr_expiry > {$db->addQuotes( $db->timestamp() )} OR pr_expiry IS NULL" );
139
140 if ( $params['prtype'] ) {
141 $this->addWhereFld( 'pr_type', $params['prtype'] );
142
143 if ( isset( $params['prlevel'] ) ) {
144 // Remove the empty string and '*' from the prlevel array
145 $prlevel = array_diff( $params['prlevel'], [ '', '*' ] );
146
147 if ( count( $prlevel ) ) {
148 $this->addWhereFld( 'pr_level', $prlevel );
149 }
150 }
151 if ( $params['prfiltercascade'] == 'cascading' ) {
152 $this->addWhereFld( 'pr_cascade', 1 );
153 } elseif ( $params['prfiltercascade'] == 'noncascading' ) {
154 $this->addWhereFld( 'pr_cascade', 0 );
155 }
156 }
157 $forceNameTitleIndex = false;
158
159 if ( $params['prexpiry'] == 'indefinite' ) {
160 $this->addWhere( "pr_expiry = {$db->addQuotes( $db->getInfinity() )} OR pr_expiry IS NULL" );
161 } elseif ( $params['prexpiry'] == 'definite' ) {
162 $this->addWhere( "pr_expiry != {$db->addQuotes( $db->getInfinity() )}" );
163 }
164
165 $this->addOption( 'DISTINCT' );
166 } elseif ( isset( $params['prlevel'] ) ) {
167 $this->dieWithError(
168 [ 'apierror-invalidparammix-mustusewith', 'prlevel', 'prtype' ], 'invalidparammix'
169 );
170 }
171
172 if ( $params['filterlanglinks'] == 'withoutlanglinks' ) {
173 $this->addTables( 'langlinks' );
174 $this->addJoinConds( [ 'langlinks' => [ 'LEFT JOIN', 'page_id=ll_from' ] ] );
175 $this->addWhere( 'll_from IS NULL' );
176 $forceNameTitleIndex = false;
177 } elseif ( $params['filterlanglinks'] == 'withlanglinks' ) {
178 $this->addTables( 'langlinks' );
179 $this->addWhere( 'page_id=ll_from' );
180 $this->addOption( 'STRAIGHT_JOIN' );
181
182 // MySQL filesorts if we use a GROUP BY that works with the rules
183 // in the 1992 SQL standard (it doesn't like having the
184 // constant-in-WHERE page_namespace column in there). Using the
185 // 1999 rules works fine, but that breaks other DBs. Sigh.
187 $dbType = $db->getType();
188 if ( $dbType === 'mysql' || $dbType === 'sqlite' ) {
189 // Ignore the rules, or 1999 rules if you count unique keys
190 // over non-NULL columns as satisfying the requirement for
191 // "functional dependency" and don't require including
192 // constant-in-WHERE columns in the GROUP BY.
193 $this->addOption( 'GROUP BY', [ 'page_title' ] );
194 } elseif ( $dbType === 'postgres' && $db->getServerVersion() >= 9.1 ) {
195 // 1999 rules only counting primary keys
196 $this->addOption( 'GROUP BY', [ 'page_title', 'page_id' ] );
197 } else {
198 // 1992 rules
199 $this->addOption( 'GROUP BY', $selectFields );
200 }
201
202 $forceNameTitleIndex = false;
203 }
204
205 if ( $forceNameTitleIndex ) {
206 $this->addOption( 'USE INDEX', 'name_title' );
207 }
208
209 $limit = $params['limit'];
210 $this->addOption( 'LIMIT', $limit + 1 );
211 $res = $this->select( __METHOD__ );
212
213 // Get gender information
214 $services = MediaWikiServices::getInstance();
215 if ( $services->getNamespaceInfo()->hasGenderDistinction( $params['namespace'] ) ) {
216 $users = [];
217 foreach ( $res as $row ) {
218 $users[] = $row->page_title;
219 }
220 $services->getGenderCache()->doQuery( $users, __METHOD__ );
221 $res->rewind(); // reset
222 }
223
224 $count = 0;
225 $result = $this->getResult();
226 foreach ( $res as $row ) {
227 if ( ++$count > $limit ) {
228 // We've reached the one extra which shows that there are
229 // additional pages to be had. Stop here...
230 $this->setContinueEnumParameter( 'continue', $row->page_title );
231 break;
232 }
233
234 if ( $miserModeFilterRedir && (int)$row->page_is_redirect !== $miserModeFilterRedirValue ) {
235 // Filter implemented in PHP due to being in Miser Mode
236 continue;
237 }
238
239 if ( is_null( $resultPageSet ) ) {
240 $title = Title::makeTitle( $row->page_namespace, $row->page_title );
241 $vals = [
242 'pageid' => (int)$row->page_id,
243 'ns' => (int)$title->getNamespace(),
244 'title' => $title->getPrefixedText()
245 ];
246 $fit = $result->addValue( [ 'query', $this->getModuleName() ], null, $vals );
247 if ( !$fit ) {
248 $this->setContinueEnumParameter( 'continue', $row->page_title );
249 break;
250 }
251 } else {
252 $resultPageSet->processDbRow( $row );
253 }
254 }
255
256 if ( is_null( $resultPageSet ) ) {
257 $result->addIndexedTagName( [ 'query', $this->getModuleName() ], 'p' );
258 }
259 }
260
261 public function getAllowedParams() {
262 $ret = [
263 'from' => null,
264 'continue' => [
265 ApiBase::PARAM_HELP_MSG => 'api-help-param-continue',
266 ],
267 'to' => null,
268 'prefix' => null,
269 'namespace' => [
271 ApiBase::PARAM_TYPE => 'namespace',
272 ],
273 'filterredir' => [
274 ApiBase::PARAM_DFLT => 'all',
276 'all',
277 'redirects',
278 'nonredirects'
279 ]
280 ],
281 'minsize' => [
282 ApiBase::PARAM_TYPE => 'integer',
283 ],
284 'maxsize' => [
285 ApiBase::PARAM_TYPE => 'integer',
286 ],
287 'prtype' => [
288 ApiBase::PARAM_TYPE => Title::getFilteredRestrictionTypes( true ),
290 ],
291 'prlevel' => [
292 ApiBase::PARAM_TYPE => $this->getConfig()->get( 'RestrictionLevels' ),
294 ],
295 'prfiltercascade' => [
296 ApiBase::PARAM_DFLT => 'all',
297 ApiBase::PARAM_TYPE => [
298 'cascading',
299 'noncascading',
300 'all'
301 ],
302 ],
303 'limit' => [
305 ApiBase::PARAM_TYPE => 'limit',
309 ],
310 'dir' => [
311 ApiBase::PARAM_DFLT => 'ascending',
313 'ascending',
314 'descending'
315 ]
316 ],
317 'filterlanglinks' => [
319 'withlanglinks',
320 'withoutlanglinks',
321 'all'
322 ],
323 ApiBase::PARAM_DFLT => 'all'
324 ],
325 'prexpiry' => [
327 'indefinite',
328 'definite',
329 'all'
330 ],
331 ApiBase::PARAM_DFLT => 'all'
332 ],
333 ];
334
335 if ( $this->getConfig()->get( 'MiserMode' ) ) {
336 $ret['filterredir'][ApiBase::PARAM_HELP_MSG_APPEND] = [ 'api-help-param-limited-in-miser-mode' ];
337 }
338
339 return $ret;
340 }
341
342 protected function getExamplesMessages() {
343 return [
344 'action=query&list=allpages&apfrom=B'
345 => 'apihelp-query+allpages-example-b',
346 'action=query&generator=allpages&gaplimit=4&gapfrom=T&prop=info'
347 => 'apihelp-query+allpages-example-generator',
348 'action=query&generator=allpages&gaplimit=2&' .
349 'gapfilterredir=nonredirects&gapfrom=Re&prop=revisions&rvprop=content'
350 => 'apihelp-query+allpages-example-generator-revisions',
351 ];
352 }
353
354 public function getHelpUrls() {
355 return 'https://www.mediawiki.org/wiki/Special:MyLanguage/API:Allpages';
356 }
357}
const PARAM_MAX2
(integer) Max value allowed for the parameter for users with the apihighlimits right,...
Definition ApiBase.php:103
const PARAM_MAX
(integer) Max value allowed for the parameter, for PARAM_TYPE 'integer' and 'limit'.
Definition ApiBase.php:97
dieWithError( $msg, $code=null, $data=null, $httpCode=null)
Abort execution with an error.
Definition ApiBase.php:2014
dieContinueUsageIf( $condition)
Die with the 'badcontinue' error.
Definition ApiBase.php:2208
const PARAM_TYPE
(string|string[]) Either an array of allowed value strings, or a string type as described below.
Definition ApiBase.php:94
const PARAM_DFLT
(null|boolean|integer|string) Default value of the parameter.
Definition ApiBase.php:55
const PARAM_HELP_MSG_APPEND
((string|array|Message)[]) Specify additional i18n messages to append to the normal message for this ...
Definition ApiBase.php:138
const PARAM_MIN
(integer) Lowest value allowed for the parameter, for PARAM_TYPE 'integer' and 'limit'.
Definition ApiBase.php:106
const LIMIT_BIG1
Fast query, standard limit.
Definition ApiBase.php:259
getResult()
Get the result object.
Definition ApiBase.php:640
extractRequestParams( $options=[])
Using getAllowedParams(), this function makes an array of the values provided by the user,...
Definition ApiBase.php:761
const PARAM_HELP_MSG
(string|array|Message) Specify an alternative i18n documentation message for this parameter.
Definition ApiBase.php:131
const LIMIT_BIG2
Fast query, apihighlimits limit.
Definition ApiBase.php:261
getModuleName()
Get the name of the module being executed by this instance.
Definition ApiBase.php:520
const PARAM_ISMULTI
(boolean) Accept multiple pipe-separated values for this parameter (e.g.
Definition ApiBase.php:58
Query module to enumerate all available pages.
getAllowedParams()
Returns an array of allowed parameters (parameter name) => (default value) or (parameter name) => (ar...
getCacheMode( $params)
Get the cache mode for the data generated by this module.
executeGenerator( $resultPageSet)
run( $resultPageSet=null)
__construct(ApiQuery $query, $moduleName)
getHelpUrls()
Return links to more detailed help pages about the module.
execute()
Evaluates the parameters, performs the requested query, and sets up the result.
getExamplesMessages()
Returns usage examples for this module.
addWhereRange( $field, $dir, $start, $end, $sort=true)
Add a WHERE clause corresponding to a range, and an ORDER BY clause to sort in the right direction.
addFields( $value)
Add a set of fields to select to the internal array.
addOption( $name, $value=null)
Add an option such as LIMIT or USE INDEX.
addTables( $tables, $alias=null)
Add a set of tables to the internal array.
getDB()
Get the Query database connection (read-only)
select( $method, $extraQuery=[], array &$hookData=null)
Execute a SELECT query based on the values in the internal arrays.
addJoinConds( $join_conds)
Add a set of JOIN conditions to the internal array.
addWhereFld( $field, $value)
Equivalent to addWhere( [ $field => $value ] )
titlePartToKey( $titlePart, $namespace=NS_MAIN)
Convert an input title or title prefix into a dbkey.
addWhere( $value)
Add a set of WHERE clauses to the internal array.
setContinueEnumParameter( $paramName, $paramValue)
Overridden to set the generator param if in generator mode.
This is the main query class.
Definition ApiQuery.php:37
MediaWikiServices is the service locator for the application scope of MediaWiki.
const NS_MAIN
Definition Defines.php:69
return true
Definition router.php:94