Index: branches/phase3_rev_deleted/includes/Image.php |
— | — | @@ -1,2351 +0,0 @@ |
2 | | -<?php |
3 | | -/** |
4 | | - */ |
5 | | - |
6 | | -/** |
7 | | - * NOTE FOR WINDOWS USERS: |
8 | | - * To enable EXIF functions, add the folloing lines to the |
9 | | - * "Windows extensions" section of php.ini: |
10 | | - * |
11 | | - * extension=extensions/php_mbstring.dll |
12 | | - * extension=extensions/php_exif.dll |
13 | | - */ |
14 | | - |
15 | | -/** |
16 | | - * Bump this number when serialized cache records may be incompatible. |
17 | | - */ |
18 | | -define( 'MW_IMAGE_VERSION', 2 ); |
19 | | - |
20 | | -/** |
21 | | - * Class to represent an image |
22 | | - * |
23 | | - * Provides methods to retrieve paths (physical, logical, URL), |
24 | | - * to generate thumbnails or for uploading. |
25 | | - * |
26 | | - * @addtogroup Media |
27 | | - */ |
28 | | -class Image |
29 | | -{ |
30 | | - const DELETED_FILE = 1; |
31 | | - const DELETED_COMMENT = 2; |
32 | | - const DELETED_USER = 4; |
33 | | - const DELETED_RESTRICTED = 8; |
34 | | - const RENDER_NOW = 1; |
35 | | - |
36 | | - /**#@+ |
37 | | - * @private |
38 | | - */ |
39 | | - var $name, # name of the image (constructor) |
40 | | - $imagePath, # Path of the image (loadFromXxx) |
41 | | - $url, # Image URL (accessor) |
42 | | - $title, # Title object for this image (constructor) |
43 | | - $fileExists, # does the image file exist on disk? (loadFromXxx) |
44 | | - $fromSharedDirectory, # load this image from $wgSharedUploadDirectory (loadFromXxx) |
45 | | - $historyLine, # Number of line to return by nextHistoryLine() (constructor) |
46 | | - $historyRes, # result of the query for the image's history (nextHistoryLine) |
47 | | - $width, # \ |
48 | | - $height, # | |
49 | | - $bits, # --- returned by getimagesize (loadFromXxx) |
50 | | - $attr, # / |
51 | | - $type, # MEDIATYPE_xxx (bitmap, drawing, audio...) |
52 | | - $mime, # MIME type, determined by MimeMagic::guessMimeType |
53 | | - $extension, # The file extension (constructor) |
54 | | - $size, # Size in bytes (loadFromXxx) |
55 | | - $metadata, # Metadata |
56 | | - $dataLoaded, # Whether or not all this has been loaded from the database (loadFromXxx) |
57 | | - $page, # Page to render when creating thumbnails |
58 | | - $lastError, # Error string associated with a thumbnail display error |
59 | | - $timeframe, # Loads the image as it was at this time (if public) |
60 | | - $oldimage; # Is this an old version? |
61 | | - |
62 | | - |
63 | | - /**#@-*/ |
64 | | - |
65 | | - /** |
66 | | - * Create an Image object from an image name |
67 | | - * |
68 | | - * @param string $name name of the image, used to create a title object using Title::makeTitleSafe |
69 | | - * @return Image |
70 | | - * @public |
71 | | - */ |
72 | | - public static function newFromName( $name ) { |
73 | | - $title = Title::makeTitleSafe( NS_IMAGE, $name ); |
74 | | - if ( is_object( $title ) ) { |
75 | | - return new Image( $title ); |
76 | | - } else { |
77 | | - return NULL; |
78 | | - } |
79 | | - } |
80 | | - |
81 | | - /** |
82 | | - * Obsolete factory function, use constructor |
83 | | - * @param Title $title |
84 | | - * @return Image |
85 | | - * @deprecated |
86 | | - */ |
87 | | - function newFromTitle( $title ) { |
88 | | - return new Image( $title ); |
89 | | - } |
90 | | - |
91 | | - /** |
92 | | - * Constructor |
93 | | - * @param Title $title |
94 | | - * @return void |
95 | | - */ |
96 | | - function Image( $title, $timeframe=null ) { |
97 | | - if( !is_object( $title ) ) { |
98 | | - throw new MWException( 'Image constructor given bogus title.' ); |
99 | | - } |
100 | | - $this->title =& $title; |
101 | | - // Name used for hash dir |
102 | | - $this->name = $title->getDBkey(); |
103 | | - $this->fileName = $this->name; |
104 | | - // $timeframe is for getting images from a time period |
105 | | - $this->timeframe = $timeframe; |
106 | | - $this->oldimage = false; |
107 | | - |
108 | | - $this->metadata = ''; |
109 | | - |
110 | | - $n = strrpos( $this->name, '.' ); |
111 | | - $this->extension = Image::normalizeExtension( $n ? |
112 | | - substr( $this->name, $n + 1 ) : '' ); |
113 | | - $this->historyLine = 0; |
114 | | - |
115 | | - $this->dataLoaded = false; |
116 | | - } |
117 | | - |
118 | | - /** |
119 | | - * Normalize a file extension to the common form, and ensure it's clean. |
120 | | - * Extensions with non-alphanumeric characters will be discarded. |
121 | | - * |
122 | | - * @param string $ext (without the .) |
123 | | - * @return string |
124 | | - */ |
125 | | - static function normalizeExtension( $ext ) { |
126 | | - $lower = strtolower( $ext ); |
127 | | - $squish = array( |
128 | | - 'htm' => 'html', |
129 | | - 'jpeg' => 'jpg', |
130 | | - 'mpeg' => 'mpg', |
131 | | - 'tiff' => 'tif' ); |
132 | | - if( isset( $squish[$lower] ) ) { |
133 | | - return $squish[$lower]; |
134 | | - } elseif( preg_match( '/^[0-9a-z]+$/', $lower ) ) { |
135 | | - return $lower; |
136 | | - } else { |
137 | | - return ''; |
138 | | - } |
139 | | - } |
140 | | - |
141 | | - /** |
142 | | - * Get the memcached keys |
143 | | - * @return array[int]mixed Returns an array, first element is the local cache key, second is the shared cache key, if there is one |
144 | | - */ |
145 | | - function getCacheKeys( ) { |
146 | | - global $wgUseSharedUploads, $wgSharedUploadDBname, $wgCacheSharedUploads; |
147 | | - |
148 | | - $hashedName = md5($this->name); |
149 | | - $keys = array( wfMemcKey( 'Image', $hashedName ) ); |
150 | | - if ( $wgUseSharedUploads && $wgSharedUploadDBname && $wgCacheSharedUploads ) { |
151 | | - $keys[] = wfForeignMemcKey( $wgSharedUploadDBname, false, 'Image', $hashedName ); |
152 | | - } |
153 | | - return $keys; |
154 | | - } |
155 | | - |
156 | | - /** |
157 | | - * Try to load image metadata from memcached. Returns true on success. |
158 | | - */ |
159 | | - function loadFromCache() { |
160 | | - global $wgUseSharedUploads, $wgMemc; |
161 | | - wfProfileIn( __METHOD__ ); |
162 | | - $this->dataLoaded = false; |
163 | | - $keys = $this->getCacheKeys(); |
164 | | - $cachedValues = $wgMemc->get( $keys[0] ); |
165 | | - |
166 | | - // Check if the key existed and belongs to this version of MediaWiki |
167 | | - if (!empty($cachedValues) && is_array($cachedValues) |
168 | | - && isset($cachedValues['version']) && ( $cachedValues['version'] == MW_IMAGE_VERSION ) |
169 | | - && isset( $cachedValues['mime'] ) && isset( $cachedValues['metadata'] ) ) |
170 | | - { |
171 | | - if ( $wgUseSharedUploads && $cachedValues['fromShared']) { |
172 | | - # if this is shared file, we need to check if image |
173 | | - # in shared repository has not changed |
174 | | - if ( isset( $keys[1] ) ) { |
175 | | - $commonsCachedValues = $wgMemc->get( $keys[1] ); |
176 | | - if (!empty($commonsCachedValues) && is_array($commonsCachedValues) |
177 | | - && isset($commonsCachedValues['version']) |
178 | | - && ( $commonsCachedValues['version'] == MW_IMAGE_VERSION ) |
179 | | - && isset($commonsCachedValues['mime'])) { |
180 | | - wfDebug( "Pulling image metadata from shared repository cache\n" ); |
181 | | - $this->name = $commonsCachedValues['name']; |
182 | | - $this->imagePath = $commonsCachedValues['imagePath']; |
183 | | - $this->fileExists = $commonsCachedValues['fileExists']; |
184 | | - $this->width = $commonsCachedValues['width']; |
185 | | - $this->height = $commonsCachedValues['height']; |
186 | | - $this->bits = $commonsCachedValues['bits']; |
187 | | - $this->type = $commonsCachedValues['type']; |
188 | | - $this->mime = $commonsCachedValues['mime']; |
189 | | - $this->metadata = $commonsCachedValues['metadata']; |
190 | | - $this->size = $commonsCachedValues['size']; |
191 | | - $this->fromSharedDirectory = true; |
192 | | - $this->dataLoaded = true; |
193 | | - $this->imagePath = $this->getFullPath(true); |
194 | | - } |
195 | | - } |
196 | | - } else { |
197 | | - wfDebug( "Pulling image metadata from local cache\n" ); |
198 | | - $this->name = $cachedValues['name']; |
199 | | - $this->imagePath = $cachedValues['imagePath']; |
200 | | - $this->fileExists = $cachedValues['fileExists']; |
201 | | - $this->width = $cachedValues['width']; |
202 | | - $this->height = $cachedValues['height']; |
203 | | - $this->bits = $cachedValues['bits']; |
204 | | - $this->type = $cachedValues['type']; |
205 | | - $this->mime = $cachedValues['mime']; |
206 | | - $this->metadata = $cachedValues['metadata']; |
207 | | - $this->size = $cachedValues['size']; |
208 | | - $this->fromSharedDirectory = false; |
209 | | - $this->dataLoaded = true; |
210 | | - $this->imagePath = $this->getFullPath(); |
211 | | - } |
212 | | - } |
213 | | - if ( $this->dataLoaded ) { |
214 | | - wfIncrStats( 'image_cache_hit' ); |
215 | | - } else { |
216 | | - wfIncrStats( 'image_cache_miss' ); |
217 | | - } |
218 | | - |
219 | | - wfProfileOut( __METHOD__ ); |
220 | | - return $this->dataLoaded; |
221 | | - } |
222 | | - |
223 | | - /** |
224 | | - * Save the image metadata to memcached |
225 | | - */ |
226 | | - function saveToCache() { |
227 | | - global $wgMemc, $wgUseSharedUploads; |
228 | | - $this->load(); |
229 | | - $keys = $this->getCacheKeys(); |
230 | | - // We can't cache negative metadata for non-existent files, |
231 | | - // because if the file later appears in commons, the local |
232 | | - // keys won't be purged. |
233 | | - if ( $this->fileExists || !$wgUseSharedUploads ) { |
234 | | - $cachedValues = array( |
235 | | - 'version' => MW_IMAGE_VERSION, |
236 | | - 'name' => $this->name, |
237 | | - 'imagePath' => $this->imagePath, |
238 | | - 'fileExists' => $this->fileExists, |
239 | | - 'fromShared' => $this->fromSharedDirectory, |
240 | | - 'width' => $this->width, |
241 | | - 'height' => $this->height, |
242 | | - 'bits' => $this->bits, |
243 | | - 'type' => $this->type, |
244 | | - 'mime' => $this->mime, |
245 | | - 'metadata' => $this->metadata, |
246 | | - 'size' => $this->size ); |
247 | | - |
248 | | - $wgMemc->set( $keys[0], $cachedValues, 60 * 60 * 24 * 7 ); // A week |
249 | | - } else { |
250 | | - // However we should clear them, so they aren't leftover |
251 | | - // if we've deleted the file. |
252 | | - $wgMemc->delete( $keys[0] ); |
253 | | - } |
254 | | - } |
255 | | - |
256 | | - /** |
257 | | - * Load metadata from the file itself |
258 | | - */ |
259 | | - function loadFromFile() { |
260 | | - global $wgUseSharedUploads, $wgSharedUploadDirectory, $wgContLang; |
261 | | - wfProfileIn( __METHOD__ ); |
262 | | - $this->imagePath = $this->getFullPath(); |
263 | | - $this->fileExists = file_exists( $this->imagePath ); |
264 | | - $this->fromSharedDirectory = false; |
265 | | - $gis = array(); |
266 | | - |
267 | | - if (!$this->fileExists) wfDebug(__METHOD__.': '.$this->imagePath." not found locally!\n"); |
268 | | - |
269 | | - # If the file is not found, and a shared upload directory is used, look for it there. |
270 | | - if (!$this->fileExists && $wgUseSharedUploads && $wgSharedUploadDirectory) { |
271 | | - # In case we're on a wgCapitalLinks=false wiki, we |
272 | | - # capitalize the first letter of the filename before |
273 | | - # looking it up in the shared repository. |
274 | | - $sharedImage = Image::newFromName( $wgContLang->ucfirst($this->name) ); |
275 | | - $this->fileExists = $sharedImage && file_exists( $sharedImage->getFullPath(true) ); |
276 | | - if ( $this->fileExists ) { |
277 | | - $this->name = $sharedImage->name; |
278 | | - $this->imagePath = $this->getFullPath(true); |
279 | | - $this->fromSharedDirectory = true; |
280 | | - } |
281 | | - } |
282 | | - |
283 | | - |
284 | | - if ( $this->fileExists ) { |
285 | | - $magic=& MimeMagic::singleton(); |
286 | | - |
287 | | - $this->mime = $magic->guessMimeType($this->imagePath,true); |
288 | | - $this->type = $magic->getMediaType($this->imagePath,$this->mime); |
289 | | - $handler = MediaHandler::getHandler( $this->mime ); |
290 | | - |
291 | | - # Get size in bytes |
292 | | - $this->size = filesize( $this->imagePath ); |
293 | | - |
294 | | - # Height, width and metadata |
295 | | - if ( $handler ) { |
296 | | - $gis = $handler->getImageSize( $this, $this->imagePath ); |
297 | | - $this->metadata = $handler->getMetadata( $this, $this->imagePath ); |
298 | | - } else { |
299 | | - $gis = false; |
300 | | - $this->metadata = ''; |
301 | | - } |
302 | | - |
303 | | - wfDebug(__METHOD__.': '.$this->imagePath." loaded, ".$this->size." bytes, ".$this->mime.".\n"); |
304 | | - } |
305 | | - else { |
306 | | - $this->mime = NULL; |
307 | | - $this->type = MEDIATYPE_UNKNOWN; |
308 | | - $this->metadata = ''; |
309 | | - wfDebug(__METHOD__.': '.$this->imagePath." NOT FOUND!\n"); |
310 | | - } |
311 | | - |
312 | | - if( $gis ) { |
313 | | - $this->width = $gis[0]; |
314 | | - $this->height = $gis[1]; |
315 | | - } else { |
316 | | - $this->width = 0; |
317 | | - $this->height = 0; |
318 | | - } |
319 | | - |
320 | | - #NOTE: $gis[2] contains a code for the image type. This is no longer used. |
321 | | - |
322 | | - #NOTE: we have to set this flag early to avoid load() to be called |
323 | | - # be some of the functions below. This may lead to recursion or other bad things! |
324 | | - # as ther's only one thread of execution, this should be safe anyway. |
325 | | - $this->dataLoaded = true; |
326 | | - |
327 | | - if ( isset( $gis['bits'] ) ) $this->bits = $gis['bits']; |
328 | | - else $this->bits = 0; |
329 | | - |
330 | | - wfProfileOut( __METHOD__ ); |
331 | | - } |
332 | | - |
333 | | - /** |
334 | | - * Load image metadata from the DB |
335 | | - */ |
336 | | - function loadFromDB() { |
337 | | - global $wgUseSharedUploads, $wgSharedUploadDBname, $wgSharedUploadDBprefix, $wgContLang; |
338 | | - wfProfileIn( __METHOD__ ); |
339 | | - |
340 | | - $dbr = wfGetDB( DB_SLAVE ); |
341 | | - // Our we we looking for images from a certain timeframe? |
342 | | - // Selective restore can make this become borked |
343 | | - // --use of oi_deleted avoids this |
344 | | - $frame = $this->timeframe ? "img_timestamp < {$this->timeframe}" : '1 = 1'; |
345 | | - // Try the current image |
346 | | - $result = $dbr->select( 'image', |
347 | | - array( 'img_size', 'img_width', 'img_height', 'img_bits', |
348 | | - 'img_media_type', 'img_major_mime', 'img_minor_mime', 'img_metadata' ), |
349 | | - array( 'img_name' => $this->name, $frame ), |
350 | | - __METHOD__ ); |
351 | | - $row = $dbr->fetchObject($result); |
352 | | - // Try older images if not found... |
353 | | - if ( $this->timeframe && !$row ) { |
354 | | - $result = $dbr->select( 'oldimage', |
355 | | - array( 'oi_archive_name','oi_width as img_width','oi_height as img_height','oi_bits as img_bits', |
356 | | - 'oi_size as img_size','oi_media_type as img_media_type', 'oi_metadata as img_metadata', |
357 | | - 'oi_major_mime as img_major_mime','oi_minor_mime as img_minor_mime','oi_deleted'), |
358 | | - array( 'oi_name' => $this->name, "oi_timestamp < {$this->timeframe}" ), |
359 | | - __METHOD__, |
360 | | - array('ORDER BY' => 'oi_timestamp DESC', 'LIMIT' => 1) ); |
361 | | - if ( $row = $dbr->fetchObject($result) ) { |
362 | | - # Set our name to the correct file name |
363 | | - if ( $row->oi_deleted & Image::DELETED_FILE ) { |
364 | | - $row = null; // public only |
365 | | - } else { |
366 | | - $this->fileName = $row->oi_archive_name; |
367 | | - $this->oldimage = true; |
368 | | - } |
369 | | - } |
370 | | - } |
371 | | - if ( $row ) { |
372 | | - $this->fromSharedDirectory = false; |
373 | | - $this->fileExists = true; |
374 | | - |
375 | | - $this->imagePath = $this->getFullPath(); |
376 | | - $this->loadFromRow( $row ); |
377 | | - // Check for rows from a previous schema, quietly upgrade them |
378 | | - $this->maybeUpgradeRow(); |
379 | | - } elseif ( $wgUseSharedUploads && $wgSharedUploadDBname ) { |
380 | | - # In case we're on a wgCapitalLinks=false wiki, we |
381 | | - # capitalize the first letter of the filename before |
382 | | - # looking it up in the shared repository. |
383 | | - $name = $wgContLang->ucfirst($this->name); |
384 | | - $dbc = Image::getCommonsDB(); |
385 | | - // Try the current image |
386 | | - $result = $dbc->select( "`$wgSharedUploadDBname`.{$wgSharedUploadDBprefix}image", |
387 | | - array('img_size', 'img_width', 'img_height', 'img_bits', |
388 | | - 'img_media_type', 'img_major_mime', 'img_minor_mime', 'img_metadata' ), |
389 | | - array( 'img_name' => $name, $frame ), |
390 | | - __METHOD__ ); |
391 | | - // Try older images if not found... |
392 | | - if ( !$row && $this->timeframe ) { |
393 | | - $result = $dbc->select( "`$wgSharedUploadDBname`.{$wgSharedUploadDBprefix}oldimage", |
394 | | - array( 'oi_archive_name','oi_width as img_width','oi_height as img_height','oi_bits as img_bits', |
395 | | - 'oi_size as img_size','oi_media_type as img_media_type', 'oi_metadata as img_metadata', |
396 | | - 'oi_major_mime as img_major_mime','oi_minor_mime as img_minor_mime','oi_deleted'), |
397 | | - array( 'oi_name' => $this->name, "oi_timestamp < {$this->timeframe}" ), |
398 | | - __METHOD__, |
399 | | - array('ORDER BY' => 'oi_timestamp DESC', 'LIMIT' => 1) ); |
400 | | - // If we found one... |
401 | | - if ( $row = $dbr->fetchObject($result) ) { |
402 | | - # Set our name to the correct file name |
403 | | - if ( $row->oi_deleted & Image::DELETED_FILE ) { |
404 | | - $row = null; // public only |
405 | | - } else { |
406 | | - $this->fileName = $row->oi_archive_name; |
407 | | - $this->oldimage = true; |
408 | | - } |
409 | | - } |
410 | | - } |
411 | | - if ( $row ) { |
412 | | - $this->fromSharedDirectory = true; |
413 | | - $this->fileExists = true; |
414 | | - $this->imagePath = $this->getFullPath(true); |
415 | | - $this->name = $name; |
416 | | - $this->loadFromRow( $row ); |
417 | | - // Check for rows from a previous schema, quietly upgrade them |
418 | | - $this->maybeUpgradeRow(); |
419 | | - } |
420 | | - } |
421 | | - |
422 | | - if ( !$row ) { |
423 | | - $this->size = 0; |
424 | | - $this->width = 0; |
425 | | - $this->height = 0; |
426 | | - $this->bits = 0; |
427 | | - $this->type = 0; |
428 | | - $this->fileExists = false; |
429 | | - $this->fromSharedDirectory = false; |
430 | | - $this->metadata = ''; |
431 | | - $this->mime = false; |
432 | | - } |
433 | | - |
434 | | - # Unconditionally set loaded=true, we don't want the accessors constantly rechecking |
435 | | - $this->dataLoaded = true; |
436 | | - wfProfileOut( __METHOD__ ); |
437 | | - } |
438 | | - |
439 | | - /* |
440 | | - * Load image metadata from a DB result row |
441 | | - */ |
442 | | - function loadFromRow( &$row ) { |
443 | | - $this->size = isset($row->img_size) ? $row->img_size : null; |
444 | | - $this->width = isset($row->img_width) ? $row->img_width : null; |
445 | | - $this->height = isset($row->img_height) ? $row->img_height : null; |
446 | | - $this->bits = isset($row->img_bits) ? $row->img_bits : null; |
447 | | - $this->type = isset($row->img_media_type) ? $row->img_media_type : null; |
448 | | - |
449 | | - $major = isset($row->img_major_mime) ? $row->img_major_mime : null; |
450 | | - $minor = isset($row->img_minor_mime) ? $row->img_minor_mime : null; |
451 | | - |
452 | | - if (!$major) $this->mime = "unknown/unknown"; |
453 | | - else { |
454 | | - if (!$minor) $minor= "unknown"; |
455 | | - $this->mime = $major.'/'.$minor; |
456 | | - } |
457 | | - $this->metadata = isset($row->img_metadata) ? $row->img_metadata : null; |
458 | | - |
459 | | - $this->dataLoaded = true; |
460 | | - } |
461 | | - |
462 | | - /** |
463 | | - * Load image metadata from cache or DB, unless already loaded |
464 | | - */ |
465 | | - function load() { |
466 | | - global $wgSharedUploadDBname, $wgUseSharedUploads; |
467 | | - if ( !$this->dataLoaded ) { |
468 | | - if ( !$this->loadFromCache() ) { |
469 | | - $this->loadFromDB(); |
470 | | - if ( !$wgSharedUploadDBname && $wgUseSharedUploads ) { |
471 | | - $this->loadFromFile(); |
472 | | - } elseif ( $this->fileExists || !$wgUseSharedUploads ) { |
473 | | - // We can do negative caching for local images, because the cache |
474 | | - // will be purged on upload. But we can't do it when shared images |
475 | | - // are enabled, since updates to that won't purge foreign caches. |
476 | | - $this->saveToCache(); |
477 | | - } |
478 | | - } |
479 | | - $this->dataLoaded = true; |
480 | | - } |
481 | | - } |
482 | | - |
483 | | - /** |
484 | | - * Upgrade a row if it needs it |
485 | | - * @return void |
486 | | - */ |
487 | | - function maybeUpgradeRow() { |
488 | | - if ( is_null($this->type) || $this->mime == 'image/svg' ) { |
489 | | - $this->upgradeRow(); |
490 | | - } else { |
491 | | - $handler = $this->getHandler(); |
492 | | - if ( $handler && !$handler->isMetadataValid( $this, $this->metadata ) ) { |
493 | | - $this->upgradeRow(); |
494 | | - } |
495 | | - } |
496 | | - } |
497 | | - |
498 | | - /** |
499 | | - * Fix assorted version-related problems with the image row by reloading it from the file |
500 | | - */ |
501 | | - function upgradeRow() { |
502 | | - global $wgDBname, $wgSharedUploadDBname; |
503 | | - wfProfileIn( __METHOD__ ); |
504 | | - |
505 | | - $this->loadFromFile(); |
506 | | - |
507 | | - if ( $this->fromSharedDirectory ) { |
508 | | - if ( !$wgSharedUploadDBname ) { |
509 | | - wfProfileOut( __METHOD__ ); |
510 | | - return; |
511 | | - } |
512 | | - |
513 | | - // Write to the other DB using selectDB, not database selectors |
514 | | - // This avoids breaking replication in MySQL |
515 | | - $dbw = Image::getCommonsDB(); |
516 | | - } else { |
517 | | - $dbw = wfGetDB( DB_MASTER ); |
518 | | - } |
519 | | - |
520 | | - list( $major, $minor ) = self::splitMime( $this->mime ); |
521 | | - |
522 | | - wfDebug(__METHOD__.': upgrading '.$this->name." to the current schema\n"); |
523 | | - // Is this an old or current image? |
524 | | - if ( !$this->oldimage ) { |
525 | | - $dbw->update( 'image', |
526 | | - array( |
527 | | - 'img_width' => $this->width, |
528 | | - 'img_height' => $this->height, |
529 | | - 'img_bits' => $this->bits, |
530 | | - 'img_media_type' => $this->type, |
531 | | - 'img_major_mime' => $major, |
532 | | - 'img_minor_mime' => $minor, |
533 | | - 'img_metadata' => $this->metadata, |
534 | | - ), array( 'img_name' => $this->name ), __METHOD__ |
535 | | - ); |
536 | | - } else { |
537 | | - $dbw->update( 'oldimage', |
538 | | - array( |
539 | | - 'oi_width' => $this->width, |
540 | | - 'oi_height' => $this->height, |
541 | | - 'oi_bits' => $this->bits, |
542 | | - 'oi_media_type' => $this->type, |
543 | | - 'oi_major_mime' => $major, |
544 | | - 'oi_minor_mime' => $minor, |
545 | | - 'oi_metadata' => $this->metadata, |
546 | | - ), array( 'oi_archive_name' => $this->fileName ), __METHOD__ |
547 | | - ); |
548 | | - } |
549 | | - if ( $this->fromSharedDirectory ) { |
550 | | - $dbw->selectDB( $wgDBname ); |
551 | | - } |
552 | | - wfProfileOut( __METHOD__ ); |
553 | | - } |
554 | | - |
555 | | - /** |
556 | | - * Split an internet media type into its two components; if not |
557 | | - * a two-part name, set the minor type to 'unknown'. |
558 | | - * |
559 | | - * @param string $mime "text/html" etc |
560 | | - * @return array ("text", "html") etc |
561 | | - */ |
562 | | - static function splitMime( $mime ) { |
563 | | - if( strpos( $mime, '/' ) !== false ) { |
564 | | - return explode( '/', $mime, 2 ); |
565 | | - } else { |
566 | | - return array( $mime, 'unknown' ); |
567 | | - } |
568 | | - } |
569 | | - |
570 | | - /** |
571 | | - * Return the name of this image |
572 | | - * @public |
573 | | - */ |
574 | | - function getName() { |
575 | | - return $this->name; |
576 | | - } |
577 | | - |
578 | | - /** |
579 | | - * Return the associated title object |
580 | | - * @public |
581 | | - */ |
582 | | - function getTitle() { |
583 | | - return $this->title; |
584 | | - } |
585 | | - |
586 | | - /** |
587 | | - * Return the URL of the image file |
588 | | - * @public |
589 | | - */ |
590 | | - function getURL() { |
591 | | - if ( !$this->url ) { |
592 | | - $this->load(); |
593 | | - if($this->fileExists) { |
594 | | - $this->url = Image::imageUrl( $this->name, $this->fromSharedDirectory ); |
595 | | - } else { |
596 | | - $this->url = ''; |
597 | | - } |
598 | | - } |
599 | | - return $this->url; |
600 | | - } |
601 | | - |
602 | | - function getViewURL() { |
603 | | - if( $this->mustRender()) { |
604 | | - if( $this->canRender() ) { |
605 | | - return $this->createThumb( $this->getWidth() ); |
606 | | - } |
607 | | - else { |
608 | | - wfDebug('Image::getViewURL(): supposed to render '.$this->name.' ('.$this->mime."), but can't!\n"); |
609 | | - return $this->getURL(); #hm... return NULL? |
610 | | - } |
611 | | - } else { |
612 | | - return $this->getURL(); |
613 | | - } |
614 | | - } |
615 | | - |
616 | | - /** |
617 | | - * Return the image path of the image in the |
618 | | - * local file system as an absolute path |
619 | | - * @public |
620 | | - */ |
621 | | - function getImagePath() { |
622 | | - $this->load(); |
623 | | - return $this->imagePath; |
624 | | - } |
625 | | - |
626 | | - /** |
627 | | - * @return mixed Return the width of the image; returns false on error. |
628 | | - * @param int $page Page number to find the width of. |
629 | | - * @public |
630 | | - */ |
631 | | - function getWidth( $page = 1 ) { |
632 | | - $this->load(); |
633 | | - if ( $this->isMultipage() ) { |
634 | | - $dim = $this->getHandler()->getPageDimensions( $this, $page ); |
635 | | - if ( $dim ) { |
636 | | - return $dim['width']; |
637 | | - } else { |
638 | | - return false; |
639 | | - } |
640 | | - } else { |
641 | | - return $this->width; |
642 | | - } |
643 | | - } |
644 | | - |
645 | | - /** |
646 | | - * @return mixed Return the height of the image; Returns false on error. |
647 | | - * @param int $page Page number to find the height of. |
648 | | - * @public |
649 | | - */ |
650 | | - function getHeight( $page = 1 ) { |
651 | | - $this->load(); |
652 | | - if ( $this->isMultipage() ) { |
653 | | - $dim = $this->getHandler()->getPageDimensions( $this, $page ); |
654 | | - if ( $dim ) { |
655 | | - return $dim['height']; |
656 | | - } else { |
657 | | - return false; |
658 | | - } |
659 | | - } else { |
660 | | - return $this->height; |
661 | | - } |
662 | | - } |
663 | | - |
664 | | - /** |
665 | | - * Get handler-specific metadata |
666 | | - */ |
667 | | - function getMetadata() { |
668 | | - $this->load(); |
669 | | - return $this->metadata; |
670 | | - } |
671 | | - |
672 | | - /** |
673 | | - * @return int the size of the image file, in bytes |
674 | | - * @public |
675 | | - */ |
676 | | - function getSize() { |
677 | | - $this->load(); |
678 | | - return $this->size; |
679 | | - } |
680 | | - |
681 | | - /** |
682 | | - * @return string the mime type of the file. |
683 | | - */ |
684 | | - function getMimeType() { |
685 | | - $this->load(); |
686 | | - return $this->mime; |
687 | | - } |
688 | | - |
689 | | - /** |
690 | | - * Return the type of the media in the file. |
691 | | - * Use the value returned by this function with the MEDIATYPE_xxx constants. |
692 | | - */ |
693 | | - function getMediaType() { |
694 | | - $this->load(); |
695 | | - return $this->type; |
696 | | - } |
697 | | - |
698 | | - /** |
699 | | - * Checks if the file can be presented to the browser as a bitmap. |
700 | | - * |
701 | | - * Currently, this checks if the file is an image format |
702 | | - * that can be converted to a format |
703 | | - * supported by all browsers (namely GIF, PNG and JPEG), |
704 | | - * or if it is an SVG image and SVG conversion is enabled. |
705 | | - * |
706 | | - * @todo remember the result of this check. |
707 | | - * @return boolean |
708 | | - */ |
709 | | - function canRender() { |
710 | | - $handler = $this->getHandler(); |
711 | | - return $handler && $handler->canRender(); |
712 | | - } |
713 | | - |
714 | | - /** |
715 | | - * Return true if the file is of a type that can't be directly |
716 | | - * rendered by typical browsers and needs to be re-rasterized. |
717 | | - * |
718 | | - * This returns true for everything but the bitmap types |
719 | | - * supported by all browsers, i.e. JPEG; GIF and PNG. It will |
720 | | - * also return true for any non-image formats. |
721 | | - * |
722 | | - * @return bool |
723 | | - */ |
724 | | - function mustRender() { |
725 | | - $handler = $this->getHandler(); |
726 | | - return $handler && $handler->mustRender(); |
727 | | - } |
728 | | - |
729 | | - /** |
730 | | - * Determines if this media file may be shown inline on a page. |
731 | | - * |
732 | | - * This is currently synonymous to canRender(), but this could be |
733 | | - * extended to also allow inline display of other media, |
734 | | - * like flash animations or videos. If you do so, please keep in mind that |
735 | | - * that could be a security risk. |
736 | | - */ |
737 | | - function allowInlineDisplay() { |
738 | | - return $this->canRender(); |
739 | | - } |
740 | | - |
741 | | - /** |
742 | | - * Determines if this media file is in a format that is unlikely to |
743 | | - * contain viruses or malicious content. It uses the global |
744 | | - * $wgTrustedMediaFormats list to determine if the file is safe. |
745 | | - * |
746 | | - * This is used to show a warning on the description page of non-safe files. |
747 | | - * It may also be used to disallow direct [[media:...]] links to such files. |
748 | | - * |
749 | | - * Note that this function will always return true if allowInlineDisplay() |
750 | | - * or isTrustedFile() is true for this file. |
751 | | - * |
752 | | - * @return boolean |
753 | | - */ |
754 | | - function isSafeFile() { |
755 | | - if ($this->allowInlineDisplay()) return true; |
756 | | - if ($this->isTrustedFile()) return true; |
757 | | - |
758 | | - global $wgTrustedMediaFormats; |
759 | | - |
760 | | - $type= $this->getMediaType(); |
761 | | - $mime= $this->getMimeType(); |
762 | | - #wfDebug("Image::isSafeFile: type= $type, mime= $mime\n"); |
763 | | - |
764 | | - if (!$type || $type===MEDIATYPE_UNKNOWN) return false; #unknown type, not trusted |
765 | | - if ( in_array( $type, $wgTrustedMediaFormats) ) return true; |
766 | | - |
767 | | - if ($mime==="unknown/unknown") return false; #unknown type, not trusted |
768 | | - if ( in_array( $mime, $wgTrustedMediaFormats) ) return true; |
769 | | - |
770 | | - return false; |
771 | | - } |
772 | | - |
773 | | - /** |
774 | | - * Returns true if the file is flagged as trusted. Files flagged that way |
775 | | - * can be linked to directly, even if that is not allowed for this type of |
776 | | - * file normally. |
777 | | - * |
778 | | - * This is a dummy function right now and always returns false. It could be |
779 | | - * implemented to extract a flag from the database. The trusted flag could be |
780 | | - * set on upload, if the user has sufficient privileges, to bypass script- |
781 | | - * and html-filters. It may even be coupled with cryptographics signatures |
782 | | - * or such. |
783 | | - * @return boolean |
784 | | - */ |
785 | | - function isTrustedFile() { |
786 | | - #this could be implemented to check a flag in the database, |
787 | | - #look for signatures, etc |
788 | | - return false; |
789 | | - } |
790 | | - |
791 | | - /** |
792 | | - * Return the escapeLocalURL of this image |
793 | | - * @param string $query URL query string |
794 | | - * @public |
795 | | - */ |
796 | | - function getEscapeLocalURL( $query=false) { |
797 | | - return $this->getTitle()->escapeLocalURL( $query ); |
798 | | - } |
799 | | - |
800 | | - /** |
801 | | - * Return the escapeFullURL of this image |
802 | | - * @public |
803 | | - */ |
804 | | - function getEscapeFullURL() { |
805 | | - $this->getTitle(); |
806 | | - return $this->title->escapeFullURL(); |
807 | | - } |
808 | | - |
809 | | - /** |
810 | | - * Return the URL of an image, provided its name. |
811 | | - * |
812 | | - * @param string $name Name of the image, without the leading "Image:" |
813 | | - * @param boolean $fromSharedDirectory Should this be in $wgSharedUploadPath? |
814 | | - * @return string URL of $name image |
815 | | - * @public |
816 | | - */ |
817 | | - static function imageUrl( $name, $fromSharedDirectory = false ) { |
818 | | - global $wgUploadPath,$wgUploadBaseUrl,$wgSharedUploadPath; |
819 | | - if($fromSharedDirectory) { |
820 | | - $base = ''; |
821 | | - $path = $wgSharedUploadPath; |
822 | | - } else { |
823 | | - $base = $wgUploadBaseUrl; |
824 | | - $path = $wgUploadPath; |
825 | | - } |
826 | | - $url = "{$base}{$path}" . wfGetHashPath($name, $fromSharedDirectory) . "{$name}"; |
827 | | - return wfUrlencode( $url ); |
828 | | - } |
829 | | - |
830 | | - /** |
831 | | - * Returns true if the image file exists on disk. |
832 | | - * @return boolean Whether image file exist on disk. |
833 | | - * @public |
834 | | - */ |
835 | | - function exists() { |
836 | | - $this->load(); |
837 | | - return $this->fileExists; |
838 | | - } |
839 | | - |
840 | | - /** |
841 | | - * @todo document |
842 | | - * @param string $thumbName |
843 | | - * @param string $subdir |
844 | | - * @return string |
845 | | - * @private |
846 | | - */ |
847 | | - function thumbUrlFromName( $thumbName, $subdir = 'thumb' ) { |
848 | | - global $wgUploadPath, $wgUploadBaseUrl, $wgSharedUploadPath; |
849 | | - if($this->fromSharedDirectory) { |
850 | | - $base = ''; |
851 | | - $path = $wgSharedUploadPath; |
852 | | - } else { |
853 | | - $base = $wgUploadBaseUrl; |
854 | | - $path = $wgUploadPath; |
855 | | - } |
856 | | - if ( Image::isHashed( $this->fromSharedDirectory ) ) { |
857 | | - $hashdir = wfGetHashPath($this->name, $this->fromSharedDirectory) . |
858 | | - wfUrlencode( $this->name ); |
859 | | - } else { |
860 | | - $hashdir = ''; |
861 | | - } |
862 | | - $url = "{$base}{$path}/{$subdir}{$hashdir}/" . wfUrlencode( $thumbName ); |
863 | | - return $url; |
864 | | - } |
865 | | - |
866 | | - /** |
867 | | - * @deprecated Use $image->transform()->getUrl() or thumbUrlFromName() |
868 | | - */ |
869 | | - function thumbUrl( $width, $subdir = 'thumb' ) { |
870 | | - $name = $this->thumbName( array( 'width' => $width ) ); |
871 | | - if ( strval( $name ) !== '' ) { |
872 | | - return array( false, $this->thumbUrlFromName( $name, $subdir ) ); |
873 | | - } else { |
874 | | - return array( false, false ); |
875 | | - } |
876 | | - } |
877 | | - |
878 | | - /** |
879 | | - * @return mixed |
880 | | - */ |
881 | | - function getTransformScript() { |
882 | | - global $wgSharedThumbnailScriptPath, $wgThumbnailScriptPath; |
883 | | - if ( $this->fromSharedDirectory ) { |
884 | | - $script = $wgSharedThumbnailScriptPath; |
885 | | - } else { |
886 | | - $script = $wgThumbnailScriptPath; |
887 | | - } |
888 | | - if ( $script ) { |
889 | | - return "$script?f=" . urlencode( $this->name ); |
890 | | - } else { |
891 | | - return false; |
892 | | - } |
893 | | - } |
894 | | - |
895 | | - /** |
896 | | - * Get a ThumbnailImage which is the same size as the source |
897 | | - * @param mixed $page |
898 | | - * @return MediaTransformOutput |
899 | | - */ |
900 | | - function getUnscaledThumb( $page = false ) { |
901 | | - if ( $page ) { |
902 | | - $params = array( |
903 | | - 'page' => $page, |
904 | | - 'width' => $this->getWidth( $page ) |
905 | | - ); |
906 | | - } else { |
907 | | - $params = array( 'width' => $this->getWidth() ); |
908 | | - } |
909 | | - return $this->transform( $params ); |
910 | | - } |
911 | | - |
912 | | - /** |
913 | | - * Return the file name of a thumbnail with the specified parameters |
914 | | - * |
915 | | - * @param array $params Handler-specific parameters |
916 | | - * @return string file name of a thumbnail with the specified parameters |
917 | | - * @private |
918 | | - */ |
919 | | - function thumbName( $params ) { |
920 | | - $handler = $this->getHandler(); |
921 | | - if ( !$handler ) { |
922 | | - return null; |
923 | | - } |
924 | | - list( $thumbExt, /* $thumbMime */ ) = self::getThumbType( $this->extension, $this->mime ); |
925 | | - $thumbName = $handler->makeParamString( $params ) . '-' . $this->fileName; |
926 | | - if ( $thumbExt != $this->extension ) { |
927 | | - $thumbName .= ".$thumbExt"; |
928 | | - } |
929 | | - return $thumbName; |
930 | | - } |
931 | | - |
932 | | - /** |
933 | | - * Create a thumbnail of the image having the specified width/height. |
934 | | - * The thumbnail will not be created if the width is larger than the |
935 | | - * image's width. Let the browser do the scaling in this case. |
936 | | - * The thumbnail is stored on disk and is only computed if the thumbnail |
937 | | - * file does not exist OR if it is older than the image. |
938 | | - * Returns the URL. |
939 | | - * |
940 | | - * Keeps aspect ratio of original image. If both width and height are |
941 | | - * specified, the generated image will be no bigger than width x height, |
942 | | - * and will also have correct aspect ratio. |
943 | | - * |
944 | | - * @param integer $width maximum width of the generated thumbnail |
945 | | - * @param integer $height maximum height of the image (optional) |
946 | | - * @public |
947 | | - */ |
948 | | - function createThumb( $width, $height = -1 ) { |
949 | | - $params = array( 'width' => $width ); |
950 | | - if ( $height != -1 ) { |
951 | | - $params['height'] = $height; |
952 | | - } |
953 | | - $thumb = $this->transform( $params ); |
954 | | - if( is_null( $thumb ) || $thumb->isError() ) return ''; |
955 | | - return $thumb->getUrl(); |
956 | | - } |
957 | | - |
958 | | - /** |
959 | | - * As createThumb, but returns a ThumbnailImage object. This can |
960 | | - * provide access to the actual file, the real size of the thumb, |
961 | | - * and can produce a convenient <img> tag for you. |
962 | | - * |
963 | | - * For non-image formats, this may return a filetype-specific icon. |
964 | | - * |
965 | | - * @param integer $width maximum width of the generated thumbnail |
966 | | - * @param integer $height maximum height of the image (optional) |
967 | | - * @param boolean $render True to render the thumbnail if it doesn't exist, |
968 | | - * false to just return the URL |
969 | | - * |
970 | | - * @return ThumbnailImage or null on failure |
971 | | - * @public |
972 | | - * |
973 | | - * @deprecated use transform() |
974 | | - */ |
975 | | - function getThumbnail( $width, $height=-1, $render = true ) { |
976 | | - $params = array( 'width' => $width ); |
977 | | - if ( $height != -1 ) { |
978 | | - $params['height'] = $height; |
979 | | - } |
980 | | - $flags = $render ? self::RENDER_NOW : 0; |
981 | | - return $this->transform( $params, $flags ); |
982 | | - } |
983 | | - |
984 | | - /** |
985 | | - * Transform a media file |
986 | | - * |
987 | | - * @param array[string]mixed $params An associative array of handler-specific parameters. |
988 | | - * Typical keys are width, height and page. |
989 | | - * @param integer $flags A bitfield, may contain self::RENDER_NOW to force rendering |
990 | | - * @return MediaTransformOutput |
991 | | - */ |
992 | | - function transform( $params, $flags = 0 ) { |
993 | | - global $wgGenerateThumbnailOnParse, $wgUseSquid, $wgIgnoreImageErrors; |
994 | | - |
995 | | - wfProfileIn( __METHOD__ ); |
996 | | - do { |
997 | | - $handler = $this->getHandler(); |
998 | | - if ( !$handler || !$handler->canRender() ) { |
999 | | - // not a bitmap or renderable image, don't try. |
1000 | | - $thumb = $this->iconThumb(); |
1001 | | - break; |
1002 | | - } |
1003 | | - |
1004 | | - $script = $this->getTransformScript(); |
1005 | | - if ( $script && !($flags & self::RENDER_NOW) ) { |
1006 | | - // Use a script to transform on client request |
1007 | | - $thumb = $handler->getScriptedTransform( $this, $script, $params ); |
1008 | | - break; |
1009 | | - } |
1010 | | - |
1011 | | - $normalisedParams = $params; |
1012 | | - $handler->normaliseParams( $this, $normalisedParams ); |
1013 | | - $thumbName = $this->thumbName( $normalisedParams ); |
1014 | | - $thumbPath = wfImageThumbDir( $this->name, $this->fromSharedDirectory ) . "/$thumbName"; |
1015 | | - $thumbUrl = $this->thumbUrlFromName( $thumbName ); |
1016 | | - |
1017 | | - |
1018 | | - if ( !$wgGenerateThumbnailOnParse && !($flags & self::RENDER_NOW ) ) { |
1019 | | - $thumb = $handler->getTransform( $this, $thumbPath, $thumbUrl, $params ); |
1020 | | - break; |
1021 | | - } |
1022 | | - |
1023 | | - wfDebug( "Doing stat for $thumbPath\n" ); |
1024 | | - $this->migrateThumbFile( $thumbName ); |
1025 | | - if ( file_exists( $thumbPath ) ) { |
1026 | | - $thumb = $handler->getTransform( $this, $thumbPath, $thumbUrl, $params ); |
1027 | | - break; |
1028 | | - } |
1029 | | - |
1030 | | - $thumb = $handler->doTransform( $this, $thumbPath, $thumbUrl, $params ); |
1031 | | - |
1032 | | - // Ignore errors if requested |
1033 | | - if ( !$thumb ) { |
1034 | | - $thumb = null; |
1035 | | - } elseif ( $thumb->isError() ) { |
1036 | | - $this->lastError = $thumb->toText(); |
1037 | | - if ( $wgIgnoreImageErrors && !($flags & self::RENDER_NOW) ) { |
1038 | | - $thumb = $handler->getTransform( $this, $thumbPath, $thumbUrl, $params ); |
1039 | | - } |
1040 | | - } |
1041 | | - |
1042 | | - if ( $wgUseSquid ) { |
1043 | | - wfPurgeSquidServers( array( $thumbUrl ) ); |
1044 | | - } |
1045 | | - } while (false); |
1046 | | - |
1047 | | - wfProfileOut( __METHOD__ ); |
1048 | | - return $thumb; |
1049 | | - } |
1050 | | - |
1051 | | - /** |
1052 | | - * Fix thumbnail files from 1.4 or before, with extreme prejudice |
1053 | | - * @param string $thumbName File name of thumbnail. |
1054 | | - * @return void |
1055 | | - */ |
1056 | | - function migrateThumbFile( $thumbName ) { |
1057 | | - $thumbDir = wfImageThumbDir( $this->name, $this->fromSharedDirectory ); |
1058 | | - $thumbPath = "$thumbDir/$thumbName"; |
1059 | | - if ( is_dir( $thumbPath ) ) { |
1060 | | - // Directory where file should be |
1061 | | - // This happened occasionally due to broken migration code in 1.5 |
1062 | | - // Rename to broken-* |
1063 | | - global $wgUploadDirectory; |
1064 | | - for ( $i = 0; $i < 100 ; $i++ ) { |
1065 | | - $broken = "$wgUploadDirectory/broken-$i-$thumbName"; |
1066 | | - if ( !file_exists( $broken ) ) { |
1067 | | - rename( $thumbPath, $broken ); |
1068 | | - break; |
1069 | | - } |
1070 | | - } |
1071 | | - // Doesn't exist anymore |
1072 | | - clearstatcache(); |
1073 | | - } |
1074 | | - if ( is_file( $thumbDir ) ) { |
1075 | | - // File where directory should be |
1076 | | - unlink( $thumbDir ); |
1077 | | - // Doesn't exist anymore |
1078 | | - clearstatcache(); |
1079 | | - } |
1080 | | - } |
1081 | | - |
1082 | | - /** |
1083 | | - * Get a MediaHandler instance for this image |
1084 | | - */ |
1085 | | - function getHandler() { |
1086 | | - return MediaHandler::getHandler( $this->getMimeType() ); |
1087 | | - } |
1088 | | - |
1089 | | - /** |
1090 | | - * Get a ThumbnailImage representing a file type icon |
1091 | | - * @return ThumbnailImage |
1092 | | - */ |
1093 | | - function iconThumb() { |
1094 | | - global $wgStylePath, $wgStyleDirectory; |
1095 | | - |
1096 | | - $icons = array( 'fileicon-' . $this->extension . '.png', 'fileicon.png' ); |
1097 | | - foreach( $icons as $icon ) { |
1098 | | - $path = '/common/images/icons/' . $icon; |
1099 | | - $filepath = $wgStyleDirectory . $path; |
1100 | | - if( file_exists( $filepath ) ) { |
1101 | | - return new ThumbnailImage( $wgStylePath . $path, 120, 120 ); |
1102 | | - } |
1103 | | - } |
1104 | | - return null; |
1105 | | - } |
1106 | | - |
1107 | | - /** |
1108 | | - * Get last thumbnailing error. |
1109 | | - * Largely obsolete. |
1110 | | - * @return mixed |
1111 | | - */ |
1112 | | - function getLastError() { |
1113 | | - return $this->lastError; |
1114 | | - } |
1115 | | - |
1116 | | - /** |
1117 | | - * Get all thumbnail names previously generated for this image |
1118 | | - * @param boolean $shared |
1119 | | - * @return array[]string |
1120 | | - */ |
1121 | | - function getThumbnails( $shared = false ) { |
1122 | | - if ( Image::isHashed( $shared ) ) { |
1123 | | - $this->load(); |
1124 | | - $files = array(); |
1125 | | - $dir = wfImageThumbDir( $this->name, $shared ); |
1126 | | - |
1127 | | - if ( is_dir( $dir ) ) { |
1128 | | - $handle = opendir( $dir ); |
1129 | | - |
1130 | | - if ( $handle ) { |
1131 | | - while ( false !== ( $file = readdir($handle) ) ) { |
1132 | | - if ( $file[0] != '.' ) { |
1133 | | - $files[] = $file; |
1134 | | - } |
1135 | | - } |
1136 | | - closedir( $handle ); |
1137 | | - } |
1138 | | - } |
1139 | | - } else { |
1140 | | - $files = array(); |
1141 | | - } |
1142 | | - |
1143 | | - return $files; |
1144 | | - } |
1145 | | - |
1146 | | - /** |
1147 | | - * Refresh metadata in memcached, but don't touch thumbnails or squid |
1148 | | - * @return void |
1149 | | - */ |
1150 | | - function purgeMetadataCache() { |
1151 | | - clearstatcache(); |
1152 | | - $this->loadFromFile(); |
1153 | | - $this->saveToCache(); |
1154 | | - } |
1155 | | - |
1156 | | - /** |
1157 | | - * Delete all previously generated thumbnails, refresh metadata in memcached and purge the squid |
1158 | | - * @param array $archiveFiles |
1159 | | - * @param boolean $shared |
1160 | | - * @return void |
1161 | | - */ |
1162 | | - function purgeCache( $archiveFiles = array(), $shared = false ) { |
1163 | | - global $wgUseSquid; |
1164 | | - |
1165 | | - // Refresh metadata cache |
1166 | | - $this->purgeMetadataCache(); |
1167 | | - |
1168 | | - // Delete thumbnails |
1169 | | - $files = $this->getThumbnails( $shared ); |
1170 | | - $dir = wfImageThumbDir( $this->name, $shared ); |
1171 | | - $urls = array(); |
1172 | | - foreach ( $files as $file ) { |
1173 | | - # Check that the base image name is part of the thumb name |
1174 | | - # This is a basic sanity check to avoid erasing unrelated directories |
1175 | | - if ( strpos( $file, $this->name ) !== false ) { |
1176 | | - $url = $this->thumbUrlFromName( $file ); |
1177 | | - $urls[] = $url; |
1178 | | - @unlink( "$dir/$file" ); |
1179 | | - } |
1180 | | - } |
1181 | | - |
1182 | | - // Purge the squid |
1183 | | - if ( $wgUseSquid ) { |
1184 | | - $urls[] = $this->getURL(); |
1185 | | - foreach ( $archiveFiles as $file ) { |
1186 | | - $urls[] = wfImageArchiveUrl( $file ); |
1187 | | - } |
1188 | | - wfPurgeSquidServers( $urls ); |
1189 | | - } |
1190 | | - } |
1191 | | - |
1192 | | - /** |
1193 | | - * Purge the image description page, but don't go after |
1194 | | - * pages using the image. Use when modifying file history |
1195 | | - * but not the current data. |
1196 | | - * @return void |
1197 | | - */ |
1198 | | - function purgeDescription() { |
1199 | | - $page = Title::makeTitle( NS_IMAGE, $this->name ); |
1200 | | - $page->invalidateCache(); |
1201 | | - $page->purgeSquid(); |
1202 | | - } |
1203 | | - |
1204 | | - /** |
1205 | | - * Purge metadata and all affected pages when the image is created, |
1206 | | - * deleted, or majorly updated. |
1207 | | - * @param array $urlArray A set of additional URLs may be passed to purge, |
1208 | | - * such as specific image files which have changed (param not used?) |
1209 | | - * @return void |
1210 | | - */ |
1211 | | - function purgeEverything( $urlArr=array() ) { |
1212 | | - // Delete thumbnails and refresh image metadata cache |
1213 | | - $this->purgeCache(); |
1214 | | - $this->purgeDescription(); |
1215 | | - |
1216 | | - // Purge cache of all pages using this image |
1217 | | - $update = new HTMLCacheUpdate( $this->getTitle(), 'imagelinks' ); |
1218 | | - $update->doUpdate(); |
1219 | | - } |
1220 | | - |
1221 | | - /** |
1222 | | - * Return the image history of this image, line by line. |
1223 | | - * starts with current version, then old versions. |
1224 | | - * uses $this->historyLine to check which line to return: |
1225 | | - * 0 return line for current version |
1226 | | - * 1 query for old versions, return first one |
1227 | | - * 2, ... return next old version from above query |
1228 | | - * |
1229 | | - * @public |
1230 | | - * @return mixed false on no next history, object otherwise. |
1231 | | - */ |
1232 | | - function nextHistoryLine() { |
1233 | | - $dbr = wfGetDB( DB_SLAVE ); |
1234 | | - |
1235 | | - if ( $this->historyLine == 0 ) {// called for the first time, return line from cur |
1236 | | - $this->historyRes = $dbr->select( 'image', |
1237 | | - array( |
1238 | | - 'img_size', |
1239 | | - 'img_description', |
1240 | | - 'img_user','img_user_text', |
1241 | | - 'img_timestamp', |
1242 | | - 'img_width', |
1243 | | - 'img_height', |
1244 | | - '0 AS oi_deleted', |
1245 | | - "'' AS oi_archive_name" |
1246 | | - ), |
1247 | | - array( 'img_name' => $this->title->getDBkey() ), |
1248 | | - __METHOD__ |
1249 | | - ); |
1250 | | - if ( 0 == $dbr->numRows( $this->historyRes ) ) { |
1251 | | - return FALSE; |
1252 | | - } |
1253 | | - } else if ( $this->historyLine == 1 ) { |
1254 | | - $this->historyRes = $dbr->select( 'oldimage', |
1255 | | - array( |
1256 | | - 'oi_size AS img_size', |
1257 | | - 'oi_description AS img_description', |
1258 | | - 'oi_user AS img_user', |
1259 | | - 'oi_user_text AS img_user_text', |
1260 | | - 'oi_timestamp AS img_timestamp', |
1261 | | - 'oi_width as img_width', |
1262 | | - 'oi_height as img_height', |
1263 | | - 'oi_archive_name', |
1264 | | - 'oi_deleted' |
1265 | | - ), |
1266 | | - array( 'oi_name' => $this->title->getDBkey() ), |
1267 | | - __METHOD__, |
1268 | | - array( 'ORDER BY' => 'oi_timestamp DESC' ) |
1269 | | - ); |
1270 | | - } |
1271 | | - $this->historyLine ++; |
1272 | | - |
1273 | | - return $dbr->fetchObject( $this->historyRes ); |
1274 | | - } |
1275 | | - |
1276 | | - /** |
1277 | | - * Reset the history pointer to the first element of the history |
1278 | | - * @public |
1279 | | - * @return void |
1280 | | - */ |
1281 | | - function resetHistory() { |
1282 | | - $this->historyLine = 0; |
1283 | | - } |
1284 | | - |
1285 | | - /** |
1286 | | - * Return the full filesystem path to the file. Note that this does |
1287 | | - * not mean that a file actually exists under that location. |
1288 | | - * |
1289 | | - * This path depends on whether directory hashing is active or not, |
1290 | | - * i.e. whether the images are all found in the same directory, |
1291 | | - * or in hashed paths like /images/3/3c. |
1292 | | - * |
1293 | | - * @public |
1294 | | - * @param boolean $fromSharedDirectory Return the path to the file |
1295 | | - * in a shared repository (see $wgUseSharedRepository and related |
1296 | | - * options in DefaultSettings.php) instead of a local one. |
1297 | | - * @return string Full filesystem path to the file. |
1298 | | - */ |
1299 | | - function getFullPath( $fromSharedRepository = false ) { |
1300 | | - global $wgUploadDirectory, $wgSharedUploadDirectory; |
1301 | | - |
1302 | | - $dir = $fromSharedRepository ? $wgSharedUploadDirectory : |
1303 | | - $wgUploadDirectory; |
1304 | | - // Is this an old version? |
1305 | | - $subdir = $this->oldimage ? '/archive' : ''; |
1306 | | - // $wgSharedUploadDirectory may be false, if thumb.php is used |
1307 | | - if ( $dir ) { |
1308 | | - $fullpath = $dir . $subdir . wfGetHashPath($this->name, $fromSharedRepository) . $this->fileName; |
1309 | | - } else { |
1310 | | - $fullpath = false; |
1311 | | - } |
1312 | | - return $fullpath; |
1313 | | - } |
1314 | | - |
1315 | | - /** |
1316 | | - * @param boolean $shared |
1317 | | - * @return bool |
1318 | | - */ |
1319 | | - public static function isHashed( $shared ) { |
1320 | | - global $wgHashedUploadDirectory, $wgHashedSharedUploadDirectory; |
1321 | | - return $shared ? $wgHashedSharedUploadDirectory : $wgHashedUploadDirectory; |
1322 | | - } |
1323 | | - |
1324 | | - /** |
1325 | | - * Record an image upload in the upload log and the image table |
1326 | | - * @param string $oldver |
1327 | | - * @param string $desc |
1328 | | - * @param string $license |
1329 | | - * @param string $copyStatus |
1330 | | - * @param string $source |
1331 | | - * @param boolean $watch |
1332 | | - * @return boolean |
1333 | | - */ |
1334 | | - function recordUpload( $oldver, $desc, $license = '', $copyStatus = '', $source = '', $watch = false ) { |
1335 | | - global $wgUser, $wgUseCopyrightUpload; |
1336 | | - |
1337 | | - $dbw = wfGetDB( DB_MASTER ); |
1338 | | - |
1339 | | - // Delete thumbnails and refresh the metadata cache |
1340 | | - $this->purgeCache(); |
1341 | | - |
1342 | | - // Fail now if the image isn't there |
1343 | | - if ( !$this->fileExists || $this->fromSharedDirectory ) { |
1344 | | - wfDebug( "Image::recordUpload: File ".$this->imagePath." went missing!\n" ); |
1345 | | - return false; |
1346 | | - } |
1347 | | - |
1348 | | - if ( $wgUseCopyrightUpload ) { |
1349 | | - if ( $license != '' ) { |
1350 | | - $licensetxt = '== ' . wfMsgForContent( 'license' ) . " ==\n" . '{{' . $license . '}}' . "\n"; |
1351 | | - } |
1352 | | - $textdesc = '== ' . wfMsg ( 'filedesc' ) . " ==\n" . $desc . "\n" . |
1353 | | - '== ' . wfMsgForContent ( 'filestatus' ) . " ==\n" . $copyStatus . "\n" . |
1354 | | - "$licensetxt" . |
1355 | | - '== ' . wfMsgForContent ( 'filesource' ) . " ==\n" . $source ; |
1356 | | - } else { |
1357 | | - if ( $license != '' ) { |
1358 | | - $filedesc = $desc == '' ? '' : '== ' . wfMsg ( 'filedesc' ) . " ==\n" . $desc . "\n"; |
1359 | | - $textdesc = $filedesc . |
1360 | | - '== ' . wfMsgForContent ( 'license' ) . " ==\n" . '{{' . $license . '}}' . "\n"; |
1361 | | - } else { |
1362 | | - $textdesc = $desc; |
1363 | | - } |
1364 | | - } |
1365 | | - |
1366 | | - $now = $dbw->timestamp(); |
1367 | | - |
1368 | | - #split mime type |
1369 | | - if (strpos($this->mime,'/')!==false) { |
1370 | | - list($major,$minor)= explode('/',$this->mime,2); |
1371 | | - } |
1372 | | - else { |
1373 | | - $major= $this->mime; |
1374 | | - $minor= "unknown"; |
1375 | | - } |
1376 | | - |
1377 | | - # Test to see if the row exists using INSERT IGNORE |
1378 | | - # This avoids race conditions by locking the row until the commit, and also |
1379 | | - # doesn't deadlock. SELECT FOR UPDATE causes a deadlock for every race condition. |
1380 | | - $dbw->insert( 'image', |
1381 | | - array( |
1382 | | - 'img_name' => $this->name, |
1383 | | - 'img_size'=> $this->size, |
1384 | | - 'img_width' => intval( $this->width ), |
1385 | | - 'img_height' => intval( $this->height ), |
1386 | | - 'img_bits' => $this->bits, |
1387 | | - 'img_media_type' => $this->type, |
1388 | | - 'img_major_mime' => $major, |
1389 | | - 'img_minor_mime' => $minor, |
1390 | | - 'img_timestamp' => $now, |
1391 | | - 'img_description' => $desc, |
1392 | | - 'img_user' => $wgUser->getID(), |
1393 | | - 'img_user_text' => $wgUser->getName(), |
1394 | | - 'img_metadata' => $this->metadata |
1395 | | - ), |
1396 | | - __METHOD__, |
1397 | | - 'IGNORE' |
1398 | | - ); |
1399 | | - |
1400 | | - if( $dbw->affectedRows() == 0 ) { |
1401 | | - # Collision, this is an update of an image |
1402 | | - # Insert previous contents into oldimage |
1403 | | - $dbw->insertSelect( 'oldimage', 'image', |
1404 | | - array( |
1405 | | - 'oi_name' => 'img_name', |
1406 | | - 'oi_archive_name' => $dbw->addQuotes( $oldver ), |
1407 | | - 'oi_size' => 'img_size', |
1408 | | - 'oi_width' => 'img_width', |
1409 | | - 'oi_height' => 'img_height', |
1410 | | - 'oi_bits' => 'img_bits', |
1411 | | - 'oi_timestamp' => 'img_timestamp', |
1412 | | - 'oi_description' => 'img_description', |
1413 | | - 'oi_user' => 'img_user', |
1414 | | - 'oi_user_text' => 'img_user_text', |
1415 | | - 'oi_media_type' => 'img_media_type', |
1416 | | - 'oi_major_mime' => 'img_major_mime', |
1417 | | - 'oi_minor_mime' => 'img_minor_mime', |
1418 | | - 'oi_metadata' => 'img_metadata', |
1419 | | - ), array( 'img_name' => $this->name ), __METHOD__ |
1420 | | - ); |
1421 | | - |
1422 | | - # Update the current image row |
1423 | | - $dbw->update( 'image', |
1424 | | - array( /* SET */ |
1425 | | - 'img_size' => $this->size, |
1426 | | - 'img_width' => intval( $this->width ), |
1427 | | - 'img_height' => intval( $this->height ), |
1428 | | - 'img_bits' => $this->bits, |
1429 | | - 'img_media_type' => $this->type, |
1430 | | - 'img_major_mime' => $major, |
1431 | | - 'img_minor_mime' => $minor, |
1432 | | - 'img_timestamp' => $now, |
1433 | | - 'img_description' => $desc, |
1434 | | - 'img_user' => $wgUser->getID(), |
1435 | | - 'img_user_text' => $wgUser->getName(), |
1436 | | - 'img_metadata' => $this->metadata, |
1437 | | - ), array( /* WHERE */ |
1438 | | - 'img_name' => $this->name |
1439 | | - ), __METHOD__ |
1440 | | - ); |
1441 | | - } else { |
1442 | | - # This is a new image |
1443 | | - # Update the image count |
1444 | | - $site_stats = $dbw->tableName( 'site_stats' ); |
1445 | | - $dbw->query( "UPDATE $site_stats SET ss_images=ss_images+1", __METHOD__ ); |
1446 | | - } |
1447 | | - |
1448 | | - $descTitle = $this->getTitle(); |
1449 | | - $article = new Article( $descTitle ); |
1450 | | - $minor = false; |
1451 | | - $watch = $watch || $wgUser->isWatched( $descTitle ); |
1452 | | - $suppressRC = true; // There's already a log entry, so don't double the RC load |
1453 | | - |
1454 | | - if( $descTitle->exists() ) { |
1455 | | - // TODO: insert a null revision into the page history for this update. |
1456 | | - if( $watch ) { |
1457 | | - $wgUser->addWatch( $descTitle ); |
1458 | | - } |
1459 | | - |
1460 | | - # Invalidate the cache for the description page |
1461 | | - $descTitle->invalidateCache(); |
1462 | | - $descTitle->purgeSquid(); |
1463 | | - } else { |
1464 | | - // New image; create the description page. |
1465 | | - $article->insertNewArticle( $textdesc, $desc, $minor, $watch, $suppressRC ); |
1466 | | - } |
1467 | | - |
1468 | | - # Hooks, hooks, the magic of hooks... |
1469 | | - wfRunHooks( 'FileUpload', array( $this ) ); |
1470 | | - |
1471 | | - # Add the log entry |
1472 | | - $log = new LogPage( 'upload' ); |
1473 | | - $log->addEntry( 'upload', $descTitle, $desc ); |
1474 | | - |
1475 | | - # Commit the transaction now, in case something goes wrong later |
1476 | | - # The most important thing is that images don't get lost, especially archives |
1477 | | - $dbw->immediateCommit(); |
1478 | | - |
1479 | | - # Invalidate cache for all pages using this image |
1480 | | - $update = new HTMLCacheUpdate( $this->getTitle(), 'imagelinks' ); |
1481 | | - $update->doUpdate(); |
1482 | | - |
1483 | | - return true; |
1484 | | - } |
1485 | | - |
1486 | | - /** |
1487 | | - * Get an array of Title objects which are articles which use this image |
1488 | | - * Also adds their IDs to the link cache |
1489 | | - * |
1490 | | - * This is mostly copied from Title::getLinksTo() |
1491 | | - * |
1492 | | - * @deprecated Use HTMLCacheUpdate, this function uses too much memory |
1493 | | - * @param string $options |
1494 | | - * @return array[int]Title |
1495 | | - */ |
1496 | | - function getLinksTo( $options = '' ) { |
1497 | | - wfProfileIn( __METHOD__ ); |
1498 | | - |
1499 | | - if ( $options ) { |
1500 | | - $db = wfGetDB( DB_MASTER ); |
1501 | | - } else { |
1502 | | - $db = wfGetDB( DB_SLAVE ); |
1503 | | - } |
1504 | | - $linkCache =& LinkCache::singleton(); |
1505 | | - |
1506 | | - list( $page, $imagelinks ) = $db->tableNamesN( 'page', 'imagelinks' ); |
1507 | | - $encName = $db->addQuotes( $this->name ); |
1508 | | - $sql = "SELECT page_namespace,page_title,page_id FROM $page,$imagelinks WHERE page_id=il_from AND il_to=$encName $options"; |
1509 | | - $res = $db->query( $sql, __METHOD__ ); |
1510 | | - |
1511 | | - $retVal = array(); |
1512 | | - if ( $db->numRows( $res ) ) { |
1513 | | - while ( $row = $db->fetchObject( $res ) ) { |
1514 | | - if ( $titleObj = Title::makeTitle( $row->page_namespace, $row->page_title ) ) { |
1515 | | - $linkCache->addGoodLinkObj( $row->page_id, $titleObj ); |
1516 | | - $retVal[] = $titleObj; |
1517 | | - } |
1518 | | - } |
1519 | | - } |
1520 | | - $db->freeResult( $res ); |
1521 | | - wfProfileOut( __METHOD__ ); |
1522 | | - return $retVal; |
1523 | | - } |
1524 | | - |
1525 | | - /** |
1526 | | - * @return array |
1527 | | - */ |
1528 | | - function getExifData() { |
1529 | | - $handler = $this->getHandler(); |
1530 | | - if ( !$handler || $handler->getMetadataType( $this ) != 'exif' ) { |
1531 | | - return array(); |
1532 | | - } |
1533 | | - if ( !$this->metadata ) { |
1534 | | - return array(); |
1535 | | - } |
1536 | | - $exif = unserialize( $this->metadata ); |
1537 | | - if ( !$exif ) { |
1538 | | - return array(); |
1539 | | - } |
1540 | | - unset( $exif['MEDIAWIKI_EXIF_VERSION'] ); |
1541 | | - $format = new FormatExif( $exif ); |
1542 | | - |
1543 | | - return $format->getFormattedData(); |
1544 | | - } |
1545 | | - |
1546 | | - /** |
1547 | | - * Returns true if the image does not come from the shared |
1548 | | - * image repository. |
1549 | | - * |
1550 | | - * @return bool |
1551 | | - */ |
1552 | | - function isLocal() { |
1553 | | - return !$this->fromSharedDirectory; |
1554 | | - } |
1555 | | - |
1556 | | - /** |
1557 | | - * Was this image ever deleted from the wiki? |
1558 | | - * |
1559 | | - * @return bool |
1560 | | - */ |
1561 | | - function wasDeleted() { |
1562 | | - $title = Title::makeTitle( NS_IMAGE, $this->name ); |
1563 | | - return ( $title->isDeleted() > 0 ); |
1564 | | - } |
1565 | | - |
1566 | | - /** |
1567 | | - * Delete all versions of the image. |
1568 | | - * |
1569 | | - * Moves the files into an archive directory (or deletes them) |
1570 | | - * and removes the database rows. |
1571 | | - * |
1572 | | - * Cache purging is done; logging is caller's responsibility. |
1573 | | - * |
1574 | | - * @param string $reason |
1575 | | - * @param boolean $suppress |
1576 | | - * @return boolean true on success, false on some kind of failure |
1577 | | - */ |
1578 | | - function delete( $reason, $suppress=false ) { |
1579 | | - $transaction = new FSTransaction(); |
1580 | | - $urlArr = array( $this->getURL() ); |
1581 | | - |
1582 | | - if( !FileStore::lock() ) { |
1583 | | - wfDebug( __METHOD__.": failed to acquire file store lock, aborting\n" ); |
1584 | | - return false; |
1585 | | - } |
1586 | | - |
1587 | | - try { |
1588 | | - $dbw = wfGetDB( DB_MASTER ); |
1589 | | - $dbw->begin(); |
1590 | | - |
1591 | | - // Delete old versions |
1592 | | - $result = $dbw->select( 'oldimage', |
1593 | | - array( 'oi_archive_name' ), |
1594 | | - array( 'oi_name' => $this->name ) ); |
1595 | | - |
1596 | | - while( $row = $dbw->fetchObject( $result ) ) { |
1597 | | - $oldName = $row->oi_archive_name; |
1598 | | - |
1599 | | - $transaction->add( $this->prepareDeleteOld( $oldName, $reason, $suppress ) ); |
1600 | | - |
1601 | | - // We'll need to purge this URL from caches... |
1602 | | - $urlArr[] = wfImageArchiveUrl( $oldName ); |
1603 | | - } |
1604 | | - $dbw->freeResult( $result ); |
1605 | | - |
1606 | | - // And the current version... |
1607 | | - $transaction->add( $this->prepareDeleteCurrent( $reason, $suppress ) ); |
1608 | | - |
1609 | | - $dbw->immediateCommit(); |
1610 | | - } catch( MWException $e ) { |
1611 | | - wfDebug( __METHOD__.": db error, rolling back file transactions\n" ); |
1612 | | - $transaction->rollback(); |
1613 | | - FileStore::unlock(); |
1614 | | - throw $e; |
1615 | | - } |
1616 | | - |
1617 | | - wfDebug( __METHOD__.": deleted db items, applying file transactions\n" ); |
1618 | | - $transaction->commit(); |
1619 | | - FileStore::unlock(); |
1620 | | - |
1621 | | - |
1622 | | - // Update site_stats |
1623 | | - $site_stats = $dbw->tableName( 'site_stats' ); |
1624 | | - $dbw->query( "UPDATE $site_stats SET ss_images=ss_images-1", __METHOD__ ); |
1625 | | - |
1626 | | - $this->purgeEverything( $urlArr ); |
1627 | | - |
1628 | | - return true; |
1629 | | - } |
1630 | | - |
1631 | | - |
1632 | | - /** |
1633 | | - * Delete an old version of the image. |
1634 | | - * |
1635 | | - * Moves the file into an archive directory (or deletes it) |
1636 | | - * and removes the database row. |
1637 | | - * |
1638 | | - * Cache purging is done; logging is caller's responsibility. |
1639 | | - * |
1640 | | - * @param string $archiveName |
1641 | | - * @param string $reason |
1642 | | - * @param boolean $suppress |
1643 | | - * @throws MWException or FSException on database or filestore failure |
1644 | | - * @return boolean true on success, false on some kind of failure |
1645 | | - */ |
1646 | | - function deleteOld( $archiveName, $reason, $suppress=false ) { |
1647 | | - $transaction = new FSTransaction(); |
1648 | | - $urlArr = array(); |
1649 | | - |
1650 | | - if( !FileStore::lock() ) { |
1651 | | - wfDebug( __METHOD__.": failed to acquire file store lock, aborting\n" ); |
1652 | | - return false; |
1653 | | - } |
1654 | | - |
1655 | | - $transaction = new FSTransaction(); |
1656 | | - try { |
1657 | | - $dbw = wfGetDB( DB_MASTER ); |
1658 | | - $dbw->begin(); |
1659 | | - $transaction->add( $this->prepareDeleteOld( $archiveName, $reason, $suppress ) ); |
1660 | | - $dbw->immediateCommit(); |
1661 | | - } catch( MWException $e ) { |
1662 | | - wfDebug( __METHOD__.": db error, rolling back file transaction\n" ); |
1663 | | - $transaction->rollback(); |
1664 | | - FileStore::unlock(); |
1665 | | - throw $e; |
1666 | | - } |
1667 | | - |
1668 | | - wfDebug( __METHOD__.": deleted db items, applying file transaction\n" ); |
1669 | | - $transaction->commit(); |
1670 | | - FileStore::unlock(); |
1671 | | - |
1672 | | - $this->purgeDescription(); |
1673 | | - |
1674 | | - // Squid purging |
1675 | | - global $wgUseSquid; |
1676 | | - if ( $wgUseSquid ) { |
1677 | | - $urlArr = array( |
1678 | | - wfImageArchiveUrl( $archiveName ), |
1679 | | - ); |
1680 | | - wfPurgeSquidServers( $urlArr ); |
1681 | | - } |
1682 | | - return true; |
1683 | | - } |
1684 | | - |
1685 | | - /** |
1686 | | - * Delete the current version of a file. |
1687 | | - * May throw a database error. |
1688 | | - * @param string $reason |
1689 | | - * @param boolean $suppress |
1690 | | - * @return FStransaction on success, false on failure |
1691 | | - */ |
1692 | | - private function prepareDeleteCurrent( $reason, $suppress=false ) { |
1693 | | - return $this->prepareDeleteVersion( |
1694 | | - $this->getFullPath(), |
1695 | | - $reason, |
1696 | | - 'image', |
1697 | | - array( |
1698 | | - 'fa_name' => 'img_name', |
1699 | | - 'fa_archive_name' => 'NULL', |
1700 | | - 'fa_size' => 'img_size', |
1701 | | - 'fa_width' => 'img_width', |
1702 | | - 'fa_height' => 'img_height', |
1703 | | - 'fa_metadata' => 'img_metadata', |
1704 | | - 'fa_bits' => 'img_bits', |
1705 | | - 'fa_media_type' => 'img_media_type', |
1706 | | - 'fa_major_mime' => 'img_major_mime', |
1707 | | - 'fa_minor_mime' => 'img_minor_mime', |
1708 | | - 'fa_description' => 'img_description', |
1709 | | - 'fa_user' => 'img_user', |
1710 | | - 'fa_user_text' => 'img_user_text', |
1711 | | - 'fa_timestamp' => 'img_timestamp' ), |
1712 | | - array( 'img_name' => $this->name ), |
1713 | | - $suppress, |
1714 | | - __METHOD__ ); |
1715 | | - } |
1716 | | - |
1717 | | - /** |
1718 | | - * Delete a given older version of a file. |
1719 | | - * May throw a database error. |
1720 | | - * @param string $archiveName |
1721 | | - * @param string $reason |
1722 | | - * @param boolean $suppress |
1723 | | - * @return FStransaction on success, false on failure |
1724 | | - */ |
1725 | | - private function prepareDeleteOld( $archiveName, $reason, $suppress=false ) { |
1726 | | - // Stored as either <time>!<name> or <time>!<key> |
1727 | | - list($timestamp,$img) = explode('!',$archiveName,2); |
1728 | | - // Is this image using a filestore key (hidden)? |
1729 | | - if( $img != $this->name && FileStore::validKey($img) ) { |
1730 | | - $group = 'hidden'; |
1731 | | - |
1732 | | - $hiddenstore = FileStore::get( $group ); |
1733 | | - $oldpath = $hiddenstore->filePath( $img ); |
1734 | | - } else { |
1735 | | - $oldpath = wfImageArchiveDir( $this->name ) . DIRECTORY_SEPARATOR . $archiveName; |
1736 | | - } |
1737 | | - return $this->prepareDeleteVersion( |
1738 | | - $oldpath, |
1739 | | - $reason, |
1740 | | - 'oldimage', |
1741 | | - array( |
1742 | | - 'fa_name' => 'oi_name', |
1743 | | - 'fa_archive_name' => 'oi_archive_name', |
1744 | | - 'fa_size' => 'oi_size', |
1745 | | - 'fa_width' => 'oi_width', |
1746 | | - 'fa_height' => 'oi_height', |
1747 | | - 'fa_metadata' => 'NULL', |
1748 | | - 'fa_bits' => 'oi_bits', |
1749 | | - 'fa_media_type' => 'NULL', |
1750 | | - 'fa_major_mime' => 'NULL', |
1751 | | - 'fa_minor_mime' => 'NULL', |
1752 | | - 'fa_description' => 'oi_description', |
1753 | | - 'fa_user' => 'oi_user', |
1754 | | - 'fa_user_text' => 'oi_user_text', |
1755 | | - 'fa_timestamp' => 'oi_timestamp', |
1756 | | - 'fa_deleted' => 'oi_deleted' ), |
1757 | | - array( |
1758 | | - 'oi_name' => $this->name, |
1759 | | - 'oi_archive_name' => $archiveName ), |
1760 | | - $suppress, |
1761 | | - __METHOD__ ); |
1762 | | - } |
1763 | | - |
1764 | | - /** |
1765 | | - * Do the dirty work of backing up an image row and its file |
1766 | | - * (if $wgSaveDeletedFiles is on) and removing the originals. |
1767 | | - * |
1768 | | - * Must be run while the file store is locked and a database |
1769 | | - * transaction is open to avoid race conditions. |
1770 | | - * |
1771 | | - * @return FSTransaction |
1772 | | - */ |
1773 | | - private function prepareDeleteVersion( $path, $reason, $table, $fieldMap, $where, $suppress=false, $fname ) { |
1774 | | - global $wgUser, $wgSaveDeletedFiles; |
1775 | | - |
1776 | | - // Dupe the file into the file store |
1777 | | - if( file_exists( $path ) ) { |
1778 | | - if( $wgSaveDeletedFiles ) { |
1779 | | - $group = 'deleted'; |
1780 | | - |
1781 | | - $store = FileStore::get( $group ); |
1782 | | - $key = FileStore::calculateKey( $path, $this->extension ); |
1783 | | - $transaction = $store->insert( $key, $path, FileStore::DELETE_ORIGINAL ); |
1784 | | - } else { |
1785 | | - $group = null; |
1786 | | - $key = null; |
1787 | | - $transaction = FileStore::deleteFile( $path ); |
1788 | | - } |
1789 | | - } else { |
1790 | | - wfDebug( __METHOD__." deleting already-missing '$path'; moving on to database\n" ); |
1791 | | - $group = null; |
1792 | | - $key = null; |
1793 | | - $transaction = new FSTransaction(); // empty |
1794 | | - } |
1795 | | - |
1796 | | - if( $transaction === false ) { |
1797 | | - // Fail to restore? |
1798 | | - wfDebug( __METHOD__.": import to file store failed, aborting\n" ); |
1799 | | - throw new MWException( "Could not archive and delete file $path" ); |
1800 | | - return false; |
1801 | | - } |
1802 | | - |
1803 | | - // Bitfields to further suppress the image content |
1804 | | - if ( $suppress ) { |
1805 | | - $bitfield = 0; |
1806 | | - # We will have to follow up with a thumb purge |
1807 | | - # and a file move to a private directory |
1808 | | - $bitfield |= self::DELETED_FILE; |
1809 | | - $bitfield |= self::DELETED_COMMENT; |
1810 | | - $bitfield |= self::DELETED_USER; |
1811 | | - $bitfield |= self::DELETED_RESTRICTED; |
1812 | | - // This should be 15... |
1813 | | - $fieldMap['fa_deleted'] = $bitfield; |
1814 | | - } |
1815 | | - |
1816 | | - $dbw = wfGetDB( DB_MASTER ); |
1817 | | - $storageMap = array( |
1818 | | - 'fa_storage_group' => $dbw->addQuotes( $group ), |
1819 | | - 'fa_storage_key' => $dbw->addQuotes( $key ), |
1820 | | - |
1821 | | - 'fa_deleted_user' => $dbw->addQuotes( $wgUser->getId() ), |
1822 | | - 'fa_deleted_timestamp' => $dbw->timestamp(), |
1823 | | - 'fa_deleted_reason' => $dbw->addQuotes( $reason ) ); |
1824 | | - $allFields = array_merge( $storageMap, $fieldMap ); |
1825 | | - |
1826 | | - try { |
1827 | | - if( $wgSaveDeletedFiles ) { |
1828 | | - $dbw->insertSelect( 'filearchive', $table, $allFields, $where, $fname ); |
1829 | | - } |
1830 | | - $dbw->delete( $table, $where, $fname ); |
1831 | | - } catch( DBQueryError $e ) { |
1832 | | - // Something went horribly wrong! |
1833 | | - // Leave the file as it was... |
1834 | | - wfDebug( __METHOD__.": database error, rolling back file transaction\n" ); |
1835 | | - $transaction->rollback(); |
1836 | | - throw $e; |
1837 | | - } |
1838 | | - |
1839 | | - return $transaction; |
1840 | | - } |
1841 | | - |
1842 | | - /** |
1843 | | - * Restore all or specified deleted revisions to the given file. |
1844 | | - * Permissions and logging are left to the caller. |
1845 | | - * |
1846 | | - * May throw database exceptions on error. |
1847 | | - * |
1848 | | - * @param string $timestamp, restore all revisions since this time |
1849 | | - * @return the number of file revisions restored if successful, |
1850 | | - * or false on failure |
1851 | | - */ |
1852 | | - function restore( $timestamp = 0, $Unsuppress = false ) { |
1853 | | - global $wgUser; |
1854 | | - |
1855 | | - if( !FileStore::lock() ) { |
1856 | | - wfDebug( __METHOD__." could not acquire filestore lock\n" ); |
1857 | | - return false; |
1858 | | - } |
1859 | | - |
1860 | | - $transaction = new FSTransaction(); |
1861 | | - try { |
1862 | | - $dbw = wfGetDB( DB_MASTER ); |
1863 | | - $dbw->begin(); |
1864 | | - |
1865 | | - // Make sure there is a page for this image |
1866 | | - $page = $dbw->selectRow( 'page', |
1867 | | - array( 'page_id', 'page_latest' ), |
1868 | | - array( 'page_namespace' => $this->title->getNamespace(), |
1869 | | - 'page_title' => $this->title->getDBkey() ), |
1870 | | - __METHOD__ ); |
1871 | | - if( !$page ) |
1872 | | - return false; |
1873 | | - |
1874 | | - // Re-confirm whether this image presently exists; |
1875 | | - // if no we'll need to create an image record for the |
1876 | | - // first item we restore. Grab the timestamp |
1877 | | - $exists = $dbw->selectField( 'image', '1', |
1878 | | - array( 'img_name' => $this->name ), |
1879 | | - __METHOD__, |
1880 | | - array('ORDER BY' => 'img_timestamp DESC') ); |
1881 | | - |
1882 | | - // Fetch all or selected archived revisions for the file, |
1883 | | - // sorted from the most recent to the oldest. |
1884 | | - $conditions = array( 'fa_name' => $this->name ); |
1885 | | - if( $timestamp ) { |
1886 | | - $conditions[] = "fa_timestamp >= {$timestamp}"; |
1887 | | - } |
1888 | | - |
1889 | | - $result = $dbw->select( 'filearchive', '*', |
1890 | | - $conditions, |
1891 | | - __METHOD__, |
1892 | | - array( 'ORDER BY' => 'fa_timestamp DESC' ) ); |
1893 | | - |
1894 | | - if( $dbw->numRows( $result ) == 0 ) { |
1895 | | - // Nothing to do. |
1896 | | - wfDebug( __METHOD__.": nothing to do\n" ); |
1897 | | - $dbw->rollback(); |
1898 | | - FileStore::unlock(); |
1899 | | - return true; |
1900 | | - } |
1901 | | - |
1902 | | - $revisions = 0; |
1903 | | - while( $row = $dbw->fetchObject( $result ) ) { |
1904 | | - $revisions++; |
1905 | | - $store = FileStore::get( $row->fa_storage_group ); |
1906 | | - if( !$store ) { |
1907 | | - wfDebug( __METHOD__.": skipping row with no file.\n" ); |
1908 | | - continue; |
1909 | | - } |
1910 | | - // Are there no live revisions? |
1911 | | - if( $revisions == 1 && !$exists ) { |
1912 | | - // We don't currently handle well changing the top revision's settings |
1913 | | - if ( !$Unsuppress && $row->fa_deleted ) { |
1914 | | - wfDebug( __METHOD__.": restoration would result in a deleted top revision\n" ); |
1915 | | - $dbw->rollback(); |
1916 | | - FileStore::unlock(); |
1917 | | - return false; |
1918 | | - } |
1919 | | - |
1920 | | - $destDir = wfImageDir( $row->fa_name ); |
1921 | | - if ( !is_dir( $destDir ) ) { |
1922 | | - wfMkdirParents( $destDir ); |
1923 | | - } |
1924 | | - $destPath = $destDir . DIRECTORY_SEPARATOR . $row->fa_name; |
1925 | | - |
1926 | | - // We may have to fill in data if this was originally |
1927 | | - // an archived file revision. |
1928 | | - if( is_null( $row->fa_metadata ) ) { |
1929 | | - $tempFile = $store->filePath( $row->fa_storage_key ); |
1930 | | - |
1931 | | - $magic = MimeMagic::singleton(); |
1932 | | - $mime = $magic->guessMimeType( $tempFile, true ); |
1933 | | - $media_type = $magic->getMediaType( $tempFile, $mime ); |
1934 | | - list( $major_mime, $minor_mime ) = self::splitMime( $mime ); |
1935 | | - $handler = MediaHandler::getHandler( $mime ); |
1936 | | - if ( $handler ) { |
1937 | | - $metadata = $handler->getMetadata( $image, $tempFile ); |
1938 | | - } else { |
1939 | | - $metadata = ''; |
1940 | | - } |
1941 | | - } else { |
1942 | | - $metadata = $row->fa_metadata; |
1943 | | - $major_mime = $row->fa_major_mime; |
1944 | | - $minor_mime = $row->fa_minor_mime; |
1945 | | - $media_type = $row->fa_media_type; |
1946 | | - } |
1947 | | - |
1948 | | - $table = 'image'; |
1949 | | - $fields = array( |
1950 | | - 'img_name' => $row->fa_name, |
1951 | | - 'img_size' => $row->fa_size, |
1952 | | - 'img_width' => $row->fa_width, |
1953 | | - 'img_height' => $row->fa_height, |
1954 | | - 'img_metadata' => $metadata, |
1955 | | - 'img_bits' => $row->fa_bits, |
1956 | | - 'img_media_type' => $media_type, |
1957 | | - 'img_major_mime' => $major_mime, |
1958 | | - 'img_minor_mime' => $minor_mime, |
1959 | | - 'img_description' => $row->fa_description, |
1960 | | - 'img_user' => $row->fa_user, |
1961 | | - 'img_user_text' => $row->fa_user_text, |
1962 | | - 'img_timestamp' => $row->fa_timestamp ); |
1963 | | - } else { |
1964 | | - // Does this image already exists? |
1965 | | - $archiveName = $row->fa_archive_name; |
1966 | | - if( $archiveName == '' ) { |
1967 | | - // This was originally a current version; we |
1968 | | - // have to devise a new archive name for it. |
1969 | | - // Format is <timestamp of archiving>!<name> |
1970 | | - $archiveName = wfTimestamp( TS_MW, $row->fa_deleted_timestamp ) . '!' . $row->fa_name; |
1971 | | - } |
1972 | | - |
1973 | | - list($timestamp,$img) = explode('!',$archiveName,2); |
1974 | | - // Is this image hidden? |
1975 | | - if( !$Unsuppress && $row->fa_deleted & Image::DELETED_FILE ) { |
1976 | | - $group = 'hidden'; |
1977 | | - // Upon restoration, this should go into the hidden directory |
1978 | | - $hiddenstore = FileStore::get( $group ); |
1979 | | - $destPath = $hiddenstore->filePath( $row->fa_storage_key ); |
1980 | | - // Follow the usual <timestamp>!<key> convention for hidden files |
1981 | | - $archiveName = "{$timestamp}!{$row->fa_storage_key}"; |
1982 | | - // Does the archivename use a filestore key? (was hidden when deleted) |
1983 | | - } else if( $img != $row->fa_name && FileStore::validKey($img) ) { |
1984 | | - // Follow the usual <timestamp>!<image> convention for old files |
1985 | | - $archiveName = "{$timestamp}!{$row->fa_name}"; |
1986 | | - $destPath = $destDir . DIRECTORY_SEPARATOR . $archiveName; |
1987 | | - } else { |
1988 | | - $destDir = wfImageArchiveDir( $row->fa_name ); |
1989 | | - |
1990 | | - if ( !is_dir( $destDir ) ) { |
1991 | | - wfMkdirParents( $destDir ); |
1992 | | - } |
1993 | | - $destPath = $destDir . DIRECTORY_SEPARATOR . $archiveName; |
1994 | | - } |
1995 | | - |
1996 | | - $table = 'oldimage'; |
1997 | | - $fields = array( |
1998 | | - 'oi_name' => $row->fa_name, |
1999 | | - 'oi_archive_name' => $archiveName, |
2000 | | - 'oi_size' => $row->fa_size, |
2001 | | - 'oi_width' => $row->fa_width, |
2002 | | - 'oi_height' => $row->fa_height, |
2003 | | - 'oi_bits' => $row->fa_bits, |
2004 | | - 'oi_description' => $row->fa_description, |
2005 | | - 'oi_user' => $row->fa_user, |
2006 | | - 'oi_user_text' => $row->fa_user_text, |
2007 | | - 'oi_timestamp' => $row->fa_timestamp, |
2008 | | - 'oi_deleted' => $Unsuppress ? 0 : $row->fa_deleted ); |
2009 | | - } |
2010 | | - |
2011 | | - $dbw->insert( $table, $fields, __METHOD__ ); |
2012 | | - // @todo this delete is not totally safe, potentially |
2013 | | - $dbw->delete( 'filearchive', |
2014 | | - array( 'fa_id' => $row->fa_id ), |
2015 | | - __METHOD__ ); |
2016 | | - |
2017 | | - // Check if any other stored revisions use this file; |
2018 | | - // if so, we shouldn't remove the file from the deletion |
2019 | | - // archives so they will still work. |
2020 | | - $useCount = $dbw->selectField( 'filearchive', |
2021 | | - 'COUNT(*)', |
2022 | | - array( |
2023 | | - 'fa_storage_group' => $row->fa_storage_group, |
2024 | | - 'fa_storage_key' => $row->fa_storage_key ), |
2025 | | - __METHOD__ ); |
2026 | | - if( $useCount == 0 ) { |
2027 | | - wfDebug( __METHOD__.": nothing else using {$row->fa_storage_key}, will deleting after\n" ); |
2028 | | - $flags = FileStore::DELETE_ORIGINAL; |
2029 | | - } else { |
2030 | | - $flags = 0; |
2031 | | - } |
2032 | | - |
2033 | | - $transaction->add( $store->export( $row->fa_storage_key, $destPath, $flags ) ); |
2034 | | - } |
2035 | | - |
2036 | | - $dbw->immediateCommit(); |
2037 | | - } catch( MWException $e ) { |
2038 | | - wfDebug( __METHOD__." caught error, aborting\n" ); |
2039 | | - $transaction->rollback(); |
2040 | | - throw $e; |
2041 | | - } |
2042 | | - |
2043 | | - $transaction->commit(); |
2044 | | - FileStore::unlock(); |
2045 | | - |
2046 | | - if( $revisions > 0 ) { |
2047 | | - if( !$exists ) { |
2048 | | - wfDebug( __METHOD__." restored $revisions items, creating a new current\n" ); |
2049 | | - |
2050 | | - // Update site_stats |
2051 | | - $site_stats = $dbw->tableName( 'site_stats' ); |
2052 | | - $dbw->query( "UPDATE $site_stats SET ss_images=ss_images+1", __METHOD__ ); |
2053 | | - |
2054 | | - $this->purgeEverything(); |
2055 | | - } else { |
2056 | | - wfDebug( __METHOD__." restored $revisions as archived versions\n" ); |
2057 | | - $this->purgeDescription(); |
2058 | | - } |
2059 | | - } |
2060 | | - |
2061 | | - return $revisions; |
2062 | | - } |
2063 | | - |
2064 | | - /** |
2065 | | - * Returns 'true' if this image is a multipage document, e.g. a DJVU |
2066 | | - * document. |
2067 | | - * |
2068 | | - * @return Bool |
2069 | | - */ |
2070 | | - function isMultipage() { |
2071 | | - $handler = $this->getHandler(); |
2072 | | - return $handler && $handler->isMultiPage(); |
2073 | | - } |
2074 | | - |
2075 | | - /** |
2076 | | - * Returns the number of pages of a multipage document, or NULL for |
2077 | | - * documents which aren't multipage documents |
2078 | | - */ |
2079 | | - function pageCount() { |
2080 | | - $handler = $this->getHandler(); |
2081 | | - if ( $handler && $handler->isMultiPage() ) { |
2082 | | - return $handler->pageCount( $this ); |
2083 | | - } else { |
2084 | | - return null; |
2085 | | - } |
2086 | | - } |
2087 | | - |
2088 | | - static function getCommonsDB() { |
2089 | | - static $dbc; |
2090 | | - global $wgLoadBalancer, $wgSharedUploadDBname; |
2091 | | - if ( !isset( $dbc ) ) { |
2092 | | - $i = $wgLoadBalancer->getGroupIndex( 'commons' ); |
2093 | | - $dbinfo = $wgLoadBalancer->mServers[$i]; |
2094 | | - $dbc = new Database( $dbinfo['host'], $dbinfo['user'], |
2095 | | - $dbinfo['password'], $wgSharedUploadDBname ); |
2096 | | - } |
2097 | | - return $dbc; |
2098 | | - } |
2099 | | - |
2100 | | - /** |
2101 | | - * Calculate the height of a thumbnail using the source and destination width |
2102 | | - */ |
2103 | | - static function scaleHeight( $srcWidth, $srcHeight, $dstWidth ) { |
2104 | | - // Exact integer multiply followed by division |
2105 | | - if ( $srcWidth == 0 ) { |
2106 | | - return 0; |
2107 | | - } else { |
2108 | | - return round( $srcHeight * $dstWidth / $srcWidth ); |
2109 | | - } |
2110 | | - } |
2111 | | - |
2112 | | - /** |
2113 | | - * Get an image size array like that returned by getimagesize(), or false if it |
2114 | | - * can't be determined. |
2115 | | - * |
2116 | | - * @param string $fileName The filename |
2117 | | - * @return array |
2118 | | - */ |
2119 | | - function getImageSize( $fileName ) { |
2120 | | - $handler = $this->getHandler(); |
2121 | | - return $handler->getImageSize( $this, $fileName ); |
2122 | | - } |
2123 | | - |
2124 | | - /** |
2125 | | - * Get the thumbnail extension and MIME type for a given source MIME type |
2126 | | - * @return array thumbnail extension and MIME type |
2127 | | - */ |
2128 | | - static function getThumbType( $ext, $mime ) { |
2129 | | - $handler = MediaHandler::getHandler( $mime ); |
2130 | | - if ( $handler ) { |
2131 | | - return $handler->getThumbType( $ext, $mime ); |
2132 | | - } else { |
2133 | | - return array( $ext, $mime ); |
2134 | | - } |
2135 | | - } |
2136 | | - |
2137 | | -} //class |
2138 | | - |
2139 | | -/** |
2140 | | - * @addtogroup Media |
2141 | | - */ |
2142 | | -class OldImage |
2143 | | -{ |
2144 | | - /** |
2145 | | - * Returns a file object from the oldimage table |
2146 | | - * @param $title, the corresponding image page title |
2147 | | - * @param $name, the storage name |
2148 | | - * @return bool, file was found? |
2149 | | - */ |
2150 | | - function OldImage( $title, $name=null ) { |
2151 | | - if( !is_object( $title ) || is_null($name) ) { |
2152 | | - throw new MWException( 'Image constructor given bogus title.' ); |
2153 | | - } |
2154 | | - if( $title->getNamespace() == NS_IMAGE ) { |
2155 | | - $dbr = wfGetDB( DB_SLAVE ); |
2156 | | - $res = $dbr->select( 'oldimage', |
2157 | | - array( |
2158 | | - 'oi_name', |
2159 | | - 'oi_archive_name', |
2160 | | - 'oi_size', |
2161 | | - 'oi_bits', |
2162 | | - 'oi_width', |
2163 | | - 'oi_height', |
2164 | | - 'oi_metadata', |
2165 | | - 'oi_media_type', |
2166 | | - 'oi_major_mime', |
2167 | | - 'oi_minor_mime', |
2168 | | - 'oi_description', |
2169 | | - 'oi_user', |
2170 | | - 'oi_user_text', |
2171 | | - 'oi_timestamp', |
2172 | | - 'oi_deleted' ), |
2173 | | - array( |
2174 | | - 'oi_name' => $title->getDbKey(), |
2175 | | - 'oi_archive_name' => $name ), |
2176 | | - __METHOD__, |
2177 | | - array( 'ORDER BY' => 'oi_timestamp DESC' ) ); |
2178 | | - // this revision does not exist? |
2179 | | - if ( $dbr->numRows( $res ) == 0 ) { |
2180 | | - return false; |
2181 | | - } |
2182 | | - $ret = $dbr->resultObject( $res ); |
2183 | | - $row = $ret->fetchObject(); |
2184 | | - |
2185 | | - // initialize fields for filestore image object |
2186 | | - $this->mName = $row->oi_name; |
2187 | | - $this->mArchiveName = $row->oi_archive_name; |
2188 | | - $this->mSize = $row->oi_size; |
2189 | | - $this->mBits = $row->oi_bits; |
2190 | | - $this->mWidth = $row->oi_width; |
2191 | | - $this->mHeight = $row->oi_height; |
2192 | | - $this->mMetaData = $row->oi_metadata; |
2193 | | - $this->mMime = "{$row->oi_major_mime}/{$row->oi_minor_mime}"; |
2194 | | - $this->mType = $row->oi_media_type; |
2195 | | - $this->mDescription = $row->oi_description; |
2196 | | - $this->mUser = $row->oi_user; |
2197 | | - $this->mUserText = $row->oi_user_text; |
2198 | | - $this->mTimestamp = $row->oi_timestamp; |
2199 | | - $this->mDeleted = $row->oi_deleted; |
2200 | | - |
2201 | | - $n = strrpos( $this->mName, '.' ); |
2202 | | - $this->extension = Image::normalizeExtension( $n ? |
2203 | | - substr( $this->mName, $n + 1 ) : '' ); |
2204 | | - } else { |
2205 | | - throw new MWException( 'This title does not correspond to an image page.' ); |
2206 | | - return false; |
2207 | | - } |
2208 | | - return true; |
2209 | | - } |
2210 | | - |
2211 | | - /** |
2212 | | - * int $field one of DELETED_* bitfield constants |
2213 | | - * for file or revision rows |
2214 | | - * @return bool |
2215 | | - */ |
2216 | | - function isDeleted( $field ) { |
2217 | | - return ($this->mDeleted & $field) == $field; |
2218 | | - } |
2219 | | - |
2220 | | - /** |
2221 | | - * Determine if the current user is allowed to view a particular |
2222 | | - * field of this OldImage file, if it's marked as deleted. |
2223 | | - * @param int $field |
2224 | | - * @return bool |
2225 | | - */ |
2226 | | - function userCan( $field ) { |
2227 | | - if( ($this->mDeleted & $field) == $field ) { |
2228 | | - global $wgUser; |
2229 | | - $permission = ( $this->mDeleted & Image::DELETED_RESTRICTED ) == Image::DELETED_RESTRICTED |
2230 | | - ? 'hiderevision' |
2231 | | - : 'deleterevision'; |
2232 | | - wfDebug( "Checking for $permission due to $field match on $this->mDeleted\n" ); |
2233 | | - return $wgUser->isAllowed( $permission ); |
2234 | | - } else { |
2235 | | - return true; |
2236 | | - } |
2237 | | - } |
2238 | | -} |
2239 | | - |
2240 | | -/** |
2241 | | - * @addtogroup Media |
2242 | | - */ |
2243 | | -class ArchivedFile |
2244 | | -{ |
2245 | | - /** |
2246 | | - * Returns a file object from the filearchive table |
2247 | | - * @param $title, the corresponding image page title |
2248 | | - * @param $id, the image id, a unique key |
2249 | | - * @param $key, optional storage key |
2250 | | - * @return bool, file was found? |
2251 | | - */ |
2252 | | - function ArchivedFile( $title, $id=0, $key='' ) { |
2253 | | - if( !is_object( $title ) ) { |
2254 | | - throw new MWException( 'Image constructor given bogus title.' ); |
2255 | | - } |
2256 | | - $conds = ($id) ? "fa_id = $id" : "fa_storage_key = '$key'"; |
2257 | | - if( $title->getNamespace() == NS_IMAGE ) { |
2258 | | - $dbr = wfGetDB( DB_SLAVE ); |
2259 | | - $res = $dbr->select( 'filearchive', |
2260 | | - array( |
2261 | | - 'fa_id', |
2262 | | - 'fa_name', |
2263 | | - 'fa_storage_key', |
2264 | | - 'fa_storage_group', |
2265 | | - 'fa_size', |
2266 | | - 'fa_bits', |
2267 | | - 'fa_width', |
2268 | | - 'fa_height', |
2269 | | - 'fa_metadata', |
2270 | | - 'fa_media_type', |
2271 | | - 'fa_major_mime', |
2272 | | - 'fa_minor_mime', |
2273 | | - 'fa_description', |
2274 | | - 'fa_user', |
2275 | | - 'fa_user_text', |
2276 | | - 'fa_timestamp', |
2277 | | - 'fa_deleted' ), |
2278 | | - array( |
2279 | | - 'fa_name' => $title->getDbKey(), |
2280 | | - $conds ), |
2281 | | - __METHOD__, |
2282 | | - array( 'ORDER BY' => 'fa_timestamp DESC' ) ); |
2283 | | - |
2284 | | - if ( $dbr->numRows( $res ) == 0 ) { |
2285 | | - // this revision does not exist? |
2286 | | - return false; |
2287 | | - } |
2288 | | - $ret = $dbr->resultObject( $res ); |
2289 | | - $row = $ret->fetchObject(); |
2290 | | - |
2291 | | - // initialize fields for filestore image object |
2292 | | - $this->mId = intval($row->fa_id); |
2293 | | - $this->mName = $row->fa_name; |
2294 | | - $this->mGroup = $row->fa_storage_group; |
2295 | | - $this->mKey = $row->fa_storage_key; |
2296 | | - $this->mSize = $row->fa_size; |
2297 | | - $this->mBits = $row->fa_bits; |
2298 | | - $this->mWidth = $row->fa_width; |
2299 | | - $this->mHeight = $row->fa_height; |
2300 | | - $this->mMetaData = $row->fa_metadata; |
2301 | | - $this->mMime = "{$row->fa_major_mime}/{$row->fa_minor_mime}"; |
2302 | | - $this->mType = $row->fa_media_type; |
2303 | | - $this->mDescription = $row->fa_description; |
2304 | | - $this->mUser = $row->fa_user; |
2305 | | - $this->mUserText = $row->fa_user_text; |
2306 | | - $this->mTimestamp = $row->fa_timestamp; |
2307 | | - $this->mDeleted = $row->fa_deleted; |
2308 | | - } else { |
2309 | | - throw new MWException( 'This title does not correspond to an image page.' ); |
2310 | | - return false; |
2311 | | - } |
2312 | | - return true; |
2313 | | - } |
2314 | | - |
2315 | | - /** |
2316 | | - * int $field one of DELETED_* bitfield constants |
2317 | | - * for file or revision rows |
2318 | | - * @return bool |
2319 | | - */ |
2320 | | - function isDeleted( $field ) { |
2321 | | - return ($this->mDeleted & $field) == $field; |
2322 | | - } |
2323 | | - |
2324 | | - /** |
2325 | | - * Determine if the current user is allowed to view a particular |
2326 | | - * field of this FileStore image file, if it's marked as deleted. |
2327 | | - * @param int $field |
2328 | | - * @return bool |
2329 | | - */ |
2330 | | - function userCan( $field ) { |
2331 | | - if( ($this->mDeleted & $field) == $field ) { |
2332 | | - global $wgUser; |
2333 | | - $permission = ( $this->mDeleted & Image::DELETED_RESTRICTED ) == Image::DELETED_RESTRICTED |
2334 | | - ? 'hiderevision' |
2335 | | - : 'deleterevision'; |
2336 | | - wfDebug( "Checking for $permission due to $field match on $this->mDeleted\n" ); |
2337 | | - return $wgUser->isAllowed( $permission ); |
2338 | | - } else { |
2339 | | - return true; |
2340 | | - } |
2341 | | - } |
2342 | | -} |
2343 | | - |
2344 | | -/** |
2345 | | - * Aliases for backwards compatibility with 1.6 |
2346 | | - */ |
2347 | | -define( 'MW_IMG_DELETED_FILE', Image::DELETED_FILE ); |
2348 | | -define( 'MW_IMG_DELETED_COMMENT', Image::DELETED_COMMENT ); |
2349 | | -define( 'MW_IMG_DELETED_USER', Image::DELETED_USER ); |
2350 | | -define( 'MW_IMG_DELETED_RESTRICTED', Image::DELETED_RESTRICTED ); |
2351 | | - |
2352 | | -?> |
Index: branches/phase3_rev_deleted/includes/ImageFunctions.php |
— | — | @@ -1,114 +1,5 @@ |
2 | 2 | <?php
|
3 | | -
|
4 | 3 | /**
|
5 | | - * Returns the image directory of an image
|
6 | | - * The result is an absolute path.
|
7 | | - *
|
8 | | - * This function is called from thumb.php before Setup.php is included
|
9 | | - *
|
10 | | - * @param $fname String: file name of the image file.
|
11 | | - * @public
|
12 | | - */
|
13 | | -function wfImageDir( $fname ) {
|
14 | | - global $wgUploadDirectory, $wgHashedUploadDirectory;
|
15 | | -
|
16 | | - if (!$wgHashedUploadDirectory) { return $wgUploadDirectory; }
|
17 | | -
|
18 | | - $hash = md5( $fname );
|
19 | | - $dest = $wgUploadDirectory . '/' . $hash{0} . '/' . substr( $hash, 0, 2 );
|
20 | | -
|
21 | | - return $dest;
|
22 | | -}
|
23 | | -
|
24 | | -/**
|
25 | | - * Returns the image directory of an image's thumbnail
|
26 | | - * The result is an absolute path.
|
27 | | - *
|
28 | | - * This function is called from thumb.php before Setup.php is included
|
29 | | - *
|
30 | | - * @param $fname String: file name of the original image file
|
31 | | - * @param $shared Boolean: (optional) use the shared upload directory (default: 'false').
|
32 | | - * @public
|
33 | | - */
|
34 | | -function wfImageThumbDir( $fname, $shared = false ) {
|
35 | | - $base = wfImageArchiveDir( $fname, 'thumb', $shared );
|
36 | | - if ( Image::isHashed( $shared ) ) {
|
37 | | - $dir = "$base/$fname";
|
38 | | - } else {
|
39 | | - $dir = $base;
|
40 | | - }
|
41 | | -
|
42 | | - return $dir;
|
43 | | -}
|
44 | | -
|
45 | | -/**
|
46 | | - * Old thumbnail directory, kept for conversion
|
47 | | - */
|
48 | | -function wfDeprecatedThumbDir( $thumbName , $subdir='thumb', $shared=false) {
|
49 | | - return wfImageArchiveDir( $thumbName, $subdir, $shared );
|
50 | | -}
|
51 | | -
|
52 | | -/**
|
53 | | - * Returns the image directory of an image's old version
|
54 | | - * The result is an absolute path.
|
55 | | - *
|
56 | | - * This function is called from thumb.php before Setup.php is included
|
57 | | - *
|
58 | | - * @param $fname String: file name of the thumbnail file, including file size prefix.
|
59 | | - * @param $subdir String: subdirectory of the image upload directory that should be used for storing the old version. Default is 'archive'.
|
60 | | - * @param $shared Boolean use the shared upload directory (only relevant for other functions which call this one). Default is 'false'.
|
61 | | - * @public
|
62 | | - */
|
63 | | -function wfImageArchiveDir( $fname , $subdir='archive', $shared=false ) {
|
64 | | - global $wgUploadDirectory, $wgHashedUploadDirectory;
|
65 | | - global $wgSharedUploadDirectory, $wgHashedSharedUploadDirectory;
|
66 | | - $dir = $shared ? $wgSharedUploadDirectory : $wgUploadDirectory;
|
67 | | - $hashdir = $shared ? $wgHashedSharedUploadDirectory : $wgHashedUploadDirectory;
|
68 | | - if (!$hashdir) { return $dir.'/'.$subdir; }
|
69 | | - $hash = md5( $fname );
|
70 | | -
|
71 | | - return $dir.'/'.$subdir.'/'.$hash[0].'/'.substr( $hash, 0, 2 );
|
72 | | -}
|
73 | | -
|
74 | | -
|
75 | | -/*
|
76 | | - * Return the hash path component of an image path (URL or filesystem),
|
77 | | - * e.g. "/3/3c/", or just "/" if hashing is not used.
|
78 | | - *
|
79 | | - * @param $dbkey The filesystem / database name of the file
|
80 | | - * @param $fromSharedDirectory Use the shared file repository? It may
|
81 | | - * use different hash settings from the local one.
|
82 | | - */
|
83 | | -function wfGetHashPath ( $dbkey, $fromSharedDirectory = false ) {
|
84 | | - if( Image::isHashed( $fromSharedDirectory ) ) {
|
85 | | - $hash = md5($dbkey);
|
86 | | - return '/' . $hash{0} . '/' . substr( $hash, 0, 2 ) . '/';
|
87 | | - } else {
|
88 | | - return '/';
|
89 | | - }
|
90 | | -}
|
91 | | -
|
92 | | -/**
|
93 | | - * Returns the image URL of an image's old version
|
94 | | - *
|
95 | | - * @param $name String: file name of the image file
|
96 | | - * @param $subdir String: (optional) subdirectory of the image upload directory that is used by the old version. Default is 'archive'
|
97 | | - * @public
|
98 | | - */
|
99 | | -function wfImageArchiveUrl( $name, $subdir='archive' ) {
|
100 | | - global $wgUploadPath, $wgHashedUploadDirectory;
|
101 | | -
|
102 | | - if ($wgHashedUploadDirectory) {
|
103 | | - $hash = md5( substr( $name, 15) );
|
104 | | - $url = $wgUploadPath.'/'.$subdir.'/' . $hash{0} . '/' .
|
105 | | - substr( $hash, 0, 2 ) . '/'.$name;
|
106 | | - } else {
|
107 | | - $url = $wgUploadPath.'/'.$subdir.'/'.$name;
|
108 | | - }
|
109 | | - return wfUrlencode($url);
|
110 | | -}
|
111 | | -
|
112 | | -/**
|
113 | 4 | * Return a rounded pixel equivalent for a labeled CSS/SVG length.
|
114 | 5 | * http://www.w3.org/TR/SVG11/coords.html#UnitIdentifiers
|
115 | 6 | *
|
Index: branches/phase3_rev_deleted/includes/SpecialRevisiondelete.php |
— | — | @@ -66,14 +66,14 @@ |
67 | 67 | |
68 | 68 | // For reviewing deleted files |
69 | 69 | if ( $file ) { |
70 | | - $oimage = new OldImage( $this->page, $file ); |
| 70 | + $oimage = RepoGroup::singleton()->getLocalRepo()->newFromArchiveName( $page, $file ); |
71 | 71 | // Check if user is allowed to see this file |
72 | | - if ( !$oimage->userCan(Image::DELETED_FILE) ) { |
| 72 | + if( !$oimage->userCan(File::DELETED_FILE) ) { |
73 | 73 | $wgOut->permissionRequired( 'hiderevision' ); |
74 | 74 | return false; |
75 | 75 | } else { |
76 | 76 | // Format for hidden images is <timestamp>!<key> |
77 | | - list($ts,$key) = explode('!',$file); |
| 77 | + list($ts,$key) = explode('!',$file,2); |
78 | 78 | return $this->showFile( $key ); |
79 | 79 | } |
80 | 80 | } |
— | — | @@ -88,11 +88,11 @@ |
89 | 89 | $this->deletetype='arid'; |
90 | 90 | } else if( $oldimages ) { |
91 | 91 | $this->ofiles = $oldimages; |
92 | | - $hide_content_name = array( 'revdelete-hide-image', 'wpHideImage', Image::DELETED_FILE ); |
| 92 | + $hide_content_name = array( 'revdelete-hide-image', 'wpHideImage', File::DELETED_FILE ); |
93 | 93 | $this->deletetype='oldimage'; |
94 | 94 | } else if( $fileids ) { |
95 | 95 | $this->afiles = $fileids; |
96 | | - $hide_content_name = array( 'revdelete-hide-image', 'wpHideImage', Image::DELETED_FILE ); |
| 96 | + $hide_content_name = array( 'revdelete-hide-image', 'wpHideImage', File::DELETED_FILE ); |
97 | 97 | $this->deletetype='fileid'; |
98 | 98 | } else if( $logids ) { |
99 | 99 | $this->events = $logids; |
— | — | @@ -127,15 +127,6 @@ |
128 | 128 | } |
129 | 129 | |
130 | 130 | /** |
131 | | - * This sets any fields that are true to a bitfield to true on a given bitfield |
132 | | - * @param $bitfield, running bitfield |
133 | | - * @param $nbitfield, new bitfiled |
134 | | - */ |
135 | | - function setBitfield( $bitfield, $nbitfield ) { |
136 | | - return $bitfield | $nbitfield; |
137 | | - } |
138 | | - |
139 | | - /** |
140 | 131 | * This lets a user set restrictions for live and archived revisions |
141 | 132 | * @param WebRequest $request |
142 | 133 | */ |
— | — | @@ -166,7 +157,7 @@ |
167 | 158 | $UserAllowed=false; |
168 | 159 | } |
169 | 160 | $wgOut->addHtml( $this->historyLine( $rev ) ); |
170 | | - $bitfields = $this->setBitfield( $bitfields, $rev->mDeleted ); |
| 161 | + $bitfields |= $rev->mDeleted; |
171 | 162 | } |
172 | 163 | // The archives... |
173 | 164 | } else { |
— | — | @@ -185,7 +176,7 @@ |
186 | 177 | $UserAllowed=false; |
187 | 178 | } |
188 | 179 | $wgOut->addHtml( $this->historyLine( $rev ) ); |
189 | | - $bitfields = $this->setBitfield( $bitfields, $rev->mDeleted ); |
| 180 | + $bitfields |= $rev->mDeleted; |
190 | 181 | } |
191 | 182 | } |
192 | 183 | $wgOut->addHtml( "</ul>" ); |
— | — | @@ -253,26 +244,27 @@ |
254 | 245 | // Our image may be hidden, if so it's name is formated as <time>!<key> |
255 | 246 | // Otherwise, it will be <time>!<image> and the URL only needs to pass the time |
256 | 247 | $archivename = ( strpos($name,'!')==false ) ? $name.'!'.$this->page->getDbKey() : $name; |
257 | | - $oimage = new OldImage( $this->page, $archivename ); |
258 | | - if( !isset( $oimage->mName ) ) { |
| 248 | + |
| 249 | + $oimage = RepoGroup::singleton()->getLocalRepo()->newFromArchiveName( $this->page, $archivename ); |
| 250 | + if( !$oimage->exists() ) { |
259 | 251 | $wgOut->showErrorPage( 'revdelete-nooldid-title', 'revdelete-nooldid-text' ); |
260 | 252 | return; |
261 | | - } else if( !$oimage->userCan(Revision::DELETED_RESTRICTED) ) { |
| 253 | + } else if( !$oimage->userCan(File::DELETED_RESTRICTED) ) { |
262 | 254 | // If a rev is hidden from sysops |
263 | | - if( $action != 'submit') { |
264 | | - $wgOut->permissionRequired( 'hiderevision' ); |
| 255 | + if( $action != 'submit' ) { |
| 256 | + $wgOut->permissionRequired( 'hiderevision' ); |
265 | 257 | return; |
266 | 258 | } |
267 | 259 | $UserAllowed=false; |
268 | 260 | } |
269 | 261 | $wgOut->addHtml( $this->uploadLine( $oimage ) ); |
270 | | - $bitfields = $this->setBitfield( $bitfields, $oimage->mDeleted ); |
| 262 | + $bitfields |= $oimage->deleted; |
271 | 263 | } |
272 | 264 | // Archived files... |
273 | 265 | } else { |
274 | 266 | foreach( $this->afiles as $fileid ) { |
275 | 267 | $file = new ArchivedFile( $this->page, $fileid ); |
276 | | - if( !isset( $file->mId ) ) { |
| 268 | + if( !isset( $file->id ) ) { |
277 | 269 | $wgOut->showErrorPage( 'revdelete-nooldid-title', 'revdelete-nooldid-text' ); |
278 | 270 | return; |
279 | 271 | } else if( !$file->userCan(Revision::DELETED_RESTRICTED) ) { |
— | — | @@ -284,7 +276,7 @@ |
285 | 277 | $UserAllowed=false; |
286 | 278 | } |
287 | 279 | $wgOut->addHtml( $this->uploadLine( $file ) ); |
288 | | - $bitfields = $this->setBitfield( $bitfields, $file->mDeleted ); |
| 280 | + $bitfields |= $file->deleted; |
289 | 281 | } |
290 | 282 | } |
291 | 283 | $wgOut->addHtml( "</ul>" ); |
— | — | @@ -360,7 +352,7 @@ |
361 | 353 | $UserAllowed=false; |
362 | 354 | } |
363 | 355 | $wgOut->addHtml( $this->logLine( $log, $event ) ); |
364 | | - $bitfields = $this->setBitfield( $bitfields, $event->log_deleted ); |
| 356 | + $bitfields |= $event->log_deleted; |
365 | 357 | } |
366 | 358 | $wgOut->addHtml( "</ul>" ); |
367 | 359 | |
— | — | @@ -438,7 +430,7 @@ |
439 | 431 | } |
440 | 432 | |
441 | 433 | /** |
442 | | - * @param OldImage or ArchivedFile $file |
| 434 | + * @param OldLocalImage or ArchivedFile $file |
443 | 435 | * This can work for old or archived revisions |
444 | 436 | * @returns string |
445 | 437 | */ |
— | — | @@ -446,19 +438,19 @@ |
447 | 439 | global $wgContLang, $wgTitle; |
448 | 440 | |
449 | 441 | $target = $this->page->getPrefixedText(); |
450 | | - $date = $wgContLang->timeanddate( $file->mTimestamp, true ); |
| 442 | + $date = $wgContLang->timeanddate( $file->timestamp, true ); |
451 | 443 | |
452 | 444 | $del = ''; |
453 | 445 | // Special:Undelete for viewing archived images |
454 | 446 | if( $this->deletetype=='fileid' ) { |
455 | 447 | $undelete = SpecialPage::getTitleFor( 'Undelete' ); |
456 | | - $pageLink = $this->skin->makeKnownLinkObj( $undelete, $date, "target=$target&file=$file->mKey" ); |
| 448 | + $pageLink = $this->skin->makeKnownLinkObj( $undelete, $date, "target=$target&file=$file->key" ); |
457 | 449 | // Revisiondelete for viewing images |
458 | 450 | } else { |
459 | 451 | # Hidden files... |
460 | | - if( $file->isDeleted(Image::DELETED_FILE) ) { |
| 452 | + if( $file->isDeleted(File::DELETED_FILE) ) { |
461 | 453 | $del = ' <tt>' . wfMsgHtml( 'deletedrev' ) . '</tt>'; |
462 | | - if( !$file->userCan(Image::DELETED_FILE) ) { |
| 454 | + if( !$file->userCan(File::DELETED_FILE) ) { |
463 | 455 | $pageLink = $date; |
464 | 456 | } else { |
465 | 457 | $pageLink = $this->skin->makeKnownLinkObj( $wgTitle, $date, "target=$target&file=$file->mArchiveName" ); |
— | — | @@ -466,18 +458,18 @@ |
467 | 459 | $pageLink = '<span class="history-deleted">' . $pageLink . '</span>'; |
468 | 460 | # Regular files... |
469 | 461 | } else { |
470 | | - $url = htmlspecialchars( wfImageArchiveUrl( $file->mArchiveName ) ); |
| 462 | + $url = $file->getUrlRel(); |
471 | 463 | $pageLink = "<a href=\"{$url}\">{$date}</a>"; |
472 | 464 | } |
473 | 465 | } |
474 | 466 | |
475 | 467 | $data = wfMsgHtml( 'widthheight', |
476 | | - $wgContLang->formatNum( $file->mWidth ), |
477 | | - $wgContLang->formatNum( $file->mHeight ) ) . |
478 | | - ' (' . wfMsgHtml( 'nbytes', $wgContLang->formatNum( $file->mSize ) ) . ')'; |
| 468 | + $wgContLang->formatNum( $file->width ), |
| 469 | + $wgContLang->formatNum( $file->height ) ) . |
| 470 | + ' (' . wfMsgHtml( 'nbytes', $wgContLang->formatNum( $file->size ) ) . ')'; |
479 | 471 | |
480 | | - return |
481 | | - "<li> $pageLink " . $this->skin->fileUserLink( $file ) . " $data " . $this->skin->fileComment( $file ) . "$del</li>"; |
| 472 | + #return "<li> $pageLink " . $this->skin->fileUserLink( $file ) . " $data " . $this->skin->fileComment( $file ) . "$del</li>"; |
| 473 | + return "<li> $pageLink $data $del</li>"; |
482 | 474 | } |
483 | 475 | |
484 | 476 | /** |
— | — | @@ -718,24 +710,24 @@ |
719 | 711 | // Our image may be hidden, if so it's name is formated as <time>!<key> |
720 | 712 | // Otherwise, it will be <time>!<image> and the URL only needs to pass the time |
721 | 713 | $archivename = ( strpos($name,'!')==false ) ? $name.'!'.$title->getDbKey() : $name; |
722 | | - $oimage = new OldImage( $title, $archivename ); |
723 | | - if( !isset($oimage->mName) ) { |
| 714 | + $oimage = RepoGroup::singleton()->getLocalRepo()->newFromArchiveName( $title, $archivename ); |
| 715 | + if( !$oimage->exists() ) { |
724 | 716 | return false; |
725 | | - } else if( !$oimage->userCan(Revision::DELETED_RESTRICTED) ) { |
| 717 | + } else if( !$oimage->userCan(File::DELETED_RESTRICTED) ) { |
726 | 718 | $UserAllowedAll=false; |
727 | 719 | continue; |
728 | 720 | } |
729 | 721 | |
730 | 722 | $transaction = true; |
731 | 723 | // Which revisions did we change anything about? |
732 | | - if( $oimage->mDeleted != $bitfield ) { |
| 724 | + if( $oimage->deleted != $bitfield ) { |
733 | 725 | $count++; |
734 | 726 | |
735 | 727 | $this->dbw->begin(); |
736 | 728 | $this->updateOldFiles( $oimage, $bitfield ); |
737 | 729 | // If this image is currently hidden... |
738 | | - if( $oimage->mDeleted & Image::DELETED_FILE ) { |
739 | | - if( $bitfield & Image::DELETED_FILE ) { |
| 730 | + if( $oimage->deleted & File::DELETED_FILE ) { |
| 731 | + if( $bitfield & File::DELETED_FILE ) { |
740 | 732 | # Leave it alone if we are not changing this... |
741 | 733 | $set[]=$name; |
742 | 734 | $transaction = true; |
— | — | @@ -745,7 +737,7 @@ |
746 | 738 | $set[]=$transaction; |
747 | 739 | } |
748 | 740 | // Is it just now becoming hidden? |
749 | | - } else if( $bitfield & Image::DELETED_FILE ) { |
| 741 | + } else if( $bitfield & File::DELETED_FILE ) { |
750 | 742 | $transaction = $this->makeOldImagePrivate( $oimage ); |
751 | 743 | $set[]=$transaction; |
752 | 744 | } else { |
— | — | @@ -790,9 +782,9 @@ |
791 | 783 | // To work! |
792 | 784 | foreach( $items as $fileid ) { |
793 | 785 | $file = new ArchivedFile( $title, $fileid ); |
794 | | - if( !isset($file->mId) ) { |
| 786 | + if( !isset($file->id) ) { |
795 | 787 | return false; |
796 | | - } else if( !$file->userCan(Revision::DELETED_RESTRICTED) ) { |
| 788 | + } else if( !$file->userCan(File::DELETED_RESTRICTED) ) { |
797 | 789 | $UserAllowedAll=false; |
798 | 790 | continue; |
799 | 791 | } |
— | — | @@ -886,16 +878,16 @@ |
887 | 879 | return false; |
888 | 880 | } |
889 | 881 | |
890 | | - list($timestamp,$img) = explode('!',$oimage->mArchiveName,2); |
| 882 | + list($timestamp,$img) = explode('!',$oimage->archive_name,2); |
891 | 883 | |
892 | | - $oldpath = wfImageArchiveDir( $oimage->mName ) . DIRECTORY_SEPARATOR . $oimage->mArchiveName; |
| 884 | + $oldpath = $oimage->getArchivePath() . DIRECTORY_SEPARATOR . $oimage->archive_name; |
893 | 885 | // Dupe the file into the file store |
894 | 886 | if( file_exists( $oldpath ) ) { |
895 | 887 | $group = 'hidden'; |
896 | 888 | // Is our directory configured? |
897 | 889 | if( $wgFileStore[$group]['directory'] ) { |
898 | 890 | $store = FileStore::get( $group ); |
899 | | - $key = FileStore::calculateKey( $oldpath, $oimage->extension ); |
| 891 | + $key = FileStore::calculateKey( $oldpath, $oimage->getExtension() ); |
900 | 892 | $transaction->add( $store->insert( $key, $oldpath, FileStore::DELETE_ORIGINAL ) ); |
901 | 893 | } else { |
902 | 894 | $group = null; |
— | — | @@ -924,12 +916,12 @@ |
925 | 917 | if ( $key ) { |
926 | 918 | $this->dbw->update( 'oldimage', |
927 | 919 | array( 'oi_archive_name' => "{$timestamp}!{$key}" ), |
928 | | - array( 'oi_name' => $oimage->mName, 'oi_archive_name' => $oimage->mArchiveName ), |
| 920 | + array( 'oi_name' => $oimage->name, 'oi_archive_name' => $oimage->archive_name ), |
929 | 921 | __METHOD__ ); |
930 | 922 | } |
931 | 923 | |
932 | 924 | // Use of $timeframe for Image objects can create thumbnails of oldimages |
933 | | - $imgtitle = Title::makeTitle( NS_IMAGE, $oimage->mName ); |
| 925 | + $imgtitle = Title::makeTitle( NS_IMAGE, $oimage->name ); |
934 | 926 | $image = new Image( $imgtitle ); |
935 | 927 | $image->purgeCache(); // Clear any thumbnails/purge squid cache |
936 | 928 | |
— | — | @@ -963,25 +955,24 @@ |
964 | 956 | return false; |
965 | 957 | } |
966 | 958 | |
967 | | - $destDir = wfImageArchiveDir( $oimage->mName ); |
| 959 | + $destDir = $oimage->getArchivePath(); |
968 | 960 | if ( !is_dir( $destDir ) ) { |
969 | 961 | wfMkdirParents( $destDir ); |
970 | 962 | } |
971 | 963 | // Deleted versions have an archive_name like <timestamp>!<key> |
972 | | - list($timestamp,$key) = explode('!',$oimage->mArchiveName); |
973 | | - $archivename = "{$timestamp}!{$oimage->mName}"; |
| 964 | + list($timestamp,$key) = explode('!',$oimage->archive_name); |
| 965 | + $archivename = "{$timestamp}!{$oimage->name}"; |
974 | 966 | |
975 | 967 | $destPath = $destDir . DIRECTORY_SEPARATOR . $archivename; |
976 | 968 | // Check if any other stored revisions use this file; |
977 | 969 | // if so, we shouldn't remove the file from the hidden |
978 | 970 | // archives so they will still work. |
979 | | - $useCount = $this->dbw->selectField( 'oldimage', |
980 | | - 'COUNT(*)', |
981 | | - array( 'oi_archive_name' => $oimage->mArchiveName, 'oi_name' => $oimage->mName ), |
| 971 | + $useCount = $this->dbw->selectField( 'oldimage','COUNT(*)', |
| 972 | + array( 'oi_archive_name' => $oimage->archive_name, 'oi_name' => $oimage->name ), |
982 | 973 | __METHOD__ ); |
983 | 974 | |
984 | 975 | if( $useCount == 0 ) { |
985 | | - wfDebug( __METHOD__.": nothing else using {$oimage->mArchiveName}, will deleting after\n" ); |
| 976 | + wfDebug( __METHOD__.": nothing else using {$oimage->archive_name}, will deleting after\n" ); |
986 | 977 | $flags = FileStore::DELETE_ORIGINAL; |
987 | 978 | } else { |
988 | 979 | $flags = 0; |
— | — | @@ -993,8 +984,8 @@ |
994 | 985 | FileStore::unlock(); |
995 | 986 | // Re-insert the original archive_name, like <timestamp>!<name> |
996 | 987 | $this->dbw->update( 'oldimage', |
997 | | - array( 'oi_archive_name' => "{$timestamp}!{$oimage->mName}" ), |
998 | | - array( 'oi_name' => $oimage->mName, 'oi_archive_name' => $oimage->mArchiveName ), |
| 988 | + array( 'oi_archive_name' => "{$timestamp}!{$oimage->name}" ), |
| 989 | + array( 'oi_name' => $oimage->name, 'oi_archive_name' => $oimage->archive_name ), |
999 | 990 | __METHOD__ ); |
1000 | 991 | |
1001 | 992 | return $timestamp; |
— | — | @@ -1032,7 +1023,7 @@ |
1033 | 1024 | function updateOldFiles( $oimage, $bitfield ) { |
1034 | 1025 | $this->dbw->update( 'oldimage', |
1035 | 1026 | array( 'oi_deleted' => $bitfield ), |
1036 | | - array( 'oi_archive_name' => $oimage->mArchiveName ), |
| 1027 | + array( 'oi_archive_name' => $oimage->archive_name ), |
1037 | 1028 | 'RevisionDeleter::updateOldFiles' ); |
1038 | 1029 | } |
1039 | 1030 | |
— | — | @@ -1044,7 +1035,7 @@ |
1045 | 1036 | function updateArchFiles( $file, $bitfield ) { |
1046 | 1037 | $this->dbw->update( 'filearchive', |
1047 | 1038 | array( 'fa_deleted' => $bitfield ), |
1048 | | - array( 'fa_id' => $file->mId ), |
| 1039 | + array( 'fa_id' => $file->id ), |
1049 | 1040 | 'RevisionDeleter::updateArchFiles' ); |
1050 | 1041 | } |
1051 | 1042 | |
Index: branches/phase3_rev_deleted/includes/OutputPage.php |
— | — | @@ -54,6 +54,8 @@ |
55 | 55 | $this->mETag = false; |
56 | 56 | $this->mRevisionId = null; |
57 | 57 | $this->mNewSectionLink = false; |
| 58 | + $this->mTemplateIds = array(); |
| 59 | + $this->mImageTimestamps = array(); |
58 | 60 | } |
59 | 61 | |
60 | 62 | public function redirect( $url, $responsecode = '302' ) { |
— | — | @@ -384,6 +386,10 @@ |
385 | 387 | } |
386 | 388 | $this->mNoGallery = $parserOutput->getNoGallery(); |
387 | 389 | $this->mHeadItems = array_merge( $this->mHeadItems, (array)$parserOutput->mHeadItems ); |
| 390 | + // Versioning... |
| 391 | + $this->mTemplateIds += (array)$parserOutput->mTemplateIds; |
| 392 | + $this->mImageTimestamps += (array)$parserOutput->mImageTimestamps; |
| 393 | + |
388 | 394 | wfRunHooks( 'OutputPageParserOutput', array( &$this, $parserOutput ) ); |
389 | 395 | } |
390 | 396 | |
— | — | @@ -1246,12 +1252,12 @@ |
1247 | 1253 | * @param int $lag Slave lag |
1248 | 1254 | */ |
1249 | 1255 | public function showLagWarning( $lag ) { |
1250 | | - global $wgSlaveLagWarning, $wgSlaveLagOhNo; |
| 1256 | + global $wgSlaveLagWarning, $wgSlaveLagCritical; |
1251 | 1257 | |
1252 | 1258 | if ($lag < $wgSlaveLagWarning) |
1253 | 1259 | return; |
1254 | 1260 | |
1255 | | - $message = $lag >= $wgSlaveLagOhNo ? 'lag-warn-high' : 'lag-warn-normal'; |
| 1261 | + $message = ($lag >= $wgSlaveLagCritical) ? 'lag-warn-high' : 'lag-warn-normal'; |
1256 | 1262 | $warning = wfMsgHtml( $message, htmlspecialchars( $lag ) ); |
1257 | 1263 | $this->addHtml( "<div class=\"mw-{$message}\">\n{$warning}\n</div>\n" ); |
1258 | 1264 | } |
Index: branches/phase3_rev_deleted/includes/Setup.php |
— | — | @@ -54,6 +54,59 @@ |
55 | 55 | if( $wgReadOnlyFile === false ) $wgReadOnlyFile = "{$wgUploadDirectory}/lock_yBgMBwiR"; |
56 | 56 | if( $wgFileCacheDirectory === false ) $wgFileCacheDirectory = "{$wgUploadDirectory}/cache"; |
57 | 57 | |
| 58 | +/** |
| 59 | + * Initialise $wgLocalFileRepo from backwards-compatible settings |
| 60 | + */ |
| 61 | +if ( !$wgLocalFileRepo ) { |
| 62 | + $wgLocalFileRepo = array( |
| 63 | + 'class' => 'LocalRepo', |
| 64 | + 'name' => 'local', |
| 65 | + 'directory' => $wgUploadDirectory, |
| 66 | + 'url' => $wgUploadBaseUrl ? $wgUploadBaseUrl . $wgUploadPath : $wgUploadPath, |
| 67 | + 'hashLevels' => $wgHashedUploadDirectory ? 2 : 0, |
| 68 | + 'thumbScriptUrl' => $wgThumbnailScriptPath, |
| 69 | + 'transformVia404' => !$wgGenerateThumbnailOnParse, |
| 70 | + ); |
| 71 | +} |
| 72 | +/** |
| 73 | + * Initialise shared repo from backwards-compatible settings |
| 74 | + */ |
| 75 | +if ( $wgUseSharedUploads ) { |
| 76 | + if ( $wgSharedUploadDBname ) { |
| 77 | + $wgForeignFileRepos[] = array( |
| 78 | + 'class' => 'ForeignDBRepo', |
| 79 | + 'name' => 'shared', |
| 80 | + 'directory' => $wgSharedUploadDirectory, |
| 81 | + 'url' => $wgSharedUploadPath, |
| 82 | + 'hashLevels' => $wgHashedSharedUploadDirectory ? 2 : 0, |
| 83 | + 'thumbScriptUrl' => $wgSharedThumbnailScriptPath, |
| 84 | + 'transformVia404' => !$wgGenerateThumbnailOnParse, |
| 85 | + 'dbType' => $wgDBtype, |
| 86 | + 'dbServer' => $wgDBserver, |
| 87 | + 'dbUser' => $wgDBuser, |
| 88 | + 'dbPassword' => $wgDBpassword, |
| 89 | + 'dbName' => $wgSharedUploadDBname, |
| 90 | + 'dbFlags' => DBO_DEFAULT, |
| 91 | + 'tablePrefix' => $wgSharedUploadDBprefix, |
| 92 | + 'hasSharedCache' => $wgCacheSharedUploads, |
| 93 | + 'descBaseUrl' => $wgRepositoryBaseUrl, |
| 94 | + 'fetchDescription' => $wgFetchCommonsDescriptions, |
| 95 | + ); |
| 96 | + } else { |
| 97 | + $wgForeignFileRepos[] = array( |
| 98 | + 'class' => 'FSRepo', |
| 99 | + 'name' => 'shared', |
| 100 | + 'directory' => $wgSharedUploadDirectory, |
| 101 | + 'url' => $wgSharedUploadPath, |
| 102 | + 'hashLevels' => $wgHashedSharedUploadDirectory ? 2 : 0, |
| 103 | + 'thumbScriptUrl' => $wgSharedThumbnailScriptPath, |
| 104 | + 'transformVia404' => !$wgGenerateThumbnailOnParse, |
| 105 | + 'descBaseUrl' => $wgRepositoryBaseUrl, |
| 106 | + 'fetchDescription' => $wgFetchCommonsDescriptions, |
| 107 | + ); |
| 108 | + } |
| 109 | +} |
| 110 | + |
58 | 111 | require_once( "$IP/includes/AutoLoader.php" ); |
59 | 112 | |
60 | 113 | wfProfileIn( $fname.'-exception' ); |
Index: branches/phase3_rev_deleted/includes/QueryPage.php |
— | — | @@ -332,6 +332,8 @@ |
333 | 333 | $num = $dbr->numRows($res); |
334 | 334 | |
335 | 335 | $this->preprocessResults( $dbr, $res ); |
| 336 | + |
| 337 | + $wgOut->addHtml( XML::openElement( 'div', array('class' => 'mw-spcontent') ) ); |
336 | 338 | |
337 | 339 | # Top header and navigation |
338 | 340 | if( $shownavigation ) { |
— | — | @@ -346,6 +348,7 @@ |
347 | 349 | # No results to show, so don't bother with "showing X of Y" etc. |
348 | 350 | # -- just let the user know and give up now |
349 | 351 | $wgOut->addHtml( '<p>' . wfMsgHtml( 'specialpage-empty' ) . '</p>' ); |
| 352 | + $wgOut->addHtml( XML::closeElement( 'div' ) ); |
350 | 353 | return; |
351 | 354 | } |
352 | 355 | } |
— | — | @@ -364,6 +367,8 @@ |
365 | 368 | if( $shownavigation ) { |
366 | 369 | $wgOut->addHtml( '<p>' . $paging . '</p>' ); |
367 | 370 | } |
| 371 | + |
| 372 | + $wgOut->addHtml( XML::closeElement( 'div' ) ); |
368 | 373 | |
369 | 374 | return $num; |
370 | 375 | } |
— | — | @@ -427,11 +432,11 @@ |
428 | 433 | } |
429 | 434 | |
430 | 435 | function openList( $offset ) { |
431 | | - return "<ol start='" . ( $offset + 1 ) . "' class='special'>"; |
| 436 | + return "\n<ol start='" . ( $offset + 1 ) . "' class='special'>\n"; |
432 | 437 | } |
433 | 438 | |
434 | 439 | function closeList() { |
435 | | - return '</ol>'; |
| 440 | + return "</ol>\n"; |
436 | 441 | } |
437 | 442 | |
438 | 443 | /** |
Index: branches/phase3_rev_deleted/includes/SpecialUndelete.php |
— | — | @@ -139,10 +139,10 @@ |
140 | 140 | } |
141 | 141 | |
142 | 142 | function getRevisionConds( $timestamp, $id ) { |
143 | | - if ( $id ) { |
| 143 | + if( $id ) { |
144 | 144 | $id = intval($id); |
145 | 145 | return "ar_rev_id=$id"; |
146 | | - } else if ( $timestamp ) { |
| 146 | + } else if( $timestamp ) { |
147 | 147 | return "ar_timestamp=$timestamp"; |
148 | 148 | } else { |
149 | 149 | return 'ar_rev_id=0'; |
— | — | @@ -277,7 +277,7 @@ |
278 | 278 | } |
279 | 279 | |
280 | 280 | if( $restoreFiles && $filetimestamp >= 0 && $this->title->getNamespace() == NS_IMAGE ) { |
281 | | - $img = new Image( $this->title ); |
| 281 | + $img = wfLocalFile( $this->title ); |
282 | 282 | $filesRestored = $img->restore( $filetimestamp, $Unsuppress ); |
283 | 283 | } else { |
284 | 284 | $filesRestored = 0; |
— | — | @@ -349,7 +349,7 @@ |
350 | 350 | array( 'rev_page' => $pageId ), |
351 | 351 | __METHOD__ ); |
352 | 352 | |
353 | | - if ( $row = $dbw->fetchObject($result) ) { |
| 353 | + if( $row = $dbw->fetchObject($result) ) { |
354 | 354 | $previousTimestamp = $row->latest; |
355 | 355 | $previousCreated = $row->created; |
356 | 356 | } else { |
— | — | @@ -396,7 +396,7 @@ |
397 | 397 | $ret = $dbw->resultObject( $result ); |
398 | 398 | |
399 | 399 | $rev_count = $dbw->numRows( $result ); |
400 | | - if ( $rev_count ) { |
| 400 | + if( $rev_count ) { |
401 | 401 | # We need to seek around as just using DESC in the ORDER BY |
402 | 402 | # would leave the revisions inserted in the wrong order |
403 | 403 | $first = $ret->fetchObject(); |
— | — | @@ -509,8 +509,7 @@ |
510 | 510 | $this->mDiff = $request->getVal( 'diff' ); |
511 | 511 | $this->mOldid = $request->getVal( 'oldid' ); |
512 | 512 | |
513 | | - $posted = $request->wasPosted() && |
514 | | - $wgUser->matchEditToken( $request->getVal( 'wpEditToken' ) ); |
| 513 | + $posted = $request->wasPosted() && $wgUser->matchEditToken( $request->getVal( 'wpEditToken' ) ); |
515 | 514 | $this->mRestore = $request->getCheck( 'restore' ) && $posted; |
516 | 515 | $this->mPreview = $request->getCheck( 'preview' ) && $posted; |
517 | 516 | $this->mComment = $request->getText( 'wpComment' ); |
— | — | @@ -520,21 +519,21 @@ |
521 | 520 | $this->mTarget = $par; |
522 | 521 | $_GET['target'] = $par; // hack for Pager |
523 | 522 | } |
524 | | - if ( $wgUser->isAllowed( 'delete' ) && !$wgUser->isBlocked() ) { |
| 523 | + if( $wgUser->isAllowed( 'delete' ) && !$wgUser->isBlocked() ) { |
525 | 524 | $this->mAllowed = true; |
526 | 525 | } else { |
527 | 526 | $this->mAllowed = false; |
528 | 527 | $this->mTimestamp = ''; |
529 | 528 | $this->mRestore = false; |
530 | 529 | } |
531 | | - if ( $this->mTarget !== "" ) { |
| 530 | + if( $this->mTarget !== "" ) { |
532 | 531 | $this->mTargetObj = Title::newFromURL( $this->mTarget ); |
533 | 532 | } else { |
534 | 533 | $this->mTargetObj = NULL; |
535 | 534 | } |
536 | 535 | if( $this->mRestore ) { |
537 | | - $this->mFileTimestamp = $request->getVal('imgrestorepoint'); |
538 | | - $this->mPageTimestamp = $request->getVal('restorepoint'); |
| 536 | + $this->mFileTimestamp = $request->getInt('imgrestorepoint'); |
| 537 | + $this->mPageTimestamp = $request->getInt('restorepoint'); |
539 | 538 | } |
540 | 539 | $this->preCacheMessages(); |
541 | 540 | } |
— | — | @@ -554,7 +553,7 @@ |
555 | 554 | |
556 | 555 | function execute() { |
557 | 556 | global $wgOut, $wgUser; |
558 | | - if ( $this->mAllowed ) { |
| 557 | + if( $this->mAllowed ) { |
559 | 558 | $wgOut->setPagetitle( wfMsgHtml( "undeletepage" ) ); |
560 | 559 | } else { |
561 | 560 | $wgOut->setPagetitle( wfMsgHtml( "viewdeletedpage" ) ); |
— | — | @@ -562,7 +561,7 @@ |
563 | 562 | |
564 | 563 | if( is_null( $this->mTargetObj ) ) { |
565 | 564 | # Not all users can just browse every deleted page from the list |
566 | | - if ( $wgUser->isAllowed( 'browsearchive' ) ) { |
| 565 | + if( $wgUser->isAllowed( 'browsearchive' ) ) { |
567 | 566 | $this->showSearchForm(); |
568 | 567 | |
569 | 568 | # List undeletable articles |
— | — | @@ -579,13 +578,13 @@ |
580 | 579 | return $this->showRevision( $this->mTimestamp ); |
581 | 580 | } |
582 | 581 | |
583 | | - if ( $this->mDiff && $this->mOldid ) |
| 582 | + if( $this->mDiff && $this->mOldid ) |
584 | 583 | return $this->showDiff( $this->mDiff, $this->mOldid ); |
585 | 584 | |
586 | 585 | if( $this->mFile !== null ) { |
587 | 586 | $file = new ArchivedFile( $this->mTargetObj, '', $this->mFile ); |
588 | 587 | // Check if user is allowed to see this file |
589 | | - if ( !$file->userCan( Image::DELETED_FILE ) ) { |
| 588 | + if( !$file->userCan( File::DELETED_FILE ) ) { |
590 | 589 | $wgOut->permissionRequired( 'hiderevision' ); |
591 | 590 | return false; |
592 | 591 | } else { |
— | — | @@ -727,7 +726,7 @@ |
728 | 727 | private function showDiff( $newid, $oldid ) { |
729 | 728 | global $wgOut, $wgUser, $wgLang; |
730 | 729 | |
731 | | - if ( is_null($this->mTargetObj) ) |
| 730 | + if( is_null($this->mTargetObj) ) |
732 | 731 | return; |
733 | 732 | $skin = $wgUser->getSkin(); |
734 | 733 | |
— | — | @@ -735,7 +734,7 @@ |
736 | 735 | $oldRev = $archive->getRevision( null, $oldid ); |
737 | 736 | $newRev = $archive->getRevision( null, $newid ); |
738 | 737 | |
739 | | - if ( !$oldRev || !$newRev ) |
| 738 | + if( !$oldRev || !$newRev ) |
740 | 739 | return; |
741 | 740 | |
742 | 741 | $oldTitle = $this->mTargetObj->getPrefixedText(); |
— | — | @@ -743,12 +742,12 @@ |
744 | 743 | |
745 | 744 | $oldminor = $newminor = ''; |
746 | 745 | |
747 | | - if ($oldRev->mMinorEdit == 1) { |
| 746 | + if($oldRev->mMinorEdit == 1) { |
748 | 747 | $oldminor = wfElement( 'span', array( 'class' => 'minor' ), |
749 | 748 | wfMsg( 'minoreditletter') ) . ' '; |
750 | 749 | } |
751 | 750 | |
752 | | - if ($newRev->mMinorEdit == 1) { |
| 751 | + if($newRev->mMinorEdit == 1) { |
753 | 752 | $newminor = wfElement( 'span', array( 'class' => 'minor' ), |
754 | 753 | wfMsg( 'minoreditletter') ) . ' '; |
755 | 754 | } |
— | — | @@ -807,7 +806,7 @@ |
808 | 807 | global $wgLang, $wgUser, $wgOut; |
809 | 808 | |
810 | 809 | $this->sk = $wgUser->getSkin(); |
811 | | - if ( $this->mAllowed ) { |
| 810 | + if( $this->mAllowed ) { |
812 | 811 | $wgOut->setPagetitle( wfMsg( "undeletepage" ) ); |
813 | 812 | } else { |
814 | 813 | $wgOut->setPagetitle( wfMsg( 'viewdeletedpage' ) ); |
— | — | @@ -815,7 +814,7 @@ |
816 | 815 | |
817 | 816 | $archive = new PageArchive( $this->mTargetObj ); |
818 | 817 | |
819 | | - if ( $this->mAllowed ) { |
| 818 | + if( $this->mAllowed ) { |
820 | 819 | $wgOut->addWikiText( '<p>' . wfMsgHtml( "undeletehistory" ) . '</p>' ); |
821 | 820 | $wgOut->addHtml( '<p>' . wfMsgHtml( "undeleterevdel" ) . '</p>' ); |
822 | 821 | } else { |
— | — | @@ -840,7 +839,7 @@ |
841 | 840 | $files->seek( 0 ); |
842 | 841 | } |
843 | 842 | |
844 | | - if ( $this->mAllowed ) { |
| 843 | + if( $this->mAllowed ) { |
845 | 844 | $titleObj = SpecialPage::getTitleFor( "Undelete" ); |
846 | 845 | $action = $titleObj->getLocalURL( "action=submit" ); |
847 | 846 | # Start the form here |
— | — | @@ -857,7 +856,7 @@ |
858 | 857 | 'type' => 'delete' ) ) ) ); |
859 | 858 | $logViewer->showList( $wgOut ); |
860 | 859 | # Show relevant lines from the oversight log if user is allowed to see it: |
861 | | - if ( $wgUser->isAllowed( 'oversight' ) ) { |
| 860 | + if( $wgUser->isAllowed( 'oversight' ) ) { |
862 | 861 | $wgOut->addHTML( "<h2>" . htmlspecialchars( LogPage::logName( 'oversight' ) ) . "</h2>\n" ); |
863 | 862 | $logViewer = new LogViewer( |
864 | 863 | new LogReader( |
— | — | @@ -873,7 +872,7 @@ |
874 | 873 | $table .= '<td colspan="2">' . wfMsgWikiHtml( 'undeleteextrahelp' ) . '</td></tr><tr>'; |
875 | 874 | $table .= '<td align="right"><strong>' . wfMsgHtml( 'undeletecomment' ) . '</strong></td>'; |
876 | 875 | $table .= '<td>' . wfInput( 'wpComment', 50, $this->mComment ) . '</td>'; |
877 | | - if ( $wgUser->isAllowed( 'oversight' ) ) { |
| 876 | + if( $wgUser->isAllowed( 'oversight' ) ) { |
878 | 877 | $table .= '</tr><tr><td> </td><td>'; |
879 | 878 | $table .= Xml::checkLabel( wfMsg( 'revdelete-unsuppress' ), 'wpUnsuppress', 'wpUnsuppress', false, array( 'tabindex' => '2' ) ); |
880 | 879 | } |
— | — | @@ -905,7 +904,7 @@ |
906 | 905 | $wgOut->addHTML( "<li>" . wfRadio( "imgrestorepoint", -1, false ) . " " . wfMsgHtml('restorenone') . "</li>" ); |
907 | 906 | while( $row = $files->fetchObject() ) { |
908 | 907 | $ts = wfTimestamp( TS_MW, $row->fa_timestamp ); |
909 | | - if ( $this->mAllowed && $row->fa_storage_key ) { |
| 908 | + if( $this->mAllowed && $row->fa_storage_key ) { |
910 | 909 | $checkBox = wfRadio( "imgrestorepoint", $ts, false ); |
911 | 910 | $key = urlencode( $row->fa_storage_key ); |
912 | 911 | $target = urlencode( $this->mTarget ); |
— | — | @@ -926,7 +925,7 @@ |
927 | 926 | $rd=''; |
928 | 927 | if( $wgUser->isAllowed( 'deleterevision' ) ) { |
929 | 928 | $revdel = SpecialPage::getTitleFor( 'Revisiondelete' ); |
930 | | - if( !$this->userCan( $row, Image::DELETED_RESTRICTED ) ) { |
| 929 | + if( !$this->userCan( $row, File::DELETED_RESTRICTED ) ) { |
931 | 930 | // If revision was hidden from sysops |
932 | 931 | $del = $this->message['rev-delundel']; |
933 | 932 | } else { |
— | — | @@ -935,7 +934,7 @@ |
936 | 935 | 'target=' . urlencode( $this->mTarget ) . |
937 | 936 | '&fileid=' . urlencode( $row->fa_id ) ); |
938 | 937 | // Bolden oversighted content |
939 | | - if( $this->isDeleted( $row, Image::DELETED_RESTRICTED ) ) |
| 938 | + if( $this->isDeleted( $row, File::DELETED_RESTRICTED ) ) |
940 | 939 | $del = "<strong>$del</strong>"; |
941 | 940 | } |
942 | 941 | $rd = "<tt>(<small>$del</small>)</tt>"; |
— | — | @@ -946,7 +945,7 @@ |
947 | 946 | $wgOut->addHTML( "</ul>" ); |
948 | 947 | } |
949 | 948 | |
950 | | - if ( $this->mAllowed ) { |
| 949 | + if( $this->mAllowed ) { |
951 | 950 | # Slip in the hidden controls here |
952 | 951 | $misc = wfHidden( 'target', $this->mTarget ); |
953 | 952 | $misc .= wfHidden( 'wpEditToken', $wgUser->editToken() ); |
— | — | @@ -962,15 +961,15 @@ |
963 | 962 | $stxt = ''; |
964 | 963 | $last = $this->message['last']; |
965 | 964 | // We don't handle top edits with rev_deleted |
966 | | - if ( $this->mAllowed ) { |
| 965 | + if( $this->mAllowed ) { |
967 | 966 | $ts = wfTimestamp( TS_MW, $row->ar_timestamp ); |
968 | 967 | $checkBox = wfRadio( "restorepoint", $ts, false ); |
969 | 968 | $titleObj = SpecialPage::getTitleFor( "Undelete" ); |
970 | 969 | $pageLink = $this->getPageLink( $row, $titleObj, $ts, $this->mTarget ); |
971 | 970 | # Last link |
972 | | - if ( !$this->userCan( $row, Revision::DELETED_TEXT ) ) |
| 971 | + if( !$this->userCan( $row, Revision::DELETED_TEXT ) ) |
973 | 972 | $last = $this->message['last']; |
974 | | - else if ( isset($this->prevId[$row->ar_rev_id]) ) |
| 973 | + else if( isset($this->prevId[$row->ar_rev_id]) ) |
975 | 974 | $last = $this->sk->makeKnownLinkObj( $titleObj, $this->message['last'], "target=" . $this->mTarget . |
976 | 975 | "&diff=" . $row->ar_rev_id . "&oldid=" . $this->prevId[$row->ar_rev_id] ); |
977 | 976 | } else { |
— | — | @@ -979,8 +978,8 @@ |
980 | 979 | } |
981 | 980 | |
982 | 981 | $userLink = $this->getUser( $row ); |
983 | | - if (!is_null($size = $row->ar_len)) { |
984 | | - if ($size == 0) |
| 982 | + if(!is_null($size = $row->ar_len)) { |
| 983 | + if($size == 0) |
985 | 984 | $stxt = wfMsgHtml('historyempty'); |
986 | 985 | else |
987 | 986 | $stxt = wfMsgHtml('historysize', $wgLang->formatNum( $size ) ); |
— | — | @@ -1018,11 +1017,11 @@ |
1019 | 1018 | function getPageLink( $row, $titleObj, $ts, $target ) { |
1020 | 1019 | global $wgLang; |
1021 | 1020 | |
1022 | | - if ( !$this->userCan($row, Revision::DELETED_TEXT) ) { |
| 1021 | + if( !$this->userCan($row, Revision::DELETED_TEXT) ) { |
1023 | 1022 | return '<span class="history-deleted">' . $wgLang->timeanddate( $ts, true ) . '</span>'; |
1024 | 1023 | } else { |
1025 | 1024 | $link = $this->sk->makeKnownLinkObj( $titleObj, $wgLang->timeanddate( $ts, true ), "target=$target×tamp=$ts" ); |
1026 | | - if ( $this->isDeleted($row, Revision::DELETED_TEXT) ) |
| 1025 | + if( $this->isDeleted($row, Revision::DELETED_TEXT) ) |
1027 | 1026 | $link = '<span class="history-deleted">' . $link . '</span>'; |
1028 | 1027 | return $link; |
1029 | 1028 | } |
— | — | @@ -1035,11 +1034,11 @@ |
1036 | 1035 | function getFileLink( $row, $titleObj, $ts, $target, $key ) { |
1037 | 1036 | global $wgLang; |
1038 | 1037 | |
1039 | | - if ( !$this->userCan($row, Image::DELETED_FILE) ) { |
| 1038 | + if( !$this->userCan($row, File::DELETED_FILE) ) { |
1040 | 1039 | return '<span class="history-deleted">' . $wgLang->timeanddate( $ts, true ) . '</span>'; |
1041 | 1040 | } else { |
1042 | 1041 | $link = $this->sk->makeKnownLinkObj( $titleObj, $wgLang->timeanddate( $ts, true ), "target=$target&file=$key" ); |
1043 | | - if ( $this->isDeleted($row, Image::DELETED_FILE) ) |
| 1042 | + if( $this->isDeleted($row, File::DELETED_FILE) ) |
1044 | 1043 | $link = '<span class="history-deleted">' . $link . '</span>'; |
1045 | 1044 | return $link; |
1046 | 1045 | } |
— | — | @@ -1050,11 +1049,11 @@ |
1051 | 1050 | * @return string |
1052 | 1051 | */ |
1053 | 1052 | function getUser( $row ) { |
1054 | | - if ( !$this->userCan($row, Revision::DELETED_USER) ) { |
| 1053 | + if( !$this->userCan($row, Revision::DELETED_USER) ) { |
1055 | 1054 | return '<span class="history-deleted">' . wfMsgHtml( 'rev-deleted-user' ) . '</span>'; |
1056 | 1055 | } else { |
1057 | 1056 | $link = $this->sk->userLink( $row->ar_user, $row->ar_user_text ) . $this->sk->userToolLinks( $row->ar_user, $row->ar_user_text ); |
1058 | | - if ( $this->isDeleted($row, Revision::DELETED_USER) ) |
| 1057 | + if( $this->isDeleted($row, Revision::DELETED_USER) ) |
1059 | 1058 | $link = '<span class="history-deleted">' . $link . '</span>'; |
1060 | 1059 | return $link; |
1061 | 1060 | } |
— | — | @@ -1065,11 +1064,11 @@ |
1066 | 1065 | * @return string |
1067 | 1066 | */ |
1068 | 1067 | function getFileUser( $row ) { |
1069 | | - if ( !$this->userCan($row, Image::DELETED_USER) ) { |
| 1068 | + if( !$this->userCan($row, File::DELETED_USER) ) { |
1070 | 1069 | return '<span class="history-deleted">' . wfMsgHtml( 'rev-deleted-user' ) . '</span>'; |
1071 | 1070 | } else { |
1072 | 1071 | $link = $this->sk->userLink( $row->fa_user, $row->fa_user_text ) . $this->sk->userToolLinks( $row->fa_user, $row->fa_user_text ); |
1073 | | - if ( $this->isDeleted($row, Image::DELETED_USER) ) |
| 1072 | + if( $this->isDeleted($row, File::DELETED_USER) ) |
1074 | 1073 | $link = '<span class="history-deleted">' . $link . '</span>'; |
1075 | 1074 | return $link; |
1076 | 1075 | } |
— | — | @@ -1080,11 +1079,11 @@ |
1081 | 1080 | * @return string |
1082 | 1081 | */ |
1083 | 1082 | function getComment( $row ) { |
1084 | | - if ( !$this->userCan($row, Revision::DELETED_COMMENT) ) { |
| 1083 | + if( !$this->userCan($row, Revision::DELETED_COMMENT) ) { |
1085 | 1084 | return '<span class="history-deleted"><span class="comment">' . wfMsgHtml( 'rev-deleted-comment' ) . '</span></span>'; |
1086 | 1085 | } else { |
1087 | 1086 | $link = $this->sk->commentBlock( $row->ar_comment ); |
1088 | | - if ( $this->isDeleted($row, Revision::DELETED_COMMENT) ) |
| 1087 | + if( $this->isDeleted($row, Revision::DELETED_COMMENT) ) |
1089 | 1088 | $link = '<span class="history-deleted">' . $link . '</span>'; |
1090 | 1089 | return $link; |
1091 | 1090 | } |
— | — | @@ -1095,11 +1094,11 @@ |
1096 | 1095 | * @return string |
1097 | 1096 | */ |
1098 | 1097 | function getFileComment( $row ) { |
1099 | | - if ( !$this->userCan($row, Image::DELETED_COMMENT) ) { |
| 1098 | + if( !$this->userCan($row, File::DELETED_COMMENT) ) { |
1100 | 1099 | return '<span class="history-deleted"><span class="comment">' . wfMsgHtml( 'rev-deleted-comment' ) . '</span></span>'; |
1101 | 1100 | } else { |
1102 | 1101 | $link = $this->sk->commentBlock( $row->fa_description ); |
1103 | | - if ( $this->isDeleted($row, Image::DELETED_COMMENT) ) |
| 1102 | + if( $this->isDeleted($row, File::DELETED_COMMENT) ) |
1104 | 1103 | $link = '<span class="history-deleted">' . $link . '</span>'; |
1105 | 1104 | return $link; |
1106 | 1105 | } |
— | — | @@ -1111,10 +1110,10 @@ |
1112 | 1111 | * @return bool |
1113 | 1112 | */ |
1114 | 1113 | function isDeleted( $row, $field ) { |
1115 | | - if ( isset($row->ar_deleted) ) |
| 1114 | + if( isset($row->ar_deleted) ) |
1116 | 1115 | // page revisions |
1117 | 1116 | return ($row->ar_deleted & $field) == $field; |
1118 | | - else if ( isset($row->fa_deleted) ) |
| 1117 | + else if( isset($row->fa_deleted) ) |
1119 | 1118 | // files |
1120 | 1119 | return ($row->fa_deleted & $field) == $field; |
1121 | 1120 | return false; |
— | — | @@ -1138,7 +1137,7 @@ |
1139 | 1138 | return $wgUser->isAllowed( $permission ); |
1140 | 1139 | } else if( isset($row->fa_deleted) && ($row->fa_deleted & $field) == $field ) { |
1141 | 1140 | // files |
1142 | | - $permission = ( $row->fa_deleted & Image::DELETED_RESTRICTED ) == Image::DELETED_RESTRICTED |
| 1141 | + $permission = ( $row->fa_deleted & File::DELETED_RESTRICTED ) == File::DELETED_RESTRICTED |
1143 | 1142 | ? 'hiderevision' |
1144 | 1143 | : 'deleterevision'; |
1145 | 1144 | wfDebug( "Checking for $permission due to $field match on $row->fa_deleted\n" ); |
— | — | @@ -1197,9 +1196,9 @@ |
1198 | 1197 | $rev_id = isset($rev_id) ? $rev_id : $row->ar_rev_id; |
1199 | 1198 | $batch->addObj( Title::makeTitleSafe( NS_USER, $row->ar_user_text ) ); |
1200 | 1199 | $batch->addObj( Title::makeTitleSafe( NS_USER_TALK, $row->ar_user_text ) ); |
1201 | | - if ( $rev_id > $row->ar_rev_id ) |
| 1200 | + if( $rev_id > $row->ar_rev_id ) |
1202 | 1201 | $this->mForm->prevId[$rev_id] = $row->ar_rev_id; |
1203 | | - else if ( $rev_id < $row->ar_rev_id ) |
| 1202 | + else if( $rev_id < $row->ar_rev_id ) |
1204 | 1203 | $this->mForm->prevId[$row->ar_rev_id] = $rev_id; |
1205 | 1204 | |
1206 | 1205 | $rev_id = $row->ar_rev_id; |
Index: branches/phase3_rev_deleted/includes/SpecialUpload.php |
— | — | @@ -27,6 +27,7 @@ |
28 | 28 | var $mUploadCopyStatus, $mUploadSource, $mReUpload, $mAction, $mUpload; |
29 | 29 | var $mOname, $mSessionKey, $mStashed, $mDestFile, $mRemoveTempFile, $mSourceType; |
30 | 30 | var $mUploadTempFileSize = 0; |
| 31 | + var $mImage; |
31 | 32 | |
32 | 33 | # Placeholders for text injection by hooks (must be HTML) |
33 | 34 | # extensions should take care to _append_ to the present value |
— | — | @@ -412,13 +413,13 @@ |
413 | 414 | |
414 | 415 | global $wgUser; |
415 | 416 | $sk = $wgUser->getSkin(); |
416 | | - $image = new Image( $nt ); |
| 417 | + $image = wfLocalFile( $nt ); |
417 | 418 | |
418 | 419 | // Check for uppercase extension. We allow these filenames but check if an image |
419 | 420 | // with lowercase extension exists already |
420 | 421 | if ( $finalExt != strtolower( $finalExt ) ) { |
421 | 422 | $nt_lc = Title::newFromText( $partname . '.' . strtolower( $finalExt ) ); |
422 | | - $image_lc = new Image( $nt_lc ); |
| 423 | + $image_lc = wfLocalFile( $nt_lc ); |
423 | 424 | } |
424 | 425 | |
425 | 426 | if( $image->exists() ) { |
— | — | @@ -452,7 +453,7 @@ |
453 | 454 | } elseif ( ( substr( $partname , 3, 3 ) == 'px-' || substr( $partname , 2, 3 ) == 'px-' ) && ereg( "[0-9]{2}" , substr( $partname , 0, 2) ) ) { |
454 | 455 | # Check for filenames like 50px- or 180px-, these are mostly thumbnails |
455 | 456 | $nt_thb = Title::newFromText( substr( $partname , strpos( $partname , '-' ) +1 ) . '.' . $finalExt ); |
456 | | - $image_thb = new Image( $nt_thb ); |
| 457 | + $image_thb = wfLocalFile( $nt_thb ); |
457 | 458 | if ($image_thb->exists() ) { |
458 | 459 | # Check if an image without leading '180px-' (or similiar) exists |
459 | 460 | $dlink = $sk->makeKnownLinkObj( $nt_thb); |
— | — | @@ -500,8 +501,8 @@ |
501 | 502 | * Update the upload log and create the description page |
502 | 503 | * if it's a new file. |
503 | 504 | */ |
504 | | - $img = Image::newFromName( $this->mUploadSaveName ); |
505 | | - $success = $img->recordUpload( $this->mUploadOldVersion, |
| 505 | + $this->mImage = wfLocalFile( $this->mUploadSaveName ); |
| 506 | + $success = $this->mImage->recordUpload( $this->mUploadOldVersion, |
506 | 507 | $this->mUploadDescription, |
507 | 508 | $this->mLicense, |
508 | 509 | $this->mUploadCopyStatus, |
— | — | @@ -512,7 +513,7 @@ |
513 | 514 | $this->showSuccess(); |
514 | 515 | wfRunHooks( 'UploadComplete', array( &$img ) ); |
515 | 516 | } else { |
516 | | - // Image::recordUpload() fails if the image went missing, which is |
| 517 | + // File::recordUpload() fails if the image went missing, which is |
517 | 518 | // unlikely, hence the lack of a specialised message |
518 | 519 | $wgOut->showFileNotFoundError( $this->mUploadSaveName ); |
519 | 520 | } |
— | — | @@ -534,48 +535,13 @@ |
535 | 536 | function saveUploadedFile( $saveName, $tempName, $useRename = false ) { |
536 | 537 | global $wgOut, $wgAllowCopyUploads; |
537 | 538 | |
538 | | - if ( !$useRename AND $wgAllowCopyUploads AND $this->mSourceType == 'web' ) $useRename = true; |
539 | | - |
540 | | - $fname= "SpecialUpload::saveUploadedFile"; |
541 | | - |
542 | | - $dest = wfImageDir( $saveName ); |
543 | | - $archive = wfImageArchiveDir( $saveName ); |
544 | | - if ( !is_dir( $dest ) ) wfMkdirParents( $dest ); |
545 | | - if ( !is_dir( $archive ) ) wfMkdirParents( $archive ); |
546 | | - |
547 | | - $this->mSavedFile = "{$dest}/{$saveName}"; |
548 | | - |
549 | | - if( is_file( $this->mSavedFile ) ) { |
550 | | - $this->mUploadOldVersion = gmdate( 'YmdHis' ) . "!{$saveName}"; |
551 | | - wfSuppressWarnings(); |
552 | | - $success = rename( $this->mSavedFile, "${archive}/{$this->mUploadOldVersion}" ); |
553 | | - wfRestoreWarnings(); |
554 | | - |
555 | | - if( ! $success ) { |
556 | | - $wgOut->showFileRenameError( $this->mSavedFile, |
557 | | - "${archive}/{$this->mUploadOldVersion}" ); |
558 | | - return false; |
559 | | - } |
560 | | - else wfDebug("$fname: moved file ".$this->mSavedFile." to ${archive}/{$this->mUploadOldVersion}\n"); |
561 | | - } |
562 | | - else { |
563 | | - $this->mUploadOldVersion = ''; |
564 | | - } |
565 | | - |
566 | | - wfSuppressWarnings(); |
567 | | - $success = $useRename |
568 | | - ? rename( $tempName, $this->mSavedFile ) |
569 | | - : move_uploaded_file( $tempName, $this->mSavedFile ); |
570 | | - wfRestoreWarnings(); |
571 | | - |
572 | | - if( ! $success ) { |
573 | | - $wgOut->showFileCopyError( $tempName, $this->mSavedFile ); |
| 539 | + $image = wfLocalFile( $saveName ); |
| 540 | + $archiveName = $image->publish( $tempName, File::DELETE_SOURCE ); |
| 541 | + if ( WikiError::isError( $archiveName ) ) { |
| 542 | + $this->showError( $archiveName ); |
574 | 543 | return false; |
575 | | - } else { |
576 | | - wfDebug("$fname: wrote tempfile $tempName to ".$this->mSavedFile."\n"); |
577 | 544 | } |
578 | | - |
579 | | - chmod( $this->mSavedFile, 0644 ); |
| 545 | + $this->mUploadOldVersion = $archiveName; |
580 | 546 | return true; |
581 | 547 | } |
582 | 548 | |
— | — | @@ -593,19 +559,14 @@ |
594 | 560 | */ |
595 | 561 | function saveTempUploadedFile( $saveName, $tempName ) { |
596 | 562 | global $wgOut; |
597 | | - $archive = wfImageArchiveDir( $saveName, 'temp' ); |
598 | | - if ( !is_dir ( $archive ) ) wfMkdirParents( $archive ); |
599 | | - $stash = $archive . '/' . gmdate( "YmdHis" ) . '!' . $saveName; |
600 | | - |
601 | | - $success = $this->mRemoveTempFile |
602 | | - ? rename( $tempName, $stash ) |
603 | | - : move_uploaded_file( $tempName, $stash ); |
604 | | - if ( !$success ) { |
605 | | - $wgOut->showFileCopyError( $tempName, $stash ); |
| 563 | + $repo = RepoGroup::singleton()->getLocalRepo(); |
| 564 | + $result = $repo->storeTemp( $saveName, $tempName ); |
| 565 | + if ( WikiError::isError( $result ) ) { |
| 566 | + $this->showError( $result ); |
606 | 567 | return false; |
| 568 | + } else { |
| 569 | + return $result; |
607 | 570 | } |
608 | | - |
609 | | - return $stash; |
610 | 571 | } |
611 | 572 | |
612 | 573 | /** |
— | — | @@ -662,7 +623,7 @@ |
663 | 624 | global $wgUser, $wgOut, $wgContLang; |
664 | 625 | |
665 | 626 | $sk = $wgUser->getSkin(); |
666 | | - $ilink = $sk->makeMediaLink( $this->mUploadSaveName, Image::imageUrl( $this->mUploadSaveName ) ); |
| 627 | + $ilink = $sk->makeMediaLinkObj( $this->mImage->getTitle() ); |
667 | 628 | $dname = $wgContLang->getNsText( NS_IMAGE ) . ':'.$this->mUploadSaveName; |
668 | 629 | $dlink = $sk->makeKnownLink( $dname, $dname ); |
669 | 630 | |
— | — | @@ -1274,15 +1235,10 @@ |
1275 | 1236 | * @access private |
1276 | 1237 | */ |
1277 | 1238 | function checkOverwrite( $name ) { |
1278 | | - $img = Image::newFromName( $name ); |
1279 | | - if( is_null( $img ) ) { |
1280 | | - // Uh... this shouldn't happen ;) |
1281 | | - // But if it does, fall through to previous behavior |
1282 | | - return false; |
1283 | | - } |
| 1239 | + $img = wfFindFile( $name ); |
1284 | 1240 | |
1285 | 1241 | $error = ''; |
1286 | | - if( $img->exists() ) { |
| 1242 | + if( $img ) { |
1287 | 1243 | global $wgUser, $wgOut; |
1288 | 1244 | if( $img->isLocal() ) { |
1289 | 1245 | if( !self::userCanReUpload( $wgUser, $img->name ) ) { |
— | — | @@ -1328,5 +1284,17 @@ |
1329 | 1285 | |
1330 | 1286 | return $user->getID() == $row->img_user; |
1331 | 1287 | } |
| 1288 | + |
| 1289 | + /** |
| 1290 | + * Display an error from a wikitext-formatted WikiError object |
| 1291 | + */ |
| 1292 | + function showError( WikiError $error ) { |
| 1293 | + global $wgOut; |
| 1294 | + $wgOut->setPageTitle( wfMsg( "internalerror" ) ); |
| 1295 | + $wgOut->setRobotpolicy( "noindex,nofollow" ); |
| 1296 | + $wgOut->setArticleRelated( false ); |
| 1297 | + $wgOut->enableClientCache( false ); |
| 1298 | + $wgOut->addWikiText( $error->getMessage() ); |
| 1299 | + } |
1332 | 1300 | } |
1333 | 1301 | ?> |
Index: branches/phase3_rev_deleted/includes/AutoLoader.php |
— | — | @@ -96,9 +96,6 @@ |
97 | 97 | 'HTMLCacheUpdateJob' => 'includes/HTMLCacheUpdate.php',
|
98 | 98 | 'EnotifNotifyJob' => 'includes/JobQueue.php',
|
99 | 99 | 'Http' => 'includes/HttpFunctions.php',
|
100 | | - 'Image' => 'includes/Image.php',
|
101 | | - 'OldImage' => 'includes/Image.php',
|
102 | | - 'ArchivedFile' => 'includes/Image.php',
|
103 | 100 | 'IP' => 'includes/IP.php',
|
104 | 101 | 'ThumbnailImage' => 'includes/Image.php',
|
105 | 102 | 'ImageGallery' => 'includes/ImageGallery.php',
|
— | — | @@ -251,6 +248,19 @@ |
252 | 249 | 'memcached' => 'includes/memcached-client.php',
|
253 | 250 | 'EmaillingJob' => 'includes/JobQueue.php',
|
254 | 251 |
|
| 252 | + # filerepo
|
| 253 | + 'ArchivedFile' => 'includes/filerepo/ArchivedFile.php',
|
| 254 | + 'File' => 'includes/filerepo/File.php',
|
| 255 | + 'ForeignDBFile' => 'includes/filerepo/ForeignDBFile.php',
|
| 256 | + 'ForeignDBRepo' => 'includes/filerepo/ForeignDBRepo.php',
|
| 257 | + 'FSRepo' => 'includes/filerepo/FSRepo.php',
|
| 258 | + 'Image' => 'includes/filerepo/LocalFile.php',
|
| 259 | + 'LocalFile' => 'includes/filerepo/LocalFile.php',
|
| 260 | + 'LocalRepo' => 'includes/filerepo/LocalRepo.php',
|
| 261 | + 'OldLocalFile' => 'includes/filerepo/OldLocalFile.php',
|
| 262 | + 'RepoGroup' => 'includes/filerepo/RepoGroup.php',
|
| 263 | + 'UnregisteredLocalFile' => 'includes/filerepo/UnregisteredLocalFile.php',
|
| 264 | +
|
255 | 265 | # Media
|
256 | 266 | 'BitmapHandler' => 'includes/media/Bitmap.php',
|
257 | 267 | 'BmpHandler' => 'includes/media/BMP.php',
|
Index: branches/phase3_rev_deleted/includes/Skin.php |
— | — | @@ -740,8 +740,8 @@ |
741 | 741 | if ( $wgOut->isArticleRelated() ) { |
742 | 742 | if ( $wgTitle->getNamespace() == NS_IMAGE ) { |
743 | 743 | $name = $wgTitle->getDBkey(); |
744 | | - $image = new Image( $wgTitle ); |
745 | | - if( $image->exists() ) { |
| 744 | + $image = wfFindFile( $wgTitle ); |
| 745 | + if( $image ) { |
746 | 746 | $link = htmlspecialchars( $image->getURL() ); |
747 | 747 | $style = $this->getInternalLinkAttributes( $link, $name ); |
748 | 748 | $s .= " | <a href=\"{$link}\"{$style}>{$name}</a>"; |
Index: branches/phase3_rev_deleted/includes/DefaultSettings.php |
— | — | @@ -190,6 +190,49 @@ |
191 | 191 | $wgFileStore['hidden']['url'] = null; // Private |
192 | 192 | $wgFileStore['hidden']['hash'] = 3; // 3-level subdirectory split |
193 | 193 | |
| 194 | +/**#@+ |
| 195 | + * File repository structures |
| 196 | + * |
| 197 | + * $wgLocalFileRepo is a single repository structure, and $wgForeignFileRepo is |
| 198 | + * a an array of such structures. Each repository structure is an associative |
| 199 | + * array of properties configuring the repository. |
| 200 | + * |
| 201 | + * Properties required for all repos: |
| 202 | + * class The class name for the repository. May come from the core or an extension. |
| 203 | + * The core repository classes are LocalRepo, ForeignDBRepo, FSRepo. |
| 204 | + * |
| 205 | + * name A unique name for the repository. |
| 206 | + * |
| 207 | + * For all core repos: |
| 208 | + * url Base public URL |
| 209 | + * hashLevels The number of directory levels for hash-based division of files |
| 210 | + * thumbScriptUrl The URL for thumb.php (optional, not recommended) |
| 211 | + * transformVia404 Whether to skip media file transformation on parse and rely on a 404 |
| 212 | + * handler instead. |
| 213 | + * |
| 214 | + * These settings describe a foreign MediaWiki installation. They are optional, and will be ignored |
| 215 | + * for local repositories: |
| 216 | + * descBaseUrl URL of image description pages, e.g. http://en.wikipedia.org/wiki/Image: |
| 217 | + * scriptDirUrl URL of the MediaWiki installation, equivalent to $wgScriptPath, e.g. |
| 218 | + * http://en.wikipedia.org/w |
| 219 | + * |
| 220 | + * articleUrl Equivalent to $wgArticlePath, e.g. http://en.wikipedia.org/wiki/$1 |
| 221 | + * fetchDescription Fetch the text of the remote file description page. Equivalent to |
| 222 | + * $wgFetchCommonsDescriptions. |
| 223 | + * |
| 224 | + * ForeignDBRepo: |
| 225 | + * dbType, dbServer, dbUser, dbPassword, dbName, dbFlags |
| 226 | + * equivalent to the corresponding member of $wgDBservers |
| 227 | + * tablePrefix Table prefix, the foreign wiki's $wgDBprefix |
| 228 | + * hasSharedCache True if the wiki's shared cache is accessible via the local $wgMemc |
| 229 | + * |
| 230 | + * The default is to initialise these arrays from the MW<1.11 backwards compatible settings: |
| 231 | + * $wgUploadPath, $wgThumbnailScriptPath, $wgSharedUploadDirectory, etc. |
| 232 | + */ |
| 233 | +$wgLocalFileRepo = false; |
| 234 | +$wgForeignFileRepos = array(); |
| 235 | +/**#@-*/ |
| 236 | + |
194 | 237 | /** |
195 | 238 | * Allowed title characters -- regex character class |
196 | 239 | * Don't change this unless you know what you're doing |
— | — | @@ -361,6 +404,10 @@ |
362 | 405 | * no file of the given name is found in the local repository (for [[Image:..]], |
363 | 406 | * [[Media:..]] links). Thumbnails will also be looked for and generated in this |
364 | 407 | * directory. |
| 408 | + * |
| 409 | + * Note that these configuration settings can now be defined on a per- |
| 410 | + * repository basis for an arbitrary number of file repositories, using the |
| 411 | + * $wgForeignFileRepos variable. |
365 | 412 | */ |
366 | 413 | $wgUseSharedUploads = false; |
367 | 414 | /** Full path on the web server where shared uploads can be found */ |
— | — | @@ -1136,7 +1183,7 @@ |
1137 | 1184 | * to ensure that client-side caches don't keep obsolete copies of global |
1138 | 1185 | * styles. |
1139 | 1186 | */ |
1140 | | -$wgStyleVersion = '72'; |
| 1187 | +$wgStyleVersion = '73'; |
1141 | 1188 | |
1142 | 1189 | |
1143 | 1190 | # Server-side caching: |
— | — | @@ -2019,7 +2066,13 @@ |
2020 | 2067 | * @link http://en.wikipedia.org/w/index.php?title=User%3A%C6var_Arnfj%F6r%F0_Bjarmason%2Ftestme&diff=12356041&oldid=12355864 |
2021 | 2068 | * @link http://en.wikipedia.org/wiki/Template%3AOS9 |
2022 | 2069 | */ |
2023 | | - '/^Mozilla\/4\.0 \(compatible; MSIE \d+\.\d+; Mac_PowerPC\)/' |
| 2070 | + '/^Mozilla\/4\.0 \(compatible; MSIE \d+\.\d+; Mac_PowerPC\)/', |
| 2071 | + |
| 2072 | + /** |
| 2073 | + * Google wireless transcoder, seems to eat a lot of chars alive |
| 2074 | + * http://it.wikipedia.org/w/index.php?title=Luciano_Ligabue&diff=prev&oldid=8857361 |
| 2075 | + */ |
| 2076 | + '/^Mozilla\/4\.0 \(compatible; MSIE 6.0; Windows NT 5.0; Google Wireless Transcoder;\)/' |
2024 | 2077 | ); |
2025 | 2078 | |
2026 | 2079 | /** |
— | — | @@ -2594,10 +2647,10 @@ |
2595 | 2648 | |
2596 | 2649 | /** |
2597 | 2650 | * If lag is higher than $wgSlaveLagWarning, show a warning in some special |
2598 | | - * pages (like watchlist). If the lag is higher than $wgSlaveLagOhNo, show a |
2599 | | - * more obvious warning. |
| 2651 | + * pages (like watchlist). If the lag is higher than $wgSlaveLagCritical, |
| 2652 | + * show a more obvious warning. |
2600 | 2653 | */ |
2601 | 2654 | $wgSlaveLagWarning = 10; |
2602 | | -$wgSlaveLagOhNo = 30; |
| 2655 | +$wgSlaveLagCritical = 30; |
2603 | 2656 | |
2604 | 2657 | ?> |
Index: branches/phase3_rev_deleted/includes/ImageQueryPage.php |
— | — | @@ -30,8 +30,8 @@ |
31 | 31 | # $num [should update this to use a Pager]
|
32 | 32 | for( $i = 0; $i < $num && $row = $dbr->fetchObject( $res ); $i++ ) {
|
33 | 33 | $image = $this->prepareImage( $row );
|
34 | | - if( $image instanceof Image ) {
|
35 | | - $gallery->add( $image, $this->getCellHtml( $row ) );
|
| 34 | + if( $image ) {
|
| 35 | + $gallery->add( $image->getTitle(), $this->getCellHtml( $row ) );
|
36 | 36 | }
|
37 | 37 | }
|
38 | 38 |
|
— | — | @@ -49,7 +49,7 @@ |
50 | 50 | $namespace = isset( $row->namespace ) ? $row->namespace : NS_IMAGE;
|
51 | 51 | $title = Title::makeTitleSafe( $namespace, $row->title );
|
52 | 52 | return ( $title instanceof Title && $title->getNamespace() == NS_IMAGE )
|
53 | | - ? new Image( $title )
|
| 53 | + ? wfFindFile( $title )
|
54 | 54 | : null;
|
55 | 55 | }
|
56 | 56 |
|
Index: branches/phase3_rev_deleted/includes/SpecialLog.php |
— | — | @@ -712,7 +712,7 @@ |
713 | 713 | // Restricted types |
714 | 714 | if ( isset($wgLogRestrictions[$type]) ) { |
715 | 715 | if ( $wgUser->isAllowed( $wgLogRestrictions[$type] ) ) { |
716 | | - $out .= Xml::option( $text, $type, $selected ) . "\n"; |
| 716 | + $out .= Xml::option( $text, $type, $selected ) . "\n"; |
717 | 717 | } |
718 | 718 | } else { |
719 | 719 | $out .= Xml::option( $text, $type, $selected ) . "\n"; |
Index: branches/phase3_rev_deleted/includes/StreamFile.php |
— | — | @@ -31,6 +31,9 @@ |
32 | 32 | header('Content-type: application/x-wiki'); |
33 | 33 | } |
34 | 34 | |
| 35 | + global $wgContLanguageCode; |
| 36 | + header( "Content-Disposition: inline;filename*=utf-8'$wgContLanguageCode'" . urlencode( basename( $fname ) ) ); |
| 37 | + |
35 | 38 | if ( !empty( $_SERVER['HTTP_IF_MODIFIED_SINCE'] ) ) { |
36 | 39 | $modsince = preg_replace( '/;.*$/', '', $_SERVER['HTTP_IF_MODIFIED_SINCE'] ); |
37 | 40 | $sinceTime = strtotime( $modsince ); |
Index: branches/phase3_rev_deleted/includes/MediaTransformOutput.php |
— | — | @@ -1,7 +1,7 @@ |
2 | 2 | <?php
|
3 | 3 |
|
4 | 4 | /**
|
5 | | - * Base class for the output of MediaHandler::doTransform() and Image::transform().
|
| 5 | + * Base class for the output of MediaHandler::doTransform() and File::transform().
|
6 | 6 | *
|
7 | 7 | * @addtogroup Media
|
8 | 8 | */
|
Index: branches/phase3_rev_deleted/includes/ImageGallery.php |
— | — | @@ -17,6 +17,7 @@ |
18 | 18 | var $mImages, $mShowBytes, $mShowFilename; |
19 | 19 | var $mCaption = false; |
20 | 20 | var $mSkin = false; |
| 21 | + var $mRevisionId = 0; |
21 | 22 | |
22 | 23 | /** |
23 | 24 | * Is the gallery on a wiki page (i.e. not a special page) |
— | — | @@ -127,22 +128,26 @@ |
128 | 129 | /** |
129 | 130 | * Add an image to the gallery. |
130 | 131 | * |
131 | | - * @param $image Image object that is added to the gallery |
| 132 | + * @param $title Title object of the image that is added to the gallery |
132 | 133 | * @param $html String: additional HTML text to be shown. The name and size of the image are always shown. |
133 | 134 | */ |
134 | | - function add( $image, $html='' ) { |
135 | | - $this->mImages[] = array( &$image, $html ); |
136 | | - wfDebug( "ImageGallery::add " . $image->getName() . "\n" ); |
| 135 | + function add( $title, $html='' ) { |
| 136 | + if ( $title instanceof File ) { |
| 137 | + // Old calling convention |
| 138 | + $title = $title->getTitle(); |
| 139 | + } |
| 140 | + $this->mImages[] = array( $title, $html ); |
| 141 | + wfDebug( "ImageGallery::add " . $title->getText() . "\n" ); |
137 | 142 | } |
138 | 143 | |
139 | 144 | /** |
140 | 145 | * Add an image at the beginning of the gallery. |
141 | 146 | * |
142 | | - * @param $image Image object that is added to the gallery |
| 147 | + * @param $title Title object of the image that is added to the gallery |
143 | 148 | * @param $html String: Additional HTML text to be shown. The name and size of the image are always shown. |
144 | 149 | */ |
145 | | - function insert( $image, $html='' ) { |
146 | | - array_unshift( $this->mImages, array( &$image, $html ) ); |
| 150 | + function insert( $title, $html='' ) { |
| 151 | + array_unshift( $this->mImages, array( &$title, $html ) ); |
147 | 152 | } |
148 | 153 | |
149 | 154 | |
— | — | @@ -195,12 +200,16 @@ |
196 | 201 | $params = array( 'width' => $this->mWidths, 'height' => $this->mHeights ); |
197 | 202 | $i = 0; |
198 | 203 | foreach ( $this->mImages as $pair ) { |
199 | | - $img =& $pair[0]; |
| 204 | + $nt = $pair[0]; |
200 | 205 | $text = $pair[1]; |
| 206 | + |
| 207 | + # Give extensions a chance to select the file revision for us |
| 208 | + $time = false; |
| 209 | + wfRunHooks( 'BeforeGalleryFindFile', array( &$this, &$nt, &$time ) ); |
201 | 210 | |
202 | | - $nt = $img->getTitle(); |
| 211 | + $img = wfFindFile( $nt, $time ); |
203 | 212 | |
204 | | - if( $nt->getNamespace() != NS_IMAGE ) { |
| 213 | + if( $nt->getNamespace() != NS_IMAGE || !$img ) { |
205 | 214 | # We're dealing with a non-image, spit out the name and be done with it. |
206 | 215 | $thumbhtml = "\n\t\t\t".'<div style="height: '.($this->mHeights*1.25+2).'px;">' |
207 | 216 | . htmlspecialchars( $nt->getText() ) . '</div>'; |
— | — | @@ -222,7 +231,7 @@ |
223 | 232 | //$ul = $sk->makeLink( $wgContLang->getNsText( Namespace::getUser() ) . ":{$ut}", $ut ); |
224 | 233 | |
225 | 234 | if( $this->mShowBytes ) { |
226 | | - if( $img->exists() ) { |
| 235 | + if( $img ) { |
227 | 236 | $nb = wfMsgExt( 'nbytes', array( 'parsemag', 'escape'), |
228 | 237 | $wgLang->formatNum( $img->getSize() ) ); |
229 | 238 | } else { |
Index: branches/phase3_rev_deleted/includes/SpecialNewimages.php |
— | — | @@ -135,10 +135,9 @@ |
136 | 136 | $ut = $s->img_user_text; |
137 | 137 | |
138 | 138 | $nt = Title::newFromText( $name, NS_IMAGE ); |
139 | | - $img = new Image( $nt ); |
140 | 139 | $ul = $sk->makeLinkObj( Title::makeTitle( NS_USER, $ut ), $ut ); |
141 | 140 | |
142 | | - $gallery->add( $img, "$ul<br />\n<i>".$wgLang->timeanddate( $s->img_timestamp, true )."</i><br />\n" ); |
| 141 | + $gallery->add( $nt, "$ul<br />\n<i>".$wgLang->timeanddate( $s->img_timestamp, true )."</i><br />\n" ); |
143 | 142 | |
144 | 143 | $timestamp = wfTimestamp( TS_MW, $s->img_timestamp ); |
145 | 144 | if( empty( $firstTimestamp ) ) { |
Index: branches/phase3_rev_deleted/includes/Title.php |
— | — | @@ -2407,13 +2407,12 @@ |
2408 | 2408 | * Should a link should be displayed as a known link, just based on its title? |
2409 | 2409 | * |
2410 | 2410 | * Currently, a self-link with a fragment and special pages are in |
2411 | | - * this category. Special pages never exist in the database. System |
2412 | | - * messages that have defined default values are also always known. |
| 2411 | + * this category. System messages that have defined default values are also |
| 2412 | + * always known. |
2413 | 2413 | */ |
2414 | 2414 | public function isAlwaysKnown() { |
2415 | 2415 | return ( $this->isExternal() || |
2416 | 2416 | ( 0 == $this->mNamespace && "" == $this->mDbkeyform ) || |
2417 | | - ( NS_SPECIAL == $this->mNamespace ) || |
2418 | 2417 | ( NS_MEDIAWIKI == $this->mNamespace && wfMsgWeirdKey( $this->mDbkeyform ) ) ); |
2419 | 2418 | } |
2420 | 2419 | |
Index: branches/phase3_rev_deleted/includes/Linker.php |
— | — | @@ -218,6 +218,19 @@ |
219 | 219 | $retVal = $this->makeKnownLinkObj( $nt, $text, $query, $trail, $prefix ); |
220 | 220 | } else { |
221 | 221 | wfProfileIn( $fname.'-immediate' ); |
| 222 | + |
| 223 | + # Handles links to special pages wich do not exist in the database: |
| 224 | + if( $nt->getNamespace() == NS_SPECIAL ) { |
| 225 | + if( SpecialPage::exists( $nt->getDbKey() ) ) { |
| 226 | + $retVal = $this->makeKnownLinkObj( $nt, $text, $query, $trail, $prefix ); |
| 227 | + } else { |
| 228 | + $retVal = $this->makeBrokenLinkObj( $nt, $text, $query, $trail, $prefix ); |
| 229 | + } |
| 230 | + wfProfileOut( $fname.'-immediate' ); |
| 231 | + wfProfileOut( $fname ); |
| 232 | + return $retVal; |
| 233 | + } |
| 234 | + |
222 | 235 | # Work out link colour immediately |
223 | 236 | $aid = $nt->getArticleID() ; |
224 | 237 | if ( 0 == $aid ) { |
— | — | @@ -318,7 +331,9 @@ |
319 | 332 | $fname = 'Linker::makeBrokenLinkObj'; |
320 | 333 | wfProfileIn( $fname ); |
321 | 334 | |
322 | | - if ( '' == $query ) { |
| 335 | + if( $nt->getNamespace() == NS_SPECIAL ) { |
| 336 | + $q = $query; |
| 337 | + } else if ( '' == $query ) { |
323 | 338 | $q = 'action=edit'; |
324 | 339 | } else { |
325 | 340 | $q = 'action=edit&'.$query; |
— | — | @@ -412,15 +427,27 @@ |
413 | 428 | return $s; |
414 | 429 | } |
415 | 430 | |
416 | | - /** @todo document */ |
| 431 | + /** Creates the HTML source for images |
| 432 | + * @param object $nt |
| 433 | + * @param string $label label text |
| 434 | + * @param string $alt alt text |
| 435 | + * @param string $align horizontal alignment: none, left, center, right) |
| 436 | + * @param array $params some format keywords: width, height, page, upright, upright_factor, frameless, border |
| 437 | + * @param boolean $framed shows image in original size in a frame |
| 438 | + * @param boolean $thumb shows image as thumbnail in a frame |
| 439 | + * @param string $manual_thumb image name for the manual thumbnail |
| 440 | + * @param string $valign vertical alignment: baseline, sub, super, top, text-top, middle, bottom, text-bottom |
| 441 | + * @return string |
| 442 | + */ |
417 | 443 | function makeImageLinkObj( $nt, $label, $alt, $align = '', $params = array(), $framed = false, |
418 | | - $thumb = false, $manual_thumb = '', $valign = '', $upright = false, $upright_factor = 0, $timeframe=null ) |
| 444 | + $thumb = false, $manual_thumb = '', $valign = '', $time = false ) |
419 | 445 | { |
420 | 446 | global $wgContLang, $wgUser, $wgThumbLimits, $wgThumbUpright; |
421 | 447 | |
422 | | - $img = new Image( $nt, $timeframe ); |
| 448 | + $img = wfFindFile( $nt, $time ); |
423 | 449 | |
424 | | - if ( !$img->allowInlineDisplay() && $img->exists() ) { |
| 450 | + if ( $img && !$img->allowInlineDisplay() ) { |
| 451 | + wfDebug( __METHOD__.': '.$nt->getPrefixedDBkey()." does not allow inline display\n" ); |
425 | 452 | return $this->makeKnownLinkObj( $nt ); |
426 | 453 | } |
427 | 454 | |
— | — | @@ -433,10 +460,9 @@ |
434 | 461 | $postfix = '</div>'; |
435 | 462 | $align = 'none'; |
436 | 463 | } |
437 | | - |
438 | | - if ( !isset( $params['width'] ) ) { |
| 464 | + if ( $img && !isset( $params['width'] ) ) { |
439 | 465 | $params['width'] = $img->getWidth( $page ); |
440 | | - if( $thumb || $framed ) { |
| 466 | + if( $thumb || $framed || isset( $params['frameless'] ) ) { |
441 | 467 | $wopt = $wgUser->getOption( 'thumbsize' ); |
442 | 468 | |
443 | 469 | if( !isset( $wgThumbLimits[$wopt] ) ) { |
— | — | @@ -444,12 +470,12 @@ |
445 | 471 | } |
446 | 472 | |
447 | 473 | // Reduce width for upright images when parameter 'upright' is used |
448 | | - if ( $upright_factor == 0 ) { |
449 | | - $upright_factor = $wgThumbUpright; |
| 474 | + if ( !isset( $params['upright_factor'] ) || $params['upright_factor'] == 0 ) { |
| 475 | + $params['upright_factor'] = $wgThumbUpright; |
450 | 476 | } |
451 | 477 | // Use width which is smaller: real image width or user preference width |
452 | 478 | // For caching health: If width scaled down due to upright parameter, round to full __0 pixel to avoid the creation of a lot of odd thumbs |
453 | | - $params['width'] = min( $params['width'], $upright ? round( $wgThumbLimits[$wopt] * $upright_factor, -1 ) : $wgThumbLimits[$wopt] ); |
| 479 | + $params['width'] = min( $params['width'], isset( $params['upright'] ) ? round( $wgThumbLimits[$wopt] * $params['upright_factor'], -1 ) : $wgThumbLimits[$wopt] ); |
454 | 480 | } |
455 | 481 | } |
456 | 482 | |
— | — | @@ -465,10 +491,10 @@ |
466 | 492 | if ( $align == '' ) { |
467 | 493 | $align = $wgContLang->isRTL() ? 'left' : 'right'; |
468 | 494 | } |
469 | | - return $prefix.$this->makeThumbLinkObj( $img, $label, $alt, $align, $params, $framed, $manual_thumb, $upright ).$postfix; |
| 495 | + return $prefix.$this->makeThumbLinkObj( $nt, $img, $label, $alt, $align, $params, $framed, $manual_thumb ).$postfix; |
470 | 496 | } |
471 | 497 | |
472 | | - if ( $params['width'] && $img->exists() ) { |
| 498 | + if ( $img && $params['width'] ) { |
473 | 499 | # Create a resized image, without the additional thumbnail features |
474 | 500 | $thumb = $img->transform( $params ); |
475 | 501 | } else { |
— | — | @@ -485,9 +511,13 @@ |
486 | 512 | 'alt' => $alt, |
487 | 513 | 'longdesc' => $u |
488 | 514 | ); |
| 515 | + |
489 | 516 | if ( $valign ) { |
490 | 517 | $imgAttribs['style'] = "vertical-align: $valign"; |
491 | 518 | } |
| 519 | + if ( isset( $params['border'] ) ) { |
| 520 | + $imgAttribs['class'] = "thumbborder"; |
| 521 | + } |
492 | 522 | $linkAttribs = array( |
493 | 523 | 'href' => $u, |
494 | 524 | 'class' => 'image', |
— | — | @@ -495,7 +525,7 @@ |
496 | 526 | ); |
497 | 527 | |
498 | 528 | if ( !$thumb ) { |
499 | | - $s = $this->makeBrokenImageLinkObj( $img->getTitle() ); |
| 529 | + $s = $this->makeBrokenImageLinkObj( $nt ); |
500 | 530 | } else { |
501 | 531 | $s = $thumb->toHtml( $imgAttribs, $linkAttribs ); |
502 | 532 | } |
— | — | @@ -507,58 +537,69 @@ |
508 | 538 | |
509 | 539 | /** |
510 | 540 | * Make HTML for a thumbnail including image, border and caption |
511 | | - * $img is an Image object |
| 541 | + * @param Title $nt |
| 542 | + * @param Image $img Image object or false if it doesn't exist |
512 | 543 | */ |
513 | | - function makeThumbLinkObj( $img, $label = '', $alt, $align = 'right', $params = array(), $framed=false , $manual_thumb = "", $upright = false ) { |
| 544 | + function makeThumbLinkObj( Title $nt, $img, $label = '', $alt, $align = 'right', $params = array(), $framed=false , $manual_thumb = "" ) { |
514 | 545 | global $wgStylePath, $wgContLang; |
| 546 | + $exists = $img && $img->exists(); |
515 | 547 | |
516 | 548 | $page = isset( $params['page'] ) ? $params['page'] : false; |
517 | 549 | |
518 | 550 | if ( empty( $params['width'] ) ) { |
519 | 551 | // Reduce width for upright images when parameter 'upright' is used |
520 | | - $params['width'] = $upright ? 130 : 180; |
| 552 | + $params['width'] = isset( $params['upright'] ) ? 130 : 180; |
521 | 553 | } |
522 | 554 | $thumb = false; |
523 | | - if ( $manual_thumb != '' ) { |
524 | | - # Use manually specified thumbnail |
525 | | - $manual_title = Title::makeTitleSafe( NS_IMAGE, $manual_thumb ); |
526 | | - if( $manual_title ) { |
527 | | - $manual_img = new Image( $manual_title ); |
528 | | - $thumb = $manual_img->getUnscaledThumb(); |
529 | | - } |
530 | | - } elseif ( $framed ) { |
531 | | - // Use image dimensions, don't scale |
532 | | - $thumb = $img->getUnscaledThumb( $page ); |
| 555 | + |
| 556 | + if ( !$exists ) { |
| 557 | + $outerWidth = $params['width'] + 2; |
533 | 558 | } else { |
534 | | - # Do not present an image bigger than the source, for bitmap-style images |
535 | | - # This is a hack to maintain compatibility with arbitrary pre-1.10 behaviour |
536 | | - $srcWidth = $img->getWidth( $page ); |
537 | | - if ( $srcWidth && !$img->mustRender() && $params['width'] > $srcWidth ) { |
538 | | - $params['width'] = $srcWidth; |
| 559 | + if ( $manual_thumb != '' ) { |
| 560 | + # Use manually specified thumbnail |
| 561 | + $manual_title = Title::makeTitleSafe( NS_IMAGE, $manual_thumb ); |
| 562 | + if( $manual_title ) { |
| 563 | + $manual_img = wfFindFile( $manual_title ); |
| 564 | + if ( $manual_img ) { |
| 565 | + $thumb = $manual_img->getUnscaledThumb(); |
| 566 | + } else { |
| 567 | + $exists = false; |
| 568 | + } |
| 569 | + } |
| 570 | + } elseif ( $framed ) { |
| 571 | + // Use image dimensions, don't scale |
| 572 | + $thumb = $img->getUnscaledThumb( $page ); |
| 573 | + } else { |
| 574 | + # Do not present an image bigger than the source, for bitmap-style images |
| 575 | + # This is a hack to maintain compatibility with arbitrary pre-1.10 behaviour |
| 576 | + $srcWidth = $img->getWidth( $page ); |
| 577 | + if ( $srcWidth && !$img->mustRender() && $params['width'] > $srcWidth ) { |
| 578 | + $params['width'] = $srcWidth; |
| 579 | + } |
| 580 | + $thumb = $img->transform( $params ); |
539 | 581 | } |
540 | | - $thumb = $img->transform( $params ); |
541 | | - } |
542 | 582 | |
543 | | - if ( $thumb ) { |
544 | | - $outerWidth = $thumb->getWidth() + 2; |
545 | | - } else { |
546 | | - $outerWidth = $params['width'] + 2; |
| 583 | + if ( $thumb ) { |
| 584 | + $outerWidth = $thumb->getWidth() + 2; |
| 585 | + } else { |
| 586 | + $outerWidth = $params['width'] + 2; |
| 587 | + } |
547 | 588 | } |
548 | 589 | |
549 | 590 | $query = $page ? 'page=' . urlencode( $page ) : ''; |
550 | | - $u = $img->getTitle()->getLocalURL( $query ); |
| 591 | + $u = $nt->getLocalURL( $query ); |
551 | 592 | |
552 | 593 | $more = htmlspecialchars( wfMsg( 'thumbnail-more' ) ); |
553 | 594 | $magnifyalign = $wgContLang->isRTL() ? 'left' : 'right'; |
554 | 595 | $textalign = $wgContLang->isRTL() ? ' style="text-align:right"' : ''; |
555 | 596 | |
556 | 597 | $s = "<div class=\"thumb t{$align}\"><div class=\"thumbinner\" style=\"width:{$outerWidth}px;\">"; |
557 | | - if ( !$thumb ) { |
| 598 | + if( !$exists ) { |
| 599 | + $s .= $this->makeBrokenImageLinkObj( $nt ); |
| 600 | + $zoomicon = ''; |
| 601 | + } elseif ( !$thumb ) { |
558 | 602 | $s .= htmlspecialchars( wfMsg( 'thumbnail_error', '' ) ); |
559 | 603 | $zoomicon = ''; |
560 | | - } elseif( !$img->exists() ) { |
561 | | - $s .= $this->makeBrokenImageLinkObj( $img->getTitle() ); |
562 | | - $zoomicon = ''; |
563 | 604 | } else { |
564 | 605 | $imgAttribs = array( |
565 | 606 | 'alt' => $alt, |
— | — | @@ -616,10 +657,10 @@ |
617 | 658 | return $s; |
618 | 659 | } |
619 | 660 | |
620 | | - /** @todo document */ |
621 | | - function makeMediaLink( $name, /* wtf?! */ $url, $alt = '' ) { |
| 661 | + /** @deprecated use Linker::makeMediaLinkObj() */ |
| 662 | + function makeMediaLink( $name, $unused = '', $text = '' ) { |
622 | 663 | $nt = Title::makeTitleSafe( NS_IMAGE, $name ); |
623 | | - return $this->makeMediaLinkObj( $nt, $alt ); |
| 664 | + return $this->makeMediaLinkObj( $nt, $text ); |
624 | 665 | } |
625 | 666 | |
626 | 667 | /** |
— | — | @@ -637,13 +678,13 @@ |
638 | 679 | ### HOTFIX. Instead of breaking, return empty string. |
639 | 680 | return $text; |
640 | 681 | } else { |
641 | | - $img = new Image( $title ); |
642 | | - if( $img->exists() ) { |
| 682 | + $img = wfFindFile( $title ); |
| 683 | + if( $img ) { |
643 | 684 | $url = $img->getURL(); |
644 | 685 | $class = 'internal'; |
645 | 686 | } else { |
646 | 687 | $upload = SpecialPage::getTitleFor( 'Upload' ); |
647 | | - $url = $upload->getLocalUrl( 'wpDestFile=' . urlencode( $img->getName() ) ); |
| 688 | + $url = $upload->getLocalUrl( 'wpDestFile=' . urlencode( $title->getText() ) ); |
648 | 689 | $class = 'new'; |
649 | 690 | } |
650 | 691 | $alt = htmlspecialchars( $title->getText() ); |
— | — | @@ -790,7 +831,7 @@ |
791 | 832 | |
792 | 833 | /** |
793 | 834 | * Generate a user link if the current user is allowed to view it |
794 | | - * @param $event, log item. |
| 835 | + * @param $event, log row item. |
795 | 836 | * @param $isPublic, bool, show only if all users can see it |
796 | 837 | * @return string HTML |
797 | 838 | */ |
— | — | @@ -815,19 +856,19 @@ |
816 | 857 | |
817 | 858 | /** |
818 | 859 | * Generate a user link if the current user is allowed to view it |
819 | | - * @param ArchivedFile or OldImage $file |
| 860 | + * @param File $file |
820 | 861 | * @param $isPublic, bool, show only if all users can see it |
821 | 862 | * @return string HTML |
822 | 863 | */ |
823 | 864 | function fileUserLink( $file, $isPublic = false ) { |
824 | | - if( $file->isDeleted( Revision::DELETED_USER ) && $isPublic ) { |
| 865 | + if( $file->isDeleted( File::DELETED_USER ) && $isPublic ) { |
825 | 866 | $link = wfMsgHtml( 'rev-deleted-user' ); |
826 | | - } else if( $file->userCan( Revision::DELETED_USER ) ) { |
827 | | - $link = $this->userLink( $file->mUser, $file->mUserText ); |
| 867 | + } else if( $file->userCan( File::DELETED_USER ) ) { |
| 868 | + $link = $this->userLink( $file->user, $file->userText ); |
828 | 869 | } else { |
829 | 870 | $link = wfMsgHtml( 'rev-deleted-user' ); |
830 | 871 | } |
831 | | - if( $file->isDeleted( Revision::DELETED_USER ) ) { |
| 872 | + if( $file->isDeleted( File::DELETED_USER ) ) { |
832 | 873 | return '<span class="history-deleted">' . $link . '</span>'; |
833 | 874 | } |
834 | 875 | return $link; |
— | — | @@ -883,7 +924,7 @@ |
884 | 925 | |
885 | 926 | /** |
886 | 927 | * Generate a user tool link cluster if the current user is allowed to view it |
887 | | - * @param ArchivedFile or OldImage $file |
| 928 | + * @param File $file |
888 | 929 | * @param $isPublic, bool, show only if all users can see it |
889 | 930 | * @return string HTML |
890 | 931 | */ |
— | — | @@ -891,8 +932,8 @@ |
892 | 933 | if( $file->isDeleted( Revision::DELETED_USER ) && $isPublic ) { |
893 | 934 | $link = wfMsgHtml( 'rev-deleted-user' ); |
894 | 935 | } else if( $file->userCan( Revision::DELETED_USER ) ) { |
895 | | - $link = $this->userLink( $file->mUser, $file->mUserText ) . |
896 | | - $this->userToolLinks( $file->mUser, $file->mUserText ); |
| 936 | + $link = $this->userLink( $file->user, $file->userText ) . |
| 937 | + $this->userToolLinks( $file->user, $file->userText ); |
897 | 938 | } else { |
898 | 939 | $link = wfMsgHtml( 'rev-deleted-user' ); |
899 | 940 | } |
— | — | @@ -1094,18 +1135,18 @@ |
1095 | 1136 | * Wrap and format the given file's comment block, if the current |
1096 | 1137 | * user is allowed to view it. |
1097 | 1138 | * |
1098 | | - * @param ArchivedFile or OldImage $file |
| 1139 | + * @param File $file |
1099 | 1140 | * @return string HTML |
1100 | 1141 | */ |
1101 | 1142 | function fileComment( $file, $isPublic = false ) { |
1102 | | - if( $file->isDeleted( Revision::DELETED_COMMENT ) && $isPublic ) { |
| 1143 | + if( $file->isDeleted( File::DELETED_COMMENT ) && $isPublic ) { |
1103 | 1144 | $block = ' ' . wfMsgHtml( 'rev-deleted-comment' ); |
1104 | | - } else if( $file->userCan( Revision::DELETED_COMMENT ) ) { |
1105 | | - $block = $this->commentBlock( $file->mDescription ); |
| 1145 | + } else if( $file->userCan( File::DELETED_COMMENT ) ) { |
| 1146 | + $block = $this->commentBlock( $file->description ); |
1106 | 1147 | } else { |
1107 | 1148 | $block = ' ' . wfMsgHtml( 'rev-deleted-comment' ); |
1108 | 1149 | } |
1109 | | - if( $file->isDeleted( Revision::DELETED_COMMENT ) ) { |
| 1150 | + if( $file->isDeleted( File::DELETED_COMMENT ) ) { |
1110 | 1151 | return "<span class=\"history-deleted\">$block</span>"; |
1111 | 1152 | } |
1112 | 1153 | return $block; |
Index: branches/phase3_rev_deleted/includes/Parser.php |
— | — | @@ -99,11 +99,6 @@ |
100 | 100 | # Persistent: |
101 | 101 | var $mTagHooks, $mFunctionHooks, $mFunctionSynonyms, $mVariables; |
102 | 102 | |
103 | | - # Are we trying to get revs from a certain timeframe? |
104 | | - # Use $mTimeframe to set the revision to show as it was at that time |
105 | | - # Deletions/moves can cause red linkage or templates to become mere links |
106 | | - var $mTimeframe; |
107 | | - |
108 | 103 | # Cleared with clearState(): |
109 | 104 | var $mOutput, $mAutonumber, $mDTopen, $mStripState; |
110 | 105 | var $mIncludeCount, $mArgStack, $mLastSection, $mInPre; |
— | — | @@ -279,7 +274,7 @@ |
280 | 275 | * @param int $revid number to pass in {{REVISIONID}} |
281 | 276 | * @return ParserOutput a ParserOutput |
282 | 277 | */ |
283 | | - public function parse( $text, &$title, $options, $linestart = true, $clearState = true, $revid = null, $timeframe=null ) { |
| 278 | + public function parse( $text, &$title, $options, $linestart = true, $clearState = true, $revid = null ) { |
284 | 279 | /** |
285 | 280 | * First pass--just handle <nowiki> sections, pass the rest off |
286 | 281 | * to internalParse() which does all the real work. |
— | — | @@ -296,9 +291,6 @@ |
297 | 292 | |
298 | 293 | $this->mOptions = $options; |
299 | 294 | $this->mTitle =& $title; |
300 | | - // This variable is used for gettings Templates/Images from a certain time |
301 | | - $this->mTimeframe = $timeframe; |
302 | | - |
303 | 295 | $oldRevisionId = $this->mRevisionId; |
304 | 296 | $oldRevisionTimestamp = $this->mRevisionTimestamp; |
305 | 297 | if( $revid !== null ) { |
— | — | @@ -408,12 +400,15 @@ |
409 | 401 | * Expand templates and variables in the text, producing valid, static wikitext. |
410 | 402 | * Also removes comments. |
411 | 403 | */ |
412 | | - function preprocess( $text, $title, $options ) { |
| 404 | + function preprocess( $text, $title, $options, $revid = null ) { |
413 | 405 | wfProfileIn( __METHOD__ ); |
414 | 406 | $this->clearState(); |
415 | 407 | $this->setOutputType( OT_PREPROCESS ); |
416 | 408 | $this->mOptions = $options; |
417 | 409 | $this->mTitle = $title; |
| 410 | + if( $revid !== null ) { |
| 411 | + $this->mRevisionId = $revid; |
| 412 | + } |
418 | 413 | wfRunHooks( 'ParserBeforeStrip', array( &$this, &$text, &$this->mStripState ) ); |
419 | 414 | $text = $this->strip( $text, $this->mStripState ); |
420 | 415 | wfRunHooks( 'ParserAfterStrip', array( &$this, &$text, &$this->mStripState ) ); |
— | — | @@ -1807,11 +1802,15 @@ |
1808 | 1803 | $this->mOutput->addImage( $nt->getDBkey() ); |
1809 | 1804 | continue; |
1810 | 1805 | } elseif( $ns == NS_SPECIAL ) { |
1811 | | - $s .= $this->makeKnownLinkHolder( $nt, $text, '', $trail, $prefix ); |
| 1806 | + if( SpecialPage::exists( $nt->getDBkey() ) ) { |
| 1807 | + $s .= $this->makeKnownLinkHolder( $nt, $text, '', $trail, $prefix ); |
| 1808 | + } else { |
| 1809 | + $s .= $this->makeLinkHolder( $nt, $text, '', $trail, $prefix ); |
| 1810 | + } |
1812 | 1811 | continue; |
1813 | 1812 | } elseif( $ns == NS_IMAGE ) { |
1814 | | - $img = new Image( $nt ); |
1815 | | - if( $img->exists() ) { |
| 1813 | + $img = wfFindFile( $nt ); |
| 1814 | + if( $img ) { |
1816 | 1815 | // Force a blue link if the file exists; may be a remote |
1817 | 1816 | // upload on the shared repository, and we want to see its |
1818 | 1817 | // auto-generated page. |
— | — | @@ -3268,18 +3267,25 @@ |
3269 | 3268 | * Fetch the unparsed text of a template and register a reference to it. |
3270 | 3269 | */ |
3271 | 3270 | function fetchTemplateAndtitle( $title ) { |
3272 | | - $text = false; |
| 3271 | + $text = $skip = false; |
3273 | 3272 | $finalTitle = $title; |
3274 | 3273 | // Loop to fetch the article, with up to 1 redirect |
3275 | 3274 | for ( $i = 0; $i < 2 && is_object( $title ); $i++ ) { |
3276 | | - # Are we trying to get revs from a certain timeframe? |
3277 | | - if ( $this->mTimeframe ) { |
3278 | | - $rev = Revision::newFromTimeframe( $title, $this->mTimeframe ); |
3279 | | - } else { |
3280 | | - $rev = Revision::newFromTitle( $title ); |
| 3275 | + # Give extensions a chance to select the revision instead |
| 3276 | + $id = false; // Assume current |
| 3277 | + wfRunHooks( 'BeforeParserFetchTemplateAndtitle', array( &$this, &$title, &$skip, &$id ) ); |
| 3278 | + |
| 3279 | + if( $skip ) { |
| 3280 | + $text = false; |
| 3281 | + $this->mOutput->addTemplate( $title, $title->getArticleID(), 0 ); |
| 3282 | + break; |
3281 | 3283 | } |
3282 | | - $this->mOutput->addTemplate( $title, $title->getArticleID() ); |
3283 | | - if ( $rev ) { |
| 3284 | + $rev = $id ? Revision::newFromId( $id ) : Revision::newFromTitle( $title ); |
| 3285 | + $rev_id = $rev ? $rev->getId() : 0; |
| 3286 | + |
| 3287 | + $this->mOutput->addTemplate( $title, $title->getArticleID(), $rev_id ); |
| 3288 | + |
| 3289 | + if( $rev ) { |
3284 | 3290 | $text = $rev->getText(); |
3285 | 3291 | } elseif( $title->getNamespace() == NS_MEDIAWIKI ) { |
3286 | 3292 | global $wgLang; |
— | — | @@ -4050,6 +4056,8 @@ |
4051 | 4057 | $this->mOutput->addLink( $title, $id ); |
4052 | 4058 | } elseif ( $linkCache->isBadLink( $pdbk ) ) { |
4053 | 4059 | $colours[$pdbk] = 0; |
| 4060 | + } elseif ( $title->getNamespace() == NS_SPECIAL && !SpecialPage::exists( $pdbk ) ) { |
| 4061 | + $colours[$pdbk] = 0; |
4054 | 4062 | } else { |
4055 | 4063 | # Not in the link cache, add it to the query |
4056 | 4064 | if ( !isset( $current ) ) { |
— | — | @@ -4131,7 +4139,7 @@ |
4132 | 4140 | } |
4133 | 4141 | |
4134 | 4142 | // process categories, check if a category exists in some variant |
4135 | | - foreach( $categories as $category){ |
| 4143 | + foreach( $categories as $category ){ |
4136 | 4144 | $variants = $wgContLang->convertLinkToAllVariants($category); |
4137 | 4145 | foreach($variants as $variant){ |
4138 | 4146 | if($variant != $category){ |
— | — | @@ -4353,6 +4361,7 @@ |
4354 | 4362 | $ig->setShowFilename( false ); |
4355 | 4363 | $ig->setParsing(); |
4356 | 4364 | $ig->useSkin( $this->mOptions->getSkin() ); |
| 4365 | + $ig->mRevisionId = $this->mRevisionId; |
4357 | 4366 | |
4358 | 4367 | if( isset( $params['caption'] ) ) { |
4359 | 4368 | $caption = $params['caption']; |
— | — | @@ -4369,6 +4378,8 @@ |
4370 | 4379 | if( isset( $params['heights'] ) ) { |
4371 | 4380 | $ig->setHeights( $params['heights'] ); |
4372 | 4381 | } |
| 4382 | + |
| 4383 | + wfRunHooks( 'parserBeforerenderImageGallery', array( &$this, &$ig ) ); |
4373 | 4384 | |
4374 | 4385 | $lines = explode( "\n", $text ); |
4375 | 4386 | foreach ( $lines as $line ) { |
— | — | @@ -4400,7 +4411,7 @@ |
4401 | 4412 | ); |
4402 | 4413 | $html = $pout->getText(); |
4403 | 4414 | |
4404 | | - $ig->add( new Image( $nt ), $html ); |
| 4415 | + $ig->add( $nt, $html ); |
4405 | 4416 | |
4406 | 4417 | # Only add real images (bug #5586) |
4407 | 4418 | if ( $nt->getNamespace() == NS_IMAGE ) { |
— | — | @@ -4425,7 +4436,9 @@ |
4426 | 4437 | # * ___px scale to ___ pixels width, no aligning. e.g. use in taxobox |
4427 | 4438 | # * center center the image |
4428 | 4439 | # * framed Keep original image size, no magnify-button. |
| 4440 | + # * frameless like 'thumb' but without a frame. Keeps user preferences for width |
4429 | 4441 | # * upright reduce width for upright images, rounded to full __0 px |
| 4442 | + # * border draw a 1px border around the image |
4430 | 4443 | # vertical-align values (no % or length right now): |
4431 | 4444 | # * baseline |
4432 | 4445 | # * sub |
— | — | @@ -4448,14 +4461,14 @@ |
4449 | 4462 | $mwManualThumb =& MagicWord::get( 'img_manualthumb' ); |
4450 | 4463 | $mwWidth =& MagicWord::get( 'img_width' ); |
4451 | 4464 | $mwFramed =& MagicWord::get( 'img_framed' ); |
| 4465 | + $mwFrameless =& MagicWord::get( 'img_frameless' ); |
4452 | 4466 | $mwUpright =& MagicWord::get( 'img_upright' ); |
| 4467 | + $mwBorder =& MagicWord::get( 'img_border' ); |
4453 | 4468 | $mwPage =& MagicWord::get( 'img_page' ); |
4454 | 4469 | $caption = ''; |
4455 | 4470 | |
4456 | 4471 | $params = array(); |
4457 | 4472 | $framed = $thumb = false; |
4458 | | - $upright = false; |
4459 | | - $upright_factor = 0; |
4460 | 4473 | $manual_thumb = '' ; |
4461 | 4474 | $align = $valign = ''; |
4462 | 4475 | $sk = $this->mOptions->getSkin(); |
— | — | @@ -4464,8 +4477,12 @@ |
4465 | 4478 | if ( !is_null( $mwThumb->matchVariableStartToEnd($val) ) ) { |
4466 | 4479 | $thumb=true; |
4467 | 4480 | } elseif ( !is_null( $match = $mwUpright->matchVariableStartToEnd( $val ) ) ) { |
4468 | | - $upright = true; |
4469 | | - $upright_factor = floatval( $match ); |
| 4481 | + $params['upright'] = true; |
| 4482 | + $params['upright_factor'] = floatval( $match ); |
| 4483 | + } elseif ( !is_null( $match = $mwFrameless->matchVariableStartToEnd( $val ) ) ) { |
| 4484 | + $params['frameless'] = true; |
| 4485 | + } elseif ( !is_null( $mwBorder->matchVariableStartToEnd( $val ) ) ) { |
| 4486 | + $params['border'] = true; |
4470 | 4487 | } elseif ( ! is_null( $match = $mwManualThumb->matchVariableStartToEnd($val) ) ) { |
4471 | 4488 | # use manually specified thumbnail |
4472 | 4489 | $thumb=true; |
— | — | @@ -4511,9 +4528,18 @@ |
4512 | 4529 | $alt = $this->mStripState->unstripBoth( $alt ); |
4513 | 4530 | $alt = Sanitizer::stripAllTags( $alt ); |
4514 | 4531 | |
| 4532 | + # Give extensions a chance to select the file revision for us |
| 4533 | + $link = $skip = $time = false; |
| 4534 | + wfRunHooks( 'BeforeParserMakeImageLinkObj', array( &$this, &$nt, &$skip, &$time ) ); |
| 4535 | + |
4515 | 4536 | # Linker does the rest |
4516 | | - return $sk->makeImageLinkObj( $nt, $caption, $alt, $align, $params, $framed, $thumb, $manual_thumb, |
4517 | | - $valign, $upright, $upright_factor, $this->mTimeframe ); |
| 4537 | + if( $skip ) { |
| 4538 | + $link = $sk->makeLinkObj( $nt ); |
| 4539 | + } else { |
| 4540 | + $link = $sk->makeImageLinkObj( $nt, $caption, $alt, $align, $params, $framed, $thumb, $manual_thumb, $valign, $time ); |
| 4541 | + } |
| 4542 | + |
| 4543 | + return $link; |
4518 | 4544 | } |
4519 | 4545 | |
4520 | 4546 | /** |
Index: branches/phase3_rev_deleted/includes/Revision.php |
— | — | @@ -49,79 +49,6 @@ |
50 | 50 | 'page_namespace' => $title->getNamespace(), |
51 | 51 | 'page_title' => $title->getDbkey() ) ); |
52 | 52 | } |
53 | | - |
54 | | - /** |
55 | | - * Gets the revision that was current at said time |
56 | | - * as accurately as possible. Archiving of individual |
57 | | - * revisions can cause this to become borked. |
58 | | - * --Use of rev_deleted instead avoids that. |
59 | | - * History merges can break this |
60 | | - * --Requiring either all restored revs to be all newer |
61 | | - * --or all older to than those of the live page avoids that. |
62 | | - * |
63 | | - * --Also, if a page has archived revs, deletion should have |
64 | | - * --the same limitations |
65 | | - * |
66 | | - * @param Database $db |
67 | | - * @param Title $title |
68 | | - * @param timestamp $timeframe, desired view time |
69 | | - * @return Revision |
70 | | - * @access public |
71 | | - * @static |
72 | | - */ |
73 | | - public static function newFromTimeframe( &$title, $timeframe ) { |
74 | | - $relocated = true; // Assume true to begin with |
75 | | - $isdeleted = false; |
76 | | - $id = 0; |
77 | | - |
78 | | - $dbr = wfGetDB( DB_SLAVE ); |
79 | | - // Initial query conds... |
80 | | - $d = "log_action='delete'"; |
81 | | - $r = '1 = 0'; // we don't care if it was restored yet |
82 | | - $m = "log_action='move'"; |
83 | | - // Recursively check logs for page moves since $timeframe... |
84 | | - while( $relocated ) { |
85 | | - $result = $dbr->select( 'logging', array('log_params', 'log_action', 'log_id'), |
86 | | - array("log_timestamp >= $timeframe", "log_id > $id", |
87 | | - 'log_namespace' => $title->getNamespace(), 'log_title' => $title->getDbkey(), |
88 | | - "($m) OR ($d) OR ($r)"), |
89 | | - __METHOD__, |
90 | | - array('ORDER BY' => 'log_timestamp ASC', 'LIMIT' => 1) ); |
91 | | - if( $row = $dbr->fetchObject($result) ) { |
92 | | - // Was it deleted? |
93 | | - if( $row->log_action=='delete' ) { |
94 | | - $isdeleted = true; |
95 | | - $d = '1 = 0'; |
96 | | - $r = "log_action='restore'"; |
97 | | - $m = '1 = 0'; |
98 | | - // Was it restored? |
99 | | - } else if( $row->log_action=='restore' ) { |
100 | | - // Check the restore point (format is <page time>\n<image time>) |
101 | | - $restpoints = explode('\n',$row->log_params); |
102 | | - if( $restpoints[0] >= 0 && $restpoints[0] <= $timeframe ) { |
103 | | - $isdeleted = false; // our desired revision was restored |
104 | | - $d = "log_action='delete'"; |
105 | | - $r = '1 = 0'; |
106 | | - $m = "log_action='move'"; |
107 | | - } |
108 | | - // Was it moved? |
109 | | - } else { |
110 | | - $title = Title::newFromText( $row->log_params ); // New name is stored here |
111 | | - } |
112 | | - $id = $row->log_id; |
113 | | - } else if( $isdeleted ) { |
114 | | - return null; |
115 | | - } else { |
116 | | - $relocated = false; |
117 | | - } |
118 | | - } |
119 | | - // Fetch the revision |
120 | | - return Revision::newFromConds( |
121 | | - array( "rev_timestamp < $timeframe", |
122 | | - 'page_id=rev_page', |
123 | | - 'page_namespace' => $title->getNamespace(), |
124 | | - 'page_title' => $title->getDbkey() ) ); |
125 | | - } |
126 | 53 | |
127 | 54 | /** |
128 | 55 | * Load a page revision from a given revision ID number. |
— | — | @@ -315,7 +242,7 @@ |
316 | 243 | 'rev_len' ), |
317 | 244 | $conditions, |
318 | 245 | 'Revision::fetchRow', |
319 | | - array( 'ORDER BY' => 'rev_id DESC', 'LIMIT' => 1 ) ); |
| 246 | + array( 'LIMIT' => 1 ) ); |
320 | 247 | $ret = $db->resultObject( $res ); |
321 | 248 | return $ret; |
322 | 249 | } |
Index: branches/phase3_rev_deleted/includes/CategoryPage.php |
— | — | @@ -147,7 +147,7 @@ |
148 | 148 | /** |
149 | 149 | * Add a page in the image namespace |
150 | 150 | */ |
151 | | - function addImage( $title, $sortkey, $pageLength, $isRedirect = false ) { |
| 151 | + function addImage( Title $title, $sortkey, $pageLength, $isRedirect = false ) { |
152 | 152 | if ( $this->showGallery ) { |
153 | 153 | $image = new Image( $title ); |
154 | 154 | if( $this->flip ) { |
— | — | @@ -222,7 +222,7 @@ |
223 | 223 | |
224 | 224 | if( $title->getNamespace() == NS_CATEGORY ) { |
225 | 225 | $this->addSubcategory( $title, $x->cl_sortkey, $x->page_len ); |
226 | | - } elseif( $title->getNamespace() == NS_IMAGE ) { |
| 226 | + } elseif( $this->showGallery && $title->getNamespace() == NS_IMAGE ) { |
227 | 227 | $this->addImage( $title, $x->cl_sortkey, $x->page_len, $x->page_is_redirect ); |
228 | 228 | } else { |
229 | 229 | $this->addPage( $title, $x->cl_sortkey, $x->page_len, $x->page_is_redirect ); |
Index: branches/phase3_rev_deleted/includes/ParserOutput.php |
— | — | @@ -14,7 +14,9 @@ |
15 | 15 | $mTitleText, # title text of the chosen language variant
|
16 | 16 | $mLinks, # 2-D map of NS/DBK to ID for the links in the document. ID=zero for broken.
|
17 | 17 | $mTemplates, # 2-D map of NS/DBK to ID for the template references. ID=zero for broken.
|
| 18 | + $mTemplateIds, # 2-D map of NS/DBK to rev ID for the template references. ID=zero for broken.
|
18 | 19 | $mImages, # DB keys of the images used, in the array key only
|
| 20 | + $mImageTimestamps, # Map of DBK to rev ID for the template references. ID=zero for broken.
|
19 | 21 | $mExternalLinks, # External link URLs, in the key only
|
20 | 22 | $mHTMLtitle, # Display HTML title
|
21 | 23 | $mSubtitle, # Additional subtitle
|
— | — | @@ -41,10 +43,12 @@ |
42 | 44 | $this->mNewSection = false;
|
43 | 45 | $this->mNoGallery = false;
|
44 | 46 | $this->mHeadItems = array();
|
| 47 | + $this->mTemplateIds = array();
|
| 48 | + $this->mImageTimestamps = array();
|
45 | 49 | }
|
46 | 50 |
|
47 | 51 | function getText() { return $this->mText; }
|
48 | | - function &getLanguageLinks() { return $this->mLanguageLinks; }
|
| 52 | + function &getLanguageLinks() { return $this->mLanguageLinks; }
|
49 | 53 | function getCategoryLinks() { return array_keys( $this->mCategories ); }
|
50 | 54 | function &getCategories() { return $this->mCategories; }
|
51 | 55 | function getCacheTime() { return $this->mCacheTime; }
|
— | — | @@ -66,7 +70,6 @@ |
67 | 71 | function setSubtitle( $st ) { return wfSetVar( $this->mSubtitle, $st ); }
|
68 | 72 |
|
69 | 73 | function addCategory( $c, $sort ) { $this->mCategories[$c] = $sort; }
|
70 | | - function addImage( $name ) { $this->mImages[$name] = 1; }
|
71 | 74 | function addLanguageLink( $t ) { $this->mLanguageLinks[] = $t; }
|
72 | 75 | function addExternalLink( $url ) { $this->mExternalLinks[$url] = 1; }
|
73 | 76 |
|
— | — | @@ -88,14 +91,33 @@ |
89 | 92 | }
|
90 | 93 | $this->mLinks[$ns][$dbk] = $id;
|
91 | 94 | }
|
| 95 | +
|
| 96 | + function addImage( $name, $timestamp=NULL ) {
|
| 97 | + if( isset($this->mImages[$name]) )
|
| 98 | + return; // No repeated pointless DB calls!
|
| 99 | + $this->mImages[$name] = 1;
|
| 100 | + if( is_null($timestamp) ) {
|
| 101 | + wfProfileIn( __METHOD__ );
|
| 102 | + $dbr = wfGetDB(DB_SLAVE);
|
| 103 | + $timestamp = $dbr->selectField('image', 'img_timestamp',
|
| 104 | + array('img_name' => $name),
|
| 105 | + __METHOD__ );
|
| 106 | + }
|
| 107 | + $timestamp = $timestamp ? $timestamp : 0;
|
| 108 | + $this->mImageTimestamps[$name] = $timestamp; // For versioning
|
| 109 | + }
|
92 | 110 |
|
93 | | - function addTemplate( $title, $id ) {
|
| 111 | + function addTemplate( $title, $page_id, $rev_id ) {
|
94 | 112 | $ns = $title->getNamespace();
|
95 | 113 | $dbk = $title->getDBkey();
|
96 | 114 | if ( !isset( $this->mTemplates[$ns] ) ) {
|
97 | 115 | $this->mTemplates[$ns] = array();
|
98 | 116 | }
|
99 | | - $this->mTemplates[$ns][$dbk] = $id;
|
| 117 | + $this->mTemplates[$ns][$dbk] = $page_id;
|
| 118 | + if ( !isset( $this->mTemplateIds[$ns] ) ) {
|
| 119 | + $this->mTemplateIds[$ns] = array();
|
| 120 | + }
|
| 121 | + $this->mTemplateIds[$ns][$dbk] = $rev_id; // For versioning
|
100 | 122 | }
|
101 | 123 |
|
102 | 124 | /**
|
Index: branches/phase3_rev_deleted/includes/ImagePage.php |
— | — | @@ -18,6 +18,14 @@ |
19 | 19 | /* private */ var $img; // Image object this page is shown for |
20 | 20 | var $mExtraDescription = false; |
21 | 21 | |
| 22 | + function __construct( $title ) { |
| 23 | + parent::__construct( $title ); |
| 24 | + $this->img = wfFindFile( $this->mTitle ); |
| 25 | + if ( !$this->img ) { |
| 26 | + $this->img = wfLocalFile( $this->mTitle ); |
| 27 | + } |
| 28 | + } |
| 29 | + |
22 | 30 | /** |
23 | 31 | * Handler for action=render |
24 | 32 | * Include body text only; none of the image extras |
— | — | @@ -31,8 +39,6 @@ |
32 | 40 | function view() { |
33 | 41 | global $wgOut, $wgShowEXIF, $wgRequest, $wgUser; |
34 | 42 | |
35 | | - $this->img = new Image( $this->mTitle ); |
36 | | - |
37 | 43 | $diff = $wgRequest->getVal( 'diff' ); |
38 | 44 | $diffOnly = $wgRequest->getBool( 'diffonly', $wgUser->getOption( 'diffonly' ) ); |
39 | 45 | |
— | — | @@ -160,7 +166,7 @@ |
161 | 167 | * shared upload server if possible. |
162 | 168 | */ |
163 | 169 | function getContent() { |
164 | | - if( $this->img && $this->img->fromSharedDirectory && 0 == $this->getID() ) { |
| 170 | + if( $this->img && !$this->img->isLocal() && 0 == $this->getID() ) { |
165 | 171 | return ''; |
166 | 172 | } |
167 | 173 | return Article::getContent(); |
— | — | @@ -332,26 +338,26 @@ |
333 | 339 | $dirmark = $wgContLang->getDirMark(); |
334 | 340 | if (!$this->img->isSafeFile()) { |
335 | 341 | $warning = wfMsg( 'mediawarning' ); |
336 | | - $wgOut->addWikiText( <<<END |
| 342 | + $wgOut->addWikiText( <<<EOT |
337 | 343 | <div class="fullMedia">$infores |
338 | 344 | <span class="dangerousLink">[[Media:$filename|$filename]]</span>$dirmark |
339 | 345 | <span class="fileInfo"> $info</span> |
340 | 346 | </div> |
341 | 347 | |
342 | 348 | <div class="mediaWarning">$warning</div> |
343 | | -END |
| 349 | +EOT |
344 | 350 | ); |
345 | 351 | } else { |
346 | | - $wgOut->addWikiText( <<<END |
| 352 | + $wgOut->addWikiText( <<<EOT |
347 | 353 | <div class="fullMedia">$infores |
348 | 354 | [[Media:$filename|$filename]]$dirmark <span class="fileInfo"> $info</span> |
349 | 355 | </div> |
350 | | -END |
| 356 | +EOT |
351 | 357 | ); |
352 | 358 | } |
353 | 359 | } |
354 | 360 | |
355 | | - if($this->img->fromSharedDirectory) { |
| 361 | + if(!$this->img->isLocal()) { |
356 | 362 | $this->printSharedImageText(); |
357 | 363 | } |
358 | 364 | } else { |
— | — | @@ -365,27 +371,21 @@ |
366 | 372 | } |
367 | 373 | |
368 | 374 | function printSharedImageText() { |
369 | | - global $wgRepositoryBaseUrl, $wgFetchCommonsDescriptions, $wgOut, $wgUser; |
| 375 | + global $wgOut, $wgUser; |
370 | 376 | |
371 | | - $url = $wgRepositoryBaseUrl . urlencode($this->mTitle->getDBkey()); |
372 | | - $sharedtext = "<div class='sharedUploadNotice'>" . wfMsgWikiHtml("sharedupload"); |
373 | | - if ($wgRepositoryBaseUrl && !$wgFetchCommonsDescriptions) { |
374 | | - |
| 377 | + $descUrl = $this->img->getDescriptionUrl(); |
| 378 | + $descText = $this->img->getDescriptionText(); |
| 379 | + $s = "<div class='sharedUploadNotice'>" . wfMsgWikiHtml("sharedupload"); |
| 380 | + if ( $descUrl && !$descText) { |
375 | 381 | $sk = $wgUser->getSkin(); |
376 | | - $title = SpecialPage::getTitleFor( 'Upload' ); |
377 | | - $link = $sk->makeKnownLinkObj($title, wfMsgHtml('shareduploadwiki-linktext'), |
378 | | - array( 'wpDestFile' => urlencode( $this->img->getName() ))); |
379 | | - $sharedtext .= " " . wfMsgWikiHtml('shareduploadwiki', $link); |
| 382 | + $link = $sk->makeExternalLink( $descUrl, wfMsg('shareduploadwiki-linktext') ); |
| 383 | + $s .= " " . wfMsgWikiHtml('shareduploadwiki', $link); |
380 | 384 | } |
381 | | - $sharedtext .= "</div>"; |
382 | | - $wgOut->addHTML($sharedtext); |
| 385 | + $s .= "</div>"; |
| 386 | + $wgOut->addHTML($s); |
383 | 387 | |
384 | | - if ($wgRepositoryBaseUrl && $wgFetchCommonsDescriptions) { |
385 | | - $renderUrl = wfAppendQuery( $url, 'action=render' ); |
386 | | - wfDebug( "Fetching shared description from $renderUrl\n" ); |
387 | | - $text = Http::get( $renderUrl ); |
388 | | - if ($text) |
389 | | - $this->mExtraDescription = $text; |
| 388 | + if ( $descText ) { |
| 389 | + $this->mExtraDescription = $descText; |
390 | 390 | } |
391 | 391 | } |
392 | 392 | |
— | — | @@ -402,7 +402,7 @@ |
403 | 403 | function uploadLinksBox() { |
404 | 404 | global $wgUser, $wgOut; |
405 | 405 | |
406 | | - if( $this->img->fromSharedDirectory ) |
| 406 | + if( !$this->img->isLocal() ) |
407 | 407 | return; |
408 | 408 | |
409 | 409 | $sk = $wgUser->getSkin(); |
— | — | @@ -441,7 +441,7 @@ |
442 | 442 | $line = $this->img->nextHistoryLine(); |
443 | 443 | |
444 | 444 | if ( $line ) { |
445 | | - $list = new ImageHistoryList( $sk ); |
| 445 | + $list = new ImageHistoryList( $sk, $this->img ); |
446 | 446 | // Our top image |
447 | 447 | $s = $list->beginImageHistoryList() . |
448 | 448 | $list->imageHistoryLine( true, wfTimestamp(TS_MW, $line->img_timestamp), |
— | — | @@ -533,8 +533,6 @@ |
534 | 534 | return; |
535 | 535 | } |
536 | 536 | |
537 | | - $this->img = new Image( $this->mTitle ); |
538 | | - |
539 | 537 | # Deleting old images doesn't require confirmation |
540 | 538 | if ( !is_null( $oldimage ) || $confirm ) { |
541 | 539 | if( $wgUser->matchEditToken( $wgRequest->getVal( 'wpEditToken' ), $oldimage ) ) { |
— | — | @@ -658,41 +656,23 @@ |
659 | 657 | $wgOut->showErrorPage( 'internalerror', 'sessionfailure' ); |
660 | 658 | return; |
661 | 659 | } |
662 | | - $name = substr( $oldimage, 15 ); |
663 | 660 | |
664 | | - $dest = wfImageDir( $name ); |
665 | | - $archive = wfImageArchiveDir( $name ); |
666 | | - $curfile = "{$dest}/{$name}"; |
| 661 | + $sourcePath = $this->img->getArchiveVirtualUrl( $oldimage ); |
| 662 | + $result = $this->img->publish( $sourcePath ); |
667 | 663 | |
668 | | - if ( !is_dir( $dest ) ) wfMkdirParents( $dest ); |
669 | | - if ( !is_dir( $archive ) ) wfMkdirParents( $archive ); |
670 | | - |
671 | | - if ( ! is_file( $curfile ) ) { |
672 | | - $wgOut->showFileNotFoundError( htmlspecialchars( $curfile ) ); |
| 664 | + if ( WikiError::isError( $result ) ) { |
| 665 | + $this->showError( $result ); |
673 | 666 | return; |
674 | 667 | } |
675 | | - $oldver = wfTimestampNow() . "!{$name}"; |
676 | 668 | |
677 | | - wfSuppressWarnings(); |
678 | | - if ( ! rename( $curfile, "${archive}/{$oldver}" ) ) { |
679 | | - $wgOut->showFileRenameError( $curfile, "${archive}/{$oldver}" ); |
680 | | - return; |
681 | | - } |
682 | | - if ( ! copy( "{$archive}/{$oldimage}", $curfile ) ) { |
683 | | - $wgOut->showFileCopyError( "${archive}/{$oldimage}", $curfile ); |
684 | | - return; |
685 | | - } |
686 | | - wfRestoreWarnings(); |
687 | | - |
688 | 669 | # Record upload and update metadata cache |
689 | | - $img = Image::newFromName( $name ); |
690 | | - $img->recordUpload( $oldver, wfMsg( "reverted" ) ); |
| 670 | + $this->img->recordUpload( $result, wfMsg( "reverted" ) ); |
691 | 671 | |
692 | 672 | $wgOut->setPagetitle( wfMsg( 'actioncomplete' ) ); |
693 | 673 | $wgOut->setRobotpolicy( 'noindex,nofollow' ); |
694 | 674 | $wgOut->addHTML( wfMsg( 'imagereverted' ) ); |
695 | 675 | |
696 | | - $descTitle = $img->getTitle(); |
| 676 | + $descTitle = $this->img->getTitle(); |
697 | 677 | $wgOut->returnToMain( false, $descTitle->getPrefixedText() ); |
698 | 678 | } |
699 | 679 | |
— | — | @@ -700,7 +680,6 @@ |
701 | 681 | * Override handling of action=purge |
702 | 682 | */ |
703 | 683 | function doPurge() { |
704 | | - $this->img = new Image( $this->mTitle ); |
705 | 684 | if( $this->img->exists() ) { |
706 | 685 | wfDebug( "ImagePage::doPurge purging " . $this->img->getName() . "\n" ); |
707 | 686 | $update = new HTMLCacheUpdate( $this->mTitle, 'imagelinks' ); |
— | — | @@ -713,6 +692,18 @@ |
714 | 693 | parent::doPurge(); |
715 | 694 | } |
716 | 695 | |
| 696 | + /** |
| 697 | + * Display an error from a wikitext-formatted WikiError object |
| 698 | + */ |
| 699 | + function showError( WikiError $error ) { |
| 700 | + global $wgOut; |
| 701 | + $wgOut->setPageTitle( wfMsg( "internalerror" ) ); |
| 702 | + $wgOut->setRobotpolicy( "noindex,nofollow" ); |
| 703 | + $wgOut->setArticleRelated( false ); |
| 704 | + $wgOut->enableClientCache( false ); |
| 705 | + $wgOut->addWikiText( $error->getMessage() ); |
| 706 | + } |
| 707 | + |
717 | 708 | } |
718 | 709 | |
719 | 710 | /** |
— | — | @@ -720,8 +711,10 @@ |
721 | 712 | * @addtogroup Media |
722 | 713 | */ |
723 | 714 | class ImageHistoryList { |
724 | | - function ImageHistoryList( &$skin ) { |
725 | | - $this->skin =& $skin; |
| 715 | + var $img, $skin; |
| 716 | + function ImageHistoryList( $skin, $img ) { |
| 717 | + $this->skin = $skin; |
| 718 | + $this->img = $img; |
726 | 719 | } |
727 | 720 | |
728 | 721 | function beginImageHistoryList() { |
— | — | @@ -744,11 +737,12 @@ |
745 | 738 | $del = wfMsgHtml( 'rev-delundel' ); |
746 | 739 | $delall = wfMsgHtml( 'deleteimgcompletely' ); |
747 | 740 | $cur = wfMsgHtml( 'cur' ); |
| 741 | + $local = $this->img->isLocal(); |
748 | 742 | |
749 | 743 | if ( $iscur ) { |
750 | | - $url = Image::imageUrl( $img ); |
| 744 | + $url = htmlspecialchars( $this->img->getURL() ); |
751 | 745 | $rlink = $cur; |
752 | | - if ( $wgUser->isAllowed('delete') ) { |
| 746 | + if ( $local && $wgUser->isAllowed('delete') ) { |
753 | 747 | $link = $wgTitle->escapeLocalURL( 'image=' . $wgTitle->getPartialURL() . |
754 | 748 | '&action=delete' ); |
755 | 749 | $style = $this->skin->getInternalLinkAttributes( $link, $delall ); |
— | — | @@ -758,8 +752,8 @@ |
759 | 753 | $dlink = ''; |
760 | 754 | } |
761 | 755 | } else { |
762 | | - $url = htmlspecialchars( wfImageArchiveUrl( $img ) ); |
763 | | - if( $wgUser->getID() != 0 && $wgTitle->userCan( 'edit' ) ) { |
| 756 | + $url = htmlspecialchars( $this->img->getArchiveUrl( $img ) ); |
| 757 | + if( $local && $wgUser->getID() != 0 && $wgTitle->userCan( 'edit' ) ) { |
764 | 758 | # Revert link, for public files only |
765 | 759 | if ( $deleted ) { |
766 | 760 | $rlink = wfMsgHtml( 'revertimg' ); |
— | — | @@ -811,13 +805,17 @@ |
812 | 806 | $dlink = ''; |
813 | 807 | } |
814 | 808 | } |
| 809 | + |
815 | 810 | # Hide deleted usernames |
816 | 811 | if ( $this->isDeleted($deleted,Image::DELETED_USER) ) |
817 | 812 | $userlink = '<span class="history-deleted">' . wfMsgHtml( 'rev-deleted-user' ) . '</span>'; |
818 | | - else |
| 813 | + else if ( $local ) { |
819 | 814 | $userlink = $this->skin->userLink( $user, $usertext ) . $this->skin->userToolLinks( $user, $usertext ); |
820 | | - |
| 815 | + } else { |
| 816 | + $userlink = htmlspecialchars( $usertext ); |
| 817 | + } |
821 | 818 | $nbytes = wfMsgExt( 'nbytes', array( 'parsemag', 'escape' ), $wgLang->formatNum( $size ) ); |
| 819 | + |
822 | 820 | $widthheight = wfMsgHtml( 'widthheight', $width, $height ); |
823 | 821 | $style = $this->skin->getInternalLinkAttributes( $url, $datetime ); |
824 | 822 | |
Index: branches/phase3_rev_deleted/includes/SpecialImagelist.php |
— | — | @@ -115,7 +115,9 @@ |
116 | 116 | case 'img_name': |
117 | 117 | $name = $this->mCurrentRow->img_name; |
118 | 118 | $link = $this->getSkin()->makeKnownLinkObj( Title::makeTitle( NS_IMAGE, $name ), $value ); |
119 | | - $download = Xml::element('a', array( "href" => Image::imageUrl( $name ) ), $this->mMessages['imgfile'] ); |
| 119 | + $image = wfLocalFile( $value ); |
| 120 | + $url = $image->getURL(); |
| 121 | + $download = Xml::element('a', array( "href" => $url ), $this->mMessages['imgfile'] ); |
120 | 122 | return "$link ($download)"; |
121 | 123 | case 'img_user_text': |
122 | 124 | if ( $this->mCurrentRow->img_user ) { |
Index: branches/phase3_rev_deleted/includes/SpecialBlockip.php |
— | — | @@ -61,7 +61,7 @@ |
62 | 62 | $this->BlockCreateAccount = $wgRequest->getBool( 'wpCreateAccount', $byDefault ); |
63 | 63 | $this->BlockEnableAutoblock = $wgRequest->getBool( 'wpEnableAutoblock', $byDefault ); |
64 | 64 | # Re-check user's rights to hide names, very serious, defaults to 0 |
65 | | - $this->BlockHideName = $wgRequest->getBool( 'wpHideName', 0 ) && $wgUser->isAllowed( 'hideuser' ); |
| 65 | + $this->BlockHideName = ( $wgRequest->getBool( 'wpHideName', 0 ) && $wgUser->isAllowed( 'hideuser' ) ) ? 1 : 0; |
66 | 66 | } |
67 | 67 | |
68 | 68 | function showForm( $err ) { |
— | — | @@ -196,7 +196,8 @@ |
197 | 197 | <td align=\"$alignRight\">{$mIpbreason}</td> |
198 | 198 | <td> |
199 | 199 | " . Xml::input( 'wpBlockReason', 45, $this->BlockReason, |
200 | | - array( 'tabindex' => '5', 'id' => 'mw-bi-reason' ) ) . " |
| 200 | + array( 'tabindex' => '5', 'id' => 'mw-bi-reason', |
| 201 | + 'maxlength'=> '200' ) ) . " |
201 | 202 | </td> |
202 | 203 | </tr> |
203 | 204 | <tr id='wpAnonOnlyRow'> |
Index: branches/phase3_rev_deleted/includes/DatabasePostgres.php |
— | — | @@ -561,7 +561,7 @@ |
562 | 562 | } |
563 | 563 | |
564 | 564 | function affectedRows() { |
565 | | - if( !isset( $this->mLastResult ) ) |
| 565 | + if( !isset( $this->mLastResult ) or ! $this->mLastResult ) |
566 | 566 | return 0; |
567 | 567 | |
568 | 568 | return pg_affected_rows( $this->mLastResult ); |
Index: branches/phase3_rev_deleted/includes/ChangesList.php |
— | — | @@ -593,7 +593,7 @@ |
594 | 594 | $chardiff = $rcObj->getCharacterDifference( $block[ count( $block ) - 1 ]->mAttribs['rc_old_len'], |
595 | 595 | $block[0]->mAttribs['rc_new_len'] ); |
596 | 596 | if( $chardiff == '' ) { |
597 | | - $r .= ' ('; |
| 597 | + $r .= ') '; |
598 | 598 | } else { |
599 | 599 | $r .= ' ' . $chardiff. ' . . '; |
600 | 600 | } |
Index: branches/phase3_rev_deleted/includes/SpecialWhatlinkshere.php |
— | — | @@ -230,6 +230,12 @@ |
231 | 231 | $wgOut->addHTML( ' (' . implode( ', ', $props ) . ') ' ); |
232 | 232 | } |
233 | 233 | |
| 234 | + //add whatlinkshere link |
| 235 | + $whatlink = $this->skin->makeKnownLinkObj( |
| 236 | + SpecialPage::getTitleFor( 'Whatlinkshere', $nt->getPrefixedDBkey() ), |
| 237 | + wfMsgHtml( 'whatlinkshere-links' ) ); |
| 238 | + $wgOut->addHTML(" ($whatlink)" ); |
| 239 | + |
234 | 240 | if ( $row->page_is_redirect ) { |
235 | 241 | if ( $level < 2 ) { |
236 | 242 | $this->showIndirectLinks( $level + 1, $nt, 500 ); |
Index: branches/phase3_rev_deleted/includes/Defines.php |
— | — | @@ -205,5 +205,61 @@ |
206 | 206 | define( 'LIST_NAMES', 3); |
207 | 207 | define( 'LIST_OR', 4); |
208 | 208 | |
| 209 | +/** |
| 210 | + * Unicode and normalisation related |
| 211 | + */ |
| 212 | +define( 'UNICODE_HANGUL_FIRST', 0xac00 ); |
| 213 | +define( 'UNICODE_HANGUL_LAST', 0xd7a3 ); |
209 | 214 | |
| 215 | +define( 'UNICODE_HANGUL_LBASE', 0x1100 ); |
| 216 | +define( 'UNICODE_HANGUL_VBASE', 0x1161 ); |
| 217 | +define( 'UNICODE_HANGUL_TBASE', 0x11a7 ); |
| 218 | + |
| 219 | +define( 'UNICODE_HANGUL_LCOUNT', 19 ); |
| 220 | +define( 'UNICODE_HANGUL_VCOUNT', 21 ); |
| 221 | +define( 'UNICODE_HANGUL_TCOUNT', 28 ); |
| 222 | +define( 'UNICODE_HANGUL_NCOUNT', UNICODE_HANGUL_VCOUNT * UNICODE_HANGUL_TCOUNT ); |
| 223 | + |
| 224 | +define( 'UNICODE_HANGUL_LEND', UNICODE_HANGUL_LBASE + UNICODE_HANGUL_LCOUNT - 1 ); |
| 225 | +define( 'UNICODE_HANGUL_VEND', UNICODE_HANGUL_VBASE + UNICODE_HANGUL_VCOUNT - 1 ); |
| 226 | +define( 'UNICODE_HANGUL_TEND', UNICODE_HANGUL_TBASE + UNICODE_HANGUL_TCOUNT - 1 ); |
| 227 | + |
| 228 | +define( 'UNICODE_SURROGATE_FIRST', 0xd800 ); |
| 229 | +define( 'UNICODE_SURROGATE_LAST', 0xdfff ); |
| 230 | +define( 'UNICODE_MAX', 0x10ffff ); |
| 231 | +define( 'UNICODE_REPLACEMENT', 0xfffd ); |
| 232 | + |
| 233 | + |
| 234 | +define( 'UTF8_HANGUL_FIRST', "\xea\xb0\x80" /*codepointToUtf8( UNICODE_HANGUL_FIRST )*/ ); |
| 235 | +define( 'UTF8_HANGUL_LAST', "\xed\x9e\xa3" /*codepointToUtf8( UNICODE_HANGUL_LAST )*/ ); |
| 236 | + |
| 237 | +define( 'UTF8_HANGUL_LBASE', "\xe1\x84\x80" /*codepointToUtf8( UNICODE_HANGUL_LBASE )*/ ); |
| 238 | +define( 'UTF8_HANGUL_VBASE', "\xe1\x85\xa1" /*codepointToUtf8( UNICODE_HANGUL_VBASE )*/ ); |
| 239 | +define( 'UTF8_HANGUL_TBASE', "\xe1\x86\xa7" /*codepointToUtf8( UNICODE_HANGUL_TBASE )*/ ); |
| 240 | + |
| 241 | +define( 'UTF8_HANGUL_LEND', "\xe1\x84\x92" /*codepointToUtf8( UNICODE_HANGUL_LEND )*/ ); |
| 242 | +define( 'UTF8_HANGUL_VEND', "\xe1\x85\xb5" /*codepointToUtf8( UNICODE_HANGUL_VEND )*/ ); |
| 243 | +define( 'UTF8_HANGUL_TEND', "\xe1\x87\x82" /*codepointToUtf8( UNICODE_HANGUL_TEND )*/ ); |
| 244 | + |
| 245 | +define( 'UTF8_SURROGATE_FIRST', "\xed\xa0\x80" /*codepointToUtf8( UNICODE_SURROGATE_FIRST )*/ ); |
| 246 | +define( 'UTF8_SURROGATE_LAST', "\xed\xbf\xbf" /*codepointToUtf8( UNICODE_SURROGATE_LAST )*/ ); |
| 247 | +define( 'UTF8_MAX', "\xf4\x8f\xbf\xbf" /*codepointToUtf8( UNICODE_MAX )*/ ); |
| 248 | +define( 'UTF8_REPLACEMENT', "\xef\xbf\xbd" /*codepointToUtf8( UNICODE_REPLACEMENT )*/ ); |
| 249 | +#define( 'UTF8_REPLACEMENT', '!' ); |
| 250 | + |
| 251 | +define( 'UTF8_OVERLONG_A', "\xc1\xbf" ); |
| 252 | +define( 'UTF8_OVERLONG_B', "\xe0\x9f\xbf" ); |
| 253 | +define( 'UTF8_OVERLONG_C', "\xf0\x8f\xbf\xbf" ); |
| 254 | + |
| 255 | +# These two ranges are illegal |
| 256 | +define( 'UTF8_FDD0', "\xef\xb7\x90" /*codepointToUtf8( 0xfdd0 )*/ ); |
| 257 | +define( 'UTF8_FDEF', "\xef\xb7\xaf" /*codepointToUtf8( 0xfdef )*/ ); |
| 258 | +define( 'UTF8_FFFE', "\xef\xbf\xbe" /*codepointToUtf8( 0xfffe )*/ ); |
| 259 | +define( 'UTF8_FFFF', "\xef\xbf\xbf" /*codepointToUtf8( 0xffff )*/ ); |
| 260 | + |
| 261 | +define( 'UTF8_HEAD', false ); |
| 262 | +define( 'UTF8_TAIL', true ); |
| 263 | + |
| 264 | + |
| 265 | + |
210 | 266 | ?> |
Index: branches/phase3_rev_deleted/includes/Article.php |
— | — | @@ -371,6 +371,10 @@ |
372 | 372 | } |
373 | 373 | } |
374 | 374 | |
| 375 | + // FIXME: Horrible, horrible! This content-loading interface just plain sucks. |
| 376 | + // We should instead work with the Revision object when we need it... |
| 377 | + $this->mContent = $revision->userCan( Revision::DELETED_TEXT ) ? $revision->getRawText() : ""; |
| 378 | + //$this->mContent = $revision->getText(); |
375 | 379 | $this->mContent = $revision->revText(); // Loads if user is allowed |
376 | 380 | |
377 | 381 | $this->mUser = $revision->getUser(); |
Index: branches/phase3_rev_deleted/includes/ExternalEdit.php |
— | — | @@ -46,7 +46,7 @@ |
47 | 47 | $extension="wiki"; |
48 | 48 | } elseif($this->mMode=="file") { |
49 | 49 | $type="Edit file"; |
50 | | - $image = new Image( $this->mTitle ); |
| 50 | + $image = wfLocalFile( $this->mTitle ); |
51 | 51 | $img_url = $image->getURL(); |
52 | 52 | if(strpos($img_url,"://")) { |
53 | 53 | $url = $img_url; |
Index: branches/phase3_rev_deleted/includes/GlobalFunctions.php |
— | — | @@ -592,7 +592,7 @@ |
593 | 593 | } elseif ( in_array('parseinline', $options) ) { |
594 | 594 | $string = $wgOut->parse( $string, true, true ); |
595 | 595 | $m = array(); |
596 | | - if( preg_match( "~^<p>(.*)\n?</p>$~", $string, $m ) ) { |
| 596 | + if( preg_match( '/^<p>(.*)\n?<\/p>$/sU', $string, $m ) ) { |
597 | 597 | $string = $m[1]; |
598 | 598 | } |
599 | 599 | } elseif ( in_array('parsemag', $options) ) { |
— | — | @@ -819,7 +819,7 @@ |
820 | 820 | if ( $po < 0 ) { $po = 0; } |
821 | 821 | $q = "limit={$limit}&offset={$po}"; |
822 | 822 | if ( '' != $query ) { $q .= '&'.$query; } |
823 | | - $plink = '<a href="' . $title->escapeLocalUrl( $q ) . "\">{$prev}</a>"; |
| 823 | + $plink = '<a href="' . $title->escapeLocalUrl( $q ) . "\" class=\"mw-prevlink\">{$prev}</a>"; |
824 | 824 | } else { $plink = $prev; } |
825 | 825 | |
826 | 826 | $no = $offset + $limit; |
— | — | @@ -829,7 +829,7 @@ |
830 | 830 | if ( $atend ) { |
831 | 831 | $nlink = $next; |
832 | 832 | } else { |
833 | | - $nlink = '<a href="' . $title->escapeLocalUrl( $q ) . "\">{$next}</a>"; |
| 833 | + $nlink = '<a href="' . $title->escapeLocalUrl( $q ) . "\" class=\"mw-nextlink\">{$next}</a>"; |
834 | 834 | } |
835 | 835 | $nums = wfNumLink( $offset, 20, $title, $query ) . ' | ' . |
836 | 836 | wfNumLink( $offset, 50, $title, $query ) . ' | ' . |
— | — | @@ -850,7 +850,7 @@ |
851 | 851 | $q .= 'limit='.$limit.'&offset='.$offset; |
852 | 852 | |
853 | 853 | $fmtLimit = $wgLang->formatNum( $limit ); |
854 | | - $s = '<a href="' . $title->escapeLocalUrl( $q ) . "\">{$fmtLimit}</a>"; |
| 854 | + $s = '<a href="' . $title->escapeLocalUrl( $q ) . "\" class=\"mw-numlink\">{$fmtLimit}</a>"; |
855 | 855 | return $s; |
856 | 856 | } |
857 | 857 | |
— | — | @@ -2272,4 +2272,26 @@ |
2273 | 2273 | $ret = $wgLoadBalancer->getConnection( $db, true, $groups ); |
2274 | 2274 | return $ret; |
2275 | 2275 | } |
| 2276 | + |
| 2277 | +/** |
| 2278 | + * Find a file. |
| 2279 | + * Shortcut for RepoGroup::singleton()->findFile() |
| 2280 | + * @param mixed $title Title object or string. May be interwiki. |
| 2281 | + * @param mixed $time Requested time for an archived image, or false for the |
| 2282 | + * current version. An image object will be returned which |
| 2283 | + * existed at or before the specified time. |
| 2284 | + * @return File, or false if the file does not exist |
| 2285 | + */ |
| 2286 | +function wfFindFile( $title, $time = false ) { |
| 2287 | + return RepoGroup::singleton()->findFile( $title, $time ); |
| 2288 | +} |
| 2289 | + |
| 2290 | +/** |
| 2291 | + * Get an object referring to a locally registered file. |
| 2292 | + * Returns a valid placeholder object if the file does not exist. |
| 2293 | + */ |
| 2294 | +function wfLocalFile( $title ) { |
| 2295 | + return RepoGroup::singleton()->getLocalRepo()->newFile( $title ); |
| 2296 | +} |
| 2297 | + |
2276 | 2298 | ?> |
Index: branches/phase3_rev_deleted/includes/SearchEngine.php |
— | — | @@ -122,8 +122,8 @@ |
123 | 123 | # There may have been a funny upload, or it may be on a shared |
124 | 124 | # file repository such as Wikimedia Commons. |
125 | 125 | if( $title->getNamespace() == NS_IMAGE ) { |
126 | | - $image = new Image( $title ); |
127 | | - if( $image->exists() ) { |
| 126 | + $image = wfFindFile( $title ); |
| 127 | + if( $image ) { |
128 | 128 | return $title; |
129 | 129 | } |
130 | 130 | } |
Index: branches/phase3_rev_deleted/includes/SpecialMIMEsearch.php |
— | — | @@ -66,7 +66,7 @@ |
67 | 67 | $text = $wgContLang->convert( $nt->getText() ); |
68 | 68 | $plink = $skin->makeLink( $nt->getPrefixedText(), $text ); |
69 | 69 | |
70 | | - $download = $skin->makeMediaLink( $nt->getText(), 'fuck me!', wfMsgHtml( 'download' ) ); |
| 70 | + $download = $skin->makeMediaLinkObj( $nt, wfMsgHtml( 'download' ) ); |
71 | 71 | $bytes = wfMsgExt( 'nbytes', array( 'parsemag', 'escape'), |
72 | 72 | $wgLang->formatNum( $result->img_size ) ); |
73 | 73 | $dimensions = wfMsgHtml( 'widthheight', $wgLang->formatNum( $result->img_width ), |
Index: branches/phase3_rev_deleted/includes/memcached-client.php |
— | — | @@ -152,7 +152,7 @@ |
153 | 153 | /** |
154 | 154 | * At how many bytes should we compress? |
155 | 155 | * |
156 | | - * @var interger |
| 156 | + * @var integer |
157 | 157 | * @access private |
158 | 158 | */ |
159 | 159 | var $_compress_threshold; |
— | — | @@ -192,7 +192,7 @@ |
193 | 193 | /** |
194 | 194 | * Total # of bit buckets we have |
195 | 195 | * |
196 | | - * @var interger |
| 196 | + * @var integer |
197 | 197 | * @access private |
198 | 198 | */ |
199 | 199 | var $_bucketcount; |
— | — | @@ -200,7 +200,7 @@ |
201 | 201 | /** |
202 | 202 | * # of total servers we have |
203 | 203 | * |
204 | | - * @var interger |
| 204 | + * @var integer |
205 | 205 | * @access private |
206 | 206 | */ |
207 | 207 | var $_active; |
— | — | @@ -272,9 +272,9 @@ |
273 | 273 | * Adds a key/value to the memcache server if one isn't already set with |
274 | 274 | * that key |
275 | 275 | * |
276 | | - * @param string $key Key to set with data |
277 | | - * @param mixed $val Value to store |
278 | | - * @param interger $exp (optional) Time to expire data at |
| 276 | + * @param string $key Key to set with data |
| 277 | + * @param mixed $val Value to store |
| 278 | + * @param integer $exp (optional) Time to expire data at |
279 | 279 | * |
280 | 280 | * @return boolean |
281 | 281 | * @access public |
— | — | @@ -291,7 +291,7 @@ |
292 | 292 | * Decriment a value stored on the memcache server |
293 | 293 | * |
294 | 294 | * @param string $key Key to decriment |
295 | | - * @param interger $amt (optional) Amount to decriment |
| 295 | + * @param integer $amt (optional) Amount to decriment |
296 | 296 | * |
297 | 297 | * @return mixed FALSE on failure, value on success |
298 | 298 | * @access public |
— | — | @@ -308,7 +308,7 @@ |
309 | 309 | * Deletes a key from the server, optionally after $time |
310 | 310 | * |
311 | 311 | * @param string $key Key to delete |
312 | | - * @param interger $time (optional) How long to wait before deleting |
| 312 | + * @param integer $time (optional) How long to wait before deleting |
313 | 313 | * |
314 | 314 | * @return boolean TRUE on success, FALSE on failure |
315 | 315 | * @access public |
— | — | @@ -506,9 +506,9 @@ |
507 | 507 | * Increments $key (optionally) by $amt |
508 | 508 | * |
509 | 509 | * @param string $key Key to increment |
510 | | - * @param interger $amt (optional) amount to increment |
| 510 | + * @param integer $amt (optional) amount to increment |
511 | 511 | * |
512 | | - * @return interger New key value? |
| 512 | + * @return integer New key value? |
513 | 513 | * @access public |
514 | 514 | */ |
515 | 515 | function incr ($key, $amt=1) |
— | — | @@ -524,7 +524,7 @@ |
525 | 525 | * |
526 | 526 | * @param string $key Key to set value as |
527 | 527 | * @param mixed $value Value to store |
528 | | - * @param interger $exp (optional) Experiation time |
| 528 | + * @param integer $exp (optional) Experiation time |
529 | 529 | * |
530 | 530 | * @return boolean |
531 | 531 | * @access public |
— | — | @@ -582,7 +582,7 @@ |
583 | 583 | * |
584 | 584 | * @param string $key Key to set value as |
585 | 585 | * @param mixed $value Value to set |
586 | | - * @param interger $exp (optional) Experiation time |
| 586 | + * @param integer $exp (optional) Experiation time |
587 | 587 | * |
588 | 588 | * @return boolean TRUE on success |
589 | 589 | * @access public |
— | — | @@ -598,7 +598,7 @@ |
599 | 599 | /** |
600 | 600 | * Sets the compression threshold |
601 | 601 | * |
602 | | - * @param interger $thresh Threshold to compress if larger than |
| 602 | + * @param integer $thresh Threshold to compress if larger than |
603 | 603 | * |
604 | 604 | * @access public |
605 | 605 | */ |
— | — | @@ -687,7 +687,7 @@ |
688 | 688 | /** |
689 | 689 | * Connects $sock to $host, timing out after $timeout |
690 | 690 | * |
691 | | - * @param interger $sock Socket to connect |
| 691 | + * @param integer $sock Socket to connect |
692 | 692 | * @param string $host Host:IP to connect to |
693 | 693 | * |
694 | 694 | * @return boolean |
— | — | @@ -807,11 +807,11 @@ |
808 | 808 | // {{{ _hashfunc() |
809 | 809 | |
810 | 810 | /** |
811 | | - * Creates a hash interger based on the $key |
| 811 | + * Creates a hash integer based on the $key |
812 | 812 | * |
813 | 813 | * @param string $key Key to hash |
814 | 814 | * |
815 | | - * @return interger Hash value |
| 815 | + * @return integer Hash value |
816 | 816 | * @access private |
817 | 817 | */ |
818 | 818 | function _hashfunc ($key) |
— | — | @@ -830,9 +830,9 @@ |
831 | 831 | * |
832 | 832 | * @param string $cmd Command to perform |
833 | 833 | * @param string $key Key to perform it on |
834 | | - * @param interger $amt Amount to adjust |
| 834 | + * @param integer $amt Amount to adjust |
835 | 835 | * |
836 | | - * @return interger New value of $key |
| 836 | + * @return integer New value of $key |
837 | 837 | * @access private |
838 | 838 | */ |
839 | 839 | function _incrdecr ($cmd, $key, $amt=1) |
— | — | @@ -929,7 +929,7 @@ |
930 | 930 | * @param string $cmd Command to perform |
931 | 931 | * @param string $key Key to act on |
932 | 932 | * @param mixed $val What we need to store |
933 | | - * @param interger $exp When it should expire |
| 933 | + * @param integer $exp When it should expire |
934 | 934 | * |
935 | 935 | * @return boolean |
936 | 936 | * @access private |
Index: branches/phase3_rev_deleted/includes/SpecialImport.php |
— | — | @@ -328,12 +328,9 @@ |
329 | 329 | } else { |
330 | 330 | $created = false; |
331 | 331 | |
332 | | - $result = $dbw->select( 'revision', |
333 | | - array('MIN(rev_timestamp) as created', 'MAX(rev_timestamp) as latest'), |
334 | | - array( 'rev_page' => $pageId ), __METHOD__ ); |
335 | | - $row = $dbw->fetchObject($result); |
336 | | - // Don't make fucked up alternating page histories |
337 | | - if( $row && $row->latest > $this->timestamp && $row->created < $this->timestamp ) { |
| 332 | + $prior = Revision::loadFromTimestamp( $dbw, $this->title, $this->timestamp ); |
| 333 | + if( !is_null( $prior ) ) { |
| 334 | + // FIXME: this could fail slightly for multiple matches :P |
338 | 335 | wfDebug( __METHOD__ . ": skipping existing revision for [[" . |
339 | 336 | $this->title->getPrefixedText() . "]], timestamp " . |
340 | 337 | $this->timestamp . "\n" ); |
— | — | @@ -860,13 +857,13 @@ |
861 | 858 | } |
862 | 859 | } |
863 | 860 | |
864 | | - function newFromURL( $url ) { |
| 861 | + function newFromURL( $url, $method = 'GET' ) { |
865 | 862 | wfDebug( __METHOD__ . ": opening $url\n" ); |
866 | 863 | # Use the standard HTTP fetch function; it times out |
867 | 864 | # quicker and sorts out user-agent problems which might |
868 | 865 | # otherwise prevent importing from large sites, such |
869 | 866 | # as the Wikimedia cluster, etc. |
870 | | - $data = Http::get( $url ); |
| 867 | + $data = Http::request( $method, $url ); |
871 | 868 | if( $data !== false ) { |
872 | 869 | $file = tmpfile(); |
873 | 870 | fwrite( $file, $data ); |
— | — | @@ -885,7 +882,8 @@ |
886 | 883 | } else { |
887 | 884 | $params = $history ? 'history=1' : ''; |
888 | 885 | $url = $link->getFullUrl( $params ); |
889 | | - return ImportStreamSource::newFromURL( $url ); |
| 886 | + # For interwikis, use POST to avoid redirects. |
| 887 | + return ImportStreamSource::newFromURL( $url, "POST" ); |
890 | 888 | } |
891 | 889 | } |
892 | 890 | } |
Index: branches/phase3_rev_deleted/includes/SpecialPage.php |
— | — | @@ -275,6 +275,30 @@ |
276 | 276 | } |
277 | 277 | |
278 | 278 | /** |
| 279 | + * Check if a given name exist as a special page or as a special page alias |
| 280 | + * @param $name string: name of a special page |
| 281 | + * @return boolean: true if a special page exists with this name |
| 282 | + */ |
| 283 | + static function exists( $name ) { |
| 284 | + global $wgContLang; |
| 285 | + if ( !self::$mListInitialised ) { |
| 286 | + self::initList(); |
| 287 | + } |
| 288 | + if( !self::$mAliases ) { |
| 289 | + self::initAliasList(); |
| 290 | + } |
| 291 | + |
| 292 | + # Remove special pages inline parameters: |
| 293 | + $bits = explode( '/', $name ); |
| 294 | + $name = $wgContLang->caseFold($bits[0]); |
| 295 | + |
| 296 | + return |
| 297 | + array_key_exists( $name, self::$mList ) |
| 298 | + or array_key_exists( $name, self::$mAliases ) |
| 299 | + ; |
| 300 | + } |
| 301 | + |
| 302 | + /** |
279 | 303 | * Find the object with a given name and return it (or NULL) |
280 | 304 | * @static |
281 | 305 | * @param string $name |
— | — | @@ -423,7 +447,7 @@ |
424 | 448 | wfProfileOut( __METHOD__ ); |
425 | 449 | return false; |
426 | 450 | } elseif ( !$including ) { |
427 | | - $wgTitle = $page->getTitle( $par ); |
| 451 | + $wgTitle = $page->getTitle(); |
428 | 452 | } |
429 | 453 | $page->including( $including ); |
430 | 454 | |
Index: branches/phase3_rev_deleted/languages/messages/MessagesEn.php |
— | — | @@ -282,6 +282,8 @@ |
283 | 283 | 'img_center' => array( 1, 'center', 'centre' ), |
284 | 284 | 'img_framed' => array( 1, 'framed', 'enframed', 'frame' ), |
285 | 285 | 'img_page' => array( 1, 'page=$1', 'page $1' ), |
| 286 | + 'img_upright' => array( 1, 'upright', 'upright=$1', 'upright $1' ), |
| 287 | + 'img_border' => array( 1, 'border' ), |
286 | 288 | 'img_baseline' => array( 1, 'baseline' ), |
287 | 289 | 'img_sub' => array( 1, 'sub' ), |
288 | 290 | 'img_super' => array( 1, 'super', 'sup' ), |
— | — | @@ -765,7 +767,9 @@ |
766 | 768 | 'unexpected' => 'Unexpected value: "$1"="$2".', |
767 | 769 | 'formerror' => 'Error: could not submit form', |
768 | 770 | 'badarticleerror' => 'This action cannot be performed on this page.', |
769 | | -'cannotdelete' => 'Could not delete the page or file specified. (It may have already been deleted by someone else.)', |
| 771 | +'cannotdelete' => 'Could not delete the page or file specified. It may have already been deleted by someone else.<br/> |
| 772 | +Pages will not be deleted if it will result in an alternating archive history between these and any archived |
| 773 | +revisions for this page. If such is the case, please move this page to another location and delete it there.', |
770 | 774 | 'badtitle' => 'Bad title', |
771 | 775 | 'badtitletext' => 'The requested page title was invalid, empty, or an incorrectly linked inter-language or inter-wiki title. It may contain one or more characters which cannot be used in titles.', |
772 | 776 | 'perfdisabled' => 'Sorry! This feature has been temporarily disabled because it slows the database down to the point that no one can use the wiki.', |
— | — | @@ -1150,10 +1154,8 @@ |
1151 | 1155 | the search function at [[Special:Undelete]]. |
1152 | 1156 | |
1153 | 1157 | Blocked users listed here can cannot edit their talk pages and thus can only communicate via email. Their accounts |
1154 | | -will remain hidden only as long as they are blocked. |
| 1158 | +will remain hidden only as long as they are blocked.', |
1155 | 1159 | |
1156 | | -Content listed here should never be released to the general public unless it was hidden by mistake.', |
1157 | | - |
1158 | 1160 | # Diffs |
1159 | 1161 | # |
1160 | 1162 | 'difference' => '(Difference between revisions)', |
— | — | @@ -1767,7 +1769,9 @@ |
1768 | 1770 | 'enotif_subject' => '{{SITENAME}} page $PAGETITLE has been $CHANGEDORCREATED by $PAGEEDITOR', |
1769 | 1771 | 'enotif_lastvisited' => 'See $1 for all changes since your last visit.', |
1770 | 1772 | 'enotif_lastdiff' => 'See $1 to view this change.', |
| 1773 | +'enotif_anon_editor' => 'anonymous user $1', |
1771 | 1774 | 'enotif_body' => 'Dear $WATCHINGUSERNAME, |
| 1775 | + |
1772 | 1776 | |
1773 | 1777 | The {{SITENAME}} page $PAGETITLE has been $CHANGEDORCREATED on $PAGEEDITDATE by $PAGEEDITOR, see $PAGETITLE_URL for the current version. |
1774 | 1778 | |
— | — | @@ -2928,6 +2932,11 @@ |
2929 | 2933 | 'livepreview-failed' => "Live preview failed!\nTry normal preview.", |
2930 | 2934 | 'livepreview-error' => "Failed to connect: $1 \"$2\"\nTry normal preview.", |
2931 | 2935 | |
| 2936 | +# Friendlier slave lag warnings |
| 2937 | +'lag-warn-normal' => 'Changes newer than $1 seconds may not be shown in this list.', |
| 2938 | +'lag-warn-high' => 'Due to high database server lag, changes newer than $1 seconds |
| 2939 | +may not be shown in this list.', |
| 2940 | + |
2932 | 2941 | ); |
2933 | 2942 | |
2934 | 2943 | ?> |