MediaWiki master
ApiQueryRandom.php
Go to the documentation of this file.
1<?php
2
10namespace MediaWiki\Api;
11
16
23
24 public function __construct(
25 ApiQuery $query,
26 string $moduleName,
27 private readonly ContentHandlerFactory $contentHandlerFactory,
28 ) {
29 parent::__construct( $query, $moduleName, 'rn' );
30 }
31
32 public function execute() {
33 $this->run();
34 }
35
37 public function executeGenerator( $resultPageSet ) {
38 $this->run( $resultPageSet );
39 }
40
50 protected function runQuery( $resultPageSet, $limit, $start, $startId, $end ) {
51 $params = $this->extractRequestParams();
52
53 $this->resetQueryParams();
54 $this->addTables( 'page' );
55 $this->addFields( [ 'page_id', 'page_random' ] );
56 if ( $resultPageSet === null ) {
57 $this->addFields( [ 'page_title', 'page_namespace' ] );
58 } else {
59 $this->addFields( $resultPageSet->getPageTableFields() );
60 }
61 $this->addWhereFld( 'page_namespace', $params['namespace'] );
62 if ( $params['redirect'] || $params['filterredir'] === 'redirects' ) {
63 $this->addWhereFld( 'page_is_redirect', 1 );
64 } elseif ( $params['filterredir'] === 'nonredirects' ) {
65 $this->addWhereFld( 'page_is_redirect', 0 );
66 } elseif ( $resultPageSet === null ) {
67 $this->addFields( [ 'page_is_redirect' ] );
68 }
69
70 $db = $this->getDB();
71 if ( isset( $params['minsize'] ) ) {
72 $this->addWhere( $db->expr( 'page_len', '>=', (int)$params['minsize'] ) );
73 }
74 if ( isset( $params['maxsize'] ) ) {
75 $this->addWhere( $db->expr( 'page_len', '<=', (int)$params['maxsize'] ) );
76 }
77
78 if ( isset( $params['contentmodel'] ) ) {
79 $this->addWhereFld( 'page_content_model', $params['contentmodel'] );
80 }
81
82 $this->addOption( 'LIMIT', $limit + 1 );
83
84 if ( $start !== null ) {
85 if ( $startId > 0 ) {
86 $this->addWhere( $db->buildComparison( '>=', [
87 'page_random' => $start,
88 'page_id' => $startId,
89 ] ) );
90 } else {
91 $this->addWhere( $db->buildComparison( '>=', [
92 'page_random' => $start,
93 ] ) );
94 }
95 }
96 if ( $end !== null ) {
97 $this->addWhere( $db->expr( 'page_random', '<', $end ) );
98 }
99 $this->addOption( 'ORDER BY', [ 'page_random', 'page_id' ] );
100
101 $result = $this->getResult();
102 $path = [ 'query', $this->getModuleName() ];
103
104 $res = $this->select( __METHOD__ );
105
106 if ( $resultPageSet === null ) {
107 $this->executeGenderCacheFromResultWrapper( $res, __METHOD__ );
108 }
109
110 $count = 0;
111 foreach ( $res as $row ) {
112 if ( $count++ >= $limit ) {
113 return [ 0, "{$row->page_random}|{$row->page_id}" ];
114 }
115 if ( $resultPageSet === null ) {
116 $title = Title::makeTitle( $row->page_namespace, $row->page_title );
117 $page = [
118 'id' => (int)$row->page_id,
119 ];
120 ApiQueryBase::addTitleInfo( $page, $title );
121 if ( isset( $row->page_is_redirect ) ) {
122 $page['redirect'] = (bool)$row->page_is_redirect;
123 }
124 $fit = $result->addValue( $path, null, $page );
125 if ( !$fit ) {
126 return [ 0, "{$row->page_random}|{$row->page_id}" ];
127 }
128 } else {
129 $resultPageSet->processDbRow( $row );
130 }
131 }
132
133 return [ $limit - $count, null ];
134 }
135
139 public function run( $resultPageSet = null ) {
140 $params = $this->extractRequestParams();
141
142 // Since 'filterredir' will always be set in $params, we have to dig
143 // into the WebRequest to see if it was actually passed.
144 $request = $this->getMain()->getRequest();
145 if ( $request->getCheck( $this->encodeParamName( 'filterredir' ) ) ) {
146 $this->requireMaxOneParameter( $params, 'filterredir', 'redirect' );
147 }
148
149 if ( isset( $params['continue'] ) ) {
150 $cont = $this->parseContinueParamOrDie( $params['continue'], [ 'string', 'string', 'int', 'string' ] );
151 $rand = $cont[0];
152 $start = $cont[1];
153 $startId = $cont[2];
154 $end = $cont[3] ? $rand : null;
155 $this->dieContinueUsageIf( !preg_match( '/^0\.\d+$/', $rand ) );
156 $this->dieContinueUsageIf( !preg_match( '/^0\.\d+$/', $start ) );
157 $this->dieContinueUsageIf( $cont[3] !== '0' && $cont[3] !== '1' );
158 } else {
159 $rand = wfRandom();
160 $start = $rand;
161 $startId = 0;
162 $end = null;
163 }
164
165 // Set the non-continue if this is being used as a generator
166 // (as a list it doesn't matter because lists never non-continue)
167 if ( $resultPageSet !== null ) {
168 $endFlag = $end === null ? 0 : 1;
169 $this->getContinuationManager()->addGeneratorNonContinueParam(
170 $this, 'continue', "$rand|$start|$startId|$endFlag"
171 );
172 }
173
174 [ $left, $continue ] =
175 $this->runQuery( $resultPageSet, $params['limit'], $start, $startId, $end );
176 if ( $end === null && $continue === null ) {
177 // Wrap around. We do this even if $left === 0 for continuation
178 // (saving a DB query in this rare case probably isn't worth the
179 // added code complexity it would require).
180 $end = $rand;
181 [ , $continue ] = $this->runQuery( $resultPageSet, $left, null, null, $end );
182 }
183
184 if ( $continue !== null ) {
185 $endFlag = $end === null ? 0 : 1;
186 $this->setContinueEnumParameter( 'continue', "$rand|$continue|$endFlag" );
187 }
188
189 if ( $resultPageSet === null ) {
190 $this->getResult()->addIndexedTagName( [ 'query', $this->getModuleName() ], 'page' );
191 }
192 }
193
195 public function getCacheMode( $params ) {
196 return 'public';
197 }
198
200 public function getAllowedParams() {
201 return [
202 'namespace' => [
203 ParamValidator::PARAM_TYPE => 'namespace',
204 ParamValidator::PARAM_ISMULTI => true
205 ],
206 'filterredir' => [
207 ParamValidator::PARAM_TYPE => [ 'all', 'redirects', 'nonredirects' ],
208 ParamValidator::PARAM_DEFAULT => 'nonredirects', // for BC
209 ],
210 'minsize' => [
211 ParamValidator::PARAM_TYPE => 'integer',
212 ],
213 'maxsize' => [
214 ParamValidator::PARAM_TYPE => 'integer',
215 ],
216 'contentmodel' => [
217 ParamValidator::PARAM_TYPE => $this->contentHandlerFactory->getContentModels(),
218 ],
219 'redirect' => [
220 ParamValidator::PARAM_DEPRECATED => true,
221 ParamValidator::PARAM_DEFAULT => false,
222 ],
223 'limit' => [
224 ParamValidator::PARAM_TYPE => 'limit',
225 ParamValidator::PARAM_DEFAULT => 1,
226 IntegerDef::PARAM_MIN => 1,
227 IntegerDef::PARAM_MAX => ApiBase::LIMIT_BIG1,
228 IntegerDef::PARAM_MAX2 => ApiBase::LIMIT_BIG2
229 ],
230 'continue' => [
231 ApiBase::PARAM_HELP_MSG => 'api-help-param-continue'
232 ],
233 ];
234 }
235
237 protected function getExamplesMessages() {
238 return [
239 'action=query&list=random&rnnamespace=0&rnlimit=2'
240 => 'apihelp-query+random-example-simple',
241 'action=query&generator=random&grnnamespace=0&grnlimit=2&prop=info'
242 => 'apihelp-query+random-example-generator',
243 'action=query&list=random&rnnamespace=0&rnlimit=1&minsize=500'
244 => 'apihelp-query+random-example-minsize',
245 ];
246 }
247
249 public function getHelpUrls() {
250 return 'https://www.mediawiki.org/wiki/Special:MyLanguage/API:Random';
251 }
252}
253
255class_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:1012
const PARAM_HELP_MSG
(string|array|Message) Specify an alternative i18n documentation message for this parameter.
Definition ApiBase.php:166
const LIMIT_BIG2
Fast query, apihighlimits limit.
Definition ApiBase.php:233
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:231
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.Return value has query strings as keys, with values being eith...
__construct(ApiQuery $query, string $moduleName, private readonly ContentHandlerFactory $contentHandlerFactory,)
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.1.25, returning boolean false is deprecated...
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.Override this in the module subclass....
run( $resultPageSet=null)
This is the main query class.
Definition ApiQuery.php:36
makeTitle( $linkId)
Convert a link ID to a Title.to override Title
Represents a title within MediaWiki.
Definition Title.php:69
Service for formatting and validating API parameters.
Type definition for integer types.