MediaWiki
REL1_24
|
00001 <?php 00034 abstract class ApiQueryBase extends ApiBase { 00035 00036 private $mQueryModule, $mDb, $tables, $where, $fields, $options, $join_conds; 00037 00043 public function __construct( ApiQuery $queryModule, $moduleName, $paramPrefix = '' ) { 00044 parent::__construct( $queryModule->getMain(), $moduleName, $paramPrefix ); 00045 $this->mQueryModule = $queryModule; 00046 $this->mDb = null; 00047 $this->resetQueryParams(); 00048 } 00049 00050 /************************************************************************/ 00066 public function getCacheMode( $params ) { 00067 return 'private'; 00068 } 00069 00075 public function requestExtraData( $pageSet ) { 00076 } 00077 00080 /************************************************************************/ 00089 public function getQuery() { 00090 return $this->mQueryModule; 00091 } 00092 00097 protected function getDB() { 00098 if ( is_null( $this->mDb ) ) { 00099 $this->mDb = $this->getQuery()->getDB(); 00100 } 00101 00102 return $this->mDb; 00103 } 00104 00113 public function selectNamedDB( $name, $db, $groups ) { 00114 $this->mDb = $this->getQuery()->getNamedDB( $name, $db, $groups ); 00115 } 00116 00121 protected function getPageSet() { 00122 return $this->getQuery()->getPageSet(); 00123 } 00124 00127 /************************************************************************/ 00135 protected function resetQueryParams() { 00136 $this->tables = array(); 00137 $this->where = array(); 00138 $this->fields = array(); 00139 $this->options = array(); 00140 $this->join_conds = array(); 00141 } 00142 00149 protected function addTables( $tables, $alias = null ) { 00150 if ( is_array( $tables ) ) { 00151 if ( !is_null( $alias ) ) { 00152 ApiBase::dieDebug( __METHOD__, 'Multiple table aliases not supported' ); 00153 } 00154 $this->tables = array_merge( $this->tables, $tables ); 00155 } else { 00156 if ( !is_null( $alias ) ) { 00157 $this->tables[$alias] = $tables; 00158 } else { 00159 $this->tables[] = $tables; 00160 } 00161 } 00162 } 00163 00173 protected function addJoinConds( $join_conds ) { 00174 if ( !is_array( $join_conds ) ) { 00175 ApiBase::dieDebug( __METHOD__, 'Join conditions have to be arrays' ); 00176 } 00177 $this->join_conds = array_merge( $this->join_conds, $join_conds ); 00178 } 00179 00184 protected function addFields( $value ) { 00185 if ( is_array( $value ) ) { 00186 $this->fields = array_merge( $this->fields, $value ); 00187 } else { 00188 $this->fields[] = $value; 00189 } 00190 } 00191 00198 protected function addFieldsIf( $value, $condition ) { 00199 if ( $condition ) { 00200 $this->addFields( $value ); 00201 00202 return true; 00203 } 00204 00205 return false; 00206 } 00207 00219 protected function addWhere( $value ) { 00220 if ( is_array( $value ) ) { 00221 // Sanity check: don't insert empty arrays, 00222 // Database::makeList() chokes on them 00223 if ( count( $value ) ) { 00224 $this->where = array_merge( $this->where, $value ); 00225 } 00226 } else { 00227 $this->where[] = $value; 00228 } 00229 } 00230 00237 protected function addWhereIf( $value, $condition ) { 00238 if ( $condition ) { 00239 $this->addWhere( $value ); 00240 00241 return true; 00242 } 00243 00244 return false; 00245 } 00246 00252 protected function addWhereFld( $field, $value ) { 00253 // Use count() to its full documented capabilities to simultaneously 00254 // test for null, empty array or empty countable object 00255 if ( count( $value ) ) { 00256 $this->where[$field] = $value; 00257 } 00258 } 00259 00272 protected function addWhereRange( $field, $dir, $start, $end, $sort = true ) { 00273 $isDirNewer = ( $dir === 'newer' ); 00274 $after = ( $isDirNewer ? '>=' : '<=' ); 00275 $before = ( $isDirNewer ? '<=' : '>=' ); 00276 $db = $this->getDB(); 00277 00278 if ( !is_null( $start ) ) { 00279 $this->addWhere( $field . $after . $db->addQuotes( $start ) ); 00280 } 00281 00282 if ( !is_null( $end ) ) { 00283 $this->addWhere( $field . $before . $db->addQuotes( $end ) ); 00284 } 00285 00286 if ( $sort ) { 00287 $order = $field . ( $isDirNewer ? '' : ' DESC' ); 00288 // Append ORDER BY 00289 $optionOrderBy = isset( $this->options['ORDER BY'] ) 00290 ? (array)$this->options['ORDER BY'] 00291 : array(); 00292 $optionOrderBy[] = $order; 00293 $this->addOption( 'ORDER BY', $optionOrderBy ); 00294 } 00295 } 00296 00307 protected function addTimestampWhereRange( $field, $dir, $start, $end, $sort = true ) { 00308 $db = $this->getDb(); 00309 $this->addWhereRange( $field, $dir, 00310 $db->timestampOrNull( $start ), $db->timestampOrNull( $end ), $sort ); 00311 } 00312 00319 protected function addOption( $name, $value = null ) { 00320 if ( is_null( $value ) ) { 00321 $this->options[] = $name; 00322 } else { 00323 $this->options[$name] = $value; 00324 } 00325 } 00326 00341 protected function select( $method, $extraQuery = array() ) { 00342 00343 $tables = array_merge( 00344 $this->tables, 00345 isset( $extraQuery['tables'] ) ? (array)$extraQuery['tables'] : array() 00346 ); 00347 $fields = array_merge( 00348 $this->fields, 00349 isset( $extraQuery['fields'] ) ? (array)$extraQuery['fields'] : array() 00350 ); 00351 $where = array_merge( 00352 $this->where, 00353 isset( $extraQuery['where'] ) ? (array)$extraQuery['where'] : array() 00354 ); 00355 $options = array_merge( 00356 $this->options, 00357 isset( $extraQuery['options'] ) ? (array)$extraQuery['options'] : array() 00358 ); 00359 $join_conds = array_merge( 00360 $this->join_conds, 00361 isset( $extraQuery['join_conds'] ) ? (array)$extraQuery['join_conds'] : array() 00362 ); 00363 00364 // getDB has its own profileDBIn/Out calls 00365 $db = $this->getDB(); 00366 00367 $this->profileDBIn(); 00368 $res = $db->select( $tables, $fields, $where, $method, $options, $join_conds ); 00369 $this->profileDBOut(); 00370 00371 return $res; 00372 } 00373 00379 public function prepareUrlQuerySearchString( $query = null, $protocol = null ) { 00380 $db = $this->getDb(); 00381 if ( !is_null( $query ) || $query != '' ) { 00382 if ( is_null( $protocol ) ) { 00383 $protocol = 'http://'; 00384 } 00385 00386 $likeQuery = LinkFilter::makeLikeArray( $query, $protocol ); 00387 if ( !$likeQuery ) { 00388 $this->dieUsage( 'Invalid query', 'bad_query' ); 00389 } 00390 00391 $likeQuery = LinkFilter::keepOneWildcard( $likeQuery ); 00392 00393 return 'el_index ' . $db->buildLike( $likeQuery ); 00394 } elseif ( !is_null( $protocol ) ) { 00395 return 'el_index ' . $db->buildLike( "$protocol", $db->anyString() ); 00396 } 00397 00398 return null; 00399 } 00400 00408 public function showHiddenUsersAddBlockInfo( $showBlockInfo ) { 00409 $this->addTables( 'ipblocks' ); 00410 $this->addJoinConds( array( 00411 'ipblocks' => array( 'LEFT JOIN', 'ipb_user=user_id' ), 00412 ) ); 00413 00414 $this->addFields( 'ipb_deleted' ); 00415 00416 if ( $showBlockInfo ) { 00417 $this->addFields( array( 'ipb_id', 'ipb_by', 'ipb_by_text', 'ipb_reason', 'ipb_expiry', 'ipb_timestamp' ) ); 00418 } 00419 00420 // Don't show hidden names 00421 if ( !$this->getUser()->isAllowed( 'hideuser' ) ) { 00422 $this->addWhere( 'ipb_deleted = 0 OR ipb_deleted IS NULL' ); 00423 } 00424 } 00425 00428 /************************************************************************/ 00440 public static function addTitleInfo( &$arr, $title, $prefix = '' ) { 00441 $arr[$prefix . 'ns'] = intval( $title->getNamespace() ); 00442 $arr[$prefix . 'title'] = $title->getPrefixedText(); 00443 } 00444 00451 protected function addPageSubItems( $pageId, $data ) { 00452 $result = $this->getResult(); 00453 $result->setIndexedTagName( $data, $this->getModulePrefix() ); 00454 00455 return $result->addValue( array( 'query', 'pages', intval( $pageId ) ), 00456 $this->getModuleName(), 00457 $data ); 00458 } 00459 00468 protected function addPageSubItem( $pageId, $item, $elemname = null ) { 00469 if ( is_null( $elemname ) ) { 00470 $elemname = $this->getModulePrefix(); 00471 } 00472 $result = $this->getResult(); 00473 $fit = $result->addValue( array( 'query', 'pages', $pageId, 00474 $this->getModuleName() ), null, $item ); 00475 if ( !$fit ) { 00476 return false; 00477 } 00478 $result->setIndexedTagName_internal( array( 'query', 'pages', $pageId, 00479 $this->getModuleName() ), $elemname ); 00480 00481 return true; 00482 } 00483 00489 protected function setContinueEnumParameter( $paramName, $paramValue ) { 00490 $this->getResult()->setContinueParam( $this, $paramName, $paramValue ); 00491 } 00492 00503 public function titlePartToKey( $titlePart, $namespace = NS_MAIN ) { 00504 $t = Title::makeTitleSafe( $namespace, $titlePart . 'x' ); 00505 if ( !$t ) { 00506 $this->dieUsageMsg( array( 'invalidtitle', $titlePart ) ); 00507 } 00508 if ( $namespace != $t->getNamespace() || $t->isExternal() ) { 00509 // This can happen in two cases. First, if you call titlePartToKey with a title part 00510 // that looks like a namespace, but with $defaultNamespace = NS_MAIN. It would be very 00511 // difficult to handle such a case. Such cases cannot exist and are therefore treated 00512 // as invalid user input. The second case is when somebody specifies a title interwiki 00513 // prefix. 00514 $this->dieUsageMsg( array( 'invalidtitle', $titlePart ) ); 00515 } 00516 00517 return substr( $t->getDbKey(), 0, -1 ); 00518 } 00519 00527 public function getDirectionDescription( $p = '', $extraDirText = '' ) { 00528 return array( 00529 "In which direction to enumerate{$extraDirText}", 00530 " newer - List oldest first. Note: {$p}start has to be before {$p}end.", 00531 " older - List newest first (default). Note: {$p}start has to be later than {$p}end.", 00532 ); 00533 } 00534 00539 public function validateSha1Hash( $hash ) { 00540 return preg_match( '/^[a-f0-9]{40}$/', $hash ); 00541 } 00542 00547 public function validateSha1Base36Hash( $hash ) { 00548 return preg_match( '/^[a-z0-9]{31}$/', $hash ); 00549 } 00550 00556 public function userCanSeeRevDel() { 00557 return $this->getUser()->isAllowedAny( 00558 'deletedhistory', 00559 'deletedtext', 00560 'suppressrevision', 00561 'viewsuppressed' 00562 ); 00563 } 00564 00567 /************************************************************************/ 00578 protected function checkRowCount() { 00579 wfDeprecated( __METHOD__, '1.24' ); 00580 $db = $this->getDB(); 00581 $this->profileDBIn(); 00582 $rowcount = $db->estimateRowCount( 00583 $this->tables, 00584 $this->fields, 00585 $this->where, 00586 __METHOD__, 00587 $this->options 00588 ); 00589 $this->profileDBOut(); 00590 00591 if ( $rowcount > $this->getConfig()->get( 'APIMaxDBRows' ) ) { 00592 return false; 00593 } 00594 00595 return true; 00596 } 00597 00605 public function titleToKey( $title ) { 00606 wfDeprecated( __METHOD__, '1.24' ); 00607 // Don't throw an error if we got an empty string 00608 if ( trim( $title ) == '' ) { 00609 return ''; 00610 } 00611 $t = Title::newFromText( $title ); 00612 if ( !$t ) { 00613 $this->dieUsageMsg( array( 'invalidtitle', $title ) ); 00614 } 00615 00616 return $t->getPrefixedDBkey(); 00617 } 00618 00625 public function keyToTitle( $key ) { 00626 wfDeprecated( __METHOD__, '1.24' ); 00627 // Don't throw an error if we got an empty string 00628 if ( trim( $key ) == '' ) { 00629 return ''; 00630 } 00631 $t = Title::newFromDBkey( $key ); 00632 // This really shouldn't happen but we gotta check anyway 00633 if ( !$t ) { 00634 $this->dieUsageMsg( array( 'invalidtitle', $key ) ); 00635 } 00636 00637 return $t->getPrefixedText(); 00638 } 00639 00646 public function keyPartToTitle( $keyPart ) { 00647 wfDeprecated( __METHOD__, '1.24' ); 00648 return substr( $this->keyToTitle( $keyPart . 'x' ), 0, -1 ); 00649 } 00650 00652 } 00653 00657 abstract class ApiQueryGeneratorBase extends ApiQueryBase { 00658 00659 private $mGeneratorPageSet = null; 00660 00668 public function setGeneratorMode( ApiPageSet $generatorPageSet ) { 00669 if ( $generatorPageSet === null ) { 00670 ApiBase::dieDebug( __METHOD__, 'Required parameter missing - $generatorPageSet' ); 00671 } 00672 $this->mGeneratorPageSet = $generatorPageSet; 00673 } 00674 00680 protected function getPageSet() { 00681 if ( $this->mGeneratorPageSet !== null ) { 00682 return $this->mGeneratorPageSet; 00683 } 00684 00685 return parent::getPageSet(); 00686 } 00687 00693 public function encodeParamName( $paramName ) { 00694 if ( $this->mGeneratorPageSet !== null ) { 00695 return 'g' . parent::encodeParamName( $paramName ); 00696 } else { 00697 return parent::encodeParamName( $paramName ); 00698 } 00699 } 00700 00706 protected function setContinueEnumParameter( $paramName, $paramValue ) { 00707 if ( $this->mGeneratorPageSet !== null ) { 00708 $this->getResult()->setGeneratorContinueParam( $this, $paramName, $paramValue ); 00709 } else { 00710 parent::setContinueEnumParameter( $paramName, $paramValue ); 00711 } 00712 } 00713 00718 abstract public function executeGenerator( $resultPageSet ); 00719 }