MediaWiki REL1_35
ApiQueryExtLinksUsage.php
Go to the documentation of this file.
1<?php
27
28 public function __construct( ApiQuery $query, $moduleName ) {
29 parent::__construct( $query, $moduleName, 'eu' );
30 }
31
32 public function execute() {
33 $this->run();
34 }
35
36 public function getCacheMode( $params ) {
37 return 'public';
38 }
39
40 public function executeGenerator( $resultPageSet ) {
41 $this->run( $resultPageSet );
42 }
43
48 private function run( $resultPageSet = null ) {
49 $params = $this->extractRequestParams();
50 $db = $this->getDB();
51
52 $query = $params['query'];
53 $protocol = self::getProtocolPrefix( $params['protocol'] );
54
55 $this->addTables( [ 'externallinks', 'page' ] );
56 $this->addJoinConds( [ 'page' => [ 'JOIN', 'page_id=el_from' ] ] );
57
58 $miser_ns = [];
59 if ( $this->getConfig()->get( 'MiserMode' ) ) {
60 $miser_ns = $params['namespace'] ?: [];
61 } else {
62 $this->addWhereFld( 'page_namespace', $params['namespace'] );
63 }
64
65 $orderBy = [];
66
67 if ( $query !== null && $query !== '' ) {
68 if ( $protocol === null ) {
69 $protocol = 'http://';
70 }
71
72 // Normalize query to match the normalization applied for the externallinks table
73 $query = Parser::normalizeLinkUrl( $protocol . $query );
74
75 $conds = LinkFilter::getQueryConditions( $query, [
76 'protocol' => '',
77 'oneWildcard' => true,
78 'db' => $db
79 ] );
80 if ( !$conds ) {
81 $this->dieWithError( 'apierror-badquery' );
82 }
83 $this->addWhere( $conds );
84 if ( !isset( $conds['el_index_60'] ) ) {
85 $orderBy[] = 'el_index_60';
86 }
87 } else {
88 $orderBy[] = 'el_index_60';
89
90 if ( $protocol !== null ) {
91 $this->addWhere( 'el_index_60' . $db->buildLike( "$protocol", $db->anyString() ) );
92 } else {
93 // We're querying all protocols, filter out duplicate protocol-relative links
94 $this->addWhere( $db->makeList( [
95 'el_to NOT' . $db->buildLike( '//', $db->anyString() ),
96 'el_index_60 ' . $db->buildLike( 'http://', $db->anyString() ),
97 ], LIST_OR ) );
98 }
99 }
100
101 $orderBy[] = 'el_id';
102 $this->addOption( 'ORDER BY', $orderBy );
103 $this->addFields( $orderBy ); // Make sure
104
105 $prop = array_flip( $params['prop'] );
106 $fld_ids = isset( $prop['ids'] );
107 $fld_title = isset( $prop['title'] );
108 $fld_url = isset( $prop['url'] );
109
110 if ( $resultPageSet === null ) {
111 $this->addFields( [
112 'page_id',
113 'page_namespace',
114 'page_title'
115 ] );
116 $this->addFieldsIf( 'el_to', $fld_url );
117 } else {
118 $this->addFields( $resultPageSet->getPageTableFields() );
119 }
120
121 $limit = $params['limit'];
122 $this->addOption( 'LIMIT', $limit + 1 );
123
124 // T244254: Avoid MariaDB deciding to scan all of `page`.
125 $this->addOption( 'STRAIGHT_JOIN' );
126
127 if ( $params['continue'] !== null ) {
128 $cont = explode( '|', $params['continue'] );
129 $this->dieContinueUsageIf( count( $cont ) !== count( $orderBy ) );
130 $i = count( $cont ) - 1;
131 $cond = $orderBy[$i] . ' >= ' . $db->addQuotes( rawurldecode( $cont[$i] ) );
132 while ( $i-- > 0 ) {
133 $field = $orderBy[$i];
134 $v = $db->addQuotes( rawurldecode( $cont[$i] ) );
135 $cond = "($field > $v OR ($field = $v AND $cond))";
136 }
137 $this->addWhere( $cond );
138 }
139
140 $res = $this->select( __METHOD__ );
141
142 $result = $this->getResult();
143
144 if ( $resultPageSet === null ) {
145 $this->executeGenderCacheFromResultWrapper( $res, __METHOD__ );
146 }
147
148 $count = 0;
149 foreach ( $res as $row ) {
150 if ( ++$count > $limit ) {
151 // We've reached the one extra which shows that there are
152 // additional pages to be had. Stop here...
153 $this->setContinue( $orderBy, $row );
154 break;
155 }
156
157 if ( count( $miser_ns ) && !in_array( $row->page_namespace, $miser_ns ) ) {
158 continue;
159 }
160
161 if ( $resultPageSet === null ) {
162 $vals = [
163 ApiResult::META_TYPE => 'assoc',
164 ];
165 if ( $fld_ids ) {
166 $vals['pageid'] = (int)$row->page_id;
167 }
168 if ( $fld_title ) {
169 $title = Title::makeTitle( $row->page_namespace, $row->page_title );
171 }
172 if ( $fld_url ) {
173 $to = $row->el_to;
174 // expand protocol-relative urls
175 if ( $params['expandurl'] ) {
176 $to = wfExpandUrl( $to, PROTO_CANONICAL );
177 }
178 $vals['url'] = $to;
179 }
180 $fit = $result->addValue( [ 'query', $this->getModuleName() ], null, $vals );
181 if ( !$fit ) {
182 $this->setContinue( $orderBy, $row );
183 break;
184 }
185 } else {
186 $resultPageSet->processDbRow( $row );
187 }
188 }
189
190 if ( $resultPageSet === null ) {
191 $result->addIndexedTagName( [ 'query', $this->getModuleName() ],
192 $this->getModulePrefix() );
193 }
194 }
195
196 private function setContinue( $orderBy, $row ) {
197 $fields = [];
198 foreach ( $orderBy as $field ) {
199 $fields[] = strtr( $row->$field, [ '%' => '%25', '|' => '%7C' ] );
200 }
201 $this->setContinueEnumParameter( 'continue', implode( '|', $fields ) );
202 }
203
204 public function getAllowedParams() {
205 $ret = [
206 'prop' => [
208 ApiBase::PARAM_DFLT => 'ids|title|url',
210 'ids',
211 'title',
212 'url'
213 ],
215 ],
216 'continue' => [
217 ApiBase::PARAM_HELP_MSG => 'api-help-param-continue',
218 ],
219 'protocol' => [
222 ],
223 'query' => null,
224 'namespace' => [
226 ApiBase::PARAM_TYPE => 'namespace'
227 ],
228 'limit' => [
230 ApiBase::PARAM_TYPE => 'limit',
234 ],
235 'expandurl' => false,
236 ];
237
238 if ( $this->getConfig()->get( 'MiserMode' ) ) {
239 $ret['namespace'][ApiBase::PARAM_HELP_MSG_APPEND] = [
240 'api-help-param-limited-in-miser-mode',
241 ];
242 }
243
244 return $ret;
245 }
246
247 public static function prepareProtocols() {
248 global $wgUrlProtocols;
249 $protocols = [ '' ];
250 foreach ( $wgUrlProtocols as $p ) {
251 if ( $p !== '//' ) {
252 $protocols[] = substr( $p, 0, strpos( $p, ':' ) );
253 }
254 }
255
256 return $protocols;
257 }
258
259 public static function getProtocolPrefix( $protocol ) {
260 // Find the right prefix
261 global $wgUrlProtocols;
262 if ( $protocol && !in_array( $protocol, $wgUrlProtocols ) ) {
263 foreach ( $wgUrlProtocols as $p ) {
264 if ( substr( $p, 0, strlen( $protocol ) ) === $protocol ) {
265 $protocol = $p;
266 break;
267 }
268 }
269
270 return $protocol;
271 } else {
272 return null;
273 }
274 }
275
276 protected function getExamplesMessages() {
277 return [
278 'action=query&list=exturlusage&euquery=www.mediawiki.org'
279 => 'apihelp-query+exturlusage-example-simple',
280 ];
281 }
282
283 public function getHelpUrls() {
284 return 'https://www.mediawiki.org/wiki/Special:MyLanguage/API:Exturlusage';
285 }
286}
$wgUrlProtocols
URL schemes that should be recognized as valid by wfParseUrl().
wfExpandUrl( $url, $defaultProto=PROTO_CURRENT)
Expand a potentially local URL to a fully-qualified URL.
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
const PARAM_TYPE
Definition ApiBase.php:78
const PARAM_DFLT
Definition ApiBase.php:70
const PARAM_HELP_MSG_APPEND
((string|array|Message)[]) Specify additional i18n messages to append to the normal message for this ...
Definition ApiBase.php:169
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
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.
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.
executeGenderCacheFromResultWrapper(IResultWrapper $res, $fname=__METHOD__, $fieldPrefix='page')
Preprocess the result set to fill the GenderCache with the necessary information before using self::a...
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.
addJoinConds( $join_conds)
Add a set of JOIN conditions to the internal array.
addWhereFld( $field, $value)
Equivalent to addWhere( [ $field => $value ] )
addWhere( $value)
Add a set of WHERE clauses to the internal array.
executeGenerator( $resultPageSet)
Execute this module as a generator.
getExamplesMessages()
Returns usage examples for this module.
execute()
Evaluates the parameters, performs the requested query, and sets up the result.
getHelpUrls()
Return links to more detailed help pages about the module.
getCacheMode( $params)
Get the cache mode for the data generated by this module.
run( $resultPageSet=null)
static getProtocolPrefix( $protocol)
__construct(ApiQuery $query, $moduleName)
getAllowedParams()
Returns an array of allowed parameters (parameter name) => (default value) or (parameter name) => (ar...
setContinueEnumParameter( $paramName, $paramValue)
Overridden to set the generator param if in generator mode.
This is the main query class.
Definition ApiQuery.php:37
static getQueryConditions( $filterEntry, array $options=[])
Return query conditions which will match the specified string.
const PROTO_CANONICAL
Definition Defines.php:213
const LIST_OR
Definition Defines.php:52