(bug 30192) Thumbnails of archived images don't get deleted. Patch by Russ and Sam...
authorChad Horohoe <demon@users.mediawiki.org>
Tue, 6 Sep 2011 21:01:42 +0000 (21:01 +0000)
committerChad Horohoe <demon@users.mediawiki.org>
Tue, 6 Sep 2011 21:01:42 +0000 (21:01 +0000)
RELEASE-NOTES-1.19
includes/filerepo/File.php
includes/filerepo/LocalFile.php

index d758152..1e7528d 100644 (file)
@@ -84,6 +84,7 @@ production.
 * (bug 30684) Fix bad escaping in mw.message for inexistent messages (i.e. <key>)
 * (bug 23057) Importers no longer can 'edit' or 'create' a fully-protected page by
   importing a new revision into it
+* (bug 30192) Thumbnails of archived files are now deleted
 
 === API changes in 1.19 ===
 * (bug 19838) siprop=interwikimap can now use the interwiki cache.
index 2ca0977..c0f7d70 100644 (file)
@@ -890,14 +890,26 @@ abstract class File {
        }
 
        /**
-        * Get the relative path for an archive file
-        *
-        * @param $suffix bool
+        * Get the relative path for an archived file
+        * 
+        * @param $archiveName string the timestamped name of an archived image
+        * @param $suffix bool|string if not false, the name of a thumbnail file
         *
-        * @return string
+        * @return string 
         */
-       function getArchiveRel( $suffix = false ) {
-               $path = 'archive/' . $this->getHashPath();
+       function getArchiveRel( $archiveName ) {
+               return 'archive/' . $this->getHashPath() . $archiveName;
+       }
+
+       /**
+        * Get the relative path for an archived file's thumbs directory
+        * or a specific thumb if the $suffix is given.
+        * 
+        * @param $archiveName string the timestamped name of an archived image
+        * @param $suffix bool|string if not false, the name of a thumbnail file
+        */
+       function getArchiveThumbRel( $archiveName, $suffix = false ) {
+               $path = 'archive/' . $this->getHashPath() . $archiveName . "/";
                if ( $suffix === false ) {
                        $path = substr( $path, 0, -1 );
                } else {
@@ -907,20 +919,32 @@ abstract class File {
        }
 
        /**
-        * Get the path of the archive directory, or a particular file if $suffix is specified
+        * Get the path of the archived file.
+        *
+        * @param $archiveName the timestamped name of an archived image
+        *
+        * @return string
+        */
+       function getArchivePath( $archiveName ) {
+               return $this->repo->getZonePath( 'public' ) . '/' . $this->getArchiveRel( $archiveName );
+       }
+
+       /**
+        * Get the path of the archived file's thumbs, or a particular thumb if $suffix is specified
         *
-        * @param $suffix bool
+        * @param $archiveName string the timestamped name of an archived image
+        * @param $suffix bool|string if not false, the name of a thumbnail file
         *
         * @return string
         */
-       function getArchivePath( $suffix = false ) {
-               return $this->repo->getZonePath( 'public' ) . '/' . $this->getArchiveRel( $suffix );
+       function getArchiveThumbPath( $archiveName, $suffix = false ) {
+               return $this->repo->getZonePath( 'thumb' ) . '/' . $this->getArchiveThumbRel( $archiveName, $suffix );
        }
 
        /**
         * Get the path of the thumbnail directory, or a particular file if $suffix is specified
         *
-        * @param $suffix bool
+        * @param $suffix bool|string if not false, the name of a thumbnail file
         *
         * @return string
         */
@@ -933,14 +957,26 @@ abstract class File {
        }
 
        /**
-        * Get the URL of the archive directory, or a particular file if $suffix is specified
+        * Get the URL of the archived file
+        *
+        * @param $archiveName string
+        *
+        * @return string
+        */
+       function getArchiveUrl( $archiveName ) {
+               return $this->repo->getZoneUrl('public') . '/archive/' . $this->getHashPath() . rawurlencode( $archiveName );
+       }
+
+       /**
+        * Get the URL of the archived file's thumbs, or a particular thumb if $suffix is specified
         *
-        * @param $suffix bool
+        * @param $archiveName string the timestamped name of an archived image
+        * @param $suffix bool|string if not false, the name of a thumbnail file
         *
         * @return string
         */
-       function getArchiveUrl( $suffix = false ) {
-               $path = $this->repo->getZoneUrl('public') . '/archive/' . $this->getHashPath();
+       function getArchiveThumbUrl( $archiveName, $suffix = false ) {
+               $path = $this->repo->getZoneUrl('thumb') . '/archive/' . $this->getHashPath() . rawurlencode( $archiveName ) . "/";
                if ( $suffix === false ) {
                        $path = substr( $path, 0, -1 );
                } else {
@@ -952,7 +988,7 @@ abstract class File {
        /**
         * Get the URL of the thumbnail directory, or a particular file if $suffix is specified
         *
-        * @param $suffix bool
+        * @param $suffix bool|string if not false, the name of a thumbnail file
         *
         * @return path
         */
@@ -965,9 +1001,9 @@ abstract class File {
        }
 
        /**
-        * Get the virtual URL for an archive file or directory
+        * Get the virtual URL for an archived file's thumbs, or a specific thumb.
         *
-        * @param bool|string $suffix
+        * @param $suffix bool|string if not false, the name of a thumbnail file
         *
         * @return string
         */
@@ -984,7 +1020,7 @@ abstract class File {
        /**
         * Get the virtual URL for a thumbnail file or directory
         *
-        * @param $suffix bool
+        * @param $suffix bool|string if not false, the name of a thumbnail file
         *
         * @return string
         */
@@ -999,7 +1035,7 @@ abstract class File {
        /**
         * Get the virtual URL for the file itself
         *
-        * @param $suffix bool
+        * @param $suffix bool|string if not false, the name of a thumbnail file
         *
         * @return string
         */
index 2ba42a6..001cace 100644 (file)
@@ -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,16 +687,65 @@ class LocalFile extends File {
        }
 
        /**
-        * Delete cached transformed files
+        * Delete cached transformed files for archived files
+        * @param $archiveName string name of the archived file
         */
-       function purgeThumbnails() {
-               global $wgUseSquid, $wgExcludeFromThumbnailPurge;
+       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 );
 
-               // Delete thumbnails
+               // 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 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;
+               // get a list of thumbnails and URLs
                $files = $this->getThumbnails();
-               $dir = $this->getThumbPath();
-               $urls = array();
+               $dir = array_shift( $files );
+               $this->purgeThumbList( $dir, $files );
+
+               // 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)
+        */
+       function purgeThumbList($dir, $files) {
+               global $wgExcludeFromThumbnailPurge;
+
+               wfDebug( __METHOD__ . ": " . var_export( $files, true ) . "\n" );
                foreach ( $files as $file ) {
                        // Only remove files not in the $wgExcludeFromThumbnailPurge configuration variable
                        $ext = pathinfo( "$dir/$file", PATHINFO_EXTENSION );
@@ -700,18 +756,11 @@ class LocalFile extends 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 */
@@ -1185,6 +1234,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();
 
@@ -1219,6 +1269,7 @@ class LocalFile extends File {
 
                $batch = new LocalFileDeleteBatch( $this, $reason, $suppress );
                $batch->addOld( $archiveName );
+               $this->purgeOldThumbnails( $archiveName );
                $status = $batch->execute();
 
                $this->unlock();