31 private string $table;
32 private string $tablePrefix;
33 private string $indexTag;
35 private $fieldTitle =
'title';
37 private $dfltNamespace =
NS_MAIN;
39 private $hasNamespace =
true;
41 private $useIndex =
null;
45 private $virtualDomain =
false;
58 switch ( $moduleName ) {
61 $this->table =
'pagelinks';
62 $this->tablePrefix =
'pl_';
63 $this->useIndex =
'pl_namespace';
64 $this->indexTag =
'l';
65 $this->virtualDomain = PageLinksTable::VIRTUAL_DOMAIN;
67 case 'alltransclusions':
69 $this->table =
'templatelinks';
70 $this->tablePrefix =
'tl_';
72 $this->indexTag =
't';
73 $this->virtualDomain = TemplateLinksTable::VIRTUAL_DOMAIN;
77 $this->table =
'imagelinks';
78 $this->tablePrefix =
'il_';
79 $this->fieldTitle =
'to';
81 $this->hasNamespace =
false;
82 $this->indexTag =
'f';
83 $this->virtualDomain = ImageLinksTable::VIRTUAL_DOMAIN;
87 $this->table =
'redirect';
88 $this->tablePrefix =
'rd_';
89 $this->indexTag =
'r';
91 'fragment' =>
'rd_fragment',
92 'interwiki' =>
'rd_interwiki',
99 parent::__construct( $query, $moduleName, $prefix );
100 $this->namespaceInfo = $namespaceInfo;
101 $this->genderCache = $genderCache;
102 $this->linksMigration = $linksMigration;
116 $this->run( $resultPageSet );
123 private function run( $resultPageSet =
null ) {
125 $db = $this->
getDB();
128 $pfx = $this->tablePrefix;
130 $nsField = $pfx .
'namespace';
131 $titleField = $pfx . $this->fieldTitle;
132 $linktargetReadNew =
false;
133 $targetIdColumn =
'';
134 if ( isset( $this->linksMigration::$mapping[$this->table] ) ) {
135 [ $nsField, $titleField ] = $this->linksMigration->getTitleFields( $this->table );
136 $queryInfo = $this->linksMigration->getQueryInfo( $this->table,
'linktarget',
'STRAIGHT_JOIN' );
137 $this->
addTables( $queryInfo[
'tables'] );
139 if ( in_array(
'linktarget', $queryInfo[
'tables'] ) ) {
140 $linktargetReadNew =
true;
141 $targetIdColumn =
"{$pfx}target_id";
145 if ( $this->useIndex ) {
146 $this->
addOption(
'USE INDEX', $this->useIndex );
151 $prop = array_fill_keys( $params[
'prop'],
true );
152 $fld_ids = isset( $prop[
'ids'] );
153 $fld_title = isset( $prop[
'title'] );
154 if ( $this->hasNamespace ) {
155 $namespace =
$params[
'namespace'];
157 $namespace = $this->dfltNamespace;
160 if ( $params[
'unique'] ) {
161 $matches = array_intersect_key( $prop, $this->props + [
'ids' => 1 ] );
166 'apierror-invalidparammix-cannotusewith',
167 "{$p}prop=" . implode(
'|', array_keys(
$matches ) ),
176 if ( $this->hasNamespace ) {
180 $continue =
$params[
'continue'] !==
null;
182 $op =
$params[
'dir'] ==
'descending' ?
'<=' :
'>=';
183 if ( $params[
'unique'] ) {
185 $this->
addWhere( $db->expr( $titleField, $op, $cont[0] ) );
186 } elseif ( !$linktargetReadNew ) {
188 $this->
addWhere( $db->buildComparison( $op, [
189 $titleField => $cont[0],
190 "{$pfx}from" => $cont[1],
194 $this->
addWhere( $db->buildComparison( $op, [
195 $targetIdColumn => $cont[0],
196 "{$pfx}from" => $cont[1],
202 $from = $continue ||
$params[
'from'] ===
null ? null :
204 $to =
$params[
'to'] ===
null ? null :
208 if ( isset( $params[
'prefix'] ) ) {
213 new LikeValue( $this->
titlePartToKey( $params[
'prefix'], $namespace ), $db->anyString() )
218 $this->
addFields( [
'pl_title' => $titleField ] );
219 $this->
addFieldsIf( [
'pl_from' => $pfx .
'from' ], !$params[
'unique'] );
220 foreach ( $this->props as $name => $field ) {
221 $this->
addFieldsIf( $field, isset( $prop[$name] ) );
227 $sort = (
$params[
'dir'] ==
'descending' ?
' DESC' :
'' );
229 if ( $linktargetReadNew ) {
230 $orderBy[] = $targetIdColumn;
232 $orderBy[] = $titleField . $sort;
234 if ( !$params[
'unique'] ) {
235 $orderBy[] = $pfx .
'from' . $sort;
237 $this->
addOption(
'ORDER BY', $orderBy );
239 $res = $this->
select( __METHOD__ );
242 if ( $resultPageSet ===
null && $res->numRows() && $this->namespaceInfo->hasGenderDistinction( $namespace ) ) {
244 foreach ( $res as $row ) {
245 $users[] = $row->pl_title;
247 if ( $users !== [] ) {
248 $this->genderCache->doQuery( $users, __METHOD__ );
257 foreach ( $res as $row ) {
258 if ( ++$count > $limit ) {
261 if ( $params[
'unique'] ) {
263 } elseif ( $linktargetReadNew ) {
271 if ( $resultPageSet ===
null ) {
276 $vals[
'fromid'] = (int)$row->pl_from;
282 foreach ( $this->props as $name => $field ) {
283 if ( isset( $prop[$name] ) && $row->$field !==
null && $row->$field !==
'' ) {
284 $vals[$name] = $row->$field;
287 $fit = $result->addValue( [
'query', $this->
getModuleName() ],
null, $vals );
289 if ( $params[
'unique'] ) {
291 } elseif ( $linktargetReadNew ) {
298 } elseif ( $params[
'unique'] ) {
301 $pageids[] = $row->pl_from;
305 if ( $resultPageSet ===
null ) {
306 $result->addIndexedTagName( [
'query', $this->getModuleName() ], $this->indexTag );
307 } elseif ( $params[
'unique'] ) {
308 $resultPageSet->populateFromTitles( $titles );
310 $resultPageSet->populateFromPageIDs( $pageids );
318 ApiBase::PARAM_HELP_MSG =>
'api-help-param-continue',
325 ParamValidator::PARAM_ISMULTI =>
true,
326 ParamValidator::PARAM_DEFAULT =>
'title',
327 ParamValidator::PARAM_TYPE => [
'ids',
'title', ...array_keys( $this->props ) ],
328 ApiBase::PARAM_HELP_MSG_PER_VALUE => [],
331 ParamValidator::PARAM_DEFAULT => $this->dfltNamespace,
332 ParamValidator::PARAM_TYPE =>
'namespace',
336 ParamValidator::PARAM_DEFAULT => 10,
337 ParamValidator::PARAM_TYPE =>
'limit',
338 IntegerDef::PARAM_MIN => 1,
339 IntegerDef::PARAM_MAX => ApiBase::LIMIT_BIG1,
340 IntegerDef::PARAM_MAX2 => ApiBase::LIMIT_BIG2
343 ParamValidator::PARAM_DEFAULT =>
'ascending',
344 ParamValidator::PARAM_TYPE => [
350 if ( !$this->hasNamespace ) {
351 unset( $allowedParams[
'namespace'] );
354 return $allowedParams;
359 $p = $this->getModulePrefix();
360 $name = $this->getModuleName();
361 $path = $this->getModulePath();
364 "action=query&list={$name}&{$p}from=B&{$p}prop=ids|title"
365 =>
"apihelp-$path-example-b",
366 "action=query&list={$name}&{$p}unique=&{$p}from=B"
367 =>
"apihelp-$path-example-unique",
368 "action=query&generator={$name}&g{$p}unique=&g{$p}from=B"
369 =>
"apihelp-$path-example-unique-generator",
370 "action=query&generator={$name}&g{$p}from=B"
371 =>
"apihelp-$path-example-generator",
377 $name = ucfirst( $this->getModuleName() );
379 return "https://www.mediawiki.org/wiki/Special:MyLanguage/API:{$name}";
384class_alias( ApiQueryAllLinks::class,
'ApiQueryAllLinks' );