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