r104382 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r104381‎ | r104382 | r104383 >
Date:00:29, 28 November 2011
Author:aaron
Status:deferred
Tags:
Comment:
* Removed raw FS access in ForeignAPIFile and added FileBackend::clean() function
* Removed raw FS access in ForeignAPIRepo
* Added FileRepo functions (sha1/timestamp) to loosen File-FileBackend coupling a bit
* Added FileRepo::resolveToStoragePath()
* Fixed bogus var in FSFile::getTimestamp()
* Moved FileRepo::findBySha1() up a bit and getHashPathForLevel() down a bit
* Added doOperation() convenience function to backends and renamed 'operation' => 'op' to be more concise for file ops
Modified paths:
  • /branches/FileBackend/phase3/includes/filerepo/FileRepo.php (modified) (history)
  • /branches/FileBackend/phase3/includes/filerepo/ForeignAPIRepo.php (modified) (history)
  • /branches/FileBackend/phase3/includes/filerepo/LocalRepo.php (modified) (history)
  • /branches/FileBackend/phase3/includes/filerepo/backend/FSFileBackend.php (modified) (history)
  • /branches/FileBackend/phase3/includes/filerepo/backend/FileBackend.php (modified) (history)
  • /branches/FileBackend/phase3/includes/filerepo/file/FSFile.php (modified) (history)
  • /branches/FileBackend/phase3/includes/filerepo/file/File.php (modified) (history)
  • /branches/FileBackend/phase3/includes/filerepo/file/ForeignAPIFile.php (modified) (history)
  • /branches/FileBackend/phase3/includes/filerepo/file/LocalFile.php (modified) (history)
  • /branches/FileBackend/phase3/includes/filerepo/file/UnregisteredLocalFile.php (modified) (history)

Diff [purge]

Index: branches/FileBackend/phase3/includes/filerepo/ForeignAPIRepo.php
@@ -280,9 +280,9 @@
281281 $localFilename = $localPath . "/" . $fileName;
282282 $localUrl = $this->getZoneUrl( 'thumb' ) . "/" . $this->getHashPath( $name ) . rawurlencode( $name ) . "/" . rawurlencode( $fileName );
283283
284 - if( file_exists( $localFilename ) && isset( $metadata['timestamp'] ) ) {
 284+ if( $this->repo->fileExists( $localFilename ) && isset( $metadata['timestamp'] ) ) {
285285 wfDebug( __METHOD__ . " Thumbnail was already downloaded before\n" );
286 - $modified = filemtime( $localFilename );
 286+ $modified = $this->repo->getFileTimestamp( $localFilename );
287287 $remoteModified = strtotime( $metadata['timestamp'] );
288288 $current = time();
289289 $diff = abs( $modified - $current );
@@ -299,16 +299,12 @@
300300 wfDebug( __METHOD__ . " Could not download thumb\n" );
301301 return false;
302302 }
303 - if ( !is_dir($localPath) ) {
304 - if( !wfMkdirParents( $localPath, null, __METHOD__ ) ) {
305 - wfDebug( __METHOD__ . " could not create directory $localPath for thumb\n" );
306 - return $foreignUrl;
307 - }
308 - }
309303
310304 # @todo FIXME: Delete old thumbs that aren't being used. Maintenance script?
311305 wfSuppressWarnings();
312 - if( !file_put_contents( $localFilename, $thumb ) ) {
 306+ $backend = $this->repo->getBackend();
 307+ $op = array( 'op' => 'create', 'dest' => $localFilename, 'content' => $thumb );
 308+ if( !$backend->doOperation( $op )->isOK() ) {
313309 wfRestoreWarnings();
314310 wfDebug( __METHOD__ . " could not write to thumb path\n" );
315311 return $foreignUrl;
Index: branches/FileBackend/phase3/includes/filerepo/file/LocalFile.php
@@ -604,8 +604,8 @@
605605
606606 if ( $this->repo->fileExists( $thumbDir, FileRepo::FILES_ONLY ) ) {
607607 // File where directory should be
608 - $op = array( 'operation' => 'delete', 'source' => $thumbDir );
609 - $this->repo->getBackend()->doOperations( array( $op ) );
 608+ $op = array( 'op' => 'delete', 'source' => $thumbDir );
 609+ $this->repo->getBackend()->doOperation( $op );
610610 }
611611 }
612612
@@ -749,8 +749,8 @@
750750 # Check that the base file name is part of the thumb name
751751 # This is a basic sanity check to avoid erasing unrelated directories
752752 if ( strpos( $file, $this->getName() ) !== false ) {
753 - $op = array( 'operation' => 'delete', 'source' => "$dir/$file" );
754 - $this->repo->getBackend()->doOperations( array( $op ) );
 753+ $op = array( 'op' => 'delete', 'source' => "$dir/$file" );
 754+ $this->repo->getBackend()->doOperation( $op );
755755 }
756756 }
757757 }
Index: branches/FileBackend/phase3/includes/filerepo/file/UnregisteredLocalFile.php
@@ -69,6 +69,7 @@
7070 if ( $path ) {
7171 $this->path = $path;
7272 } else {
 73+ $this->assertRepoDefined();
7374 $this->path = $repo->getRootDirectory() . '/' .
7475 $repo->getHashPath( $this->name ) . $this->name;
7576 }
Index: branches/FileBackend/phase3/includes/filerepo/file/File.php
@@ -179,8 +179,7 @@
180180 static function checkExtensionCompatibility( File $old, $new ) {
181181 $oldMime = $old->getMimeType();
182182 $n = strrpos( $new, '.' );
183 - $newExt = self::normalizeExtension(
184 - $n ? substr( $new, $n + 1 ) : '' );
 183+ $newExt = self::normalizeExtension( $n ? substr( $new, $n + 1 ) : '' );
185184 $mimeMagic = MimeMagic::singleton();
186185 return $mimeMagic->isMatchingExtension( $newExt, $oldMime );
187186 }
@@ -238,7 +237,9 @@
239238 * Return the associated title object
240239 * @return Title|false
241240 */
242 - public function getTitle() { return $this->title; }
 241+ public function getTitle() {
 242+ return $this->title;
 243+ }
243244
244245 /**
245246 * Return the title used to find this file
@@ -409,7 +410,7 @@
410411 public function convertMetadataVersion($metadata, $version) {
411412 $handler = $this->getHandler();
412413 if ( !is_array( $metadata ) ) {
413 - //just to make the return type consistant
 414+ // Just to make the return type consistent
414415 $metadata = unserialize( $metadata );
415416 }
416417 if ( $handler ) {
@@ -454,7 +455,9 @@
455456 * Overridden by LocalFile,
456457 * STUB
457458 */
458 - function getMediaType() { return MEDIATYPE_UNKNOWN; }
 459+ function getMediaType() {
 460+ return MEDIATYPE_UNKNOWN;
 461+ }
459462
460463 /**
461464 * Checks if the output of transform() for this file is likely
@@ -540,6 +543,8 @@
541544 * @return bool
542545 */
543546 protected function _getIsSafeFile() {
 547+ global $wgTrustedMediaFormats;
 548+
544549 if ( $this->allowInlineDisplay() ) {
545550 return true;
546551 }
@@ -547,8 +552,6 @@
548553 return true;
549554 }
550555
551 - global $wgTrustedMediaFormats;
552 -
553556 $type = $this->getMediaType();
554557 $mime = $this->getMimeType();
555558 #wfDebug("LocalFile::isSafeFile: type= $type, mime= $mime\n");
@@ -731,10 +734,10 @@
732735 wfDebug( __METHOD__.": Doing stat for $thumbPath\n" );
733736 $this->migrateThumbFile( $thumbName );
734737 if ( $this->repo->fileExists( $thumbPath ) && !($flags & self::RENDER_FORCE) ) {
735 - $thumbTime = filemtime( $thumbPath );
736 - if ( $thumbTime !== FALSE &&
737 - gmdate( 'YmdHis', $thumbTime ) >= $wgThumbnailEpoch ) {
738 -
 738+ $thumbTime = $this->repo->getFileTimestamp( $thumbPath );
 739+ if ( $thumbTime !== false
 740+ && gmdate( 'YmdHis', $thumbTime ) >= $wgThumbnailEpoch )
 741+ {
739742 return $this->handler->getTransform( $this, $thumbPath, $thumbUrl, $params );
740743 }
741744 } elseif( $flags & self::RENDER_FORCE ) {
@@ -1456,7 +1459,7 @@
14571460 */
14581461 function getTimestamp() {
14591462 $this->assertRepoDefined();
1460 - return $this->repo->getBackend()->getFileTimestamp( $this->getPath() );
 1463+ return $this->repo->getFileTimestamp( $this->getVirtualUrl() );
14611464 }
14621465
14631466 /**
@@ -1466,11 +1469,7 @@
14671470 */
14681471 function getSha1() {
14691472 $this->assertRepoDefined();
1470 - $tmpFile = $this->repo->getBackend()->getLocalCopy( $this->getPath() );
1471 - if ( !$tmpFile ) {
1472 - return false;
1473 - }
1474 - return $tmpFile->sha1Base36();
 1473+ return $this->repo->getFileSha1( $this->getVirtualUrl() );
14751474 }
14761475
14771476 /**
Index: branches/FileBackend/phase3/includes/filerepo/file/ForeignAPIFile.php
@@ -13,7 +13,6 @@
1414 * @ingroup FileRepo
1515 */
1616 class ForeignAPIFile extends File {
17 -
1817 private $mExists;
1918
2019 protected $repoClass = 'ForeignApiRepo';
@@ -149,16 +148,16 @@
150149 }
151150
152151 function getSha1() {
153 - return isset( $this->mInfo['sha1'] ) ?
154 - wfBaseConvert( strval( $this->mInfo['sha1'] ), 16, 36, 31 ) :
155 - null;
 152+ return isset( $this->mInfo['sha1'] )
 153+ ? wfBaseConvert( strval( $this->mInfo['sha1'] ), 16, 36, 31 )
 154+ : null;
156155 }
157156
158157 function getTimestamp() {
159158 return wfTimestamp( TS_MW,
160 - isset( $this->mInfo['timestamp'] ) ?
161 - strval( $this->mInfo['timestamp'] ) :
162 - null
 159+ isset( $this->mInfo['timestamp'] )
 160+ ? strval( $this->mInfo['timestamp'] )
 161+ : null
163162 );
164163 }
165164
@@ -198,19 +197,14 @@
199198 }
200199
201200 function getThumbnails() {
202 - $files = array();
203201 $dir = $this->getThumbPath( $this->getName() );
204 - if ( is_dir( $dir ) ) {
205 - $handle = opendir( $dir );
206 - if ( $handle ) {
207 - while ( false !== ( $file = readdir($handle) ) ) {
208 - if ( $file[0] != '.' ) {
209 - $files[] = $file;
210 - }
211 - }
212 - closedir( $handle );
213 - }
 202+ $iter = $this->repo->getBackend()->getFileList( array( 'directory' => $dir ) );
 203+
 204+ $files = array();
 205+ foreach ( $iter as $file ) {
 206+ $files[] = $file;
214207 }
 208+
215209 return $files;
216210 }
217211
@@ -221,22 +215,26 @@
222216
223217 function purgeDescriptionPage() {
224218 global $wgMemc, $wgContLang;
 219+
225220 $url = $this->repo->getDescriptionRenderUrl( $this->getName(), $wgContLang->getCode() );
226221 $key = $this->repo->getLocalCacheKey( 'RemoteFileDescription', 'url', md5($url) );
 222+
227223 $wgMemc->delete( $key );
228224 }
229225
230226 function purgeThumbnails() {
231227 global $wgMemc;
 228+
232229 $key = $this->repo->getLocalCacheKey( 'ForeignAPIRepo', 'ThumbUrl', $this->getName() );
233230 $wgMemc->delete( $key );
 231+
 232+ $backend = $this->repo->getBackend();
234233 $files = $this->getThumbnails();
235234 $dir = $this->getThumbPath( $this->getName() );
236235 foreach ( $files as $file ) {
237 - unlink( $dir . $file );
 236+ $op = array( 'op' => 'delete', 'source' => "{$dir}{$file}" );
 237+ $backend->doOperation( $op );
238238 }
239 - if ( is_dir( $dir ) ) {
240 - rmdir( $dir ); // Might have already gone away, spews errors if we don't.
241 - }
 239+ $backend->clean( array( 'directory' => $dir ) );
242240 }
243241 }
Index: branches/FileBackend/phase3/includes/filerepo/file/FSFile.php
@@ -49,7 +49,7 @@
5050 public function getTimestamp() {
5151 $timestamp = filemtime( $this->path );
5252 if ( $timestamp !== false ) {
53 - $timestamp = wfTimestamp( TS_MW, $ts );
 53+ $timestamp = wfTimestamp( TS_MW, $timestamp );
5454 }
5555 return $timestamp;
5656 }
Index: branches/FileBackend/phase3/includes/filerepo/LocalRepo.php
@@ -71,8 +71,8 @@
7272 $hidden = $this->hiddenFileHasKey( $key, 'lock' );
7373 if ( !$deleted && !$hidden ) { // not in use now
7474 wfDebug( __METHOD__ . ": deleting $key\n" );
75 - $op = array( 'operation' => 'delete', 'source' => $path );
76 - if ( !$backend->doOperations( array( $op ) )->isOK() ) {
 75+ $op = array( 'op' => 'delete', 'source' => $path );
 76+ if ( !$backend->doOperation( $op )->isOK() ) {
7777 $status->error( 'undelete-cleanup-error', $path );
7878 $status->failCount++;
7979 }
Index: branches/FileBackend/phase3/includes/filerepo/backend/FSFileBackend.php
@@ -355,6 +355,21 @@
356356 return $status;
357357 }
358358
 359+ function clean( array $params ) {
 360+ $status = Status::newGood();
 361+ list( $c, $dir ) = $this->resolveStoragePath( $params['directory'] );
 362+ if ( $dir === null ) {
 363+ $status->fatal( 'backend-fail-invalidpath', $params['directory'] );
 364+ return $status; // invalid storage path
 365+ }
 366+ wfSuppressWarnings();
 367+ if ( is_dir( $dir ) ) {
 368+ rmdir( $dir ); // Might have already gone away, spews errors if we don't.
 369+ }
 370+ wfRestoreWarnings();
 371+ return $status;
 372+ }
 373+
359374 function fileExists( array $params ) {
360375 list( $c, $source ) = $this->resolveStoragePath( $params['source'] );
361376 if ( $source === null ) {
Index: branches/FileBackend/phase3/includes/filerepo/backend/FileBackend.php
@@ -63,8 +63,8 @@
6464 * <code>
6565 * $ops = array(
6666 * array(
67 - * 'operation' => 'store',
68 - * 'src' => '/tmp/uploads/picture.png',
 67+ * 'op' => 'store',
 68+ * 'source' => '/tmp/uploads/picture.png',
6969 * 'dest' => 'mwstore://container/uploadedFilename.png'
7070 * )
7171 * );
@@ -78,11 +78,21 @@
7979 abstract public function doOperations( array $ops );
8080
8181 /**
 82+ * Same as doOperations() except it takes a single operation array
 83+ *
 84+ * @param $op Array
 85+ * @return Status
 86+ */
 87+ final public function doOperation( $op ) {
 88+ return $this->doOperation( $op );
 89+ }
 90+
 91+ /**
8292 * Prepare a storage path for usage. This will create containers
8393 * that don't yet exists or, on FS backends, create parent directories.
8494 * Do not call this function from places outside FileBackend and FileOp.
8595 * $params include:
86 - * directory : destination storage path
 96+ * directory : storage directory
8797 *
8898 * @param Array $params
8999 * @return Status
@@ -94,7 +104,7 @@
95105 * This is not guaranteed to actually do anything.
96106 * Do not call this function from places outside FileBackend and FileOp.
97107 * $params include:
98 - * directory : destination storage path
 108+ * directory : storage directory
99109 * noAccess : try to deny file access
100110 * noListing : try to deny file listing
101111 *
@@ -104,6 +114,18 @@
105115 abstract public function secure( array $params );
106116
107117 /**
 118+ * Clean up an empty storage directory.
 119+ * On FS backends, the directory will be deleted. Others may do nothing.
 120+ * Do not call this function from places outside FileBackend and FileOp.
 121+ * $params include:
 122+ * directory : storage directory
 123+ *
 124+ * @param Array $params
 125+ * @return Status
 126+ */
 127+ abstract public function clean( array $params );
 128+
 129+ /**
108130 * Check if a file exits at a storage path in the backend.
109131 * Do not call this function from places outside FileBackend and FileOp.
110132 * $params include:
@@ -310,6 +332,10 @@
311333 return Status::newGood();
312334 }
313335
 336+ public function clean( array $params ) {
 337+ return Status::newGood();
 338+ }
 339+
314340 /**
315341 * Whether this backend implements move() and is applies to a potential
316342 * move from one storage path to another. No backends hits are required.
@@ -366,12 +392,12 @@
367393 $performOps = array(); // array of FileOp objects
368394 // Build up ordered array of FileOps...
369395 foreach ( $ops as $operation ) {
370 - $opName = $operation['operation'];
 396+ $opName = $operation['op'];
371397 if ( isset( $supportedOps[$opName] ) ) {
372398 $class = $supportedOps[$opName];
373399 // Get params for this operation
374400 $params = $operation;
375 - unset( $params['operation'] ); // don't need this
 401+ unset( $params['op'] ); // don't need this
376402 unset( $params['ignoreErrors'] ); // don't need this
377403 // Append the FileOp class
378404 $performOps[] = new $class( $params );
Index: branches/FileBackend/phase3/includes/filerepo/FileRepo.php
@@ -287,7 +287,7 @@
288288 * @param $zone string
289289 * @return Array (container, base path) or (null, null)
290290 */
291 - function getZoneLocation( $zone ) {
 291+ protected function getZoneLocation( $zone ) {
292292 if ( !isset( $this->zones[$zone] ) ) {
293293 return array( null, null ); // bogus
294294 }
@@ -464,6 +464,16 @@
465465 }
466466
467467 /**
 468+ * Get an array or iterator of file objects for files that have a given
 469+ * SHA-1 content hash.
 470+ *
 471+ * STUB
 472+ */
 473+ public function findBySha1( $hash ) {
 474+ return array();
 475+ }
 476+
 477+ /**
468478 * Get the public root URL of the repository
469479 *
470480 * @return string
@@ -518,25 +528,7 @@
519529 }
520530
521531 /**
522 - * @param $name
523 - * @param $levels
524 - * @return string
525 - */
526 - static function getHashPathForLevel( $name, $levels ) {
527 - if ( $levels == 0 ) {
528 - return '';
529 - } else {
530 - $hash = md5( $name );
531 - $path = '';
532 - for ( $i = 1; $i <= $levels; $i++ ) {
533 - $path .= substr( $hash, 0, $i ) . '/';
534 - }
535 - return $path;
536 - }
537 - }
538 -
539 - /**
540 - * Get the public zone root directory of the repository.
 532+ * Get the public zone root storage directory of the repository
541533 *
542534 * @return string
543535 */
@@ -556,6 +548,24 @@
557549 }
558550
559551 /**
 552+ * @param $name
 553+ * @param $levels
 554+ * @return string
 555+ */
 556+ static function getHashPathForLevel( $name, $levels ) {
 557+ if ( $levels == 0 ) {
 558+ return '';
 559+ } else {
 560+ $hash = md5( $name );
 561+ $path = '';
 562+ for ( $i = 1; $i <= $levels; $i++ ) {
 563+ $path .= substr( $hash, 0, $i ) . '/';
 564+ }
 565+ return $path;
 566+ }
 567+ }
 568+
 569+ /**
560570 * Get the name of this repository, as specified by $info['name]' to the constructor
561571 *
562572 * @return string
@@ -739,7 +749,7 @@
740750 }
741751 }
742752 $operations[] = array(
743 - 'operation' => $opName,
 753+ 'op' => $opName,
744754 'source' => $srcPath,
745755 'dest' => $dstPath,
746756 'overwriteDest' => $flags & self::OVERWRITE,
@@ -761,9 +771,9 @@
762772 }
763773
764774 /**
765 - * Deletes a batch of files. Each file can be a (zone, rel) pairs, a
766 - * virtual url or a real path. It will try to delete each file, but
767 - * ignores any errors that may occur
 775+ * Deletes a batch of files.
 776+ * Each file can be a (zone, rel) pair, virtual url, storage path, or FS path.
 777+ * It will try to delete each file, but ignores any errors that may occur.
768778 *
769779 * @param $pairs array List of files to delete
770780 * @return void
@@ -789,8 +799,8 @@
790800 // Get a file operation if needed
791801 if ( FileBackend::isStoragePath( $path ) ) {
792802 $operations[] = array(
793 - 'operation' => 'delete',
794 - 'source' => $path,
 803+ 'op' => 'delete',
 804+ 'source' => $path,
795805 'ignoreErrors' => true
796806 );
797807 } else {
@@ -829,6 +839,7 @@
830840
831841 /**
832842 * Remove a temporary file or mark it for garbage collection
 843+ *
833844 * @param $virtualUrl String: the virtual URL returned by storeTemp
834845 * @return Boolean: true on success, false on failure
835846 */
@@ -839,13 +850,13 @@
840851 return false;
841852 }
842853 $path = $this->resolveVirtualUrl( $virtualUrl );
843 - $op = array( 'operation' => 'delete', 'source' => $path );
844 - $status = $this->backend->doOperations( array( $op ) );
 854+ $op = array( 'op' => 'delete', 'source' => $path );
 855+ $status = $this->backend->doOperation( $op );
845856 return $status->isOK();
846857 }
847858
848859 /**
849 - * Copy or move a file either from the local filesystem or from an mwrepo://
 860+ * Copy or move a file either from a storage path or from a mwrepo://
850861 * virtual URL, into this repository at the specified destination location.
851862 *
852863 * Returns a FileRepoStatus object. On success, the value contains "new" or
@@ -928,11 +939,11 @@
929940 // publishBatch's caller should prevent races. In Windows there's no
930941 // problem because the rename primitive fails if the destination exists.
931942 if ( $backend->fileExists( array( 'source' => $archivePath ) ) ) {
932 - $operations[] = array( 'operation' => 'null' );
 943+ $operations[] = array( 'op' => 'null' );
933944 continue;
934945 } else {
935946 $operations[] = array(
936 - 'operation' => 'move',
 947+ 'op' => 'move',
937948 'source' => $dstPath,
938949 'dest' => $archivePath,
939950 'ignoreErrors' => true
@@ -944,14 +955,14 @@
945956 }
946957 if ( $flags & self::DELETE_SOURCE ) {
947958 $operations[] = array(
948 - 'operation' => 'move',
 959+ 'op' => 'move',
949960 'source' => $srcPath,
950961 'dest' => $dstPath,
951962 'ignoreErrors' => true
952963 );
953964 } else {
954965 $operations[] = array(
955 - 'operation' => 'copy',
 966+ 'op' => 'copy',
956967 'source' => $srcPath,
957968 'dest' => $dstPath,
958969 'ignoreErrors' => true
@@ -1086,12 +1097,12 @@
10871098
10881099 if ( $backend->fileExists( array( 'source' => $archivePath ) ) ) {
10891100 $operations[] = array(
1090 - 'operation' => 'delete',
 1101+ 'op' => 'delete',
10911102 'source' => $srcPath
10921103 );
10931104 } else {
10941105 $operations[] = array(
1095 - 'operation' => 'move',
 1106+ 'op' => 'move',
10961107 'source' => $srcPath,
10971108 'dest' => $archivePath
10981109 );
@@ -1121,19 +1132,58 @@
11221133 }
11231134
11241135 /**
1125 - * Get properties of a file with a given virtual URL
1126 - * The virtual URL must refer to this repo
1127 - * Properties should ultimately be obtained via FSFile::getProps()
 1136+ * If a path is a virtual URL, resolve it to a storage path.
 1137+ * Otherwise, just return the path as it is.
11281138 *
 1139+ * @return string
 1140+ * @throws MWException
 1141+ */
 1142+ protected function resolveToStoragePath( $path ) {
 1143+ if ( $this->isVirtualUrl( $path ) ) {
 1144+ return $this->resolveVirtualUrl( $path );
 1145+ }
 1146+ return $path;
 1147+ }
 1148+
 1149+ /**
 1150+ * Get properties of a file with a given virtual URL/storage path.
 1151+ * Properties should ultimately be obtained via FSFile::getProps().
 1152+ *
11291153 * @param $virtualUrl string
11301154 * @return Array
11311155 */
11321156 public function getFileProps( $virtualUrl ) {
1133 - $path = $this->resolveVirtualUrl( $virtualUrl );
1134 - return $this->backend->getFileProps( $path );
 1157+ $path = $this->resolveToStoragePath( $virtualUrl );
 1158+ return $this->backend->getFileProps( array( 'source' => $path ) );
11351159 }
11361160
11371161 /**
 1162+ * Get the timestamp of a file with a given virtual URL/storage path
 1163+ *
 1164+ * @param $virtualUrl
 1165+ * @return string|false
 1166+ */
 1167+ public function getFileTimestamp( $virtualUrl ) {
 1168+ $path = $this->resolveToStoragePath( $virtualUrl );
 1169+ return $this->backend->getFileTimestamp( array( 'source' => $path ) );
 1170+ }
 1171+
 1172+ /**
 1173+ * Get the sha1 of a file with a given virtual URL/storage path
 1174+ *
 1175+ * @param $virtualUrl
 1176+ * @return string|false
 1177+ */
 1178+ public function getFileSha1( $virtualUrl ) {
 1179+ $path = $this->resolveToStoragePath( $virtualUrl );
 1180+ $tmpFile = $this->backend->getLocalCopy( array( 'source' => $path ) );
 1181+ if ( !$tmpFile ) {
 1182+ return false;
 1183+ }
 1184+ return $tmpFile->sha1Base36();
 1185+ }
 1186+
 1187+ /**
11381188 * Call a callback function for every public file in the repository.
11391189 * May use either the database or the filesystem.
11401190 *
@@ -1309,16 +1359,6 @@
13101360 public function invalidateImageRedirect( Title $title ) {}
13111361
13121362 /**
1313 - * Get an array or iterator of file objects for files that have a given
1314 - * SHA-1 content hash.
1315 - *
1316 - * STUB
1317 - */
1318 - public function findBySha1( $hash ) {
1319 - return array();
1320 - }
1321 -
1322 - /**
13231363 * Get the human-readable name of the repo
13241364 *
13251365 * @return string

Follow-up revisions

RevisionCommit summaryAuthorDate
r104405* Fixed S&R mistake from r104382 in doOperation()...aaron06:59, 28 November 2011

Status & tagging log