SvgHandler::getThumbType()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 3
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * Handler for SVG images.
4
 *
5
 * This program is free software; you can redistribute it and/or modify
6
 * it under the terms of the GNU General Public License as published by
7
 * the Free Software Foundation; either version 2 of the License, or
8
 * (at your option) any later version.
9
 *
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License along
16
 * with this program; if not, write to the Free Software Foundation, Inc.,
17
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18
 * http://www.gnu.org/copyleft/gpl.html
19
 *
20
 * @file
21
 * @ingroup Media
22
 */
23
use Wikimedia\ScopedCallback;
0 ignored issues
show
Bug introduced by
This use statement conflicts with another class in this namespace, ScopedCallback.

Let’s assume that you have a directory layout like this:

.
|-- OtherDir
|   |-- Bar.php
|   `-- Foo.php
`-- SomeDir
    `-- Foo.php

and let’s assume the following content of Bar.php:

// Bar.php
namespace OtherDir;

use SomeDir\Foo; // This now conflicts the class OtherDir\Foo

If both files OtherDir/Foo.php and SomeDir/Foo.php are loaded in the same runtime, you will see a PHP error such as the following:

PHP Fatal error:  Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php

However, as OtherDir/Foo.php does not necessarily have to be loaded and the error is only triggered if it is loaded before OtherDir/Bar.php, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias:

// Bar.php
namespace OtherDir;

use SomeDir\Foo as SomeDirFoo; // There is no conflict anymore.
Loading history...
24
25
/**
26
 * Handler for SVG images.
27
 *
28
 * @ingroup Media
29
 */
30
class SvgHandler extends ImageHandler {
31
	const SVG_METADATA_VERSION = 2;
32
33
	/** @var array A list of metadata tags that can be converted
34
	 *  to the commonly used exif tags. This allows messages
35
	 *  to be reused, and consistent tag names for {{#formatmetadata:..}}
36
	 */
37
	private static $metaConversion = [
38
		'originalwidth' => 'ImageWidth',
39
		'originalheight' => 'ImageLength',
40
		'description' => 'ImageDescription',
41
		'title' => 'ObjectName',
42
	];
43
44
	function isEnabled() {
45
		global $wgSVGConverters, $wgSVGConverter;
46
		if ( !isset( $wgSVGConverters[$wgSVGConverter] ) ) {
47
			wfDebug( "\$wgSVGConverter is invalid, disabling SVG rendering.\n" );
48
49
			return false;
50
		} else {
51
			return true;
52
		}
53
	}
54
55
	public function mustRender( $file ) {
56
		return true;
57
	}
58
59
	function isVectorized( $file ) {
60
		return true;
61
	}
62
63
	/**
64
	 * @param File $file
65
	 * @return bool
66
	 */
67
	function isAnimatedImage( $file ) {
68
		# @todo Detect animated SVGs
69
		$metadata = $file->getMetadata();
70
		if ( $metadata ) {
71
			$metadata = $this->unpackMetadata( $metadata );
72
			if ( isset( $metadata['animated'] ) ) {
73
				return $metadata['animated'];
74
			}
75
		}
76
77
		return false;
78
	}
79
80
	/**
81
	 * Which languages (systemLanguage attribute) is supported.
82
	 *
83
	 * @note This list is not guaranteed to be exhaustive.
84
	 * To avoid OOM errors, we only look at first bit of a file.
85
	 * Thus all languages on this list are present in the file,
86
	 * but its possible for the file to have a language not on
87
	 * this list.
88
	 *
89
	 * @param File $file
90
	 * @return array Array of language codes, or empty if no language switching supported.
91
	 */
92
	public function getAvailableLanguages( File $file ) {
93
		$metadata = $file->getMetadata();
94
		$langList = [];
95
		if ( $metadata ) {
96
			$metadata = $this->unpackMetadata( $metadata );
97
			if ( isset( $metadata['translations'] ) ) {
98
				foreach ( $metadata['translations'] as $lang => $langType ) {
99
					if ( $langType === SVGReader::LANG_FULL_MATCH ) {
100
						$langList[] = $lang;
101
					}
102
				}
103
			}
104
		}
105
		return $langList;
106
	}
107
108
	/**
109
	 * What language to render file in if none selected.
110
	 *
111
	 * @param File $file
112
	 * @return string Language code.
113
	 */
114
	public function getDefaultRenderLanguage( File $file ) {
115
		return 'en';
116
	}
117
118
	/**
119
	 * We do not support making animated svg thumbnails
120
	 * @param File $file
121
	 * @return bool
122
	 */
123
	function canAnimateThumbnail( $file ) {
124
		return false;
125
	}
126
127
	/**
128
	 * @param File $image
129
	 * @param array $params
130
	 * @return bool
131
	 */
132
	function normaliseParams( $image, &$params ) {
133
		global $wgSVGMaxSize;
134
		if ( !parent::normaliseParams( $image, $params ) ) {
135
			return false;
136
		}
137
		# Don't make an image bigger than wgMaxSVGSize on the smaller side
138
		if ( $params['physicalWidth'] <= $params['physicalHeight'] ) {
139 View Code Duplication
			if ( $params['physicalWidth'] > $wgSVGMaxSize ) {
140
				$srcWidth = $image->getWidth( $params['page'] );
141
				$srcHeight = $image->getHeight( $params['page'] );
142
				$params['physicalWidth'] = $wgSVGMaxSize;
143
				$params['physicalHeight'] = File::scaleHeight( $srcWidth, $srcHeight, $wgSVGMaxSize );
0 ignored issues
show
Bug introduced by
It seems like $srcWidth defined by $image->getWidth($params['page']) on line 140 can also be of type boolean; however, File::scaleHeight() does only seem to accept integer, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
Bug introduced by
It seems like $srcHeight defined by $image->getHeight($params['page']) on line 141 can also be of type boolean; however, File::scaleHeight() does only seem to accept integer, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
144
			}
145 View Code Duplication
		} else {
146
			if ( $params['physicalHeight'] > $wgSVGMaxSize ) {
147
				$srcWidth = $image->getWidth( $params['page'] );
148
				$srcHeight = $image->getHeight( $params['page'] );
149
				$params['physicalWidth'] = File::scaleHeight( $srcHeight, $srcWidth, $wgSVGMaxSize );
0 ignored issues
show
Bug introduced by
It seems like $srcHeight defined by $image->getHeight($params['page']) on line 148 can also be of type boolean; however, File::scaleHeight() does only seem to accept integer, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
Bug introduced by
It seems like $srcWidth defined by $image->getWidth($params['page']) on line 147 can also be of type boolean; however, File::scaleHeight() does only seem to accept integer, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
150
				$params['physicalHeight'] = $wgSVGMaxSize;
151
			}
152
		}
153
154
		return true;
155
	}
156
157
	/**
158
	 * @param File $image
159
	 * @param string $dstPath
160
	 * @param string $dstUrl
161
	 * @param array $params
162
	 * @param int $flags
163
	 * @return bool|MediaTransformError|ThumbnailImage|TransformParameterError
164
	 */
165
	function doTransform( $image, $dstPath, $dstUrl, $params, $flags = 0 ) {
166
		if ( !$this->normaliseParams( $image, $params ) ) {
167
			return new TransformParameterError( $params );
168
		}
169
		$clientWidth = $params['width'];
170
		$clientHeight = $params['height'];
171
		$physicalWidth = $params['physicalWidth'];
172
		$physicalHeight = $params['physicalHeight'];
173
		$lang = isset( $params['lang'] ) ? $params['lang'] : $this->getDefaultRenderLanguage( $image );
174
175
		if ( $flags & self::TRANSFORM_LATER ) {
176
			return new ThumbnailImage( $image, $dstUrl, $dstPath, $params );
177
		}
178
179
		$metadata = $this->unpackMetadata( $image->getMetadata() );
180
		if ( isset( $metadata['error'] ) ) { // sanity check
181
			$err = wfMessage( 'svg-long-error', $metadata['error']['message'] )->text();
182
183
			return new MediaTransformError( 'thumbnail_error', $clientWidth, $clientHeight, $err );
184
		}
185
186 View Code Duplication
		if ( !wfMkdirParents( dirname( $dstPath ), null, __METHOD__ ) ) {
187
			return new MediaTransformError( 'thumbnail_error', $clientWidth, $clientHeight,
188
				wfMessage( 'thumbnail_dest_directory' )->text() );
189
		}
190
191
		$srcPath = $image->getLocalRefPath();
192 View Code Duplication
		if ( $srcPath === false ) { // Failed to get local copy
193
			wfDebugLog( 'thumbnail',
194
				sprintf( 'Thumbnail failed on %s: could not get local copy of "%s"',
195
					wfHostname(), $image->getName() ) );
196
197
			return new MediaTransformError( 'thumbnail_error',
198
				$params['width'], $params['height'],
199
				wfMessage( 'filemissing' )->text()
200
			);
201
		}
202
203
		// Make a temp dir with a symlink to the local copy in it.
204
		// This plays well with rsvg-convert policy for external entities.
205
		// https://git.gnome.org/browse/librsvg/commit/?id=f01aded72c38f0e18bc7ff67dee800e380251c8e
206
		$tmpDir = wfTempDir() . '/svg_' . wfRandomString( 24 );
207
		$lnPath = "$tmpDir/" . basename( $srcPath );
208
		$ok = mkdir( $tmpDir, 0771 ) && symlink( $srcPath, $lnPath );
209
		/** @noinspection PhpUnusedLocalVariableInspection */
210
		$cleaner = new ScopedCallback( function () use ( $tmpDir, $lnPath ) {
0 ignored issues
show
Unused Code introduced by
$cleaner is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
211
			MediaWiki\suppressWarnings();
212
			unlink( $lnPath );
213
			rmdir( $tmpDir );
214
			MediaWiki\restoreWarnings();
215
		} );
216 View Code Duplication
		if ( !$ok ) {
217
			wfDebugLog( 'thumbnail',
218
				sprintf( 'Thumbnail failed on %s: could not link %s to %s',
219
					wfHostname(), $lnPath, $srcPath ) );
220
			return new MediaTransformError( 'thumbnail_error',
221
				$params['width'], $params['height'],
222
				wfMessage( 'thumbnail-temp-create' )->text()
223
			);
224
		}
225
226
		$status = $this->rasterize( $lnPath, $dstPath, $physicalWidth, $physicalHeight, $lang );
227
		if ( $status === true ) {
228
			return new ThumbnailImage( $image, $dstUrl, $dstPath, $params );
229
		} else {
230
			return $status; // MediaTransformError
231
		}
232
	}
233
234
	/**
235
	 * Transform an SVG file to PNG
236
	 * This function can be called outside of thumbnail contexts
237
	 * @param string $srcPath
238
	 * @param string $dstPath
239
	 * @param string $width
240
	 * @param string $height
241
	 * @param bool|string $lang Language code of the language to render the SVG in
242
	 * @throws MWException
243
	 * @return bool|MediaTransformError
244
	 */
245
	public function rasterize( $srcPath, $dstPath, $width, $height, $lang = false ) {
246
		global $wgSVGConverters, $wgSVGConverter, $wgSVGConverterPath;
247
		$err = false;
248
		$retval = '';
249
		if ( isset( $wgSVGConverters[$wgSVGConverter] ) ) {
250
			if ( is_array( $wgSVGConverters[$wgSVGConverter] ) ) {
251
				// This is a PHP callable
252
				$func = $wgSVGConverters[$wgSVGConverter][0];
253
				$args = array_merge( [ $srcPath, $dstPath, $width, $height, $lang ],
254
					array_slice( $wgSVGConverters[$wgSVGConverter], 1 ) );
255
				if ( !is_callable( $func ) ) {
256
					throw new MWException( "$func is not callable" );
257
				}
258
				$err = call_user_func_array( $func, $args );
259
				$retval = (bool)$err;
260
			} else {
261
				// External command
262
				$cmd = str_replace(
263
					[ '$path/', '$width', '$height', '$input', '$output' ],
264
					[ $wgSVGConverterPath ? wfEscapeShellArg( "$wgSVGConverterPath/" ) : "",
265
						intval( $width ),
266
						intval( $height ),
267
						wfEscapeShellArg( $srcPath ),
268
						wfEscapeShellArg( $dstPath ) ],
269
					$wgSVGConverters[$wgSVGConverter]
270
				);
271
272
				$env = [];
273
				if ( $lang !== false ) {
274
					$env['LANG'] = $lang;
275
				}
276
277
				wfDebug( __METHOD__ . ": $cmd\n" );
278
				$err = wfShellExecWithStderr( $cmd, $retval, $env );
279
			}
280
		}
281
		$removed = $this->removeBadFile( $dstPath, $retval );
282
		if ( $retval != 0 || $removed ) {
283
			$this->logErrorForExternalProcess( $retval, $err, $cmd );
0 ignored issues
show
Bug introduced by
The variable $cmd does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
284
			return new MediaTransformError( 'thumbnail_error', $width, $height, $err );
285
		}
286
287
		return true;
288
	}
289
290
	public static function rasterizeImagickExt( $srcPath, $dstPath, $width, $height ) {
291
		$im = new Imagick( $srcPath );
292
		$im->setImageFormat( 'png' );
293
		$im->setBackgroundColor( 'transparent' );
294
		$im->setImageDepth( 8 );
295
296
		if ( !$im->thumbnailImage( intval( $width ), intval( $height ), /* fit */ false ) ) {
297
			return 'Could not resize image';
298
		}
299
		if ( !$im->writeImage( $dstPath ) ) {
300
			return "Could not write to $dstPath";
301
		}
302
	}
303
304
	/**
305
	 * @param File|FSFile $file
306
	 * @param string $path Unused
307
	 * @param bool|array $metadata
308
	 * @return array
309
	 */
310
	function getImageSize( $file, $path, $metadata = false ) {
311
		if ( $metadata === false && $file instanceof File ) {
312
			$metadata = $file->getMetadata();
313
		}
314
		$metadata = $this->unpackMetadata( $metadata );
315
316
		if ( isset( $metadata['width'] ) && isset( $metadata['height'] ) ) {
317
			return [ $metadata['width'], $metadata['height'], 'SVG',
318
				"width=\"{$metadata['width']}\" height=\"{$metadata['height']}\"" ];
319
		} else { // error
320
			return [ 0, 0, 'SVG', "width=\"0\" height=\"0\"" ];
321
		}
322
	}
323
324
	function getThumbType( $ext, $mime, $params = null ) {
325
		return [ 'png', 'image/png' ];
326
	}
327
328
	/**
329
	 * Subtitle for the image. Different from the base
330
	 * class so it can be denoted that SVG's have
331
	 * a "nominal" resolution, and not a fixed one,
332
	 * as well as so animation can be denoted.
333
	 *
334
	 * @param File $file
335
	 * @return string
336
	 */
337
	function getLongDesc( $file ) {
338
		global $wgLang;
339
340
		$metadata = $this->unpackMetadata( $file->getMetadata() );
341
		if ( isset( $metadata['error'] ) ) {
342
			return wfMessage( 'svg-long-error', $metadata['error']['message'] )->text();
343
		}
344
345
		$size = $wgLang->formatSize( $file->getSize() );
346
347
		if ( $this->isAnimatedImage( $file ) ) {
348
			$msg = wfMessage( 'svg-long-desc-animated' );
349
		} else {
350
			$msg = wfMessage( 'svg-long-desc' );
351
		}
352
353
		$msg->numParams( $file->getWidth(), $file->getHeight() )->params( $size );
354
355
		return $msg->parse();
356
	}
357
358
	/**
359
	 * @param File|FSFile $file
360
	 * @param string $filename
361
	 * @return string Serialised metadata
362
	 */
363
	function getMetadata( $file, $filename ) {
364
		$metadata = [ 'version' => self::SVG_METADATA_VERSION ];
365
		try {
366
			$metadata += SVGMetadataExtractor::getMetadata( $filename );
367
		} catch ( Exception $e ) { // @todo SVG specific exceptions
368
			// File not found, broken, etc.
369
			$metadata['error'] = [
370
				'message' => $e->getMessage(),
371
				'code' => $e->getCode()
372
			];
373
			wfDebug( __METHOD__ . ': ' . $e->getMessage() . "\n" );
374
		}
375
376
		return serialize( $metadata );
377
	}
378
379 View Code Duplication
	function unpackMetadata( $metadata ) {
380
		MediaWiki\suppressWarnings();
381
		$unser = unserialize( $metadata );
382
		MediaWiki\restoreWarnings();
383
		if ( isset( $unser['version'] ) && $unser['version'] == self::SVG_METADATA_VERSION ) {
384
			return $unser;
385
		} else {
386
			return false;
387
		}
388
	}
389
390
	function getMetadataType( $image ) {
391
		return 'parsed-svg';
392
	}
393
394
	function isMetadataValid( $image, $metadata ) {
395
		$meta = $this->unpackMetadata( $metadata );
396
		if ( $meta === false ) {
397
			return self::METADATA_BAD;
398
		}
399
		if ( !isset( $meta['originalWidth'] ) ) {
400
			// Old but compatible
401
			return self::METADATA_COMPATIBLE;
402
		}
403
404
		return self::METADATA_GOOD;
405
	}
406
407
	protected function visibleMetadataFields() {
408
		$fields = [ 'objectname', 'imagedescription' ];
409
410
		return $fields;
411
	}
412
413
	/**
414
	 * @param File $file
415
	 * @param bool|IContextSource $context Context to use (optional)
416
	 * @return array|bool
417
	 */
418
	function formatMetadata( $file, $context = false ) {
419
		$result = [
420
			'visible' => [],
421
			'collapsed' => []
422
		];
423
		$metadata = $file->getMetadata();
424
		if ( !$metadata ) {
425
			return false;
426
		}
427
		$metadata = $this->unpackMetadata( $metadata );
428
		if ( !$metadata || isset( $metadata['error'] ) ) {
429
			return false;
430
		}
431
432
		/* @todo Add a formatter
433
		$format = new FormatSVG( $metadata );
434
		$formatted = $format->getFormattedData();
435
		*/
436
437
		// Sort fields into visible and collapsed
438
		$visibleFields = $this->visibleMetadataFields();
439
440
		$showMeta = false;
441
		foreach ( $metadata as $name => $value ) {
442
			$tag = strtolower( $name );
443
			if ( isset( self::$metaConversion[$tag] ) ) {
444
				$tag = strtolower( self::$metaConversion[$tag] );
445
			} else {
446
				// Do not output other metadata not in list
447
				continue;
448
			}
449
			$showMeta = true;
450
			self::addMeta( $result,
451
				in_array( $tag, $visibleFields ) ? 'visible' : 'collapsed',
452
				'exif',
453
				$tag,
454
				$value
455
			);
456
		}
457
458
		return $showMeta ? $result : false;
459
	}
460
461
	/**
462
	 * @param string $name Parameter name
463
	 * @param mixed $value Parameter value
464
	 * @return bool Validity
465
	 */
466
	public function validateParam( $name, $value ) {
467
		if ( in_array( $name, [ 'width', 'height' ] ) ) {
468
			// Reject negative heights, widths
469
			return ( $value > 0 );
470
		} elseif ( $name == 'lang' ) {
471
			// Validate $code
472
			if ( $value === '' || !Language::isValidBuiltInCode( $value ) ) {
473
				wfDebug( "Invalid user language code\n" );
474
475
				return false;
476
			}
477
478
			return true;
479
		}
480
481
		// Only lang, width and height are acceptable keys
482
		return false;
483
	}
484
485
	/**
486
	 * @param array $params Name=>value pairs of parameters
487
	 * @return string Filename to use
488
	 */
489
	public function makeParamString( $params ) {
490
		$lang = '';
491
		if ( isset( $params['lang'] ) && $params['lang'] !== 'en' ) {
492
			$params['lang'] = strtolower( $params['lang'] );
493
			$lang = "lang{$params['lang']}-";
494
		}
495
		if ( !isset( $params['width'] ) ) {
496
			return false;
497
		}
498
499
		return "$lang{$params['width']}px";
500
	}
501
502
	public function parseParamString( $str ) {
503
		$m = false;
504
		if ( preg_match( '/^lang([a-z]+(?:-[a-z]+)*)-(\d+)px$/', $str, $m ) ) {
505
			return [ 'width' => array_pop( $m ), 'lang' => $m[1] ];
506
		} elseif ( preg_match( '/^(\d+)px$/', $str, $m ) ) {
507
			return [ 'width' => $m[1], 'lang' => 'en' ];
508
		} else {
509
			return false;
510
		}
511
	}
512
513
	public function getParamMap() {
514
		return [ 'img_lang' => 'lang', 'img_width' => 'width' ];
515
	}
516
517
	/**
518
	 * @param array $params
519
	 * @return array
520
	 */
521
	function getScriptParams( $params ) {
522
		$scriptParams = [ 'width' => $params['width'] ];
523
		if ( isset( $params['lang'] ) ) {
524
			$scriptParams['lang'] = $params['lang'];
525
		}
526
527
		return $scriptParams;
528
	}
529
530
	public function getCommonMetaArray( File $file ) {
531
		$metadata = $file->getMetadata();
532
		if ( !$metadata ) {
533
			return [];
534
		}
535
		$metadata = $this->unpackMetadata( $metadata );
536
		if ( !$metadata || isset( $metadata['error'] ) ) {
537
			return [];
538
		}
539
		$stdMetadata = [];
540
		foreach ( $metadata as $name => $value ) {
541
			$tag = strtolower( $name );
542
			if ( $tag === 'originalwidth' || $tag === 'originalheight' ) {
543
				// Skip these. In the exif metadata stuff, it is assumed these
544
				// are measured in px, which is not the case here.
545
				continue;
546
			}
547
			if ( isset( self::$metaConversion[$tag] ) ) {
548
				$tag = self::$metaConversion[$tag];
549
				$stdMetadata[$tag] = $value;
550
			}
551
		}
552
553
		return $stdMetadata;
554
	}
555
}
556