In SpecialUploadStash:
authorAaron Schulz <aaron@users.mediawiki.org>
Thu, 5 Jan 2012 01:58:05 +0000 (01:58 +0000)
committerAaron Schulz <aaron@users.mediawiki.org>
Thu, 5 Jan 2012 01:58:05 +0000 (01:58 +0000)
* Updated outputLocallyScaledThumb() and outputLocalFile() to handle changes in r106752.
In MediaTransformOutput:
* Added a storage path field to the transformation output object and set it in  File::maybeDoTransform().
In File:
* Fixed maybeDoTransform() handling if repo member is not set and made it fully respect $wgIgnoreImageErrors.
In BitmapHandler:
* Don't set bogus path if TRANSFORM_LATER in doTransform() for deffered renderings.

includes/filerepo/file/File.php
includes/media/Bitmap.php
includes/media/MediaTransformOutput.php
includes/specials/SpecialUploadStash.php

index 21f2f98..5476366 100644 (file)
@@ -757,63 +757,89 @@ abstract class File {
                global $wgIgnoreImageErrors, $wgThumbnailEpoch;
 
                $thumbPath = $this->getThumbPath( $thumbName ); // final thumb path
-               if ( $this->repo && $this->repo->canTransformVia404() && !( $flags & self::RENDER_NOW ) ) {
-                       wfDebug( __METHOD__ . " transformation deferred." );
-                       // XXX: Pass in the storage path even though we are not rendering anything
-                       // and the path is supposed to be an FS path. This is due to getScalerType()
-                       // getting called on the path and clobbering $thumb->getUrl() if it's false.
-                       return $this->handler->getTransform( $this, $thumbPath, $thumbUrl, $params );
-               }
-
-               wfDebug( __METHOD__.": Doing stat for $thumbPath\n" );
-               $this->migrateThumbFile( $thumbName );
-               if ( $this->repo->fileExists( $thumbPath ) && !( $flags & self::RENDER_FORCE ) ) {
-                       $timestamp = $this->repo->getFileTimestamp( $thumbPath );
-                       if ( $timestamp !== false && $timestamp >= $wgThumbnailEpoch ) {
+               if ( $this->repo ) {
+                       // Defer rendering if a 404 handler is set up...
+                       if ( $this->repo->canTransformVia404() && !( $flags & self::RENDER_NOW ) ) {
+                               wfDebug( __METHOD__ . " transformation deferred." );
                                // XXX: Pass in the storage path even though we are not rendering anything
                                // and the path is supposed to be an FS path. This is due to getScalerType()
                                // getting called on the path and clobbering $thumb->getUrl() if it's false.
                                return $this->handler->getTransform( $this, $thumbPath, $thumbUrl, $params );
                        }
-               } elseif ( $flags & self::RENDER_FORCE ) {
-                       wfDebug( __METHOD__ . " forcing rendering per flag File::RENDER_FORCE\n" );
+                       // Clean up broken thumbnails as needed
+                       $this->migrateThumbFile( $thumbName );
+                       // Check if an up-to-date thumbnail already exists...
+                       wfDebug( __METHOD__.": Doing stat for $thumbPath\n" );
+                       if ( $this->repo->fileExists( $thumbPath ) && !( $flags & self::RENDER_FORCE ) ) {
+                               $timestamp = $this->repo->getFileTimestamp( $thumbPath );
+                               if ( $timestamp !== false && $timestamp >= $wgThumbnailEpoch ) {
+                                       // XXX: Pass in the storage path even though we are not rendering anything
+                                       // and the path is supposed to be an FS path. This is due to getScalerType()
+                                       // getting called on the path and clobbering $thumb->getUrl() if it's false.
+                                       $thumb = $this->handler->getTransform( $this, $thumbPath, $thumbUrl, $params );
+                                       $thumb->setStoragePath( $thumbPath );
+                                       return $thumb;
+                               }
+                       } elseif ( $flags & self::RENDER_FORCE ) {
+                               wfDebug( __METHOD__ . " forcing rendering per flag File::RENDER_FORCE\n" );
+                       }
                }
 
                // Create a temp FS file with the same extension and the thumbnail
                $thumbExt = FileBackend::extensionFromPath( $thumbPath );
                $tmpFile = TempFSFile::factory( 'transform_', $thumbExt );
                if ( !$tmpFile ) {
-                       return new MediaTransformError( 'thumbnail_error',
-                               $params['width'], 0, wfMsg( 'thumbnail-temp-create' ) );
+                       return $this->transformErrorOutput( $thumbPath, $thumbUrl, $params, $flags );
                }
                $tmpThumbPath = $tmpFile->getPath(); // path of 0-byte temp file
 
-               // Actually render the thumbnail
+               // Actually render the thumbnail...
                $thumb = $this->handler->doTransform( $this, $tmpThumbPath, $thumbUrl, $params );
                $tmpFile->bind( $thumb ); // keep alive with $thumb
 
-               // Ignore errors if requested
-               if ( !$thumb ) {
+               if ( !$thumb ) { // bad params?
                        $thumb = null;
-               } elseif ( $thumb->isError() ) {
+               } elseif ( $thumb->isError() ) { // transform error
                        $this->lastError = $thumb->toText();
+                       // Ignore errors if requested
                        if ( $wgIgnoreImageErrors && !( $flags & self::RENDER_NOW ) ) {
                                $thumb = $this->handler->getTransform( $this, $tmpThumbPath, $thumbUrl, $params );
                        }
                } elseif ( $thumb->hasFile() && !$thumb->fileIsSource() ) {
-                       // Copy any thumbnail from the FS into storage at $dstpath
+                       // Copy the thumbnail from the file system into storage
                        $status = $this->repo->store(
                                $tmpThumbPath, 'thumb', $this->getThumbRel( $thumbName ),
                                FileRepo::OVERWRITE | FileRepo::SKIP_LOCKING | FileRepo::ALLOW_STALE );
-                       if ( !$status->isOK() ) {
-                               return new MediaTransformError( 'thumbnail_error',
-                                       $params['width'], 0, wfMsg( 'thumbnail-dest-create' ) );
+                       if ( $status->isOK() ) {
+                               $thumb->setStoragePath( $thumbPath );
+                       } else {
+                               $thumb = $this->transformErrorOutput( $thumbPath, $thumbUrl, $params, $flags );
                        }
                }
 
                return $thumb;
        }
 
+       /**
+        * Return either a MediaTransformError or placeholder thumbnail (if $wgIgnoreImageErrors)
+        * 
+        * @param $thumbPath string Thumbnail storage path
+        * @param $thumbUrl string Thumbnail URL
+        * @param $params Array
+        * @param $flags integer
+        * @return MediaTransformOutput
+        */
+       protected function transformErrorOutput( $thumbPath, $thumbUrl, $params, $flags ) {
+               global $wgIgnoreImageErrors;
+
+               if ( $wgIgnoreImageErrors && !( $flags & self::RENDER_NOW ) ) {
+                       return $this->handler->getTransform( $this, $thumbPath, $thumbUrl, $params );
+               } else {
+                       return new MediaTransformError( 'thumbnail_error',
+                               $params['width'], 0, wfMsg( 'thumbnail-dest-create' ) );
+               }
+       }
+
        /**
         * Transform a media file
         *
index 878ad58..164f864 100644 (file)
@@ -154,7 +154,7 @@ class BitmapHandler extends ImageHandler {
                if ( $flags & self::TRANSFORM_LATER ) {
                        wfDebug( __METHOD__ . ": Transforming later per flags.\n" );
                        return new ThumbnailImage( $image, $dstUrl, $scalerParams['clientWidth'],
-                               $scalerParams['clientHeight'], $dstPath );
+                               $scalerParams['clientHeight'], false );
                }
 
                # Try to make a target path for the thumbnail
index f7c5270..de6b1c0 100644 (file)
@@ -18,6 +18,7 @@ abstract class MediaTransformOutput {
        var $file;
 
        var $width, $height, $url, $page, $path;
+       protected $storagePath = false;
 
        /**
         * Get the width of the output box
@@ -40,6 +41,21 @@ abstract class MediaTransformOutput {
                return $this->url;
        }
 
+       /**
+        * @return string|false The permanent thumbnail storage path
+        */
+       public function getStoragePath() {
+               return $this->storagePath;
+       }
+
+       /**
+        * @param $storagePath string The permanent storage path
+        * @return void
+        */
+       public function setStoragePath( $storagePath ) {
+               $this->storagePath = $storagePath;
+       }
+
        /**
         * Fetch HTML for this transform output
         *
index 5d353f1..121b6a4 100644 (file)
@@ -166,14 +166,15 @@ class SpecialUploadStash extends UnlistedSpecialPage {
                }
 
                // we should have just generated it locally
-               if ( ! $thumbnailImage->getPath() ) {
+               if ( !$thumbnailImage->getStoragePath() ) {
                        throw new UploadStashFileNotFoundException( "no local path for scaled item" );
                }
 
                // now we should construct a File, so we can get mime and other such info in a standard way
                // n.b. mimetype may be different from original (ogx original -> jpeg thumb)
-               $thumbFile = new UnregisteredLocalFile( false, $this->stash->repo, $thumbnailImage->getPath(), false );
-               if ( ! $thumbFile ) {
+               $thumbFile = new UnregisteredLocalFile( false, 
+                       $this->stash->repo, $thumbnailImage->getStoragePath(), false );
+               if ( !$thumbFile ) {
                        throw new UploadStashFileNotFoundException( "couldn't create local file object for thumbnail" );
                }
 
@@ -238,18 +239,17 @@ class SpecialUploadStash extends UnlistedSpecialPage {
        /**
         * Output HTTP response for file
         * Side effect: writes HTTP response to STDOUT.
-        * XXX could use wfStreamfile (in includes/Streamfile.php), but for consistency with outputContents() doing it this way.
-        * XXX is mimeType really enough, or do we need encoding for full Content-Type header?
         *
         * @param $file File object with a local path (e.g. UnregisteredLocalFile, LocalFile. Oddly these don't share an ancestor!)
         */
-       private function outputLocalFile( $file ) {
+       private function outputLocalFile( File $file ) {
                if ( $file->getSize() > self::MAX_SERVE_BYTES ) {
                        throw new SpecialUploadStashTooLargeException();
                }
-               self::outputFileHeaders( $file->getMimeType(), $file->getSize() );
-               readfile( $file->getPath() );
-               return true;
+               return $file->getRepo()->streamFile( $file->getPath(),
+                       array( 'Content-Transfer-Encoding: binary',
+                               'Expires: Sun, 17-Jan-2038 19:14:07 GMT' )
+               );
        }
 
        /**