MediaWiki  1.34.0
ApiQueryBase.php
Go to the documentation of this file.
1 <?php
26 
34 abstract class ApiQueryBase extends ApiBase {
36 
38 
44  public function __construct( ApiQuery $queryModule, $moduleName, $paramPrefix = '' ) {
45  parent::__construct( $queryModule->getMain(), $moduleName, $paramPrefix );
46  $this->mQueryModule = $queryModule;
47  $this->mDb = null;
48  $this->resetQueryParams();
49  }
50 
51  /************************************************************************/
67  public function getCacheMode( $params ) {
68  return 'private';
69  }
70 
80  public function requestExtraData( $pageSet ) {
81  }
82 
85  /************************************************************************/
94  public function getQuery() {
95  return $this->mQueryModule;
96  }
97 
99  public function getParent() {
100  return $this->getQuery();
101  }
102 
107  protected function getDB() {
108  if ( is_null( $this->mDb ) ) {
109  $this->mDb = $this->getQuery()->getDB();
110  }
111 
112  return $this->mDb;
113  }
114 
123  public function selectNamedDB( $name, $db, $groups ) {
124  $this->mDb = $this->getQuery()->getNamedDB( $name, $db, $groups );
125  return $this->mDb;
126  }
127 
132  protected function getPageSet() {
133  return $this->getQuery()->getPageSet();
134  }
135 
138  /************************************************************************/
146  protected function resetQueryParams() {
147  $this->tables = [];
148  $this->where = [];
149  $this->fields = [];
150  $this->options = [];
151  $this->join_conds = [];
152  }
153 
161  protected function addTables( $tables, $alias = null ) {
162  if ( is_array( $tables ) ) {
163  if ( $alias !== null ) {
164  ApiBase::dieDebug( __METHOD__, 'Multiple table aliases not supported' );
165  }
166  $this->tables = array_merge( $this->tables, $tables );
167  } elseif ( $alias !== null ) {
168  $this->tables[$alias] = $tables;
169  } else {
170  $this->tables[] = $tables;
171  }
172  }
173 
182  protected function addJoinConds( $join_conds ) {
183  if ( !is_array( $join_conds ) ) {
184  ApiBase::dieDebug( __METHOD__, 'Join conditions have to be arrays' );
185  }
186  $this->join_conds = array_merge( $this->join_conds, $join_conds );
187  }
188 
193  protected function addFields( $value ) {
194  if ( is_array( $value ) ) {
195  $this->fields = array_merge( $this->fields, $value );
196  } else {
197  $this->fields[] = $value;
198  }
199  }
200 
207  protected function addFieldsIf( $value, $condition ) {
208  if ( $condition ) {
209  $this->addFields( $value );
210 
211  return true;
212  }
213 
214  return false;
215  }
216 
228  protected function addWhere( $value ) {
229  if ( is_array( $value ) ) {
230  // Sanity check: don't insert empty arrays,
231  // Database::makeList() chokes on them
232  if ( count( $value ) ) {
233  $this->where = array_merge( $this->where, $value );
234  }
235  } else {
236  $this->where[] = $value;
237  }
238  }
239 
246  protected function addWhereIf( $value, $condition ) {
247  if ( $condition ) {
248  $this->addWhere( $value );
249 
250  return true;
251  }
252 
253  return false;
254  }
255 
261  protected function addWhereFld( $field, $value ) {
262  if ( $value !== null && !( is_array( $value ) && !$value ) ) {
263  $this->where[$field] = $value;
264  }
265  }
266 
275  protected function addWhereIDsFld( $table, $field, $ids ) {
276  // Use count() to its full documented capabilities to simultaneously
277  // test for null, empty array or empty countable object
278  if ( count( $ids ) ) {
279  $ids = $this->filterIDs( [ [ $table, $field ] ], $ids );
280 
281  if ( $ids === [] ) {
282  // Return nothing, no IDs are valid
283  $this->where[] = '0 = 1';
284  } else {
285  $this->where[$field] = $ids;
286  }
287  }
288  return count( $ids );
289  }
290 
303  protected function addWhereRange( $field, $dir, $start, $end, $sort = true ) {
304  $isDirNewer = ( $dir === 'newer' );
305  $after = ( $isDirNewer ? '>=' : '<=' );
306  $before = ( $isDirNewer ? '<=' : '>=' );
307  $db = $this->getDB();
308 
309  if ( !is_null( $start ) ) {
310  $this->addWhere( $field . $after . $db->addQuotes( $start ) );
311  }
312 
313  if ( !is_null( $end ) ) {
314  $this->addWhere( $field . $before . $db->addQuotes( $end ) );
315  }
316 
317  if ( $sort ) {
318  $order = $field . ( $isDirNewer ? '' : ' DESC' );
319  // Append ORDER BY
320  $optionOrderBy = isset( $this->options['ORDER BY'] )
321  ? (array)$this->options['ORDER BY']
322  : [];
323  $optionOrderBy[] = $order;
324  $this->addOption( 'ORDER BY', $optionOrderBy );
325  }
326  }
327 
338  protected function addTimestampWhereRange( $field, $dir, $start, $end, $sort = true ) {
339  $db = $this->getDB();
340  $this->addWhereRange( $field, $dir,
341  $db->timestampOrNull( $start ), $db->timestampOrNull( $end ), $sort );
342  }
343 
350  protected function addOption( $name, $value = null ) {
351  if ( is_null( $value ) ) {
352  $this->options[] = $name;
353  } else {
354  $this->options[$name] = $value;
355  }
356  }
357 
375  protected function select( $method, $extraQuery = [], array &$hookData = null ) {
376  $tables = array_merge(
377  $this->tables,
378  isset( $extraQuery['tables'] ) ? (array)$extraQuery['tables'] : []
379  );
380  $fields = array_merge(
381  $this->fields,
382  isset( $extraQuery['fields'] ) ? (array)$extraQuery['fields'] : []
383  );
384  $where = array_merge(
385  $this->where,
386  isset( $extraQuery['where'] ) ? (array)$extraQuery['where'] : []
387  );
388  $options = array_merge(
389  $this->options,
390  isset( $extraQuery['options'] ) ? (array)$extraQuery['options'] : []
391  );
392  $join_conds = array_merge(
393  $this->join_conds,
394  isset( $extraQuery['join_conds'] ) ? (array)$extraQuery['join_conds'] : []
395  );
396 
397  if ( $hookData !== null ) {
398  Hooks::run( 'ApiQueryBaseBeforeQuery',
399  [ $this, &$tables, &$fields, &$where, &$options, &$join_conds, &$hookData ]
400  );
401  }
402 
403  $res = $this->getDB()->select( $tables, $fields, $where, $method, $options, $join_conds );
404 
405  if ( $hookData !== null ) {
406  Hooks::run( 'ApiQueryBaseAfterQuery', [ $this, $res, &$hookData ] );
407  }
408 
409  return $res;
410  }
411 
425  protected function processRow( $row, array &$data, array &$hookData ) {
426  return Hooks::run( 'ApiQueryBaseProcessRow', [ $this, $row, &$data, &$hookData ] );
427  }
428 
431  /************************************************************************/
443  public static function addTitleInfo( &$arr, $title, $prefix = '' ) {
444  $arr[$prefix . 'ns'] = (int)$title->getNamespace();
445  $arr[$prefix . 'title'] = $title->getPrefixedText();
446  }
447 
454  protected function addPageSubItems( $pageId, $data ) {
455  $result = $this->getResult();
457 
458  return $result->addValue( [ 'query', 'pages', (int)$pageId ],
459  $this->getModuleName(),
460  $data );
461  }
462 
471  protected function addPageSubItem( $pageId, $item, $elemname = null ) {
472  if ( is_null( $elemname ) ) {
473  $elemname = $this->getModulePrefix();
474  }
475  $result = $this->getResult();
476  $fit = $result->addValue( [ 'query', 'pages', $pageId,
477  $this->getModuleName() ], null, $item );
478  if ( !$fit ) {
479  return false;
480  }
481  $result->addIndexedTagName( [ 'query', 'pages', $pageId,
482  $this->getModuleName() ], $elemname );
483 
484  return true;
485  }
486 
492  protected function setContinueEnumParameter( $paramName, $paramValue ) {
493  $this->getContinuationManager()->addContinueParam( $this, $paramName, $paramValue );
494  }
495 
506  public function titlePartToKey( $titlePart, $namespace = NS_MAIN ) {
507  $t = Title::makeTitleSafe( $namespace, $titlePart . 'x' );
508  if ( !$t || $t->hasFragment() ) {
509  // Invalid title (e.g. bad chars) or contained a '#'.
510  $this->dieWithError( [ 'apierror-invalidtitle', wfEscapeWikiText( $titlePart ) ] );
511  }
512  if ( $namespace != $t->getNamespace() || $t->isExternal() ) {
513  // This can happen in two cases. First, if you call titlePartToKey with a title part
514  // that looks like a namespace, but with $defaultNamespace = NS_MAIN. It would be very
515  // difficult to handle such a case. Such cases cannot exist and are therefore treated
516  // as invalid user input. The second case is when somebody specifies a title interwiki
517  // prefix.
518  $this->dieWithError( [ 'apierror-invalidtitle', wfEscapeWikiText( $titlePart ) ] );
519  }
520 
521  return substr( $t->getDBkey(), 0, -1 );
522  }
523 
532  public function prefixedTitlePartToKey( $titlePart, $defaultNamespace = NS_MAIN ) {
533  $t = Title::newFromText( $titlePart . 'x', $defaultNamespace );
534  if ( !$t || $t->hasFragment() || $t->isExternal() ) {
535  // Invalid title (e.g. bad chars) or contained a '#'.
536  $this->dieWithError( [ 'apierror-invalidtitle', wfEscapeWikiText( $titlePart ) ] );
537  }
538 
539  return [ $t->getNamespace(), substr( $t->getDBkey(), 0, -1 ) ];
540  }
541 
546  public function validateSha1Hash( $hash ) {
547  return (bool)preg_match( '/^[a-f0-9]{40}$/', $hash );
548  }
549 
554  public function validateSha1Base36Hash( $hash ) {
555  return (bool)preg_match( '/^[a-z0-9]{31}$/', $hash );
556  }
557 
563  public function userCanSeeRevDel() {
564  return $this->getPermissionManager()->userHasAnyRight(
565  $this->getUser(),
566  'deletedhistory',
567  'deletedtext',
568  'suppressrevision',
569  'viewsuppressed'
570  );
571  }
572 
583  IResultWrapper $res, $fname = __METHOD__, $fieldPrefix = 'page'
584  ) {
585  if ( !$res->numRows() ) {
586  return;
587  }
588 
589  $services = MediaWikiServices::getInstance();
590  $nsInfo = $services->getNamespaceInfo();
591  $namespaceField = $fieldPrefix . '_namespace';
592  $titleField = $fieldPrefix . '_title';
593 
594  $usernames = [];
595  foreach ( $res as $row ) {
596  if ( $nsInfo->hasGenderDistinction( $row->$namespaceField ) ) {
597  $usernames[] = $row->$titleField;
598  }
599  }
600 
601  if ( $usernames === [] ) {
602  return;
603  }
604 
605  $genderCache = $services->getGenderCache();
606  $genderCache->doQuery( $usernames, $fname );
607  }
608 
611  /************************************************************************/
624  public function showHiddenUsersAddBlockInfo( $showBlockInfo ) {
625  wfDeprecated( __METHOD__, '1.34' );
626  return $this->addBlockInfoToQuery( $showBlockInfo );
627  }
628 
630 }
ApiQueryBase\validateSha1Base36Hash
validateSha1Base36Hash( $hash)
Definition: ApiQueryBase.php:554
ApiQueryBase\addWhereIDsFld
addWhereIDsFld( $table, $field, $ids)
Like addWhereFld for an integer list of IDs.
Definition: ApiQueryBase.php:275
ApiQueryBase\showHiddenUsersAddBlockInfo
showHiddenUsersAddBlockInfo( $showBlockInfo)
Filters hidden users (where the user doesn't have the right to view them) Also adds relevant block in...
Definition: ApiQueryBase.php:624
ApiQueryBase\addPageSubItems
addPageSubItems( $pageId, $data)
Add a sub-element under the page element with the given page ID.
Definition: ApiQueryBase.php:454
Title\newFromText
static newFromText( $text, $defaultNamespace=NS_MAIN)
Create a new Title from text, such as what one would find in a link.
Definition: Title.php:316
ApiQueryBase\processRow
processRow( $row, array &$data, array &$hookData)
Call the ApiQueryBaseProcessRow hook.
Definition: ApiQueryBase.php:425
ApiQueryBase\addFields
addFields( $value)
Add a set of fields to select to the internal array.
Definition: ApiQueryBase.php:193
ApiQuery
This is the main query class.
Definition: ApiQuery.php:37
ApiQueryBase\resetQueryParams
resetQueryParams()
Blank the internal arrays with query parameters.
Definition: ApiQueryBase.php:146
MediaWiki\MediaWikiServices
MediaWikiServices is the service locator for the application scope of MediaWiki.
Definition: MediaWikiServices.php:117
ApiQueryBase\getParent
getParent()
Get the parent of this module.1.25 ApiBase|null
Definition: ApiQueryBase.php:99
ApiBase\dieWithError
dieWithError( $msg, $code=null, $data=null, $httpCode=null)
Abort execution with an error.
Definition: ApiBase.php:2014
ApiQueryBase\addTimestampWhereRange
addTimestampWhereRange( $field, $dir, $start, $end, $sort=true)
Add a WHERE clause corresponding to a range, similar to addWhereRange, but converts $start and $end t...
Definition: ApiQueryBase.php:338
ApiBase\getResult
getResult()
Get the result object.
Definition: ApiBase.php:640
ApiQueryBase\getQuery
getQuery()
Get the main Query module.
Definition: ApiQueryBase.php:94
ApiQueryBase\$fields
$fields
Definition: ApiQueryBase.php:37
ApiQueryBase\addOption
addOption( $name, $value=null)
Add an option such as LIMIT or USE INDEX.
Definition: ApiQueryBase.php:350
$res
$res
Definition: testCompression.php:52
ContextSource\getUser
getUser()
Definition: ContextSource.php:120
ApiQueryBase\$options
$options
Definition: ApiQueryBase.php:37
ApiQueryBase\addFieldsIf
addFieldsIf( $value, $condition)
Same as addFields(), but add the fields only if a condition is met.
Definition: ApiQueryBase.php:207
ApiBase
This abstract class implements many basic API functions, and is the base of all API classes.
Definition: ApiBase.php:42
Wikimedia\Rdbms\IDatabase
Basic database interface for live and lazy-loaded relation database handles.
Definition: IDatabase.php:38
NS_MAIN
const NS_MAIN
Definition: Defines.php:60
ApiQueryBlockInfoTrait
trait ApiQueryBlockInfoTrait
Definition: ApiQueryBlockInfoTrait.php:27
ApiQueryBase\executeGenderCacheFromResultWrapper
executeGenderCacheFromResultWrapper(IResultWrapper $res, $fname=__METHOD__, $fieldPrefix='page')
Preprocess the result set to fill the GenderCache with the necessary information before using self::a...
Definition: ApiQueryBase.php:582
wfDeprecated
wfDeprecated( $function, $version=false, $component=false, $callerOffset=2)
Throws a warning that $function is deprecated.
Definition: GlobalFunctions.php:1044
Wikimedia\Rdbms\IResultWrapper
Result wrapper for grabbing data queried from an IDatabase object.
Definition: IResultWrapper.php:24
ApiQueryBase
This is a base class for all Query modules.
Definition: ApiQueryBase.php:34
ApiQueryBase\getDB
getDB()
Get the Query database connection (read-only)
Definition: ApiQueryBase.php:107
ApiQueryBase\addTables
addTables( $tables, $alias=null)
Add a set of tables to the internal array.
Definition: ApiQueryBase.php:161
ApiQueryBase\select
select( $method, $extraQuery=[], array &$hookData=null)
Execute a SELECT query based on the values in the internal arrays.
Definition: ApiQueryBase.php:375
$t
$t
Definition: make-normalization-table.php:143
$title
$title
Definition: testCompression.php:34
ApiQueryBase\$mDb
$mDb
Definition: ApiQueryBase.php:37
$sort
$sort
Definition: profileinfo.php:331
ApiQueryBase\$where
$where
Definition: ApiQueryBase.php:37
ApiBase\getModulePrefix
getModulePrefix()
Get parameter prefix (usually two letters or an empty string).
Definition: ApiBase.php:528
ApiQueryBase\addWhereRange
addWhereRange( $field, $dir, $start, $end, $sort=true)
Add a WHERE clause corresponding to a range, and an ORDER BY clause to sort in the right direction.
Definition: ApiQueryBase.php:303
ApiBase\getContinuationManager
getContinuationManager()
Get the continuation manager.
Definition: ApiBase.php:680
Title\makeTitleSafe
static makeTitleSafe( $ns, $title, $fragment='', $interwiki='')
Create a new Title from a namespace index and a DB key.
Definition: Title.php:613
ApiResult\setIndexedTagName
static setIndexedTagName(array &$arr, $tag)
Set the tag name for numeric-keyed values in XML format.
Definition: ApiResult.php:616
ApiBase\getPermissionManager
getPermissionManager()
Obtain a PermissionManager instance that subclasses may use in their authorization checks.
Definition: ApiBase.php:710
ApiQueryBase\requestExtraData
requestExtraData( $pageSet)
Override this method to request extra fields from the pageSet using $pageSet->requestField('fieldName...
Definition: ApiQueryBase.php:80
ApiQueryBase\addJoinConds
addJoinConds( $join_conds)
Add a set of JOIN conditions to the internal array.
Definition: ApiQueryBase.php:182
wfEscapeWikiText
wfEscapeWikiText( $text)
Escapes the given text so that it may be output using addWikiText() without any linking,...
Definition: GlobalFunctions.php:1551
ApiQueryBase\addWhereFld
addWhereFld( $field, $value)
Equivalent to addWhere( [ $field => $value ] )
Definition: ApiQueryBase.php:261
ApiQueryBase\getCacheMode
getCacheMode( $params)
Get the cache mode for the data generated by this module.
Definition: ApiQueryBase.php:67
ApiQueryBase\prefixedTitlePartToKey
prefixedTitlePartToKey( $titlePart, $defaultNamespace=NS_MAIN)
Convert an input title or title prefix into a namespace constant and dbkey.
Definition: ApiQueryBase.php:532
ApiQueryBase\getPageSet
getPageSet()
Get the PageSet object to work on.
Definition: ApiQueryBase.php:132
ApiBase\filterIDs
filterIDs( $fields, array $ids)
Filter out-of-range values from a list of positive integer IDs.
Definition: ApiBase.php:1885
ApiQueryBase\selectNamedDB
selectNamedDB( $name, $db, $groups)
Selects the query database connection with the given name.
Definition: ApiQueryBase.php:123
ApiQueryBase\$join_conds
$join_conds
Definition: ApiQueryBase.php:37
ApiQueryBase\$tables
$tables
Definition: ApiQueryBase.php:37
ApiQueryBase\__construct
__construct(ApiQuery $queryModule, $moduleName, $paramPrefix='')
Definition: ApiQueryBase.php:44
ApiBase\getModuleName
getModuleName()
Get the name of the module being executed by this instance.
Definition: ApiBase.php:520
ApiQueryBase\$mQueryModule
$mQueryModule
Definition: ApiQueryBase.php:37
ApiBase\getMain
getMain()
Get the main module.
Definition: ApiBase.php:536
ApiQueryBase\addWhere
addWhere( $value)
Add a set of WHERE clauses to the internal array.
Definition: ApiQueryBase.php:228
ApiQueryBase\setContinueEnumParameter
setContinueEnumParameter( $paramName, $paramValue)
Set a query-continue value.
Definition: ApiQueryBase.php:492
ApiQueryBase\titlePartToKey
titlePartToKey( $titlePart, $namespace=NS_MAIN)
Convert an input title or title prefix into a dbkey.
Definition: ApiQueryBase.php:506
Hooks\run
static run( $event, array $args=[], $deprecatedVersion=null)
Call hook functions defined in Hooks::register and $wgHooks.
Definition: Hooks.php:200
ApiQueryBase\userCanSeeRevDel
userCanSeeRevDel()
Check whether the current user has permission to view revision-deleted fields.
Definition: ApiQueryBase.php:563
ApiQueryBase\addPageSubItem
addPageSubItem( $pageId, $item, $elemname=null)
Same as addPageSubItems(), but one element of $data at a time.
Definition: ApiQueryBase.php:471
ApiBase\dieDebug
static dieDebug( $method, $message)
Internal code errors should be reported with this method.
Definition: ApiBase.php:2220
ApiQueryBase\addWhereIf
addWhereIf( $value, $condition)
Same as addWhere(), but add the WHERE clauses only if a condition is met.
Definition: ApiQueryBase.php:246
ApiQueryBase\addTitleInfo
static addTitleInfo(&$arr, $title, $prefix='')
Add information (title and namespace) about a Title object to a result array.
Definition: ApiQueryBase.php:443
addBlockInfoToQuery
addBlockInfoToQuery( $showBlockInfo)
Filters hidden users (where the user doesn't have the right to view them) Also adds relevant block in...
Definition: ApiQueryBlockInfoTrait.php:37
ApiQueryBase\validateSha1Hash
validateSha1Hash( $hash)
Definition: ApiQueryBase.php:546