From 9bc6932c6cb4333325e623f77b4e87f1010982e4 Mon Sep 17 00:00:00 2001 From: Chad Horohoe Date: Tue, 6 Sep 2011 21:01:42 +0000 Subject: [PATCH] (bug 30192) Thumbnails of archived images don't get deleted. Patch by Russ and Sam, with minor tweaks by me. --- RELEASE-NOTES-1.19 | 1 + includes/filerepo/File.php | 76 +++++++++++++++++++++++-------- includes/filerepo/LocalFile.php | 81 +++++++++++++++++++++++++++------ 3 files changed, 123 insertions(+), 35 deletions(-) diff --git a/RELEASE-NOTES-1.19 b/RELEASE-NOTES-1.19 index d75815244f..1e7528d32f 100644 --- a/RELEASE-NOTES-1.19 +++ b/RELEASE-NOTES-1.19 @@ -84,6 +84,7 @@ production. * (bug 30684) Fix bad escaping in mw.message for inexistent messages (i.e. ) * (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. diff --git a/includes/filerepo/File.php b/includes/filerepo/File.php index 2ca0977940..c0f7d70e13 100644 --- a/includes/filerepo/File.php +++ b/includes/filerepo/File.php @@ -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 */ diff --git a/includes/filerepo/LocalFile.php b/includes/filerepo/LocalFile.php index 2ba42a62d7..001cace60a 100644 --- a/includes/filerepo/LocalFile.php +++ b/includes/filerepo/LocalFile.php @@ -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(); -- 2.20.1