MediaWiki master
ApiQueryRandom.php
Go to the documentation of this file.
1<?php
2
24namespace MediaWiki\Api;
25
30
37
38 private ContentHandlerFactory $contentHandlerFactory;
39
40 public function __construct(
41 ApiQuery $query,
42 string $moduleName,
43 ContentHandlerFactory $contentHandlerFactory
44 ) {
45 parent::__construct( $query, $moduleName, 'rn' );
46 $this->contentHandlerFactory = $contentHandlerFactory;
47 }
48
49 public function execute() {
50 $this->run();
51 }
52
53 public function executeGenerator( $resultPageSet ) {
54 $this->run( $resultPageSet );
55 }
56
66 protected function runQuery( $resultPageSet, $limit, $start, $startId, $end ) {
67 $params = $this->extractRequestParams();
68
69 $this->resetQueryParams();
70 $this->addTables( 'page' );
71 $this->addFields( [ 'page_id', 'page_random' ] );
72 if ( $resultPageSet === null ) {
73 $this->addFields( [ 'page_title', 'page_namespace' ] );
74 } else {
75 $this->addFields( $resultPageSet->getPageTableFields() );
76 }
77 $this->addWhereFld( 'page_namespace', $params['namespace'] );
78 if ( $params['redirect'] || $params['filterredir'] === 'redirects' ) {
79 $this->addWhereFld( 'page_is_redirect', 1 );
80 } elseif ( $params['filterredir'] === 'nonredirects' ) {
81 $this->addWhereFld( 'page_is_redirect', 0 );
82 } elseif ( $resultPageSet === null ) {
83 $this->addFields( [ 'page_is_redirect' ] );
84 }
85
86 $db = $this->getDB();
87 if ( isset( $params['minsize'] ) ) {
88 $this->addWhere( $db->expr( 'page_len', '>=', (int)$params['minsize'] ) );
89 }
90 if ( isset( $params['maxsize'] ) ) {
91 $this->addWhere( $db->expr( 'page_len', '<=', (int)$params['maxsize'] ) );
92 }
93
94 if ( isset( $params['contentmodel'] ) ) {
95 $this->addWhereFld( 'page_content_model', $params['contentmodel'] );
96 }
97
98 $this->addOption( 'LIMIT', $limit + 1 );
99
100 if ( $start !== null ) {
101 if ( $startId > 0 ) {
102 $this->addWhere( $db->buildComparison( '>=', [
103 'page_random' => $start,
104 'page_id' => $startId,
105 ] ) );
106 } else {
107 $this->addWhere( $db->buildComparison( '>=', [
108 'page_random' => $start,
109 ] ) );
110 }
111 }
112 if ( $end !== null ) {
113 $this->addWhere( $db->expr( 'page_random', '<', $end ) );
114 }
115 $this->addOption( 'ORDER BY', [ 'page_random', 'page_id' ] );
116
117 $result = $this->getResult();
118 $path = [ 'query', $this->getModuleName() ];
119
120 $res = $this->select( __METHOD__ );
121
122 if ( $resultPageSet === null ) {
123 $this->executeGenderCacheFromResultWrapper( $res, __METHOD__ );
124 }
125
126 $count = 0;
127 foreach ( $res as $row ) {
128 if ( $count++ >= $limit ) {
129 return [ 0, "{$row->page_random}|{$row->page_id}" ];
130 }
131 if ( $resultPageSet === null ) {
132 $title = Title::makeTitle( $row->page_namespace, $row->page_title );
133 $page = [
134 'id' => (int)$row->page_id,
135 ];
136 ApiQueryBase::addTitleInfo( $page, $title );
137 if ( isset( $row->page_is_redirect ) ) {
138 $page['redirect'] = (bool)$row->page_is_redirect;
139 }
140 $fit = $result->addValue( $path, null, $page );
141 if ( !$fit ) {
142 return [ 0, "{$row->page_random}|{$row->page_id}" ];
143 }
144 } else {
145 $resultPageSet->processDbRow( $row );
146 }
147 }
148
149 return [ $limit - $count, null ];
150 }
151
155 public function run( $resultPageSet = null ) {
156 $params = $this->extractRequestParams();
157
158 // Since 'filterredir' will always be set in $params, we have to dig
159 // into the WebRequest to see if it was actually passed.
160 $request = $this->getMain()->getRequest();
161 if ( $request->getCheck( $this->encodeParamName( 'filterredir' ) ) ) {
162 $this->requireMaxOneParameter( $params, 'filterredir', 'redirect' );
163 }
164
165 if ( isset( $params['continue'] ) ) {
166 $cont = $this->parseContinueParamOrDie( $params['continue'], [ 'string', 'string', 'int', 'string' ] );
167 $rand = $cont[0];
168 $start = $cont[1];
169 $startId = $cont[2];
170 $end = $cont[3] ? $rand : null;
171 $this->dieContinueUsageIf( !preg_match( '/^0\.\d+$/', $rand ) );
172 $this->dieContinueUsageIf( !preg_match( '/^0\.\d+$/', $start ) );
173 $this->dieContinueUsageIf( $cont[3] !== '0' && $cont[3] !== '1' );
174 } else {
175 $rand = wfRandom();
176 $start = $rand;
177 $startId = 0;
178 $end = null;
179 }
180
181 // Set the non-continue if this is being used as a generator
182 // (as a list it doesn't matter because lists never non-continue)
183 if ( $resultPageSet !== null ) {
184 $endFlag = $end === null ? 0 : 1;
185 $this->getContinuationManager()->addGeneratorNonContinueParam(
186 $this, 'continue', "$rand|$start|$startId|$endFlag"
187 );
188 }
189
190 [ $left, $continue ] =
191 $this->runQuery( $resultPageSet, $params['limit'], $start, $startId, $end );
192 if ( $end === null && $continue === null ) {
193 // Wrap around. We do this even if $left === 0 for continuation
194 // (saving a DB query in this rare case probably isn't worth the
195 // added code complexity it would require).
196 $end = $rand;
197 [ , $continue ] = $this->runQuery( $resultPageSet, $left, null, null, $end );
198 }
199
200 if ( $continue !== null ) {
201 $endFlag = $end === null ? 0 : 1;
202 $this->setContinueEnumParameter( 'continue', "$rand|$continue|$endFlag" );
203 }
204
205 if ( $resultPageSet === null ) {
206 $this->getResult()->addIndexedTagName( [ 'query', $this->getModuleName() ], 'page' );
207 }
208 }
209
210 public function getCacheMode( $params ) {
211 return 'public';
212 }
213
214 public function getAllowedParams() {
215 return [
216 'namespace' => [
217 ParamValidator::PARAM_TYPE => 'namespace',
218 ParamValidator::PARAM_ISMULTI => true
219 ],
220 'filterredir' => [
221 ParamValidator::PARAM_TYPE => [ 'all', 'redirects', 'nonredirects' ],
222 ParamValidator::PARAM_DEFAULT => 'nonredirects', // for BC
223 ],
224 'minsize' => [
225 ParamValidator::PARAM_TYPE => 'integer',
226 ],
227 'maxsize' => [
228 ParamValidator::PARAM_TYPE => 'integer',
229 ],
230 'contentmodel' => [
231 ParamValidator::PARAM_TYPE => $this->contentHandlerFactory->getContentModels(),
232 ],
233 'redirect' => [
234 ParamValidator::PARAM_DEPRECATED => true,
235 ParamValidator::PARAM_DEFAULT => false,
236 ],
237 'limit' => [
238 ParamValidator::PARAM_TYPE => 'limit',
239 ParamValidator::PARAM_DEFAULT => 1,
240 IntegerDef::PARAM_MIN => 1,
241 IntegerDef::PARAM_MAX => ApiBase::LIMIT_BIG1,
242 IntegerDef::PARAM_MAX2 => ApiBase::LIMIT_BIG2
243 ],
244 'continue' => [
245 ApiBase::PARAM_HELP_MSG => 'api-help-param-continue'
246 ],
247 ];
248 }
249
250 protected function getExamplesMessages() {
251 return [
252 'action=query&list=random&rnnamespace=0&rnlimit=2'
253 => 'apihelp-query+random-example-simple',
254 'action=query&generator=random&grnnamespace=0&grnlimit=2&prop=info'
255 => 'apihelp-query+random-example-generator',
256 'action=query&list=random&rnnamespace=0&rnlimit=1&minsize=500'
257 => 'apihelp-query+random-example-minsize',
258 ];
259 }
260
261 public function getHelpUrls() {
262 return 'https://www.mediawiki.org/wiki/Special:MyLanguage/API:Random';
263 }
264}
265
267class_alias( ApiQueryRandom::class, 'ApiQueryRandom' );
wfRandom()
Get a random decimal value in the domain of [0, 1), in a way not likely to give duplicate values for ...
getModuleName()
Get the name of the module being executed by this instance.
Definition ApiBase.php:557
getMain()
Get the main module.
Definition ApiBase.php:575
dieContinueUsageIf( $condition)
Die with the 'badcontinue' error.
Definition ApiBase.php:1746
parseContinueParamOrDie(string $continue, array $types)
Parse the 'continue' parameter in the usual format and validate the types of each part,...
Definition ApiBase.php:1707
getResult()
Get the result object.
Definition ApiBase.php:696
requireMaxOneParameter( $params,... $required)
Dies if more than one parameter from a certain set of parameters are set and not false.
Definition ApiBase.php:1011
const PARAM_HELP_MSG
(string|array|Message) Specify an alternative i18n documentation message for this parameter.
Definition ApiBase.php:181
const LIMIT_BIG2
Fast query, apihighlimits limit.
Definition ApiBase.php:248
extractRequestParams( $options=[])
Using getAllowedParams(), this function makes an array of the values provided by the user,...
Definition ApiBase.php:837
const LIMIT_BIG1
Fast query, standard limit.
Definition ApiBase.php:246
addOption( $name, $value=null)
Add an option such as LIMIT or USE INDEX.
static addTitleInfo(&$arr, $title, $prefix='')
Add information (title and namespace) about a Title object to a result array.
addTables( $tables, $alias=null)
Add a set of tables to the internal array.
getDB()
Get the Query database connection (read-only)
select( $method, $extraQuery=[], ?array &$hookData=null)
Execute a SELECT query based on the values in the internal arrays.
addWhere( $value)
Add a set of WHERE clauses to the internal array.
executeGenderCacheFromResultWrapper(IResultWrapper $res, $fname=__METHOD__, $fieldPrefix='page')
Preprocess the result set to fill the GenderCache with the necessary information before using self::a...
resetQueryParams()
Blank the internal arrays with query parameters.
addWhereFld( $field, $value)
Equivalent to addWhere( [ $field => $value ] )
addFields( $value)
Add a set of fields to select to the internal array.
setContinueEnumParameter( $paramName, $paramValue)
Overridden to set the generator param if in generator mode.
Query module to get list of random pages.
getExamplesMessages()
Returns usage examples for this module.
execute()
Evaluates the parameters, performs the requested query, and sets up the result.
runQuery( $resultPageSet, $limit, $start, $startId, $end)
Actually perform the query and add pages to the result.
executeGenerator( $resultPageSet)
Execute this module as a generator.
getHelpUrls()
Return links to more detailed help pages about the module.
__construct(ApiQuery $query, string $moduleName, ContentHandlerFactory $contentHandlerFactory)
getAllowedParams()
Returns an array of allowed parameters (parameter name) => (default value) or (parameter name) => (ar...
getCacheMode( $params)
Get the cache mode for the data generated by this module.
run( $resultPageSet=null)
This is the main query class.
Definition ApiQuery.php:48
Represents a title within MediaWiki.
Definition Title.php:78
Service for formatting and validating API parameters.
Type definition for integer types.