MediaWiki  master
ApiQueryFilearchive.php
Go to the documentation of this file.
1 <?php
28 
35 
36  public function __construct( ApiQuery $query, $moduleName ) {
37  parent::__construct( $query, $moduleName, 'fa' );
38  }
39 
40  public function execute() {
41  $user = $this->getUser();
42  $db = $this->getDB();
43  $commentStore = CommentStore::getStore();
44 
45  $params = $this->extractRequestParams();
46 
47  $prop = array_flip( $params['prop'] );
48  $fld_sha1 = isset( $prop['sha1'] );
49  $fld_timestamp = isset( $prop['timestamp'] );
50  $fld_user = isset( $prop['user'] );
51  $fld_size = isset( $prop['size'] );
52  $fld_dimensions = isset( $prop['dimensions'] );
53  $fld_description = isset( $prop['description'] ) || isset( $prop['parseddescription'] );
54  $fld_mime = isset( $prop['mime'] );
55  $fld_mediatype = isset( $prop['mediatype'] );
56  $fld_metadata = isset( $prop['metadata'] );
57  $fld_bitdepth = isset( $prop['bitdepth'] );
58  $fld_archivename = isset( $prop['archivename'] );
59 
60  if ( $fld_description &&
61  !$this->getPermissionManager()->userHasRight( $user, 'deletedhistory' )
62  ) {
63  $this->dieWithError( 'apierror-cantview-deleted-description', 'permissiondenied' );
64  }
65  if ( $fld_metadata &&
66  !$this->getPermissionManager()->userHasAnyRight( $user, 'deletedtext', 'undelete' )
67  ) {
68  $this->dieWithError( 'apierror-cantview-deleted-metadata', 'permissiondenied' );
69  }
70 
71  $fileQuery = ArchivedFile::getQueryInfo();
72  $this->addTables( $fileQuery['tables'] );
73  $this->addFields( $fileQuery['fields'] );
74  $this->addJoinConds( $fileQuery['joins'] );
75 
76  if ( !is_null( $params['continue'] ) ) {
77  $cont = explode( '|', $params['continue'] );
78  $this->dieContinueUsageIf( count( $cont ) != 3 );
79  $op = $params['dir'] == 'descending' ? '<' : '>';
80  $cont_from = $db->addQuotes( $cont[0] );
81  $cont_timestamp = $db->addQuotes( $db->timestamp( $cont[1] ) );
82  $cont_id = (int)$cont[2];
83  $this->dieContinueUsageIf( $cont[2] !== (string)$cont_id );
84  $this->addWhere( "fa_name $op $cont_from OR " .
85  "(fa_name = $cont_from AND " .
86  "(fa_timestamp $op $cont_timestamp OR " .
87  "(fa_timestamp = $cont_timestamp AND " .
88  "fa_id $op= $cont_id )))"
89  );
90  }
91 
92  // Image filters
93  $dir = ( $params['dir'] == 'descending' ? 'older' : 'newer' );
94  $from = ( $params['from'] === null ? null : $this->titlePartToKey( $params['from'], NS_FILE ) );
95  $to = ( $params['to'] === null ? null : $this->titlePartToKey( $params['to'], NS_FILE ) );
96  $this->addWhereRange( 'fa_name', $dir, $from, $to );
97  if ( isset( $params['prefix'] ) ) {
98  $this->addWhere( 'fa_name' . $db->buildLike(
99  $this->titlePartToKey( $params['prefix'], NS_FILE ),
100  $db->anyString() ) );
101  }
102 
103  $sha1Set = isset( $params['sha1'] );
104  $sha1base36Set = isset( $params['sha1base36'] );
105  if ( $sha1Set || $sha1base36Set ) {
106  $sha1 = false;
107  if ( $sha1Set ) {
108  $sha1 = strtolower( $params['sha1'] );
109  if ( !$this->validateSha1Hash( $sha1 ) ) {
110  $this->dieWithError( 'apierror-invalidsha1hash' );
111  }
112  $sha1 = Wikimedia\base_convert( $sha1, 16, 36, 31 );
113  } elseif ( $sha1base36Set ) {
114  $sha1 = strtolower( $params['sha1base36'] );
115  if ( !$this->validateSha1Base36Hash( $sha1 ) ) {
116  $this->dieWithError( 'apierror-invalidsha1base36hash' );
117  }
118  }
119  if ( $sha1 ) {
120  $this->addWhereFld( 'fa_sha1', $sha1 );
121  // Paranoia: avoid brute force searches (T19342)
122  if ( !$this->getPermissionManager()->userHasRight( $user, 'deletedtext' ) ) {
123  $bitmask = File::DELETED_FILE;
124  } elseif ( !$this->getPermissionManager()
125  ->userHasAnyRight( $user, 'suppressrevision', 'viewsuppressed' )
126  ) {
128  } else {
129  $bitmask = 0;
130  }
131  if ( $bitmask ) {
132  $this->addWhere( $this->getDB()->bitAnd( 'fa_deleted', $bitmask ) . " != $bitmask" );
133  }
134  }
135  }
136 
137  $limit = $params['limit'];
138  $this->addOption( 'LIMIT', $limit + 1 );
139  $sort = ( $params['dir'] == 'descending' ? ' DESC' : '' );
140  $this->addOption( 'ORDER BY', [
141  'fa_name' . $sort,
142  'fa_timestamp' . $sort,
143  'fa_id' . $sort,
144  ] );
145 
146  $res = $this->select( __METHOD__ );
147 
148  $count = 0;
149  $result = $this->getResult();
150  foreach ( $res as $row ) {
151  if ( ++$count > $limit ) {
152  // We've reached the one extra which shows that there are
153  // additional pages to be had. Stop here...
155  'continue', "$row->fa_name|$row->fa_timestamp|$row->fa_id"
156  );
157  break;
158  }
159 
160  $canViewFile = RevisionRecord::userCanBitfield( $row->fa_deleted, File::DELETED_FILE, $user );
161 
162  $file = [];
163  $file['id'] = (int)$row->fa_id;
164  $file['name'] = $row->fa_name;
165  $title = Title::makeTitle( NS_FILE, $row->fa_name );
166  self::addTitleInfo( $file, $title );
167 
168  if ( $fld_description &&
169  RevisionRecord::userCanBitfield( $row->fa_deleted, File::DELETED_COMMENT, $user )
170  ) {
171  $file['description'] = $commentStore->getComment( 'fa_description', $row )->text;
172  if ( isset( $prop['parseddescription'] ) ) {
173  $file['parseddescription'] = Linker::formatComment(
174  $file['description'], $title );
175  }
176  }
177  if ( $fld_user &&
178  RevisionRecord::userCanBitfield( $row->fa_deleted, File::DELETED_USER, $user )
179  ) {
180  $file['userid'] = (int)$row->fa_user;
181  $file['user'] = $row->fa_user_text;
182  }
183  if ( $fld_sha1 && $canViewFile ) {
184  $file['sha1'] = Wikimedia\base_convert( $row->fa_sha1, 36, 16, 40 );
185  }
186  if ( $fld_timestamp ) {
187  $file['timestamp'] = wfTimestamp( TS_ISO_8601, $row->fa_timestamp );
188  }
189  if ( ( $fld_size || $fld_dimensions ) && $canViewFile ) {
190  $file['size'] = $row->fa_size;
191 
192  $pageCount = ArchivedFile::newFromRow( $row )->pageCount();
193  if ( $pageCount !== false ) {
194  $file['pagecount'] = $pageCount;
195  }
196 
197  $file['height'] = $row->fa_height;
198  $file['width'] = $row->fa_width;
199  }
200  if ( $fld_mediatype && $canViewFile ) {
201  $file['mediatype'] = $row->fa_media_type;
202  }
203  if ( $fld_metadata && $canViewFile ) {
204  $file['metadata'] = $row->fa_metadata
205  ? ApiQueryImageInfo::processMetaData( unserialize( $row->fa_metadata ), $result )
206  : null;
207  }
208  if ( $fld_bitdepth && $canViewFile ) {
209  $file['bitdepth'] = $row->fa_bits;
210  }
211  if ( $fld_mime && $canViewFile ) {
212  $file['mime'] = "$row->fa_major_mime/$row->fa_minor_mime";
213  }
214  if ( $fld_archivename && !is_null( $row->fa_archive_name ) ) {
215  $file['archivename'] = $row->fa_archive_name;
216  }
217 
218  if ( $row->fa_deleted & File::DELETED_FILE ) {
219  $file['filehidden'] = true;
220  }
221  if ( $row->fa_deleted & File::DELETED_COMMENT ) {
222  $file['commenthidden'] = true;
223  }
224  if ( $row->fa_deleted & File::DELETED_USER ) {
225  $file['userhidden'] = true;
226  }
227  if ( $row->fa_deleted & File::DELETED_RESTRICTED ) {
228  // This file is deleted for normal admins
229  $file['suppressed'] = true;
230  }
231 
232  $fit = $result->addValue( [ 'query', $this->getModuleName() ], null, $file );
233  if ( !$fit ) {
235  'continue', "$row->fa_name|$row->fa_timestamp|$row->fa_id"
236  );
237  break;
238  }
239  }
240 
241  $result->addIndexedTagName( [ 'query', $this->getModuleName() ], 'fa' );
242  }
243 
244  public function getAllowedParams() {
245  return [
246  'from' => null,
247  'to' => null,
248  'prefix' => null,
249  'dir' => [
250  ApiBase::PARAM_DFLT => 'ascending',
252  'ascending',
253  'descending'
254  ]
255  ],
256  'sha1' => null,
257  'sha1base36' => null,
258  'prop' => [
259  ApiBase::PARAM_DFLT => 'timestamp',
260  ApiBase::PARAM_ISMULTI => true,
262  'sha1',
263  'timestamp',
264  'user',
265  'size',
266  'dimensions',
267  'description',
268  'parseddescription',
269  'mime',
270  'mediatype',
271  'metadata',
272  'bitdepth',
273  'archivename',
274  ],
276  ],
277  'limit' => [
278  ApiBase::PARAM_DFLT => 10,
279  ApiBase::PARAM_TYPE => 'limit',
280  ApiBase::PARAM_MIN => 1,
283  ],
284  'continue' => [
285  ApiBase::PARAM_HELP_MSG => 'api-help-param-continue',
286  ],
287  ];
288  }
289 
290  protected function getExamplesMessages() {
291  return [
292  'action=query&list=filearchive'
293  => 'apihelp-query+filearchive-example-simple',
294  ];
295  }
296 
297  public function getHelpUrls() {
298  return 'https://www.mediawiki.org/wiki/Special:MyLanguage/API:Filearchive';
299  }
300 }
select( $method, $extraQuery=[], array &$hookData=null)
Execute a SELECT query based on the values in the internal arrays.
if(PHP_SAPI !='cli-server') if(!isset( $_SERVER['SCRIPT_FILENAME'])) $file
Item class for a filearchive table row.
Definition: router.php:42
const PARAM_TYPE
(string|string[]) Either an array of allowed value strings, or a string type as described below...
Definition: ApiBase.php:94
getDB()
Get the Query database connection (read-only)
const LIMIT_BIG2
Fast query, apihighlimits limit.
Definition: ApiBase.php:261
static newFromRow( $row)
Loads a file object from the filearchive table.
const DELETED_COMMENT
Definition: File.php:64
getResult()
Get the result object.
Definition: ApiBase.php:640
addJoinConds( $join_conds)
Add a set of JOIN conditions to the internal array.
static getQueryInfo()
Return the tables, fields, and join conditions to be selected to create a new archivedfile object...
validateSha1Base36Hash( $hash)
const PARAM_DFLT
(null|boolean|integer|string) Default value of the parameter.
Definition: ApiBase.php:55
const LIMIT_BIG1
Fast query, standard limit.
Definition: ApiBase.php:259
const PARAM_MAX
(integer) Max value allowed for the parameter, for PARAM_TYPE &#39;integer&#39; and &#39;limit&#39;.
Definition: ApiBase.php:97
This is a base class for all Query modules.
$sort
dieWithError( $msg, $code=null, $data=null, $httpCode=null)
Abort execution with an error.
Definition: ApiBase.php:2005
extractRequestParams( $options=[])
Using getAllowedParams(), this function makes an array of the values provided by the user...
Definition: ApiBase.php:761
const PARAM_HELP_MSG_PER_VALUE
((string|array|Message)[]) When PARAM_TYPE is an array, this is an array mapping those values to $msg...
Definition: ApiBase.php:164
const DELETED_FILE
Definition: File.php:63
wfTimestamp( $outputtype=TS_UNIX, $ts=0)
Get a timestamp string in one of various formats.
addTables( $tables, $alias=null)
Add a set of tables to the internal array.
static formatComment( $comment, $title=null, $local=false, $wikiId=null)
This function is called by all recent changes variants, by the page history, and by the user contribu...
Definition: Linker.php:1165
titlePartToKey( $titlePart, $namespace=NS_MAIN)
Convert an input title or title prefix into a dbkey.
static processMetaData( $metadata, $result)
dieContinueUsageIf( $condition)
Die with the &#39;badcontinue&#39; error.
Definition: ApiBase.php:2199
unserialize( $serialized)
__construct(ApiQuery $query, $moduleName)
getModuleName()
Get the name of the module being executed by this instance.
Definition: ApiBase.php:520
addFields( $value)
Add a set of fields to select to the internal array.
const NS_FILE
Definition: Defines.php:66
const PARAM_MAX2
(integer) Max value allowed for the parameter for users with the apihighlimits right, for PARAM_TYPE &#39;limit&#39;.
Definition: ApiBase.php:103
This is the main query class.
Definition: ApiQuery.php:37
const PARAM_HELP_MSG
(string|array|Message) Specify an alternative i18n documentation message for this parameter...
Definition: ApiBase.php:131
const DELETED_USER
Definition: File.php:65
const DELETED_RESTRICTED
Definition: File.php:66
static makeTitle( $ns, $title, $fragment='', $interwiki='')
Create a new Title from a namespace index and a DB key.
Definition: Title.php:586
static getStore()
addWhere( $value)
Add a set of WHERE clauses to the internal array.
const PARAM_ISMULTI
(boolean) Accept multiple pipe-separated values for this parameter (e.g.
Definition: ApiBase.php:58
getPermissionManager()
Obtain a PermissionManager instance that subclasses may use in their authorization checks...
Definition: ApiBase.php:710
addWhereFld( $field, $value)
Equivalent to addWhere( [ $field => $value ] )
addOption( $name, $value=null)
Add an option such as LIMIT or USE INDEX.
const PARAM_MIN
(integer) Lowest value allowed for the parameter, for PARAM_TYPE &#39;integer&#39; and &#39;limit&#39;.
Definition: ApiBase.php:106
validateSha1Hash( $hash)
Query module to enumerate all deleted files.
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...
setContinueEnumParameter( $paramName, $paramValue)
Set a query-continue value.