Index: branches/FileBackend/phase3/tests/phpunit/includes/LocalFileTest.php |
— | — | @@ -9,25 +9,23 @@ |
10 | 10 | function setUp() { |
11 | 11 | global $wgCapitalLinks; |
12 | 12 | |
13 | | - $config = array( |
| 13 | + $wgCapitalLinks = true; |
| 14 | + |
| 15 | + $backend = new FSFileBackend( array( |
14 | 16 | 'name' => 'local-backend', |
15 | | - 'class' => 'FSFileBackend', |
16 | 17 | 'lockManager' => 'fsLockManager', |
17 | 18 | 'containerPaths' => array( |
18 | 19 | 'cont1' => "/testdir/local-backend/tempimages/cont1", |
19 | 20 | 'cont2' => "/testdir/local-backend/tempimages/cont2" |
20 | 21 | ) |
21 | | - ); |
22 | | - FileBackendGroup::singleton()->register( array( $config ) ); |
23 | | - |
24 | | - $wgCapitalLinks = true; |
| 22 | + ) ); |
25 | 23 | $info = array( |
26 | 24 | 'name' => 'test', |
27 | 25 | 'directory' => '/testdir', |
28 | 26 | 'url' => '/testurl', |
29 | 27 | 'hashLevels' => 2, |
30 | 28 | 'transformVia404' => false, |
31 | | - 'backend' => 'local-backend' |
| 29 | + 'backend' => $backend |
32 | 30 | ); |
33 | 31 | $this->repo_hl0 = new LocalRepo( array( 'hashLevels' => 0 ) + $info ); |
34 | 32 | $this->repo_hl2 = new LocalRepo( array( 'hashLevels' => 2 ) + $info ); |
Index: branches/FileBackend/phase3/tests/phpunit/includes/parser/NewParserTest.php |
— | — | @@ -56,12 +56,12 @@ |
57 | 57 | $tmpGlobals['wgStylePath'] = '/skins'; |
58 | 58 | $tmpGlobals['wgThumbnailScriptPath'] = false; |
59 | 59 | $tmpGlobals['wgLocalFileRepo'] = array( |
60 | | - 'class' => 'LocalRepo', |
61 | | - 'name' => 'local', |
62 | | - 'url' => 'http://example.com/images', |
63 | | - 'hashLevels' => 2, |
| 60 | + 'class' => 'LocalRepo', |
| 61 | + 'name' => 'local', |
| 62 | + 'url' => 'http://example.com/images', |
| 63 | + 'hashLevels' => 2, |
64 | 64 | 'transformVia404' => false, |
65 | | - 'backend' => 'local-backend' |
| 65 | + 'backend' => 'local-backend' |
66 | 66 | ); |
67 | 67 | $tmpGlobals['wgForeignFileRepos'] = array(); |
68 | 68 | $tmpGlobals['wgEnableParserCache'] = false; |
— | — | @@ -116,6 +116,7 @@ |
117 | 117 | // Restore backends |
118 | 118 | FileBackendGroup::destroySingleton(); |
119 | 119 | FileBackendGroup::singleton()->register( $GLOBALS['wgFileBackends'] ); |
| 120 | + RepoGroup::destroySingleton(); |
120 | 121 | } |
121 | 122 | |
122 | 123 | function addDBData() { |
— | — | @@ -233,12 +234,12 @@ |
234 | 235 | 'wgExtensionAssetsPath' => '/extensions', |
235 | 236 | 'wgActionPaths' => array(), |
236 | 237 | 'wgLocalFileRepo' => array( |
237 | | - 'class' => 'LocalRepo', |
238 | | - 'name' => 'local', |
239 | | - 'url' => 'http://example.com/images', |
240 | | - 'hashLevels' => 2, |
| 238 | + 'class' => 'LocalRepo', |
| 239 | + 'name' => 'local', |
| 240 | + 'url' => 'http://example.com/images', |
| 241 | + 'hashLevels' => 2, |
241 | 242 | 'transformVia404' => false, |
242 | | - 'backend' => 'local-backend' |
| 243 | + 'backend' => 'local-backend' |
243 | 244 | ), |
244 | 245 | 'wgEnableUploads' => self::getOptionValue( 'wgEnableUploads', $opts, true ), |
245 | 246 | 'wgStylePath' => '/skins', |
— | — | @@ -381,13 +382,14 @@ |
382 | 383 | * after each test runs. |
383 | 384 | */ |
384 | 385 | protected function teardownGlobals() { |
385 | | - RepoGroup::destroySingleton(); |
386 | | - LinkCache::singleton()->clear(); |
387 | | - |
388 | 386 | foreach ( $this->savedGlobals as $var => $val ) { |
389 | 387 | $GLOBALS[$var] = $val; |
390 | 388 | } |
391 | 389 | |
| 390 | + RepoGroup::destroySingleton(); |
| 391 | + LinkCache::singleton()->clear(); |
| 392 | + FileBackendGroup::destroySingleton(); |
| 393 | + |
392 | 394 | $this->teardownUploadDir( $this->uploadDir ); |
393 | 395 | } |
394 | 396 | |
Index: branches/FileBackend/phase3/tests/phpunit/suites/UploadFromUrlTestSuite.php |
— | — | @@ -26,14 +26,23 @@ |
27 | 27 | $wgStyleSheetPath = '/skins'; |
28 | 28 | $wgStylePath = '/skins'; |
29 | 29 | $wgThumbnailScriptPath = false; |
| 30 | + $backend = new FSFileBackend( array( |
| 31 | + 'name' => 'local-backend', |
| 32 | + 'lockManager' => 'fsLockManager', |
| 33 | + 'containerPaths' => array( |
| 34 | + 'images-public' => wfTempDir() . '/test-repo/public', |
| 35 | + 'images-thumb' => wfTempDir() . '/test-repo/thumb', |
| 36 | + 'images-temp' => wfTempDir() . '/test-repo/temp', |
| 37 | + 'images-deleted' => wfTempDir() . '/test-repo/delete', |
| 38 | + ) |
| 39 | + ) ); |
30 | 40 | $wgLocalFileRepo = array( |
31 | | - 'class' => 'LocalRepo', |
32 | | - 'name' => 'local', |
33 | | - 'directory' => wfTempDir() . '/test-repo', |
34 | | - 'url' => 'http://example.com/images', |
35 | | - 'deletedDir' => wfTempDir() . '/test-repo/delete', |
36 | | - 'hashLevels' => 2, |
| 41 | + 'class' => 'LocalRepo', |
| 42 | + 'name' => 'local', |
| 43 | + 'url' => 'http://example.com/images', |
| 44 | + 'hashLevels' => 2, |
37 | 45 | 'transformVia404' => false, |
| 46 | + 'backend' => $backend |
38 | 47 | ); |
39 | 48 | $wgNamespaceProtection[NS_MEDIAWIKI] = 'editinterface'; |
40 | 49 | $wgNamespaceAliases['Image'] = NS_FILE; |
Index: branches/FileBackend/phase3/tests/parser/parserTest.inc |
— | — | @@ -149,14 +149,23 @@ |
150 | 150 | $wgStylePath = '/skins'; |
151 | 151 | $wgExtensionAssetsPath = '/extensions'; |
152 | 152 | $wgThumbnailScriptPath = false; |
| 153 | + $backend = new FSFileBackend( array( |
| 154 | + 'name' => 'local-backend', |
| 155 | + 'lockManager' => 'fsLockManager', |
| 156 | + 'containerPaths' => array( |
| 157 | + 'images-public' => wfTempDir() . '/test-repo/public', |
| 158 | + 'images-thumb' => wfTempDir() . '/test-repo/thumb', |
| 159 | + 'images-temp' => wfTempDir() . '/test-repo/temp', |
| 160 | + 'images-deleted' => wfTempDir() . '/test-repo/delete', |
| 161 | + ) |
| 162 | + ) ); |
153 | 163 | $wgLocalFileRepo = array( |
154 | | - 'class' => 'LocalRepo', |
155 | | - 'name' => 'local', |
156 | | - 'directory' => wfTempDir() . '/test-repo', |
157 | | - 'url' => 'http://example.com/images', |
158 | | - 'deletedDir' => wfTempDir() . '/test-repo/delete', |
159 | | - 'hashLevels' => 2, |
| 164 | + 'class' => 'LocalRepo', |
| 165 | + 'name' => 'local', |
| 166 | + 'url' => 'http://example.com/images', |
| 167 | + 'hashLevels' => 2, |
160 | 168 | 'transformVia404' => false, |
| 169 | + 'backend' => $backend |
161 | 170 | ); |
162 | 171 | $wgNamespaceProtection[NS_MEDIAWIKI] = 'editinterface'; |
163 | 172 | $wgNamespaceAliases['Image'] = NS_FILE; |
Index: branches/FileBackend/phase3/includes/upload/UploadStash.php |
— | — | @@ -48,7 +48,7 @@ |
49 | 49 | * |
50 | 50 | * @param $repo FileRepo |
51 | 51 | */ |
52 | | - public function __construct( $repo, $user = null ) { |
| 52 | + public function __construct( FileRepo $repo, $user = null ) { |
53 | 53 | // this might change based on wiki's configuration. |
54 | 54 | $this->repo = $repo; |
55 | 55 | |
Index: branches/FileBackend/phase3/includes/filerepo/file/File.php |
— | — | @@ -751,45 +751,60 @@ |
752 | 752 | * Typical keys are width, height and page. |
753 | 753 | * @param $flags Integer: a bitfield, may contain self::RENDER_NOW to force rendering |
754 | 754 | * |
755 | | - * @return MediaTransformOutput | false |
| 755 | + * @return MediaTransformOutput|null |
756 | 756 | */ |
757 | 757 | protected function maybeDoTransform( $thumbName, $thumbUrl, $params, $flags = 0 ) { |
758 | 758 | global $wgIgnoreImageErrors, $wgThumbnailEpoch; |
759 | 759 | |
760 | | - $thumbPath = $this->getThumbPath( $thumbName ); |
761 | | - if ( $this->repo && $this->repo->canTransformVia404() && !($flags & self::RENDER_NOW ) ) { |
| 760 | + $thumbPath = $this->getThumbPath( $thumbName ); // final thumb path |
| 761 | + // Create a temp FS file with the same extension |
| 762 | + $tmpFile = TempFSFile::factory( 'transform', $this->getExtension() ); |
| 763 | + if ( !$tmpFile ) { |
| 764 | + return new MediaTransformError( 'thumbnail_error', |
| 765 | + $params['width'], 0, wfMsg( 'thumbnail-temp-create' ) ); |
| 766 | + } |
| 767 | + $tmpThumbPath = $tmpFile->getPath(); // path of 0-byte temp file |
| 768 | + |
| 769 | + if ( $this->repo && $this->repo->canTransformVia404() && !( $flags & self::RENDER_NOW ) ) { |
762 | 770 | wfDebug( __METHOD__ . " transformation deferred." ); |
763 | | - return $this->handler->getTransform( $this, $thumbPath, $thumbUrl, $params ); |
| 771 | + return $this->handler->getTransform( $this, $tmpThumbPath, $thumbUrl, $params ); |
764 | 772 | } |
765 | 773 | |
766 | 774 | wfDebug( __METHOD__.": Doing stat for $thumbPath\n" ); |
767 | 775 | $this->migrateThumbFile( $thumbName ); |
768 | | - if ( $this->repo->fileExists( $thumbPath ) && !($flags & self::RENDER_FORCE) ) { |
769 | | - $thumbTime = $this->repo->getFileTimestamp( $thumbPath ); |
770 | | - if ( $thumbTime !== false |
771 | | - && gmdate( 'YmdHis', $thumbTime ) >= $wgThumbnailEpoch ) |
772 | | - { |
773 | | - return $this->handler->getTransform( $this, $thumbPath, $thumbUrl, $params ); |
| 776 | + if ( $this->repo->fileExists( $thumbPath ) && !( $flags & self::RENDER_FORCE ) ) { |
| 777 | + $ts = $this->repo->getFileTimestamp( $thumbPath ); |
| 778 | + if ( $ts !== false && gmdate( 'YmdHis', $ts ) >= $wgThumbnailEpoch ) { |
| 779 | + return $this->handler->getTransform( $this, $tmpThumbPath, $thumbUrl, $params ); |
774 | 780 | } |
775 | | - } elseif( $flags & self::RENDER_FORCE ) { |
| 781 | + } elseif ( $flags & self::RENDER_FORCE ) { |
776 | 782 | wfDebug( __METHOD__ . " forcing rendering per flag File::RENDER_FORCE\n" ); |
777 | 783 | } |
778 | | - $thumb = $this->handler->doTransform( $this, $thumbPath, $thumbUrl, $params ); |
779 | 784 | |
| 785 | + // Actually render the thumbnail |
| 786 | + $thumb = $this->handler->doTransform( $this, $tmpThumbPath, $thumbUrl, $params ); |
| 787 | + |
780 | 788 | // Ignore errors if requested |
781 | 789 | if ( !$thumb ) { |
782 | 790 | $thumb = null; |
783 | 791 | } elseif ( $thumb->isError() ) { |
784 | 792 | $this->lastError = $thumb->toText(); |
785 | | - if ( $wgIgnoreImageErrors && !($flags & self::RENDER_NOW) ) { |
786 | | - $thumb = $this->handler->getTransform( $this, $thumbPath, $thumbUrl, $params ); |
| 793 | + if ( $wgIgnoreImageErrors && !( $flags & self::RENDER_NOW ) ) { |
| 794 | + $thumb = $this->handler->getTransform( $this, $tmpThumbPath, $thumbUrl, $params ); |
787 | 795 | } |
| 796 | + } elseif ( $thumb->hasFile() && !$thumb->fileIsSource() ) { |
| 797 | + $op = array( 'op' => 'store', |
| 798 | + 'src' => $tmpThumbPath, 'dst' => $thumbPath, 'overwriteDest' => true ); |
| 799 | + // Copy any thumbnail from the FS into storage at $dstpath |
| 800 | + if ( !$this->getRepo()->getBackend()->doOperation( $op )->isOK() ) { |
| 801 | + return new MediaTransformError( 'thumbnail_error', |
| 802 | + $params['width'], 0, wfMsg( 'thumbnail-dest-create' ) ); |
| 803 | + } |
788 | 804 | } |
789 | 805 | |
790 | 806 | return $thumb; |
791 | 807 | } |
792 | 808 | |
793 | | - |
794 | 809 | /** |
795 | 810 | * Transform a media file |
796 | 811 | * |
Index: branches/FileBackend/phase3/includes/media/MediaTransformOutput.php |
— | — | @@ -7,7 +7,7 @@ |
8 | 8 | */ |
9 | 9 | |
10 | 10 | /** |
11 | | - * Base class for the output of MediaHandler::doFSTransform() and File::transform(). |
| 11 | + * Base class for the output of MediaHandler::doTransform() and File::transform(). |
12 | 12 | * |
13 | 13 | * @ingroup Media |
14 | 14 | */ |
Index: branches/FileBackend/phase3/includes/media/SVG.php |
— | — | @@ -85,7 +85,7 @@ |
86 | 86 | * @param int $flags |
87 | 87 | * @return bool|MediaTransformError|ThumbnailImage|TransformParameterError |
88 | 88 | */ |
89 | | - function doFSTransform( $image, $dstPath, $dstUrl, $params, $flags = 0 ) { |
| 89 | + function doTransform( $image, $dstPath, $dstUrl, $params, $flags = 0 ) { |
90 | 90 | if ( !$this->normaliseParams( $image, $params ) ) { |
91 | 91 | return new TransformParameterError( $params ); |
92 | 92 | } |
Index: branches/FileBackend/phase3/includes/media/DjVu.php |
— | — | @@ -113,7 +113,7 @@ |
114 | 114 | * @param int $flags |
115 | 115 | * @return MediaTransformError|ThumbnailImage|TransformParameterError |
116 | 116 | */ |
117 | | - function doFSTransform( $image, $dstPath, $dstUrl, $params, $flags = 0 ) { |
| 117 | + function doTransform( $image, $dstPath, $dstUrl, $params, $flags = 0 ) { |
118 | 118 | global $wgDjvuRenderer, $wgDjvuPostProcessor; |
119 | 119 | |
120 | 120 | // Fetch XML and check it, to give a more informative error message than the one which |
Index: branches/FileBackend/phase3/includes/media/Bitmap.php |
— | — | @@ -106,7 +106,7 @@ |
107 | 107 | * @param int $flags |
108 | 108 | * @return MediaTransformError|ThumbnailImage|TransformParameterError |
109 | 109 | */ |
110 | | - function doFSTransform( $image, $dstPath, $dstUrl, $params, $flags = 0 ) { |
| 110 | + function doTransform( $image, $dstPath, $dstUrl, $params, $flags = 0 ) { |
111 | 111 | if ( !$this->normaliseParams( $image, $params ) ) { |
112 | 112 | return new TransformParameterError( $params ); |
113 | 113 | } |
Index: branches/FileBackend/phase3/includes/media/Bitmap_ClientOnly.php |
— | — | @@ -33,7 +33,7 @@ |
34 | 34 | * @param int $flags |
35 | 35 | * @return ThumbnailImage|TransformParameterError |
36 | 36 | */ |
37 | | - function doFSTransform( $image, $dstPath, $dstUrl, $params, $flags = 0 ) { |
| 37 | + function doTransform( $image, $dstPath, $dstUrl, $params, $flags = 0 ) { |
38 | 38 | if ( !$this->normaliseParams( $image, $params ) ) { |
39 | 39 | return new TransformParameterError( $params ); |
40 | 40 | } |
Index: branches/FileBackend/phase3/includes/media/Generic.php |
— | — | @@ -203,48 +203,9 @@ |
204 | 204 | * |
205 | 205 | * @return MediaTransformOutput |
206 | 206 | */ |
207 | | - final function doTransform( $image, $dstPath, $dstUrl, $params, $flags = 0 ) { |
208 | | - if ( FileBackend::isStoragePath( $dstPath ) ) { |
209 | | - // Create a temp FS file with the same extension |
210 | | - $tmpFile = TempFSFile::factory( 'transform', $image->getExtension() ); |
211 | | - if ( !$tmpFile ) { |
212 | | - return new MediaTransformError( 'thumbnail_error', |
213 | | - $params['width'], 0, wfMsg( 'thumbnail-temp-create' ) ); |
214 | | - } |
215 | | - $tmpDest = $tmpFile->getPath(); // path of 0-byte temp file |
216 | | - // Create the output thumbnail on the FS |
217 | | - $out = $this->doFSTransform( $image, $tmpDest, $dstUrl, $params, $flags ); |
218 | | - // Copy any thumbnail from FS into storage at $dstpath |
219 | | - // Note: no file is created if it's to be rendered client-side. |
220 | | - if ( !$out->isError() && $out->hasFile() && !$out->fileIsSource() ) { |
221 | | - $op = array( 'op' => 'store', |
222 | | - 'src' => $tmpDest, 'dst' => $dstPath, 'overwriteDest' => true ); |
223 | | - if ( !$image->getRepo()->getBackend()->doOperation( $op )->isOK() ) { |
224 | | - return new MediaTransformError( 'thumbnail_error', |
225 | | - $params['width'], 0, wfMsg( 'thumbnail-dest-create' ) ); |
226 | | - } |
227 | | - } |
228 | | - } else { |
229 | | - $out = $this->doFSTransform( $image, $dstPath, $dstUrl, $params, $flags ); |
230 | | - } |
231 | | - return $out; |
232 | | - } |
| 207 | + abstract function doTransform( $image, $dstPath, $dstUrl, $params, $flags = 0 ); |
233 | 208 | |
234 | 209 | /** |
235 | | - * Get a MediaTransformOutput object representing the transformed output. Does the |
236 | | - * transform unless $flags contains self::TRANSFORM_LATER. |
237 | | - * |
238 | | - * @param $image File: the image object |
239 | | - * @param $dstPath String: filesystem destination path |
240 | | - * @param $dstUrl String: destination URL to use in output HTML |
241 | | - * @param $params Array: arbitrary set of parameters validated by $this->validateParam() |
242 | | - * @param $flags Integer: a bitfield, may contain self::TRANSFORM_LATER |
243 | | - * |
244 | | - * @return MediaTransformOutput |
245 | | - */ |
246 | | - abstract function doFSTransform( $image, $dstPath, $dstUrl, $params, $flags = 0 ); |
247 | | - |
248 | | - /** |
249 | 210 | * Get the thumbnail extension and MIME type for a given source MIME type |
250 | 211 | * @return array thumbnail extension and MIME type |
251 | 212 | */ |