31 private string $table;
32 private string $tablePrefix;
33 private string $indexTag;
35 private $dfltNamespace =
NS_MAIN;
37 private $hasNamespace =
true;
41 private $virtualDomain =
false;
50 switch ( $moduleName ) {
53 $this->table =
'pagelinks';
54 $this->tablePrefix =
'pl_';
55 $this->indexTag =
'l';
56 $this->virtualDomain = PageLinksTable::VIRTUAL_DOMAIN;
58 case 'alltransclusions':
60 $this->table =
'templatelinks';
61 $this->tablePrefix =
'tl_';
63 $this->indexTag =
't';
64 $this->virtualDomain = TemplateLinksTable::VIRTUAL_DOMAIN;
68 $this->table =
'imagelinks';
69 $this->tablePrefix =
'il_';
71 $this->hasNamespace =
false;
72 $this->indexTag =
'f';
73 $this->virtualDomain = ImageLinksTable::VIRTUAL_DOMAIN;
77 $this->table =
'redirect';
78 $this->tablePrefix =
'rd_';
79 $this->indexTag =
'r';
81 'fragment' =>
'rd_fragment',
82 'interwiki' =>
'rd_interwiki',
89 parent::__construct( $query, $moduleName, $prefix );
103 $this->run( $resultPageSet );
110 private function run( $resultPageSet =
null ) {
112 $db = $this->
getDB();
115 $pfx = $this->tablePrefix;
117 $usesLinktarget = isset( $this->linksMigration::$mapping[$this->table] );
118 $targetIdColumn =
'';
119 if ( $usesLinktarget ) {
120 [ $nsField, $titleField ] = $this->linksMigration->getTitleFields( $this->table );
121 $queryInfo = $this->linksMigration->getQueryInfo( $this->table,
'linktarget',
'STRAIGHT_JOIN' );
122 $this->
addTables( $queryInfo[
'tables'] );
124 $targetIdColumn =
"{$pfx}target_id";
127 $nsField =
"{$pfx}namespace";
128 $titleField =
"{$pfx}title";
132 $prop = array_fill_keys( $params[
'prop'],
true );
133 $fld_ids = isset( $prop[
'ids'] );
134 $fld_title = isset( $prop[
'title'] );
135 if ( $this->hasNamespace ) {
136 $namespace = $params[
'namespace'];
138 $namespace = $this->dfltNamespace;
141 if ( $params[
'unique'] ) {
142 $matches = array_intersect_key( $prop, $this->props + [
'ids' => 1 ] );
147 'apierror-invalidparammix-cannotusewith',
148 "{$p}prop=" . implode(
'|', array_keys(
$matches ) ),
157 if ( $this->hasNamespace ) {
161 $continue =
$params[
'continue'] !==
null;
163 $op =
$params[
'dir'] ==
'descending' ?
'<=' :
'>=';
164 if ( $params[
'unique'] ) {
166 $this->
addWhere( $db->expr( $titleField, $op, $cont[0] ) );
167 } elseif ( !$usesLinktarget ) {
169 $this->
addWhere( $db->buildComparison( $op, [
170 $titleField => $cont[0],
171 "{$pfx}from" => $cont[1],
175 $this->
addWhere( $db->buildComparison( $op, [
176 $targetIdColumn => $cont[0],
177 "{$pfx}from" => $cont[1],
183 $from = $continue ||
$params[
'from'] ===
null ? null :
185 $to =
$params[
'to'] ===
null ? null :
189 if ( isset( $params[
'prefix'] ) ) {
194 new LikeValue( $this->
titlePartToKey( $params[
'prefix'], $namespace ), $db->anyString() )
199 $this->
addFields( [
'pl_title' => $titleField ] );
200 $this->
addFieldsIf( [
'pl_from' => $pfx .
'from' ], !$params[
'unique'] );
201 foreach ( $this->props as $name => $field ) {
202 $this->
addFieldsIf( $field, isset( $prop[$name] ) );
208 $sort = (
$params[
'dir'] ==
'descending' ?
' DESC' :
'' );
210 if ( $usesLinktarget ) {
211 $orderBy[] = $targetIdColumn;
213 $orderBy[] = $titleField . $sort;
215 if ( !$params[
'unique'] ) {
216 $orderBy[] = $pfx .
'from' . $sort;
218 $this->
addOption(
'ORDER BY', $orderBy );
220 $res = $this->
select( __METHOD__ );
223 if ( $resultPageSet ===
null && $res->numRows() && $this->namespaceInfo->hasGenderDistinction( $namespace ) ) {
225 foreach ( $res as $row ) {
226 $users[] = $row->pl_title;
228 if ( $users !== [] ) {
229 $this->genderCache->doQuery( $users, __METHOD__ );
238 foreach ( $res as $row ) {
239 if ( ++$count > $limit ) {
242 if ( $params[
'unique'] ) {
244 } elseif ( $usesLinktarget ) {
252 if ( $resultPageSet ===
null ) {
257 $vals[
'fromid'] = (int)$row->pl_from;
263 foreach ( $this->props as $name => $field ) {
264 if ( isset( $prop[$name] ) && $row->$field !==
null && $row->$field !==
'' ) {
265 $vals[$name] = $row->$field;
268 $fit = $result->addValue( [
'query', $this->
getModuleName() ],
null, $vals );
270 if ( $params[
'unique'] ) {
272 } elseif ( $usesLinktarget ) {
279 } elseif ( $params[
'unique'] ) {
282 $pageids[] = $row->pl_from;
286 if ( $resultPageSet ===
null ) {
287 $result->addIndexedTagName( [
'query', $this->getModuleName() ], $this->indexTag );
288 } elseif ( $params[
'unique'] ) {
289 $resultPageSet->populateFromTitles( $titles );
291 $resultPageSet->populateFromPageIDs( $pageids );
299 ApiBase::PARAM_HELP_MSG =>
'api-help-param-continue',
306 ParamValidator::PARAM_ISMULTI =>
true,
307 ParamValidator::PARAM_DEFAULT =>
'title',
308 ParamValidator::PARAM_TYPE => [
'ids',
'title', ...array_keys( $this->props ) ],
309 ApiBase::PARAM_HELP_MSG_PER_VALUE => [],
312 ParamValidator::PARAM_DEFAULT => $this->dfltNamespace,
313 ParamValidator::PARAM_TYPE =>
'namespace',
317 ParamValidator::PARAM_DEFAULT => 10,
318 ParamValidator::PARAM_TYPE =>
'limit',
319 IntegerDef::PARAM_MIN => 1,
320 IntegerDef::PARAM_MAX => ApiBase::LIMIT_BIG1,
321 IntegerDef::PARAM_MAX2 => ApiBase::LIMIT_BIG2
324 ParamValidator::PARAM_DEFAULT =>
'ascending',
325 ParamValidator::PARAM_TYPE => [
331 if ( !$this->hasNamespace ) {
332 unset( $allowedParams[
'namespace'] );
335 return $allowedParams;
340 $p = $this->getModulePrefix();
341 $name = $this->getModuleName();
342 $path = $this->getModulePath();
345 "action=query&list={$name}&{$p}from=B&{$p}prop=ids|title"
346 =>
"apihelp-$path-example-b",
347 "action=query&list={$name}&{$p}unique=&{$p}from=B"
348 =>
"apihelp-$path-example-unique",
349 "action=query&generator={$name}&g{$p}unique=&g{$p}from=B"
350 =>
"apihelp-$path-example-unique-generator",
351 "action=query&generator={$name}&g{$p}from=B"
352 =>
"apihelp-$path-example-generator",
358 $name = ucfirst( $this->getModuleName() );
360 return "https://www.mediawiki.org/wiki/Special:MyLanguage/API:{$name}";
365class_alias( ApiQueryAllLinks::class,
'ApiQueryAllLinks' );