MediaWiki  REL1_20
ApiQueryAllImages.php
Go to the documentation of this file.
00001 <?php
00002 
00034 class ApiQueryAllImages extends ApiQueryGeneratorBase {
00035 
00036         protected $mRepo;
00037 
00038         public function __construct( $query, $moduleName ) {
00039                 parent::__construct( $query, $moduleName, 'ai' );
00040                 $this->mRepo = RepoGroup::singleton()->getLocalRepo();
00041         }
00042 
00050         protected function getDB() {
00051                 return $this->mRepo->getSlaveDB();
00052         }
00053 
00054         public function execute() {
00055                 $this->run();
00056         }
00057 
00058         public function getCacheMode( $params ) {
00059                 return 'public';
00060         }
00061 
00066         public function executeGenerator( $resultPageSet ) {
00067                 if ( $resultPageSet->isResolvingRedirects() ) {
00068                         $this->dieUsage( 'Use "gaifilterredir=nonredirects" option instead of "redirects" when using allimages as a generator', 'params' );
00069                 }
00070 
00071                 $this->run( $resultPageSet );
00072         }
00073 
00078         private function run( $resultPageSet = null ) {
00079                 $repo = $this->mRepo;
00080                 if ( !$repo instanceof LocalRepo ) {
00081                         $this->dieUsage( 'Local file repository does not support querying all images', 'unsupportedrepo' );
00082                 }
00083 
00084                 $prefix = $this->getModulePrefix();
00085 
00086                 $db = $this->getDB();
00087 
00088                 $params = $this->extractRequestParams();
00089 
00090                 // Table and return fields
00091                 $this->addTables( 'image' );
00092 
00093                 $prop = array_flip( $params['prop'] );
00094                 $this->addFields( LocalFile::selectFields() );
00095 
00096                 $dir = ( in_array( $params['dir'], array( 'descending', 'older' ) ) ? 'older' : 'newer' );
00097 
00098                 if ( $params['sort'] == 'name' ) {
00099                         // Check mutually exclusive params
00100                         $disallowed = array( 'start', 'end', 'user' );
00101                         foreach ( $disallowed as $pname ) {
00102                                 if ( isset( $params[$pname] ) ) {
00103                                         $this->dieUsage( "Parameter '{$prefix}{$pname}' can only be used with {$prefix}sort=timestamp", 'badparams' );
00104                                 }
00105                         }
00106                         if ( $params['filterbots'] != 'all' ) {
00107                                         $this->dieUsage( "Parameter '{$prefix}filterbots' can only be used with {$prefix}sort=timestamp", 'badparams' );
00108                         }
00109 
00110                         // Pagination
00111                         if ( !is_null( $params['continue'] ) ) {
00112                                 $cont = explode( '|', $params['continue'] );
00113                                 if ( count( $cont ) != 1 ) {
00114                                         $this->dieUsage( 'Invalid continue param. You should pass the ' .
00115                                                 'original value returned by the previous query', '_badcontinue' );
00116                                 }
00117                                 $op = ( $dir == 'older' ? '<' : '>' );
00118                                 $cont_from = $db->addQuotes( $cont[0] );
00119                                 $this->addWhere( "img_name $op= $cont_from" );
00120                         }
00121 
00122                         // Image filters
00123                         $from = ( is_null( $params['from'] ) ? null : $this->titlePartToKey( $params['from'] ) );
00124                         $to = ( is_null( $params['to'] ) ? null : $this->titlePartToKey( $params['to'] ) );
00125                         $this->addWhereRange( 'img_name', $dir, $from, $to );
00126 
00127                         if ( isset( $params['prefix'] ) ) {
00128                                 $this->addWhere( 'img_name' . $db->buildLike( $this->titlePartToKey( $params['prefix'] ), $db->anyString() ) );
00129                         }
00130                 } else {
00131                         // Check mutually exclusive params
00132                         $disallowed = array( 'from', 'to', 'prefix' );
00133                         foreach ( $disallowed as $pname ) {
00134                                 if ( isset( $params[$pname] ) ) {
00135                                         $this->dieUsage( "Parameter '{$prefix}{$pname}' can only be used with {$prefix}sort=name", 'badparams' );
00136                                 }
00137                         }
00138                         if (!is_null( $params['user'] ) && $params['filterbots'] != 'all') {
00139                                 // Since filterbots checks if each user has the bot right, it doesn't make sense to use it with user
00140                                 $this->dieUsage( "Parameters 'user' and 'filterbots' cannot be used together", 'badparams' );
00141                         }
00142 
00143                         // Pagination
00144                         $this->addTimestampWhereRange( 'img_timestamp', $dir, $params['start'], $params['end'] );
00145 
00146                         // Image filters
00147                         if ( !is_null( $params['user'] ) ) {
00148                                 $this->addWhereFld( 'img_user_text', $params['user'] );
00149                         }
00150                         if ( $params['filterbots'] != 'all' ) {
00151                                 $this->addTables( 'user_groups' );
00152                                 $groupCond = ( $params['filterbots'] == 'nobots' ? 'NULL': 'NOT NULL' );
00153                                 $this->addWhere( "ug_group IS $groupCond" );
00154                                 $this->addJoinConds( array( 'user_groups' => array(
00155                                         'LEFT JOIN',
00156                                         array(
00157                                                 'ug_group' => User::getGroupsWithPermission( 'bot' ),
00158                                                 'ug_user = img_user'
00159                                         )
00160                                 ) ) );
00161                         }
00162                 }
00163 
00164                 // Filters not depending on sort
00165                 if ( isset( $params['minsize'] ) ) {
00166                         $this->addWhere( 'img_size>=' . intval( $params['minsize'] ) );
00167                 }
00168 
00169                 if ( isset( $params['maxsize'] ) ) {
00170                         $this->addWhere( 'img_size<=' . intval( $params['maxsize'] ) );
00171                 }
00172 
00173                 $sha1 = false;
00174                 if ( isset( $params['sha1'] ) ) {
00175                         if ( !$this->validateSha1Hash( $params['sha1'] ) ) {
00176                                 $this->dieUsage( 'The SHA1 hash provided is not valid', 'invalidsha1hash' );
00177                         }
00178                         $sha1 = wfBaseConvert( $params['sha1'], 16, 36, 31 );
00179                 } elseif ( isset( $params['sha1base36'] ) ) {
00180                         $sha1 = $params['sha1base36'];
00181                         if ( !$this->validateSha1Base36Hash( $sha1 ) ) {
00182                                 $this->dieUsage( 'The SHA1Base36 hash provided is not valid', 'invalidsha1base36hash' );
00183                         }
00184                 }
00185                 if ( $sha1 ) {
00186                         $this->addWhereFld( 'img_sha1', $sha1 );
00187                 }
00188 
00189                 if ( !is_null( $params['mime'] ) ) {
00190                         global $wgMiserMode;
00191                         if ( $wgMiserMode  ) {
00192                                 $this->dieUsage( 'MIME search disabled in Miser Mode', 'mimesearchdisabled' );
00193                         }
00194 
00195                         list( $major, $minor ) = File::splitMime( $params['mime'] );
00196 
00197                         $this->addWhereFld( 'img_major_mime', $major );
00198                         $this->addWhereFld( 'img_minor_mime', $minor );
00199                 }
00200 
00201                 $limit = $params['limit'];
00202                 $this->addOption( 'LIMIT', $limit + 1 );
00203                 $sort = ( $dir == 'older' ? ' DESC' : '' );
00204                 if ( $params['sort'] == 'timestamp' ) {
00205                         $this->addOption( 'ORDER BY', 'img_timestamp' . $sort );
00206                         if ( $params['filterbots'] == 'all' ) {
00207                                 $this->addOption( 'USE INDEX', array( 'image' => 'img_timestamp' ) );
00208                         } else {
00209                                 $this->addOption( 'USE INDEX', array( 'image' => 'img_usertext_timestamp' ) );
00210                         }
00211                 } else {
00212                         $this->addOption( 'ORDER BY', 'img_name' . $sort );
00213                 }
00214 
00215                 $res = $this->select( __METHOD__ );
00216 
00217                 $titles = array();
00218                 $count = 0;
00219                 $result = $this->getResult();
00220                 foreach ( $res as $row ) {
00221                         if ( ++ $count > $limit ) {
00222                                 // We've reached the one extra which shows that there are additional pages to be had. Stop here...
00223                                 if ( $params['sort'] == 'name' ) {
00224                                         $this->setContinueEnumParameter( 'continue', $row->img_name );
00225                                 } else {
00226                                         $this->setContinueEnumParameter( 'start', wfTimestamp( TS_ISO_8601, $row->img_timestamp ) );
00227                                 }
00228                                 break;
00229                         }
00230 
00231                         if ( is_null( $resultPageSet ) ) {
00232                                 $file = $repo->newFileFromRow( $row );
00233                                 $info = array_merge( array( 'name' => $row->img_name ),
00234                                         ApiQueryImageInfo::getInfo( $file, $prop, $result ) );
00235                                 self::addTitleInfo( $info, $file->getTitle() );
00236 
00237                                 $fit = $result->addValue( array( 'query', $this->getModuleName() ), null, $info );
00238                                 if ( !$fit ) {
00239                                         if ( $params['sort'] == 'name' ) {
00240                                                 $this->setContinueEnumParameter( 'continue', $row->img_name );
00241                                         } else {
00242                                                 $this->setContinueEnumParameter( 'start', wfTimestamp( TS_ISO_8601, $row->img_timestamp ) );
00243                                         }
00244                                         break;
00245                                 }
00246                         } else {
00247                                 $titles[] = Title::makeTitle( NS_FILE, $row->img_name );
00248                         }
00249                 }
00250 
00251                 if ( is_null( $resultPageSet ) ) {
00252                         $result->setIndexedTagName_internal( array( 'query', $this->getModuleName() ), 'img' );
00253                 } else {
00254                         $resultPageSet->populateFromTitles( $titles );
00255                 }
00256         }
00257 
00258         public function getAllowedParams() {
00259                 return array (
00260                         'sort' => array(
00261                                 ApiBase::PARAM_DFLT => 'name',
00262                                 ApiBase::PARAM_TYPE => array(
00263                                         'name',
00264                                         'timestamp'
00265                                 )
00266                         ),
00267                         'dir' => array(
00268                                 ApiBase::PARAM_DFLT => 'ascending',
00269                                 ApiBase::PARAM_TYPE => array(
00270                                         // sort=name
00271                                         'ascending',
00272                                         'descending',
00273                                         // sort=timestamp
00274                                         'newer',
00275                                         'older',
00276                                 )
00277                         ),
00278                         'from' => null,
00279                         'to' => null,
00280                         'continue' => null,
00281                         'start' => array(
00282                                 ApiBase::PARAM_TYPE => 'timestamp'
00283                         ),
00284                         'end' => array(
00285                                 ApiBase::PARAM_TYPE => 'timestamp'
00286                         ),
00287                         'prop' => array(
00288                                 ApiBase::PARAM_TYPE => ApiQueryImageInfo::getPropertyNames( $this->propertyFilter ),
00289                                 ApiBase::PARAM_DFLT => 'timestamp|url',
00290                                 ApiBase::PARAM_ISMULTI => true
00291                         ),
00292                         'prefix' => null,
00293                         'minsize' => array(
00294                                 ApiBase::PARAM_TYPE => 'integer',
00295                         ),
00296                         'maxsize' => array(
00297                                 ApiBase::PARAM_TYPE => 'integer',
00298                         ),
00299                         'sha1' => null,
00300                         'sha1base36' => null,
00301                         'user' => array(
00302                                 ApiBase::PARAM_TYPE => 'user'
00303                         ),
00304                         'filterbots' => array(
00305                                 ApiBase::PARAM_DFLT => 'all',
00306                                 ApiBase::PARAM_TYPE => array(
00307                                         'all',
00308                                         'bots',
00309                                         'nobots'
00310                                 )
00311                         ),
00312                         'mime' => null,
00313                         'limit' => array(
00314                                 ApiBase::PARAM_DFLT => 10,
00315                                 ApiBase::PARAM_TYPE => 'limit',
00316                                 ApiBase::PARAM_MIN => 1,
00317                                 ApiBase::PARAM_MAX => ApiBase::LIMIT_BIG1,
00318                                 ApiBase::PARAM_MAX2 => ApiBase::LIMIT_BIG2
00319                         ),
00320                 );
00321         }
00322 
00323         public function getParamDescription() {
00324                 $p = $this->getModulePrefix();
00325                 return array(
00326                         'sort' => 'Property to sort by',
00327                         'dir' => 'The direction in which to list',
00328                         'from' => "The image title to start enumerating from. Can only be used with {$p}sort=name",
00329                         'to' => "The image title to stop enumerating at. Can only be used with {$p}sort=name",
00330                         'continue' => 'When more results are available, use this to continue',
00331                         'start' => "The timestamp to start enumerating from. Can only be used with {$p}sort=timestamp",
00332                         'end' => "The timestamp to end enumerating. Can only be used with {$p}sort=timestamp",
00333                         'prop' => ApiQueryImageInfo::getPropertyDescriptions( $this->propertyFilter ),
00334                         'prefix' => "Search for all image titles that begin with this value. Can only be used with {$p}sort=name",
00335                         'minsize' => 'Limit to images with at least this many bytes',
00336                         'maxsize' => 'Limit to images with at most this many bytes',
00337                         'sha1' => "SHA1 hash of image. Overrides {$p}sha1base36",
00338                         'sha1base36' => 'SHA1 hash of image in base 36 (used in MediaWiki)',
00339                         'user' => "Only return files uploaded by this user. Can only be used with {$p}sort=timestamp. Cannot be used together with {$p}filterbots",
00340                         'filterbots' => "How to filter files uploaded by bots. Can only be used with {$p}sort=timestamp. Cannot be used together with {$p}user",
00341                         'mime' => 'What MIME type to search for. e.g. image/jpeg. Disabled in Miser Mode',
00342                         'limit' => 'How many images in total to return',
00343                 );
00344         }
00345 
00346         private $propertyFilter = array( 'archivename', 'thumbmime' );
00347 
00348         public function getResultProperties() {
00349                 return array_merge(
00350                         array(
00351                                 '' => array(
00352                                         'name' => 'string',
00353                                         'ns' => 'namespace',
00354                                         'title' => 'string'
00355                                 )
00356                         ),
00357                         ApiQueryImageInfo::getResultPropertiesFiltered( $this->propertyFilter )
00358                 );
00359         }
00360 
00361         public function getDescription() {
00362                 return 'Enumerate all images sequentially';
00363         }
00364 
00365         public function getPossibleErrors() {
00366                 $p = $this->getModulePrefix();
00367                 return array_merge( parent::getPossibleErrors(), array(
00368                         array( 'code' => 'params', 'info' => 'Use "gaifilterredir=nonredirects" option instead of "redirects" when using allimages as a generator' ),
00369                         array( 'code' => 'badparams', 'info' => "Parameter'{$p}start' can only be used with {$p}sort=timestamp" ),
00370                         array( 'code' => 'badparams', 'info' => "Parameter'{$p}end' can only be used with {$p}sort=timestamp" ),
00371                         array( 'code' => 'badparams', 'info' => "Parameter'{$p}user' can only be used with {$p}sort=timestamp" ),
00372                         array( 'code' => 'badparams', 'info' => "Parameter'{$p}filterbots' can only be used with {$p}sort=timestamp" ),
00373                         array( 'code' => 'badparams', 'info' => "Parameter'{$p}from' can only be used with {$p}sort=name" ),
00374                         array( 'code' => 'badparams', 'info' => "Parameter'{$p}to' can only be used with {$p}sort=name" ),
00375                         array( 'code' => 'badparams', 'info' => "Parameter'{$p}prefix' can only be used with {$p}sort=name" ),
00376                         array( 'code' => 'badparams', 'info' => "Parameters 'user' and 'filterbots' cannot be used together" ),
00377                         array( 'code' => 'unsupportedrepo', 'info' => 'Local file repository does not support querying all images' ),
00378                         array( 'code' => 'mimesearchdisabled', 'info' => 'MIME search disabled in Miser Mode' ),
00379                         array( 'code' => 'invalidsha1hash', 'info' => 'The SHA1 hash provided is not valid' ),
00380                         array( 'code' => 'invalidsha1base36hash', 'info' => 'The SHA1Base36 hash provided is not valid' ),
00381                         array( 'code' => '_badcontinue', 'info' => 'Invalid continue param. You should pass the original value returned by the previous query' ),
00382                 ) );
00383         }
00384 
00385         public function getExamples() {
00386                 return array(
00387                         'api.php?action=query&list=allimages&aifrom=B' => array(
00388                                 'Simple Use',
00389                                 'Show a list of files starting at the letter "B"',
00390                         ),
00391                         'api.php?action=query&list=allimages&aiprop=user|timestamp|url&aisort=timestamp&aidir=older' => array(
00392                                 'Simple Use',
00393                                 'Show a list of recently uploaded files similar to Special:NewFiles',
00394                         ),
00395                         'api.php?action=query&generator=allimages&gailimit=4&gaifrom=T&prop=imageinfo' => array(
00396                                 'Using as Generator',
00397                                 'Show info about 4 files starting at the letter "T"',
00398                         ),
00399                 );
00400         }
00401 
00402         public function getHelpUrls() {
00403                 return 'https://www.mediawiki.org/wiki/API:Allimages';
00404         }
00405 
00406         public function getVersion() {
00407                 return __CLASS__ . ': $Id$';
00408         }
00409 }