MediaWiki REL1_37
ApiQueryExtLinksUsage.php
Go to the documentation of this file.
1<?php
27
32 public function __construct( ApiQuery $query, $moduleName ) {
33 parent::__construct( $query, $moduleName, 'eu' );
34 }
35
36 public function execute() {
37 $this->run();
38 }
39
40 public function getCacheMode( $params ) {
41 return 'public';
42 }
43
44 public function executeGenerator( $resultPageSet ) {
45 $this->run( $resultPageSet );
46 }
47
52 private function run( $resultPageSet = null ) {
53 $params = $this->extractRequestParams();
54 $db = $this->getDB();
55
56 $query = $params['query'];
57 $protocol = self::getProtocolPrefix( $params['protocol'] );
58
59 $this->addTables( [ 'externallinks', 'page' ] );
60 $this->addJoinConds( [ 'page' => [ 'JOIN', 'page_id=el_from' ] ] );
61
62 $miser_ns = [];
63 if ( $this->getConfig()->get( 'MiserMode' ) ) {
64 $miser_ns = $params['namespace'] ?: [];
65 } else {
66 $this->addWhereFld( 'page_namespace', $params['namespace'] );
67 }
68
69 $orderBy = [];
70
71 if ( $query !== null && $query !== '' ) {
72 if ( $protocol === null ) {
73 $protocol = 'http://';
74 }
75
76 // Normalize query to match the normalization applied for the externallinks table
77 $query = Parser::normalizeLinkUrl( $protocol . $query );
78
79 $conds = LinkFilter::getQueryConditions( $query, [
80 'protocol' => '',
81 'oneWildcard' => true,
82 'db' => $db
83 ] );
84 if ( !$conds ) {
85 $this->dieWithError( 'apierror-badquery' );
86 }
87 $this->addWhere( $conds );
88 if ( !isset( $conds['el_index_60'] ) ) {
89 $orderBy[] = 'el_index_60';
90 }
91 } else {
92 $orderBy[] = 'el_index_60';
93
94 if ( $protocol !== null ) {
95 $this->addWhere( 'el_index_60' . $db->buildLike( "$protocol", $db->anyString() ) );
96 } else {
97 // We're querying all protocols, filter out duplicate protocol-relative links
98 $this->addWhere( $db->makeList( [
99 'el_to NOT' . $db->buildLike( '//', $db->anyString() ),
100 'el_index_60 ' . $db->buildLike( 'http://', $db->anyString() ),
101 ], LIST_OR ) );
102 }
103 }
104
105 $orderBy[] = 'el_id';
106 $this->addOption( 'ORDER BY', $orderBy );
107 $this->addFields( $orderBy ); // Make sure
108
109 $prop = array_fill_keys( $params['prop'], true );
110 $fld_ids = isset( $prop['ids'] );
111 $fld_title = isset( $prop['title'] );
112 $fld_url = isset( $prop['url'] );
113
114 if ( $resultPageSet === null ) {
115 $this->addFields( [
116 'page_id',
117 'page_namespace',
118 'page_title'
119 ] );
120 $this->addFieldsIf( 'el_to', $fld_url );
121 } else {
122 $this->addFields( $resultPageSet->getPageTableFields() );
123 }
124
125 $limit = $params['limit'];
126 $this->addOption( 'LIMIT', $limit + 1 );
127
128 // T244254: Avoid MariaDB deciding to scan all of `page`.
129 $this->addOption( 'STRAIGHT_JOIN' );
130
131 if ( $params['continue'] !== null ) {
132 $cont = explode( '|', $params['continue'] );
133 $this->dieContinueUsageIf( count( $cont ) !== count( $orderBy ) );
134 $i = count( $cont ) - 1;
135 $cond = $orderBy[$i] . ' >= ' . $db->addQuotes( rawurldecode( $cont[$i] ) );
136 while ( $i-- > 0 ) {
137 $field = $orderBy[$i];
138 $v = $db->addQuotes( rawurldecode( $cont[$i] ) );
139 $cond = "($field > $v OR ($field = $v AND $cond))";
140 }
141 $this->addWhere( $cond );
142 }
143
144 $res = $this->select( __METHOD__ );
145
146 $result = $this->getResult();
147
148 if ( $resultPageSet === null ) {
149 $this->executeGenderCacheFromResultWrapper( $res, __METHOD__ );
150 }
151
152 $count = 0;
153 foreach ( $res as $row ) {
154 if ( ++$count > $limit ) {
155 // We've reached the one extra which shows that there are
156 // additional pages to be had. Stop here...
157 $this->setContinue( $orderBy, $row );
158 break;
159 }
160
161 if ( count( $miser_ns ) && !in_array( $row->page_namespace, $miser_ns ) ) {
162 continue;
163 }
164
165 if ( $resultPageSet === null ) {
166 $vals = [
167 ApiResult::META_TYPE => 'assoc',
168 ];
169 if ( $fld_ids ) {
170 $vals['pageid'] = (int)$row->page_id;
171 }
172 if ( $fld_title ) {
173 $title = Title::makeTitle( $row->page_namespace, $row->page_title );
175 }
176 if ( $fld_url ) {
177 $to = $row->el_to;
178 // expand protocol-relative urls
179 if ( $params['expandurl'] ) {
180 $to = wfExpandUrl( $to, PROTO_CANONICAL );
181 }
182 $vals['url'] = $to;
183 }
184 $fit = $result->addValue( [ 'query', $this->getModuleName() ], null, $vals );
185 if ( !$fit ) {
186 $this->setContinue( $orderBy, $row );
187 break;
188 }
189 } else {
190 $resultPageSet->processDbRow( $row );
191 }
192 }
193
194 if ( $resultPageSet === null ) {
195 $result->addIndexedTagName( [ 'query', $this->getModuleName() ],
196 $this->getModulePrefix() );
197 }
198 }
199
200 private function setContinue( $orderBy, $row ) {
201 $fields = [];
202 foreach ( $orderBy as $field ) {
203 $fields[] = strtr( $row->$field, [ '%' => '%25', '|' => '%7C' ] );
204 }
205 $this->setContinueEnumParameter( 'continue', implode( '|', $fields ) );
206 }
207
208 public function getAllowedParams() {
209 $ret = [
210 'prop' => [
212 ApiBase::PARAM_DFLT => 'ids|title|url',
214 'ids',
215 'title',
216 'url'
217 ],
219 ],
220 'continue' => [
221 ApiBase::PARAM_HELP_MSG => 'api-help-param-continue',
222 ],
223 'protocol' => [
226 ],
227 'query' => null,
228 'namespace' => [
230 ApiBase::PARAM_TYPE => 'namespace'
231 ],
232 'limit' => [
234 ApiBase::PARAM_TYPE => 'limit',
238 ],
239 'expandurl' => false,
240 ];
241
242 if ( $this->getConfig()->get( 'MiserMode' ) ) {
243 $ret['namespace'][ApiBase::PARAM_HELP_MSG_APPEND] = [
244 'api-help-param-limited-in-miser-mode',
245 ];
246 }
247
248 return $ret;
249 }
250
251 public static function prepareProtocols() {
252 global $wgUrlProtocols;
253 $protocols = [ '' ];
254 foreach ( $wgUrlProtocols as $p ) {
255 if ( $p !== '//' ) {
256 $protocols[] = substr( $p, 0, strpos( $p, ':' ) );
257 }
258 }
259
260 return $protocols;
261 }
262
263 public static function getProtocolPrefix( $protocol ) {
264 // Find the right prefix
265 global $wgUrlProtocols;
266 if ( $protocol && !in_array( $protocol, $wgUrlProtocols ) ) {
267 foreach ( $wgUrlProtocols as $p ) {
268 if ( substr( $p, 0, strlen( $protocol ) ) === $protocol ) {
269 $protocol = $p;
270 break;
271 }
272 }
273
274 return $protocol;
275 } else {
276 return null;
277 }
278 }
279
280 protected function getExamplesMessages() {
281 return [
282 'action=query&list=exturlusage&euquery=www.mediawiki.org'
283 => 'apihelp-query+exturlusage-example-simple',
284 ];
285 }
286
287 public function getHelpUrls() {
288 return 'https://www.mediawiki.org/wiki/Special:MyLanguage/API:Exturlusage';
289 }
290}
$wgUrlProtocols
URL schemes that should be recognized as valid by wfParseUrl().
const PROTO_CANONICAL
Definition Defines.php:196
const LIST_OR
Definition Defines.php:46
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:1436
getModulePrefix()
Get parameter prefix (usually two letters or an empty string).
Definition ApiBase.php:505
const PARAM_MAX2
Definition ApiBase.php:89
const PARAM_MAX
Definition ApiBase.php:85
dieContinueUsageIf( $condition)
Die with the 'badcontinue' error.
Definition ApiBase.php:1620
const PARAM_TYPE
Definition ApiBase.php:81
const PARAM_DFLT
Definition ApiBase.php:73
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:93
const LIMIT_BIG1
Fast query, standard limit.
Definition ApiBase.php:220
getResult()
Get the result object.
Definition ApiBase.php:628
extractRequestParams( $options=[])
Using getAllowedParams(), this function makes an array of the values provided by the user,...
Definition ApiBase.php:764
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:497
const PARAM_ISMULTI
Definition ApiBase.php:77
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)
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.
static normalizeLinkUrl( $url)
Replace unusual escape codes in a URL with their equivalent characters.
Definition Parser.php:2287