FU r102073:
[lhc/web/wiklou.git] / includes / filerepo / LocalFile.php
index d879f07..6cd30e1 100644 (file)
@@ -58,6 +58,8 @@ class LocalFile extends File {
 
        /**#@-*/
 
+       protected $repoClass = 'LocalRepo';
+
        /**
         * Create a LocalFile from a title
         * Do not call this except from inside a repo class.
@@ -95,22 +97,21 @@ class LocalFile extends File {
         * Create a LocalFile from a SHA-1 key
         * Do not call this except from inside a repo class.
         *
-        * @param $sha1 string
+        * @param $sha1 string base-36 SHA-1
         * @param $repo LocalRepo
-        * @param $timestamp string
+        * @param string|bool $timestamp MW_timestamp (optional)
         *
-        * @return LocalFile
+        * @return bool|LocalFile
         */
        static function newFromKey( $sha1, $repo, $timestamp = false ) {
-               $conds = array( 'img_sha1' => $sha1 );
+               $dbr = $repo->getSlaveDB();
 
+               $conds = array( 'img_sha1' => $sha1 );
                if ( $timestamp ) {
-                       $conds['img_timestamp'] = $timestamp;
+                       $conds['img_timestamp'] = $dbr->timestamp( $timestamp );
                }
 
-               $dbr = $repo->getSlaveDB();
                $row = $dbr->selectRow( 'image', self::selectFields(), $conds, __METHOD__ );
-
                if ( $row ) {
                        return self::newFromRow( $row, $repo );
                } else {
@@ -145,16 +146,15 @@ class LocalFile extends File {
         * Do not call this except from inside a repo class.
         */
        function __construct( $title, $repo ) {
-               if ( !is_object( $title ) ) {
-                       throw new MWException( __CLASS__ . ' constructor given bogus title.' );
-               }
-
                parent::__construct( $title, $repo );
 
                $this->metadata = '';
                $this->historyLine = 0;
                $this->historyRes = null;
                $this->dataLoaded = false;
+
+               $this->assertRepoDefined();
+               $this->assertTitleDefined();
        }
 
        /**
@@ -613,12 +613,19 @@ class LocalFile extends File {
 
        /**
         * Get all thumbnail names previously generated for this file
+        * @param $archiveName string|false Name of an archive file
+        * @return array first element is the base dir, then files in that base dir.
         */
-       function getThumbnails() {
+       function getThumbnails( $archiveName = false ) {
                $this->load();
 
+               if ( $archiveName ) {
+                       $dir = $this->getArchiveThumbPath( $archiveName );
+               } else {
+                       $dir = $this->getThumbPath();
+               }
                $files = array();
-               $dir = $this->getThumbPath();
+               $files[] = $dir;
 
                if ( is_dir( $dir ) ) {
                        $handle = opendir( $dir );
@@ -680,38 +687,79 @@ class LocalFile extends File {
        }
 
        /**
-        * Delete cached transformed files
+        * Delete cached transformed files for archived files
+        * @param $archiveName string name of the archived file
+        */
+       function purgeOldThumbnails( $archiveName ) {
+               global $wgUseSquid;
+               // Get a list of old thumbnails and URLs
+               $files = $this->getThumbnails( $archiveName );
+               $dir = array_shift( $files );
+               $this->purgeThumbList( $dir, $files );
+
+               // Directory should be empty, delete it too. This will probably suck on
+               // something like NFS or if the directory isn't actually empty, so hide
+               // the warnings :D
+               wfSuppressWarnings();
+               if( !rmdir( $dir ) ) {
+                       wfDebug( __METHOD__ . ": unable to remove archive directory: $dir\n" );
+               }
+               wfRestoreWarnings();
+
+               // Purge any custom thumbnail caches
+               wfRunHooks( 'LocalFilePurgeThumbnails', array( $this, 'archive' ) );
+
+               // Purge the squid
+               if ( $wgUseSquid ) {
+                       $urls = array();
+                       foreach( $files as $file ) {
+                               $urls[] = $this->getArchiveThumbUrl( $archiveName, $file );
+                       }
+                       SquidUpdate::purge( $urls );
+               }
+       }
+
+
+       /**
+        * Delete cached transformed files for the current version only.
         */
        function purgeThumbnails() {
-               global $wgUseSquid, $wgExcludeFromThumbnailPurge;
+               global $wgUseSquid;
 
                // Delete thumbnails
                $files = $this->getThumbnails();
-               $dir = $this->getThumbPath();
-               $urls = array();
+               $dir = array_shift( $files );
+               $this->purgeThumbList( $dir, $files );
 
-               foreach ( $files as $file ) {
-                       // Only remove files not in the $wgExcludeFromThumbnailPurge configuration variable
-                       $ext = pathinfo( "$dir/$file", PATHINFO_EXTENSION );
-                       if ( in_array( $ext, $wgExcludeFromThumbnailPurge ) ) {
-                               continue;
+               // Purge any custom thumbnail caches
+               wfRunHooks( 'LocalFilePurgeThumbnails', array( $this, 'current' ) );
+
+               // Purge the squid
+               if ( $wgUseSquid ) {
+                       $urls = array();
+                       foreach( $files as $file ) {
+                               $urls[] = $this->getThumbUrl( $file );
                        }
+                       SquidUpdate::purge( $urls );
+               }
+       }
 
+       /**
+        * Delete a list of thumbnails visible at urls
+        * @param $dir string base dir of the files.
+        * @param $files array of strings: relative filenames (to $dir)
+        */
+       protected function purgeThumbList($dir, $files) {
+               wfDebug( __METHOD__ . ": " . var_export( $files, true ) . "\n" );
+               foreach ( $files as $file ) {
                        # Check that the base file name is part of the thumb name
                        # This is a basic sanity check to avoid erasing unrelated directories
                        if ( strpos( $file, $this->getName() ) !== false ) {
-                               $url = $this->getThumbUrl( $file );
-                               $urls[] = $url;
                                wfSuppressWarnings();
                                unlink( "$dir/$file" );
                                wfRestoreWarnings();
                        }
                }
-
-               // Purge the squid
-               if ( $wgUseSquid ) {
-                       SquidUpdate::purge( $urls );
-               }
        }
 
        /** purgeDescription inherited */
@@ -816,7 +864,6 @@ class LocalFile extends File {
                }
        }
 
-       /** getFullPath inherited */
        /** getHashPath inherited */
        /** getRel inherited */
        /** getUrlRel inherited */
@@ -860,6 +907,25 @@ class LocalFile extends File {
                return $status;
        }
 
+       /**
+        * Record a file upload in the upload log and the image table
+        */
+       function recordUpload( $oldver, $desc, $license = '', $copyStatus = '', $source = '',
+               $watch = false, $timestamp = false )
+       {
+               $pageText = SpecialUpload::getInitialPageText( $desc, $license, $copyStatus, $source );
+
+               if ( !$this->recordUpload2( $oldver, $desc, $pageText ) ) {
+                       return false;
+               }
+
+               if ( $watch ) {
+                       global $wgUser;
+                       $wgUser->addWatch( $this->getTitle() );
+               }
+               return true;
+       }
+
        /**
         * Record a file upload in the upload log and the image table
         */
@@ -974,8 +1040,14 @@ class LocalFile extends File {
                } else {
                        # This is a new file
                        # Update the image count
-                       $site_stats = $dbw->tableName( 'site_stats' );
-                       $dbw->query( "UPDATE $site_stats SET ss_images=ss_images+1", __METHOD__ );
+                       $dbw->begin( __METHOD__ );
+                       $dbw->update(
+                               'site_stats',
+                               array( 'ss_images = ss_images+1' ),
+                               '*',
+                               __METHOD__
+                       );
+                       $dbw->commit( __METHOD__ );
                }
 
                $descTitle = $this->getTitle();
@@ -1160,6 +1232,7 @@ class LocalFile extends File {
                        array( 'oi_name' => $this->getName() ) );
                foreach ( $result as $row ) {
                        $batch->addOld( $row->oi_archive_name );
+                       $this->purgeOldThumbnails( $row->oi_archive_name );
                }
                $status = $batch->execute();
 
@@ -1194,6 +1267,7 @@ class LocalFile extends File {
 
                $batch = new LocalFileDeleteBatch( $this, $reason, $suppress );
                $batch->addOld( $archiveName );
+               $this->purgeOldThumbnails( $archiveName );
                $status = $batch->execute();
 
                $this->unlock();
@@ -2007,7 +2081,18 @@ class LocalFileRestoreBatch {
  * @ingroup FileRepo
  */
 class LocalFileMoveBatch {
-       var $file, $cur, $olds, $oldCount, $archive, $target, $db;
+
+       /**
+        * @var File
+        */
+       var $file;
+
+       /**
+        * @var Title
+        */
+       var $target;
+
+       var $cur, $olds, $oldCount, $archive, $db;
 
        function __construct( File $file, Title $target ) {
                $this->file = $file;
@@ -2084,7 +2169,7 @@ class LocalFileMoveBatch {
 
                // Copy the files into their new location
                $statusMove = $repo->storeBatch( $triplets );
-               wfDebugLog( 'imagemove', "Moved files for {$this->file->name}: {$statusMove->successCount} successes, {$statusMove->failCount} failures" );
+               wfDebugLog( 'imagemove', "Moved files for {$this->file->getName()}: {$statusMove->successCount} successes, {$statusMove->failCount} failures" );
                if ( !$statusMove->isGood() ) {
                        wfDebugLog( 'imagemove', "Error in moving files: " . $statusMove->getWikiText() );
                        $this->cleanupTarget( $triplets );
@@ -2094,7 +2179,7 @@ class LocalFileMoveBatch {
 
                $this->db->begin();
                $statusDb = $this->doDBUpdates();
-               wfDebugLog( 'imagemove', "Renamed {$this->file->name} in database: {$statusDb->successCount} successes, {$statusDb->failCount} failures" );
+               wfDebugLog( 'imagemove', "Renamed {$this->file->getName()} in database: {$statusDb->successCount} successes, {$statusDb->failCount} failures" );
                if ( !$statusDb->isGood() ) {
                        $this->db->rollback();
                        // Something went wrong with the DB updates, so remove the target files
@@ -2173,7 +2258,7 @@ class LocalFileMoveBatch {
                        // $move: (oldRelativePath, newRelativePath)
                        $srcUrl = $this->file->repo->getVirtualUrl() . '/public/' . rawurlencode( $move[0] );
                        $triplets[] = array( $srcUrl, 'public', $move[1] );
-                       wfDebugLog( 'imagemove', "Generated move triplet for {$this->file->name}: {$srcUrl} :: public :: {$move[1]}" );
+                       wfDebugLog( 'imagemove', "Generated move triplet for {$this->file->getName()}: {$srcUrl} :: public :: {$move[1]}" );
                }
 
                return $triplets;