MediaWiki REL1_35
ApiQueryAllLinks.php
Go to the documentation of this file.
1<?php
24
31
33 private $fieldTitle = 'title';
35 private $hasNamespace = true;
36 private $useIndex = null;
37 private $props = [];
38
39 public function __construct( ApiQuery $query, $moduleName ) {
40 switch ( $moduleName ) {
41 case 'alllinks':
42 $prefix = 'al';
43 $this->table = 'pagelinks';
44 $this->tablePrefix = 'pl_';
45 $this->useIndex = 'pl_namespace';
46 $this->indexTag = 'l';
47 break;
48 case 'alltransclusions':
49 $prefix = 'at';
50 $this->table = 'templatelinks';
51 $this->tablePrefix = 'tl_';
52 $this->dfltNamespace = NS_TEMPLATE;
53 $this->useIndex = 'tl_namespace';
54 $this->indexTag = 't';
55 break;
56 case 'allfileusages':
57 $prefix = 'af';
58 $this->table = 'imagelinks';
59 $this->tablePrefix = 'il_';
60 $this->fieldTitle = 'to';
61 $this->dfltNamespace = NS_FILE;
62 $this->hasNamespace = false;
63 $this->indexTag = 'f';
64 break;
65 case 'allredirects':
66 $prefix = 'ar';
67 $this->table = 'redirect';
68 $this->tablePrefix = 'rd_';
69 $this->indexTag = 'r';
70 $this->props = [
71 'fragment' => 'rd_fragment',
72 'interwiki' => 'rd_interwiki',
73 ];
74 break;
75 default:
76 ApiBase::dieDebug( __METHOD__, 'Unknown module name' );
77 }
78
79 parent::__construct( $query, $moduleName, $prefix );
80 }
81
82 public function execute() {
83 $this->run();
84 }
85
86 public function getCacheMode( $params ) {
87 return 'public';
88 }
89
90 public function executeGenerator( $resultPageSet ) {
91 $this->run( $resultPageSet );
92 }
93
98 private function run( $resultPageSet = null ) {
99 $db = $this->getDB();
100 $params = $this->extractRequestParams();
101
102 $pfx = $this->tablePrefix;
104 $prop = array_flip( $params['prop'] );
105 $fld_ids = isset( $prop['ids'] );
106 $fld_title = isset( $prop['title'] );
107 if ( $this->hasNamespace ) {
108 $namespace = $params['namespace'];
109 } else {
110 $namespace = $this->dfltNamespace;
111 }
112
113 if ( $params['unique'] ) {
114 $matches = array_intersect_key( $prop, $this->props + [ 'ids' => 1 ] );
115 if ( $matches ) {
116 $p = $this->getModulePrefix();
117 $this->dieWithError(
118 [
119 'apierror-invalidparammix-cannotusewith',
120 "{$p}prop=" . implode( '|', array_keys( $matches ) ),
121 "{$p}unique"
122 ],
123 'invalidparammix'
124 );
125 }
126 $this->addOption( 'DISTINCT' );
127 }
128
129 $this->addTables( $this->table );
130 if ( $this->hasNamespace ) {
131 $this->addWhereFld( $pfx . 'namespace', $namespace );
132 }
133
134 $continue = $params['continue'] !== null;
135 if ( $continue ) {
136 $continueArr = explode( '|', $params['continue'] );
137 $op = $params['dir'] == 'descending' ? '<' : '>';
138 if ( $params['unique'] ) {
139 $this->dieContinueUsageIf( count( $continueArr ) != 1 );
140 $continueTitle = $db->addQuotes( $continueArr[0] );
141 $this->addWhere( "{$pfx}{$fieldTitle} $op= $continueTitle" );
142 } else {
143 $this->dieContinueUsageIf( count( $continueArr ) != 2 );
144 $continueTitle = $db->addQuotes( $continueArr[0] );
145 $continueFrom = (int)$continueArr[1];
146 $this->addWhere(
147 "{$pfx}{$fieldTitle} $op $continueTitle OR " .
148 "({$pfx}{$fieldTitle} = $continueTitle AND " .
149 "{$pfx}from $op= $continueFrom)"
150 );
151 }
152 }
153
154 // 'continue' always overrides 'from'
155 $from = $continue || $params['from'] === null ? null :
156 $this->titlePartToKey( $params['from'], $namespace );
157 $to = $params['to'] === null ? null :
158 $this->titlePartToKey( $params['to'], $namespace );
159 $this->addWhereRange( $pfx . $fieldTitle, 'newer', $from, $to );
160
161 if ( isset( $params['prefix'] ) ) {
162 $this->addWhere( $pfx . $fieldTitle . $db->buildLike( $this->titlePartToKey(
163 $params['prefix'], $namespace ), $db->anyString() ) );
164 }
165
166 $this->addFields( [ 'pl_title' => $pfx . $fieldTitle ] );
167 $this->addFieldsIf( [ 'pl_from' => $pfx . 'from' ], !$params['unique'] );
168 foreach ( $this->props as $name => $field ) {
169 $this->addFieldsIf( $field, isset( $prop[$name] ) );
170 }
171
172 if ( $this->useIndex ) {
173 $this->addOption( 'USE INDEX', $this->useIndex );
174 }
175 $limit = $params['limit'];
176 $this->addOption( 'LIMIT', $limit + 1 );
177
178 $sort = ( $params['dir'] == 'descending' ? ' DESC' : '' );
179 $orderBy = [];
180 $orderBy[] = $pfx . $fieldTitle . $sort;
181 if ( !$params['unique'] ) {
182 $orderBy[] = $pfx . 'from' . $sort;
183 }
184 $this->addOption( 'ORDER BY', $orderBy );
185
186 $res = $this->select( __METHOD__ );
187
188 // Get gender information
189 if ( $res->numRows() && $resultPageSet === null ) {
190 $services = MediaWikiServices::getInstance();
191 if ( $services->getNamespaceInfo()->hasGenderDistinction( $namespace ) ) {
192 $users = [];
193 foreach ( $res as $row ) {
194 $users[] = $row->pl_title;
195 }
196 if ( $users !== [] ) {
197 $services->getGenderCache()->doQuery( $users, __METHOD__ );
198 }
199 }
200 }
201
202 $pageids = [];
203 $titles = [];
204 $count = 0;
205 $result = $this->getResult();
206 foreach ( $res as $row ) {
207 if ( ++$count > $limit ) {
208 // We've reached the one extra which shows that there are
209 // additional pages to be had. Stop here...
210 if ( $params['unique'] ) {
211 $this->setContinueEnumParameter( 'continue', $row->pl_title );
212 } else {
213 $this->setContinueEnumParameter( 'continue', $row->pl_title . '|' . $row->pl_from );
214 }
215 break;
216 }
217
218 if ( $resultPageSet === null ) {
219 $vals = [
220 ApiResult::META_TYPE => 'assoc',
221 ];
222 if ( $fld_ids ) {
223 $vals['fromid'] = (int)$row->pl_from;
224 }
225 if ( $fld_title ) {
226 $title = Title::makeTitle( $namespace, $row->pl_title );
228 }
229 foreach ( $this->props as $name => $field ) {
230 if ( isset( $prop[$name] ) && $row->$field !== null && $row->$field !== '' ) {
231 $vals[$name] = $row->$field;
232 }
233 }
234 $fit = $result->addValue( [ 'query', $this->getModuleName() ], null, $vals );
235 if ( !$fit ) {
236 if ( $params['unique'] ) {
237 $this->setContinueEnumParameter( 'continue', $row->pl_title );
238 } else {
239 $this->setContinueEnumParameter( 'continue', $row->pl_title . '|' . $row->pl_from );
240 }
241 break;
242 }
243 } elseif ( $params['unique'] ) {
244 $titles[] = Title::makeTitle( $namespace, $row->pl_title );
245 } else {
246 $pageids[] = $row->pl_from;
247 }
248 }
249
250 if ( $resultPageSet === null ) {
251 $result->addIndexedTagName( [ 'query', $this->getModuleName() ], $this->indexTag );
252 } elseif ( $params['unique'] ) {
253 $resultPageSet->populateFromTitles( $titles );
254 } else {
255 $resultPageSet->populateFromPageIDs( $pageids );
256 }
257 }
258
259 public function getAllowedParams() {
260 $allowedParams = [
261 'continue' => [
262 ApiBase::PARAM_HELP_MSG => 'api-help-param-continue',
263 ],
264 'from' => null,
265 'to' => null,
266 'prefix' => null,
267 'unique' => false,
268 'prop' => [
270 ApiBase::PARAM_DFLT => 'title',
271 ApiBase::PARAM_TYPE => array_merge(
272 [ 'ids', 'title' ], array_keys( $this->props )
273 ),
275 ],
276 'namespace' => [
278 ApiBase::PARAM_TYPE => 'namespace',
280 ],
281 'limit' => [
283 ApiBase::PARAM_TYPE => 'limit',
287 ],
288 'dir' => [
289 ApiBase::PARAM_DFLT => 'ascending',
291 'ascending',
292 'descending'
293 ]
294 ],
295 ];
296 if ( !$this->hasNamespace ) {
297 unset( $allowedParams['namespace'] );
298 }
299
300 return $allowedParams;
301 }
302
303 protected function getExamplesMessages() {
304 $p = $this->getModulePrefix();
305 $name = $this->getModuleName();
306 $path = $this->getModulePath();
307
308 return [
309 "action=query&list={$name}&{$p}from=B&{$p}prop=ids|title"
310 => "apihelp-$path-example-b",
311 "action=query&list={$name}&{$p}unique=&{$p}from=B"
312 => "apihelp-$path-example-unique",
313 "action=query&generator={$name}&g{$p}unique=&g{$p}from=B"
314 => "apihelp-$path-example-unique-generator",
315 "action=query&generator={$name}&g{$p}from=B"
316 => "apihelp-$path-example-generator",
317 ];
318 }
319
320 public function getHelpUrls() {
321 $name = ucfirst( $this->getModuleName() );
322
323 return "https://www.mediawiki.org/wiki/Special:MyLanguage/API:{$name}";
324 }
325}
dieWithError( $msg, $code=null, $data=null, $httpCode=0)
Abort execution with an error.
Definition ApiBase.php:1437
getModulePrefix()
Get parameter prefix (usually two letters or an empty string).
Definition ApiBase.php:507
const PARAM_MAX2
Definition ApiBase.php:86
const PARAM_MAX
Definition ApiBase.php:82
dieContinueUsageIf( $condition)
Die with the 'badcontinue' error.
Definition ApiBase.php:1617
static dieDebug( $method, $message)
Internal code errors should be reported with this method.
Definition ApiBase.php:1629
const PARAM_TYPE
Definition ApiBase.php:78
const PARAM_DFLT
Definition ApiBase.php:70
const PARAM_HELP_MSG_PER_VALUE
((string|array|Message)[]) When PARAM_TYPE is an array, this is an array mapping those values to $msg...
Definition ApiBase.php:195
const PARAM_MIN
Definition ApiBase.php:90
const LIMIT_BIG1
Fast query, standard limit.
Definition ApiBase.php:220
getResult()
Get the result object.
Definition ApiBase.php:620
extractRequestParams( $options=[])
Using getAllowedParams(), this function makes an array of the values provided by the user,...
Definition ApiBase.php:772
getModulePath()
Get the path to this module.
Definition ApiBase.php:564
const PARAM_EXTRA_NAMESPACES
Definition ApiBase.php:118
const PARAM_HELP_MSG
(string|array|Message) Specify an alternative i18n documentation message for this parameter.
Definition ApiBase.php:162
const LIMIT_BIG2
Fast query, apihighlimits limit.
Definition ApiBase.php:222
getModuleName()
Get the name of the module being executed by this instance.
Definition ApiBase.php:499
const PARAM_ISMULTI
Definition ApiBase.php:74
static addTitleInfo(&$arr, $title, $prefix='')
Add information (title and namespace) about a Title object to a result array.
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) Stable to override.
select( $method, $extraQuery=[], array &$hookData=null)
Execute a SELECT query based on the values in the internal arrays.
addFieldsIf( $value, $condition)
Same as addFields(), but add the fields only if a condition is met.
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_FILE
Definition Defines.php:76
const NS_MAIN
Definition Defines.php:70
const NS_TEMPLATE
Definition Defines.php:80
const NS_SPECIAL
Definition Defines.php:59
const NS_MEDIA
Definition Defines.php:58