[ Index ]

PHP Cross Reference of MediaWiki-1.24.0

title

Body

[close]

/includes/api/ -> ApiQueryAllImages.php (source)

   1  <?php
   2  
   3  /**
   4   * API for MediaWiki 1.12+
   5   *
   6   * Created on Mar 16, 2008
   7   *
   8   * Copyright © 2008 Vasiliev Victor [email protected],
   9   * based on ApiQueryAllPages.php
  10   *
  11   * This program is free software; you can redistribute it and/or modify
  12   * it under the terms of the GNU General Public License as published by
  13   * the Free Software Foundation; either version 2 of the License, or
  14   * (at your option) any later version.
  15   *
  16   * This program is distributed in the hope that it will be useful,
  17   * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  19   * GNU General Public License for more details.
  20   *
  21   * You should have received a copy of the GNU General Public License along
  22   * with this program; if not, write to the Free Software Foundation, Inc.,
  23   * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  24   * http://www.gnu.org/copyleft/gpl.html
  25   *
  26   * @file
  27   */
  28  
  29  /**
  30   * Query module to enumerate all available pages.
  31   *
  32   * @ingroup API
  33   */
  34  class ApiQueryAllImages extends ApiQueryGeneratorBase {
  35      protected $mRepo;
  36  
  37  	public function __construct( ApiQuery $query, $moduleName ) {
  38          parent::__construct( $query, $moduleName, 'ai' );
  39          $this->mRepo = RepoGroup::singleton()->getLocalRepo();
  40      }
  41  
  42      /**
  43       * Override parent method to make sure the repo's DB is used
  44       * which may not necessarily be the same as the local DB.
  45       *
  46       * TODO: allow querying non-local repos.
  47       * @return DatabaseBase
  48       */
  49  	protected function getDB() {
  50          return $this->mRepo->getSlaveDB();
  51      }
  52  
  53  	public function execute() {
  54          $this->run();
  55      }
  56  
  57  	public function getCacheMode( $params ) {
  58          return 'public';
  59      }
  60  
  61      /**
  62       * @param ApiPageSet $resultPageSet
  63       * @return void
  64       */
  65  	public function executeGenerator( $resultPageSet ) {
  66          if ( $resultPageSet->isResolvingRedirects() ) {
  67              $this->dieUsage(
  68                  'Use "gaifilterredir=nonredirects" option instead of "redirects" ' .
  69                      'when using allimages as a generator',
  70                  'params'
  71              );
  72          }
  73  
  74          $this->run( $resultPageSet );
  75      }
  76  
  77      /**
  78       * @param ApiPageSet $resultPageSet
  79       * @return void
  80       */
  81  	private function run( $resultPageSet = null ) {
  82          $repo = $this->mRepo;
  83          if ( !$repo instanceof LocalRepo ) {
  84              $this->dieUsage(
  85                  'Local file repository does not support querying all images',
  86                  'unsupportedrepo'
  87              );
  88          }
  89  
  90          $prefix = $this->getModulePrefix();
  91  
  92          $db = $this->getDB();
  93  
  94          $params = $this->extractRequestParams();
  95  
  96          // Table and return fields
  97          $this->addTables( 'image' );
  98  
  99          $prop = array_flip( $params['prop'] );
 100          $this->addFields( LocalFile::selectFields() );
 101  
 102          $ascendingOrder = true;
 103          if ( $params['dir'] == 'descending' || $params['dir'] == 'older' ) {
 104              $ascendingOrder = false;
 105          }
 106  
 107          if ( $params['sort'] == 'name' ) {
 108              // Check mutually exclusive params
 109              $disallowed = array( 'start', 'end', 'user' );
 110              foreach ( $disallowed as $pname ) {
 111                  if ( isset( $params[$pname] ) ) {
 112                      $this->dieUsage(
 113                          "Parameter '{$prefix}{$pname}' can only be used with {$prefix}sort=timestamp",
 114                          'badparams'
 115                      );
 116                  }
 117              }
 118              if ( $params['filterbots'] != 'all' ) {
 119                  $this->dieUsage(
 120                      "Parameter '{$prefix}filterbots' can only be used with {$prefix}sort=timestamp",
 121                      'badparams'
 122                  );
 123              }
 124  
 125              // Pagination
 126              if ( !is_null( $params['continue'] ) ) {
 127                  $cont = explode( '|', $params['continue'] );
 128                  $this->dieContinueUsageIf( count( $cont ) != 1 );
 129                  $op = ( $ascendingOrder ? '>' : '<' );
 130                  $continueFrom = $db->addQuotes( $cont[0] );
 131                  $this->addWhere( "img_name $op= $continueFrom" );
 132              }
 133  
 134              // Image filters
 135              $from = ( $params['from'] === null ? null : $this->titlePartToKey( $params['from'], NS_FILE ) );
 136              $to = ( $params['to'] === null ? null : $this->titlePartToKey( $params['to'], NS_FILE ) );
 137              $this->addWhereRange( 'img_name', ( $ascendingOrder ? 'newer' : 'older' ), $from, $to );
 138  
 139              if ( isset( $params['prefix'] ) ) {
 140                  $this->addWhere( 'img_name' . $db->buildLike(
 141                      $this->titlePartToKey( $params['prefix'], NS_FILE ),
 142                      $db->anyString() ) );
 143              }
 144          } else {
 145              // Check mutually exclusive params
 146              $disallowed = array( 'from', 'to', 'prefix' );
 147              foreach ( $disallowed as $pname ) {
 148                  if ( isset( $params[$pname] ) ) {
 149                      $this->dieUsage(
 150                          "Parameter '{$prefix}{$pname}' can only be used with {$prefix}sort=name",
 151                          'badparams'
 152                      );
 153                  }
 154              }
 155              if ( !is_null( $params['user'] ) && $params['filterbots'] != 'all' ) {
 156                  // Since filterbots checks if each user has the bot right, it
 157                  // doesn't make sense to use it with user
 158                  $this->dieUsage(
 159                      "Parameters '{$prefix}user' and '{$prefix}filterbots' cannot be used together",
 160                      'badparams'
 161                  );
 162              }
 163  
 164              // Pagination
 165              $this->addTimestampWhereRange(
 166                  'img_timestamp',
 167                  $ascendingOrder ? 'newer' : 'older',
 168                  $params['start'],
 169                  $params['end']
 170              );
 171              // Include in ORDER BY for uniqueness
 172              $this->addWhereRange( 'img_name', $ascendingOrder ? 'newer' : 'older', null, null );
 173  
 174              if ( !is_null( $params['continue'] ) ) {
 175                  $cont = explode( '|', $params['continue'] );
 176                  $this->dieContinueUsageIf( count( $cont ) != 2 );
 177                  $op = ( $ascendingOrder ? '>' : '<' );
 178                  $continueTimestamp = $db->addQuotes( $db->timestamp( $cont[0] ) );
 179                  $continueName = $db->addQuotes( $cont[1] );
 180                  $this->addWhere( "img_timestamp $op $continueTimestamp OR " .
 181                      "(img_timestamp = $continueTimestamp AND " .
 182                      "img_name $op= $continueName)"
 183                  );
 184              }
 185  
 186              // Image filters
 187              if ( !is_null( $params['user'] ) ) {
 188                  $this->addWhereFld( 'img_user_text', $params['user'] );
 189              }
 190              if ( $params['filterbots'] != 'all' ) {
 191                  $this->addTables( 'user_groups' );
 192                  $this->addJoinConds( array( 'user_groups' => array(
 193                      'LEFT JOIN',
 194                      array(
 195                          'ug_group' => User::getGroupsWithPermission( 'bot' ),
 196                          'ug_user = img_user'
 197                      )
 198                  ) ) );
 199                  $groupCond = ( $params['filterbots'] == 'nobots' ? 'NULL' : 'NOT NULL' );
 200                  $this->addWhere( "ug_group IS $groupCond" );
 201              }
 202          }
 203  
 204          // Filters not depending on sort
 205          if ( isset( $params['minsize'] ) ) {
 206              $this->addWhere( 'img_size>=' . intval( $params['minsize'] ) );
 207          }
 208  
 209          if ( isset( $params['maxsize'] ) ) {
 210              $this->addWhere( 'img_size<=' . intval( $params['maxsize'] ) );
 211          }
 212  
 213          $sha1 = false;
 214          if ( isset( $params['sha1'] ) ) {
 215              $sha1 = strtolower( $params['sha1'] );
 216              if ( !$this->validateSha1Hash( $sha1 ) ) {
 217                  $this->dieUsage( 'The SHA1 hash provided is not valid', 'invalidsha1hash' );
 218              }
 219              $sha1 = wfBaseConvert( $sha1, 16, 36, 31 );
 220          } elseif ( isset( $params['sha1base36'] ) ) {
 221              $sha1 = strtolower( $params['sha1base36'] );
 222              if ( !$this->validateSha1Base36Hash( $sha1 ) ) {
 223                  $this->dieUsage( 'The SHA1Base36 hash provided is not valid', 'invalidsha1base36hash' );
 224              }
 225          }
 226          if ( $sha1 ) {
 227              $this->addWhereFld( 'img_sha1', $sha1 );
 228          }
 229  
 230          if ( !is_null( $params['mime'] ) ) {
 231              if ( $this->getConfig()->get( 'MiserMode' ) ) {
 232                  $this->dieUsage( 'MIME search disabled in Miser Mode', 'mimesearchdisabled' );
 233              }
 234  
 235              list( $major, $minor ) = File::splitMime( $params['mime'] );
 236  
 237              $this->addWhereFld( 'img_major_mime', $major );
 238              $this->addWhereFld( 'img_minor_mime', $minor );
 239          }
 240  
 241          $limit = $params['limit'];
 242          $this->addOption( 'LIMIT', $limit + 1 );
 243          $sortFlag = '';
 244          if ( !$ascendingOrder ) {
 245              $sortFlag = ' DESC';
 246          }
 247          if ( $params['sort'] == 'timestamp' ) {
 248              $this->addOption( 'ORDER BY', 'img_timestamp' . $sortFlag );
 249              if ( !is_null( $params['user'] ) ) {
 250                  $this->addOption( 'USE INDEX', array( 'image' => 'img_usertext_timestamp' ) );
 251              } else {
 252                  $this->addOption( 'USE INDEX', array( 'image' => 'img_timestamp' ) );
 253              }
 254          } else {
 255              $this->addOption( 'ORDER BY', 'img_name' . $sortFlag );
 256          }
 257  
 258          $res = $this->select( __METHOD__ );
 259  
 260          $titles = array();
 261          $count = 0;
 262          $result = $this->getResult();
 263          foreach ( $res as $row ) {
 264              if ( ++$count > $limit ) {
 265                  // We've reached the one extra which shows that there are
 266                  // additional pages to be had. Stop here...
 267                  if ( $params['sort'] == 'name' ) {
 268                      $this->setContinueEnumParameter( 'continue', $row->img_name );
 269                  } else {
 270                      $this->setContinueEnumParameter( 'continue', "$row->img_timestamp|$row->img_name" );
 271                  }
 272                  break;
 273              }
 274  
 275              if ( is_null( $resultPageSet ) ) {
 276                  $file = $repo->newFileFromRow( $row );
 277                  $info = array_merge( array( 'name' => $row->img_name ),
 278                      ApiQueryImageInfo::getInfo( $file, $prop, $result ) );
 279                  self::addTitleInfo( $info, $file->getTitle() );
 280  
 281                  $fit = $result->addValue( array( 'query', $this->getModuleName() ), null, $info );
 282                  if ( !$fit ) {
 283                      if ( $params['sort'] == 'name' ) {
 284                          $this->setContinueEnumParameter( 'continue', $row->img_name );
 285                      } else {
 286                          $this->setContinueEnumParameter( 'continue', "$row->img_timestamp|$row->img_name" );
 287                      }
 288                      break;
 289                  }
 290              } else {
 291                  $titles[] = Title::makeTitle( NS_FILE, $row->img_name );
 292              }
 293          }
 294  
 295          if ( is_null( $resultPageSet ) ) {
 296              $result->setIndexedTagName_internal( array( 'query', $this->getModuleName() ), 'img' );
 297          } else {
 298              $resultPageSet->populateFromTitles( $titles );
 299          }
 300      }
 301  
 302  	public function getAllowedParams() {
 303          return array(
 304              'sort' => array(
 305                  ApiBase::PARAM_DFLT => 'name',
 306                  ApiBase::PARAM_TYPE => array(
 307                      'name',
 308                      'timestamp'
 309                  )
 310              ),
 311              'dir' => array(
 312                  ApiBase::PARAM_DFLT => 'ascending',
 313                  ApiBase::PARAM_TYPE => array(
 314                      // sort=name
 315                      'ascending',
 316                      'descending',
 317                      // sort=timestamp
 318                      'newer',
 319                      'older'
 320                  )
 321              ),
 322              'from' => null,
 323              'to' => null,
 324              'continue' => null,
 325              'start' => array(
 326                  ApiBase::PARAM_TYPE => 'timestamp'
 327              ),
 328              'end' => array(
 329                  ApiBase::PARAM_TYPE => 'timestamp'
 330              ),
 331              'prop' => array(
 332                  ApiBase::PARAM_TYPE => ApiQueryImageInfo::getPropertyNames( $this->propertyFilter ),
 333                  ApiBase::PARAM_DFLT => 'timestamp|url',
 334                  ApiBase::PARAM_ISMULTI => true
 335              ),
 336              'prefix' => null,
 337              'minsize' => array(
 338                  ApiBase::PARAM_TYPE => 'integer',
 339              ),
 340              'maxsize' => array(
 341                  ApiBase::PARAM_TYPE => 'integer',
 342              ),
 343              'sha1' => null,
 344              'sha1base36' => null,
 345              'user' => array(
 346                  ApiBase::PARAM_TYPE => 'user'
 347              ),
 348              'filterbots' => array(
 349                  ApiBase::PARAM_DFLT => 'all',
 350                  ApiBase::PARAM_TYPE => array(
 351                      'all',
 352                      'bots',
 353                      'nobots'
 354                  )
 355              ),
 356              'mime' => null,
 357              'limit' => array(
 358                  ApiBase::PARAM_DFLT => 10,
 359                  ApiBase::PARAM_TYPE => 'limit',
 360                  ApiBase::PARAM_MIN => 1,
 361                  ApiBase::PARAM_MAX => ApiBase::LIMIT_BIG1,
 362                  ApiBase::PARAM_MAX2 => ApiBase::LIMIT_BIG2
 363              ),
 364          );
 365      }
 366  
 367  	public function getParamDescription() {
 368          $p = $this->getModulePrefix();
 369  
 370          return array(
 371              'sort' => 'Property to sort by',
 372              'dir' => 'The direction in which to list',
 373              'from' => "The image title to start enumerating from. Can only be used with {$p}sort=name",
 374              'to' => "The image title to stop enumerating at. Can only be used with {$p}sort=name",
 375              'continue' => 'When more results are available, use this to continue',
 376              'start' => "The timestamp to start enumerating from. Can only be used with {$p}sort=timestamp",
 377              'end' => "The timestamp to end enumerating. Can only be used with {$p}sort=timestamp",
 378              'prop' => ApiQueryImageInfo::getPropertyDescriptions( $this->propertyFilter ),
 379              'prefix' => "Search for all image titles that begin with this " .
 380                  "value. Can only be used with {$p}sort=name",
 381              'minsize' => 'Limit to images with at least this many bytes',
 382              'maxsize' => 'Limit to images with at most this many bytes',
 383              'sha1' => "SHA1 hash of image. Overrides {$p}sha1base36",
 384              'sha1base36' => 'SHA1 hash of image in base 36 (used in MediaWiki)',
 385              'user' => "Only return files uploaded by this user. Can only be used " .
 386                  "with {$p}sort=timestamp. Cannot be used together with {$p}filterbots",
 387              'filterbots' => "How to filter files uploaded by bots. Can only be " .
 388                  "used with {$p}sort=timestamp. Cannot be used together with {$p}user",
 389              'mime' => 'What MIME type to search for. e.g. image/jpeg. Disabled in Miser Mode',
 390              'limit' => 'How many images in total to return',
 391          );
 392      }
 393  
 394      private $propertyFilter = array( 'archivename', 'thumbmime', 'uploadwarning' );
 395  
 396  	public function getDescription() {
 397          return 'Enumerate all images sequentially.';
 398      }
 399  
 400  	public function getExamples() {
 401          return array(
 402              'api.php?action=query&list=allimages&aifrom=B' => array(
 403                  'Simple Use',
 404                  'Show a list of files starting at the letter "B"',
 405              ),
 406              'api.php?action=query&list=allimages&aiprop=user|timestamp|url&' .
 407                  'aisort=timestamp&aidir=older' => array(
 408                  'Simple Use',
 409                  'Show a list of recently uploaded files similar to Special:NewFiles',
 410              ),
 411              'api.php?action=query&generator=allimages&gailimit=4&' .
 412                  'gaifrom=T&prop=imageinfo' => array(
 413                  'Using as Generator',
 414                  'Show info about 4 files starting at the letter "T"',
 415              ),
 416          );
 417      }
 418  
 419  	public function getHelpUrls() {
 420          return 'https://www.mediawiki.org/wiki/API:Allimages';
 421      }
 422  }


Generated: Fri Nov 28 14:03:12 2014 Cross-referenced by PHPXref 0.7.1