MediaWiki  master
ApiQueryCategories.php
Go to the documentation of this file.
00001 <?php
00032 class ApiQueryCategories extends ApiQueryGeneratorBase {
00033 
00034         public function __construct( $query, $moduleName ) {
00035                 parent::__construct( $query, $moduleName, 'cl' );
00036         }
00037 
00038         public function execute() {
00039                 $this->run();
00040         }
00041 
00042         public function getCacheMode( $params ) {
00043                 return 'public';
00044         }
00045 
00046         public function executeGenerator( $resultPageSet ) {
00047                 $this->run( $resultPageSet );
00048         }
00049 
00054         private function run( $resultPageSet = null ) {
00055                 if ( $this->getPageSet()->getGoodTitleCount() == 0 ) {
00056                         return; // nothing to do
00057                 }
00058 
00059                 $params = $this->extractRequestParams();
00060                 $prop = array_flip( (array)$params['prop'] );
00061                 $show = array_flip( (array)$params['show'] );
00062 
00063                 $this->addFields( array(
00064                         'cl_from',
00065                         'cl_to'
00066                 ) );
00067 
00068                 $this->addFieldsIf( array( 'cl_sortkey', 'cl_sortkey_prefix' ), isset( $prop['sortkey'] ) );
00069                 $this->addFieldsIf( 'cl_timestamp', isset( $prop['timestamp'] ) );
00070 
00071                 $this->addTables( 'categorylinks' );
00072                 $this->addWhereFld( 'cl_from', array_keys( $this->getPageSet()->getGoodTitles() ) );
00073                 if ( !is_null( $params['categories'] ) ) {
00074                         $cats = array();
00075                         foreach ( $params['categories'] as $cat ) {
00076                                 $title = Title::newFromText( $cat );
00077                                 if ( !$title || $title->getNamespace() != NS_CATEGORY ) {
00078                                         $this->setWarning( "\"$cat\" is not a category" );
00079                                 } else {
00080                                         $cats[] = $title->getDBkey();
00081                                 }
00082                         }
00083                         $this->addWhereFld( 'cl_to', $cats );
00084                 }
00085 
00086                 if ( !is_null( $params['continue'] ) ) {
00087                         $cont = explode( '|', $params['continue'] );
00088                         if ( count( $cont ) != 2 ) {
00089                                 $this->dieUsage( "Invalid continue param. You should pass the " .
00090                                         "original value returned by the previous query", "_badcontinue" );
00091                         }
00092                         $op = $params['dir'] == 'descending' ? '<' : '>';
00093                         $clfrom = intval( $cont[0] );
00094                         $clto = $this->getDB()->addQuotes( $cont[1] );
00095                         $this->addWhere(
00096                                 "cl_from $op $clfrom OR " .
00097                                 "(cl_from = $clfrom AND " .
00098                                 "cl_to $op= $clto)"
00099                         );
00100                 }
00101 
00102                 if ( isset( $show['hidden'] ) && isset( $show['!hidden'] ) ) {
00103                         $this->dieUsageMsg( 'show' );
00104                 }
00105                 if ( isset( $show['hidden'] ) || isset( $show['!hidden'] ) || isset( $prop['hidden'] ) )
00106                 {
00107                         $this->addOption( 'STRAIGHT_JOIN' );
00108                         $this->addTables( array( 'page', 'page_props' ) );
00109                         $this->addFieldsIf( 'pp_propname', isset( $prop['hidden'] ) );
00110                         $this->addJoinConds( array(
00111                                 'page' => array( 'LEFT JOIN', array(
00112                                         'page_namespace' => NS_CATEGORY,
00113                                         'page_title = cl_to' ) ),
00114                                 'page_props' => array( 'LEFT JOIN', array(
00115                                         'pp_page=page_id',
00116                                         'pp_propname' => 'hiddencat' ) )
00117                         ) );
00118                         if ( isset( $show['hidden'] ) ) {
00119                                 $this->addWhere( array( 'pp_propname IS NOT NULL' ) );
00120                         } elseif ( isset( $show['!hidden'] ) ) {
00121                                 $this->addWhere( array( 'pp_propname IS NULL' ) );
00122                         }
00123                 }
00124 
00125                 $this->addOption( 'USE INDEX', array( 'categorylinks' => 'cl_from' ) );
00126 
00127                 $sort = ( $params['dir'] == 'descending' ? ' DESC' : '' );
00128                 // Don't order by cl_from if it's constant in the WHERE clause
00129                 if ( count( $this->getPageSet()->getGoodTitles() ) == 1 ) {
00130                         $this->addOption( 'ORDER BY', 'cl_to' . $sort );
00131                 } else {
00132                         $this->addOption( 'ORDER BY', array(
00133                                                 'cl_from' . $sort,
00134                                                 'cl_to' . $sort
00135                         ));
00136                 }
00137 
00138                 $res = $this->select( __METHOD__ );
00139 
00140                 $count = 0;
00141                 if ( is_null( $resultPageSet ) ) {
00142                         foreach ( $res as $row ) {
00143                                 if ( ++$count > $params['limit'] ) {
00144                                         // We've reached the one extra which shows that
00145                                         // there are additional pages to be had. Stop here...
00146                                         $this->setContinueEnumParameter( 'continue', $row->cl_from . '|' . $row->cl_to );
00147                                         break;
00148                                 }
00149 
00150                                 $title = Title::makeTitle( NS_CATEGORY, $row->cl_to );
00151                                 $vals = array();
00152                                 ApiQueryBase::addTitleInfo( $vals, $title );
00153                                 if ( isset( $prop['sortkey'] ) ) {
00154                                         $vals['sortkey'] = bin2hex( $row->cl_sortkey );
00155                                         $vals['sortkeyprefix'] = $row->cl_sortkey_prefix;
00156                                 }
00157                                 if ( isset( $prop['timestamp'] ) ) {
00158                                         $vals['timestamp'] = wfTimestamp( TS_ISO_8601, $row->cl_timestamp );
00159                                 }
00160                                 if ( isset( $prop['hidden'] ) && !is_null( $row->pp_propname ) ) {
00161                                         $vals['hidden'] = '';
00162                                 }
00163 
00164                                 $fit = $this->addPageSubItem( $row->cl_from, $vals );
00165                                 if ( !$fit ) {
00166                                         $this->setContinueEnumParameter( 'continue', $row->cl_from . '|' . $row->cl_to );
00167                                         break;
00168                                 }
00169                         }
00170                 } else {
00171                         $titles = array();
00172                         foreach ( $res as $row ) {
00173                                 if ( ++$count > $params['limit'] ) {
00174                                         // We've reached the one extra which shows that
00175                                         // there are additional pages to be had. Stop here...
00176                                         $this->setContinueEnumParameter( 'continue', $row->cl_from . '|' . $row->cl_to );
00177                                         break;
00178                                 }
00179 
00180                                 $titles[] = Title :: makeTitle( NS_CATEGORY, $row->cl_to );
00181                         }
00182                         $resultPageSet->populateFromTitles( $titles );
00183                 }
00184         }
00185 
00186         public function getAllowedParams() {
00187                 return array(
00188                         'prop' => array(
00189                                 ApiBase::PARAM_ISMULTI => true,
00190                                 ApiBase::PARAM_TYPE => array (
00191                                         'sortkey',
00192                                         'timestamp',
00193                                         'hidden',
00194                                 )
00195                         ),
00196                         'show' => array(
00197                                 ApiBase::PARAM_ISMULTI => true,
00198                                 ApiBase::PARAM_TYPE => array(
00199                                         'hidden',
00200                                         '!hidden',
00201                                 )
00202                         ),
00203                         'limit' => array(
00204                                 ApiBase::PARAM_DFLT => 10,
00205                                 ApiBase::PARAM_TYPE => 'limit',
00206                                 ApiBase::PARAM_MIN => 1,
00207                                 ApiBase::PARAM_MAX => ApiBase::LIMIT_BIG1,
00208                                 ApiBase::PARAM_MAX2 => ApiBase::LIMIT_BIG2
00209                         ),
00210                         'continue' => null,
00211                         'categories' => array(
00212                                 ApiBase::PARAM_ISMULTI => true,
00213                         ),
00214                         'dir' => array(
00215                                 ApiBase::PARAM_DFLT => 'ascending',
00216                                 ApiBase::PARAM_TYPE => array(
00217                                         'ascending',
00218                                         'descending'
00219                                 )
00220                         ),
00221                 );
00222         }
00223 
00224         public function getParamDescription() {
00225                 return array(
00226                         'prop' => array(
00227                                 'Which additional properties to get for each category',
00228                                 ' sortkey    - Adds the sortkey (hexadecimal string) and sortkey prefix (human-readable part) for the category',
00229                                 ' timestamp  - Adds timestamp of when the category was added',
00230                                 ' hidden     - Tags categories that are hidden with __HIDDENCAT__',
00231                         ),
00232                         'limit' => 'How many categories to return',
00233                         'show' => 'Which kind of categories to show',
00234                         'continue' => 'When more results are available, use this to continue',
00235                         'categories' => 'Only list these categories. Useful for checking whether a certain page is in a certain category',
00236                         'dir' => 'The direction in which to list',
00237                 );
00238         }
00239 
00240         public function getResultProperties() {
00241                 return array(
00242                         '' => array(
00243                                 'ns' => 'namespace',
00244                                 'title' => 'string'
00245                         ),
00246                         'sortkey' => array(
00247                                 'sortkey' => 'string',
00248                                 'sortkeyprefix' => 'string'
00249                         ),
00250                         'timestamp' => array(
00251                                 'timestamp' => 'timestamp'
00252                         ),
00253                         'hidden' => array(
00254                                 'hidden' => 'boolean'
00255                         )
00256                 );
00257         }
00258 
00259         public function getDescription() {
00260                 return 'List all categories the page(s) belong to';
00261         }
00262 
00263         public function getPossibleErrors() {
00264                 return array_merge( parent::getPossibleErrors(), array(
00265                         array( 'show' ),
00266                 ) );
00267         }
00268 
00269         public function getExamples() {
00270                 return array(
00271                         'api.php?action=query&prop=categories&titles=Albert%20Einstein' => 'Get a list of categories [[Albert Einstein]] belongs to',
00272                         'api.php?action=query&generator=categories&titles=Albert%20Einstein&prop=info' => 'Get information about all categories used in the [[Albert Einstein]]',
00273                 );
00274         }
00275 
00276         public function getHelpUrls() {
00277                 return 'https://www.mediawiki.org/wiki/API:Properties#categories_.2F_cl';
00278         }
00279 
00280         public function getVersion() {
00281                 return __CLASS__ . ': $Id$';
00282         }
00283 }