Index: trunk/phase3/includes/filerepo/LocalFile.php |
— | — | @@ -13,6 +13,15 @@ |
14 | 14 | * Provides methods to retrieve paths (physical, logical, URL), |
15 | 15 | * to generate image thumbnails or for uploading. |
16 | 16 | * |
| 17 | + * Note that only the repo object knows what its file class is called. You should |
| 18 | + * never name a file class explictly outside of the repo class. Instead use the |
| 19 | + * repo's factory functions to generate file objects, for example: |
| 20 | + * |
| 21 | + * RepoGroup::singleton()->getLocalRepo()->newFile($title); |
| 22 | + * |
| 23 | + * The convenience functions wfLocalFile() and wfFindFile() should be sufficient |
| 24 | + * in most cases. |
| 25 | + * |
17 | 26 | * @addtogroup FileRepo |
18 | 27 | */ |
19 | 28 | class LocalFile extends File |
— | — | @@ -39,10 +48,18 @@ |
40 | 49 | |
41 | 50 | /**#@-*/ |
42 | 51 | |
| 52 | + /** |
| 53 | + * Create a LocalFile from a title |
| 54 | + * Do not call this except from inside a repo class. |
| 55 | + */ |
43 | 56 | function newFromTitle( $title, $repo ) { |
44 | 57 | return new self( $title, $repo ); |
45 | 58 | } |
46 | 59 | |
| 60 | + /** |
| 61 | + * Create a LocalFile from a title |
| 62 | + * Do not call this except from inside a repo class. |
| 63 | + */ |
47 | 64 | function newFromRow( $row, $repo ) { |
48 | 65 | $title = Title::makeTitle( NS_IMAGE, $row->img_name ); |
49 | 66 | $file = new self( $title, $repo ); |
— | — | @@ -50,6 +67,10 @@ |
51 | 68 | return $file; |
52 | 69 | } |
53 | 70 | |
| 71 | + /** |
| 72 | + * Constructor. |
| 73 | + * Do not call this except from inside a repo class. |
| 74 | + */ |
54 | 75 | function __construct( $title, $repo ) { |
55 | 76 | if( !is_object( $title ) ) { |
56 | 77 | throw new MWException( __CLASS__.' constructor given bogus title.' ); |
— | — | @@ -1134,7 +1155,7 @@ |
1135 | 1156 | continue; |
1136 | 1157 | } |
1137 | 1158 | |
1138 | | - $restoredImage = new self( $row->fa_name, $this->repo ); |
| 1159 | + $restoredImage = new self( Title::makeTitle( NS_IMAGE, $row->fa_name ), $this->repo ); |
1139 | 1160 | |
1140 | 1161 | if( $revisions == 1 && !$exists ) { |
1141 | 1162 | $destPath = $restoredImage->getFullPath(); |
Index: trunk/phase3/includes/filerepo/FSRepo.php |
— | — | @@ -3,6 +3,8 @@ |
4 | 4 | /** |
5 | 5 | * A repository for files accessible via the local filesystem. Does not support |
6 | 6 | * database access or registration. |
| 7 | + * |
| 8 | + * TODO: split off abstract base FileRepo |
7 | 9 | */ |
8 | 10 | |
9 | 11 | class FSRepo { |
— | — | @@ -11,6 +13,7 @@ |
12 | 14 | var $directory, $url, $hashLevels, $thumbScriptUrl, $transformVia404; |
13 | 15 | var $descBaseUrl, $scriptDirUrl, $articleUrl, $fetchDescription; |
14 | 16 | var $fileFactory = array( 'UnregisteredLocalFile', 'newFromTitle' ); |
| 17 | + var $oldFileFactory = false; |
15 | 18 | |
16 | 19 | function __construct( $info ) { |
17 | 20 | // Required settings |
— | — | @@ -47,7 +50,11 @@ |
48 | 51 | } |
49 | 52 | } |
50 | 53 | if ( $time ) { |
51 | | - return call_user_func( $this->oldFileFactor, $title, $this, $time ); |
| 54 | + if ( $this->oldFileFactory ) { |
| 55 | + return call_user_func( $this->oldFileFactory, $title, $this, $time ); |
| 56 | + } else { |
| 57 | + return false; |
| 58 | + } |
52 | 59 | } else { |
53 | 60 | return call_user_func( $this->fileFactory, $title, $this ); |
54 | 61 | } |
— | — | @@ -61,39 +68,59 @@ |
62 | 69 | * @param mixed $time 14-character timestamp, or false for the current version |
63 | 70 | */ |
64 | 71 | function findFile( $title, $time = false ) { |
| 72 | + # First try the current version of the file to see if it precedes the timestamp |
65 | 73 | $img = $this->newFile( $title ); |
66 | 74 | if ( !$img ) { |
67 | 75 | return false; |
68 | 76 | } |
69 | | - if ( $img->exists() && $img->getTimestamp() <= $time ) { |
| 77 | + if ( $img->exists() && ( !$time || $img->getTimestamp() <= $time ) ) { |
70 | 78 | return $img; |
71 | 79 | } |
| 80 | + # Now try an old version of the file |
72 | 81 | $img = $this->newFile( $title, $time ); |
73 | 82 | if ( $img->exists() ) { |
74 | 83 | return $img; |
75 | 84 | } |
76 | 85 | } |
77 | 86 | |
| 87 | + /** |
| 88 | + * Get the public root directory of the repository. |
| 89 | + */ |
78 | 90 | function getRootDirectory() { |
79 | 91 | return $this->directory; |
80 | 92 | } |
81 | 93 | |
| 94 | + /** |
| 95 | + * Get the public root URL of the repository |
| 96 | + */ |
82 | 97 | function getRootUrl() { |
83 | 98 | return $this->url; |
84 | 99 | } |
85 | 100 | |
| 101 | + /** |
| 102 | + * Returns true if the repository uses a multi-level directory structure |
| 103 | + */ |
86 | 104 | function isHashed() { |
87 | 105 | return (bool)$this->hashLevels; |
88 | 106 | } |
89 | 107 | |
| 108 | + /** |
| 109 | + * Get the URL of thumb.php |
| 110 | + */ |
90 | 111 | function getThumbScriptUrl() { |
91 | 112 | return $this->thumbScriptUrl; |
92 | 113 | } |
93 | 114 | |
| 115 | + /** |
| 116 | + * Returns true if the repository can transform files via a 404 handler |
| 117 | + */ |
94 | 118 | function canTransformVia404() { |
95 | 119 | return $this->transformVia404; |
96 | 120 | } |
97 | 121 | |
| 122 | + /** |
| 123 | + * Get the local directory corresponding to one of the three basic zones |
| 124 | + */ |
98 | 125 | function getZonePath( $zone ) { |
99 | 126 | switch ( $zone ) { |
100 | 127 | case 'public': |
— | — | @@ -107,6 +134,9 @@ |
108 | 135 | } |
109 | 136 | } |
110 | 137 | |
| 138 | + /** |
| 139 | + * Get the URL corresponding to one of the three basic zones |
| 140 | + */ |
111 | 141 | function getZoneUrl( $zone ) { |
112 | 142 | switch ( $zone ) { |
113 | 143 | case 'public': |
— | — | @@ -205,6 +235,17 @@ |
206 | 236 | } |
207 | 237 | } |
208 | 238 | |
| 239 | + /** |
| 240 | + * Copy or move a file either from the local filesystem or from an mwrepo:// |
| 241 | + * virtual URL, into this repository at the specified destination location. |
| 242 | + * |
| 243 | + * @param string $srcPath The source path or URL |
| 244 | + * @param string $dstPath The destination relative path |
| 245 | + * @param string $archivePath The relative path where the existing file is to |
| 246 | + * be archived, if there is one. |
| 247 | + * @param integer $flags Bitfield, may be FSRepo::DELETE_SOURCE to indicate |
| 248 | + * that the source file should be deleted if possible |
| 249 | + */ |
209 | 250 | function publish( $srcPath, $dstPath, $archivePath, $flags = 0 ) { |
210 | 251 | if ( substr( $srcPath, 0, 9 ) == 'mwrepo://' ) { |
211 | 252 | $srcPath = $this->resolveVirtualUrl( $srcPath ); |
— | — | @@ -272,6 +313,9 @@ |
273 | 314 | } |
274 | 315 | } |
275 | 316 | |
| 317 | + /** |
| 318 | + * Get the name of this repository, as specified by $info['name]' to the constructor |
| 319 | + */ |
276 | 320 | function getName() { |
277 | 321 | return $this->name; |
278 | 322 | } |
Index: trunk/phase3/includes/filerepo/File.php |
— | — | @@ -10,13 +10,14 @@ |
11 | 11 | * Stub functions which should be overridden are marked with STUB. Some more |
12 | 12 | * concrete functions are also typically overridden by child classes. |
13 | 13 | * |
| 14 | + * Note that only the repo object knows what its file class is called. You should |
| 15 | + * never name a file class explictly outside of the repo class. Instead use the |
| 16 | + * repo's factory functions to generate file objects, for example: |
14 | 17 | * |
15 | | - * NOTE FOR WINDOWS USERS: |
16 | | - * To enable EXIF functions, add the folloing lines to the |
17 | | - * "Windows extensions" section of php.ini: |
| 18 | + * RepoGroup::singleton()->getLocalRepo()->newFile($title); |
18 | 19 | * |
19 | | - * extension=extensions/php_mbstring.dll |
20 | | - * extension=extensions/php_exif.dll |
| 20 | + * The convenience functions wfLocalFile() and wfFindFile() should be sufficient |
| 21 | + * in most cases. |
21 | 22 | * |
22 | 23 | * @addtogroup FileRepo |
23 | 24 | */ |
— | — | @@ -49,6 +50,9 @@ |
50 | 51 | */ |
51 | 52 | var $repo, $title, $lastError; |
52 | 53 | |
| 54 | + /** |
| 55 | + * Call this constructor from child classes |
| 56 | + */ |
53 | 57 | function __construct( $title, $repo ) { |
54 | 58 | $this->title = $title; |
55 | 59 | $this->repo = $repo; |
Index: trunk/phase3/includes/filerepo/LocalRepo.php |
— | — | @@ -5,6 +5,7 @@ |
6 | 6 | */ |
7 | 7 | class LocalRepo extends FSRepo { |
8 | 8 | var $fileFactory = array( 'LocalFile', 'newFromTitle' ); |
| 9 | + var $oldFileFactory = array( 'OldLocalFile', 'newFromTitle' ); |
9 | 10 | |
10 | 11 | function getSlaveDB() { |
11 | 12 | return wfGetDB( DB_SLAVE ); |
Index: trunk/phase3/includes/filerepo/RepoGroup.php |
— | — | @@ -1,11 +1,19 @@ |
2 | 2 | <?php |
3 | 3 | |
| 4 | +/** |
| 5 | + * Prioritized list of file repositories |
| 6 | + * @addtogroup filerepo |
| 7 | + */ |
4 | 8 | class RepoGroup { |
5 | 9 | var $localRepo, $foreignRepos, $reposInitialised = false; |
6 | 10 | var $localInfo, $foreignInfo; |
7 | 11 | |
8 | 12 | protected static $instance; |
9 | 13 | |
| 14 | + /** |
| 15 | + * Get a RepoGroup instance. At present only one instance of RepoGroup is |
| 16 | + * needed in a MediaWiki invocation, this may change in the future. |
| 17 | + */ |
10 | 18 | function singleton() { |
11 | 19 | if ( self::$instance ) { |
12 | 20 | return self::$instance; |
— | — | @@ -45,7 +53,7 @@ |
46 | 54 | return $image; |
47 | 55 | } |
48 | 56 | foreach ( $this->foreignRepos as $repo ) { |
49 | | - $image = $repo->findFile( $image, $time ); |
| 57 | + $image = $repo->findFile( $title, $time ); |
50 | 58 | if ( $image ) { |
51 | 59 | return $image; |
52 | 60 | } |
— | — | @@ -69,6 +77,10 @@ |
70 | 78 | } |
71 | 79 | } |
72 | 80 | |
| 81 | + /** |
| 82 | + * Get the local repository, i.e. the one corresponding to the local image |
| 83 | + * table. Files are typically uploaded to the local repository. |
| 84 | + */ |
73 | 85 | function getLocalRepo() { |
74 | 86 | return $this->getRepo( 'local' ); |
75 | 87 | } |
— | — | @@ -89,7 +101,10 @@ |
90 | 102 | } |
91 | 103 | } |
92 | 104 | |
93 | | - function newRepo( $info ) { |
| 105 | + /** |
| 106 | + * Create a repo class based on an info structure |
| 107 | + */ |
| 108 | + protected function newRepo( $info ) { |
94 | 109 | $class = $info['class']; |
95 | 110 | return new $class( $info ); |
96 | 111 | } |
Index: trunk/phase3/includes/DefaultSettings.php |
— | — | @@ -1405,6 +1405,13 @@ |
1406 | 1406 | /** |
1407 | 1407 | * Show EXIF data, on by default if available. |
1408 | 1408 | * Requires PHP's EXIF extension: http://www.php.net/manual/en/ref.exif.php |
| 1409 | + * |
| 1410 | + * NOTE FOR WINDOWS USERS: |
| 1411 | + * To enable EXIF functions, add the folloing lines to the |
| 1412 | + * "Windows extensions" section of php.ini: |
| 1413 | + * |
| 1414 | + * extension=extensions/php_mbstring.dll |
| 1415 | + * extension=extensions/php_exif.dll |
1409 | 1416 | */ |
1410 | 1417 | $wgShowEXIF = function_exists( 'exif_read_data' ); |
1411 | 1418 | |
Index: trunk/phase3/RELEASE-NOTES |
— | — | @@ -47,6 +47,7 @@ |
48 | 48 | file repositories. |
49 | 49 | * Added a Content-Disposition header to thumb.php output |
50 | 50 | * Improved thumb.php error handling |
| 51 | +* Display file history on local image description pages of shared images |
51 | 52 | |
52 | 53 | |
53 | 54 | == Bugfixes since 1.10 == |