MediaWiki master
ApiQueryExtLinksUsage.php
Go to the documentation of this file.
1<?php
2
33
38
39 private UrlUtils $urlUtils;
40
46 public function __construct( ApiQuery $query, $moduleName, UrlUtils $urlUtils ) {
47 parent::__construct( $query, $moduleName, 'eu' );
48
49 $this->urlUtils = $urlUtils;
50 }
51
52 public function execute() {
53 $this->run();
54 }
55
56 public function getCacheMode( $params ) {
57 return 'public';
58 }
59
60 public function executeGenerator( $resultPageSet ) {
61 $this->run( $resultPageSet );
62 }
63
68 private function run( $resultPageSet = null ) {
70 $db = $this->getDB();
71
72 $query = $params['query'];
73 $protocol = LinkFilter::getProtocolPrefix( $params['protocol'] );
74
75 $this->addTables( [ 'externallinks', 'page' ] );
76 $this->addJoinConds( [ 'page' => [ 'JOIN', 'page_id=el_from' ] ] );
77 $fields = [ 'el_to_domain_index', 'el_to_path' ];
78
79 $miser_ns = [];
80 if ( $this->getConfig()->get( MainConfigNames::MiserMode ) ) {
81 $miser_ns = $params['namespace'] ?: [];
82 } else {
83 $this->addWhereFld( 'page_namespace', $params['namespace'] );
84 }
85 if ( $query !== null && $query !== '' ) {
86 // Normalize query to match the normalization applied for the externallinks table
87 $query = Parser::normalizeLinkUrl( $query );
88 $conds = LinkFilter::getQueryConditions( $query, [
89 'protocol' => $protocol,
90 'oneWildcard' => true,
91 'db' => $db
92 ] );
93 if ( !$conds ) {
94 $this->dieWithError( 'apierror-badquery' );
95 }
96 $this->addWhere( $conds );
97 } else {
98 if ( $protocol !== null ) {
99 $this->addWhere(
100 $db->expr( 'el_to_domain_index', IExpression::LIKE, new LikeValue( "$protocol", $db->anyString() ) )
101 );
102 }
103 }
104 $orderBy = [ 'el_id' ];
105
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 foreach ( $fields as $field ) {
121 $this->addFieldsIf( $field, $fld_url );
122 }
123 } else {
124 $this->addFields( $resultPageSet->getPageTableFields() );
125 }
126
127 $limit = $params['limit'];
128 $this->addOption( 'LIMIT', $limit + 1 );
129
130 // T244254: Avoid MariaDB deciding to scan all of `page`.
131 $this->addOption( 'STRAIGHT_JOIN' );
132
133 if ( $params['continue'] !== null ) {
134 $cont = $this->parseContinueParamOrDie( $params['continue'],
135 array_fill( 0, count( $orderBy ), 'string' ) );
136 $conds = array_combine( $orderBy, array_map( 'rawurldecode', $cont ) );
137 $this->addWhere( $db->buildComparison( '>=', $conds ) );
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 );
170 ApiQueryBase::addTitleInfo( $vals, $title );
171 }
172 if ( $fld_url ) {
173 $to = LinkFilter::reverseIndexes( $row->el_to_domain_index ) . $row->el_to_path;
174 // expand protocol-relative urls
175 if ( $params['expandurl'] ) {
176 $to = (string)$this->urlUtils->expand( $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' => [
207 ParamValidator::PARAM_ISMULTI => true,
208 ParamValidator::PARAM_DEFAULT => 'ids|title|url',
209 ParamValidator::PARAM_TYPE => [
210 'ids',
211 'title',
212 'url'
213 ],
215 ],
216 'continue' => [
217 ApiBase::PARAM_HELP_MSG => 'api-help-param-continue',
218 ],
219 'protocol' => [
220 ParamValidator::PARAM_TYPE => LinkFilter::prepareProtocols(),
221 ParamValidator::PARAM_DEFAULT => '',
222 ],
223 'query' => null,
224 'namespace' => [
225 ParamValidator::PARAM_ISMULTI => true,
226 ParamValidator::PARAM_TYPE => 'namespace'
227 ],
228 'limit' => [
229 ParamValidator::PARAM_DEFAULT => 10,
230 ParamValidator::PARAM_TYPE => 'limit',
231 IntegerDef::PARAM_MIN => 1,
232 IntegerDef::PARAM_MAX => ApiBase::LIMIT_BIG1,
233 IntegerDef::PARAM_MAX2 => ApiBase::LIMIT_BIG2
234 ],
235 'expandurl' => [
236 ParamValidator::PARAM_TYPE => 'boolean',
237 ParamValidator::PARAM_DEFAULT => false,
238 ParamValidator::PARAM_DEPRECATED => true,
239 ],
240 ];
241
242 if ( $this->getConfig()->get( MainConfigNames::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 protected function getExamplesMessages() {
252 return [
253 'action=query&list=exturlusage&euquery=www.mediawiki.org'
254 => 'apihelp-query+exturlusage-example-simple',
255 ];
256 }
257
258 public function getHelpUrls() {
259 return 'https://www.mediawiki.org/wiki/Special:MyLanguage/API:Exturlusage';
260 }
261}
const PROTO_CANONICAL
Definition Defines.php:208
array $params
The job parameters.
run()
Run the job.
dieWithError( $msg, $code=null, $data=null, $httpCode=0)
Abort execution with an error.
Definition ApiBase.php:1542
getModulePrefix()
Get parameter prefix (usually two letters or an empty string).
Definition ApiBase.php:550
const PARAM_HELP_MSG_APPEND
((string|array|Message)[]) Specify additional i18n messages to append to the normal message for this ...
Definition ApiBase.php:178
parseContinueParamOrDie(string $continue, array $types)
Parse the 'continue' parameter in the usual format and validate the types of each part,...
Definition ApiBase.php:1734
const PARAM_HELP_MSG_PER_VALUE
((string|array|Message)[]) When PARAM_TYPE is an array, or 'string' with PARAM_ISMULTI,...
Definition ApiBase.php:211
const LIMIT_BIG1
Fast query, standard limit.
Definition ApiBase.php:236
getResult()
Get the result object.
Definition ApiBase.php:680
extractRequestParams( $options=[])
Using getAllowedParams(), this function makes an array of the values provided by the user,...
Definition ApiBase.php:820
const PARAM_HELP_MSG
(string|array|Message) Specify an alternative i18n documentation message for this parameter.
Definition ApiBase.php:171
const LIMIT_BIG2
Fast query, apihighlimits limit.
Definition ApiBase.php:238
getModuleName()
Get the name of the module being executed by this instance.
Definition ApiBase.php:541
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.
__construct(ApiQuery $query, $moduleName, UrlUtils $urlUtils)
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.
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:43
const META_TYPE
Key for the 'type' metadata item.
A class containing constants representing the names of configuration variables.
PHP Parser - Processes wiki markup (which uses a more user-friendly syntax, such as "[[link]]" for ma...
Definition Parser.php:156
Represents a title within MediaWiki.
Definition Title.php:78
A service to expand, parse, and otherwise manipulate URLs.
Definition UrlUtils.php:16
Service for formatting and validating API parameters.
Type definition for integer types.
Content of like value.
Definition LikeValue.php:14