26use Wikimedia\ScopedCallback;
41 'originalwidth' =>
'ImageWidth',
42 'originalheight' =>
'ImageLength',
43 'description' =>
'ImageDescription',
44 'title' =>
'ObjectName',
50 wfDebug(
"\$wgSVGConverter is invalid, disabling SVG rendering." );
71 # @todo Detect animated SVGs
72 $metadata =
$file->getMetadata();
75 if ( isset( $metadata[
'animated'] ) ) {
76 return $metadata[
'animated'];
96 $metadata =
$file->getMetadata();
100 if ( isset( $metadata[
'translations'] ) ) {
101 foreach ( $metadata[
'translations'] as
$lang => $langType ) {
103 $langList[] = strtolower(
$lang );
108 return array_unique( $langList );
127 foreach ( $svgLanguages as $svgLang ) {
128 if ( strcasecmp( $svgLang, $userPreferredLanguage ) === 0 ) {
131 $trimmedSvgLang = $svgLang;
132 while ( strpos( $trimmedSvgLang,
'-' ) !==
false ) {
133 $trimmedSvgLang = substr( $trimmedSvgLang, 0, strrpos( $trimmedSvgLang,
'-' ) );
134 if ( strcasecmp( $trimmedSvgLang, $userPreferredLanguage ) === 0 ) {
149 return $params[
'lang'] ?? $params[
'targetlang'] ??
'en';
177 if ( parent::normaliseParams( $image, $params ) ) {
197 # Don't make an image bigger than wgMaxSVGSize on the smaller side
198 if ( $params[
'physicalWidth'] <= $params[
'physicalHeight'] ) {
200 $srcWidth = $image->getWidth( $params[
'page'] );
201 $srcHeight = $image->getHeight( $params[
'page'] );
203 $params[
'physicalHeight'] = File::scaleHeight( $srcWidth, $srcHeight,
$wgSVGMaxSize );
206 $srcWidth = $image->getWidth( $params[
'page'] );
207 $srcHeight = $image->getHeight( $params[
'page'] );
208 $params[
'physicalWidth'] = File::scaleHeight( $srcHeight, $srcWidth,
$wgSVGMaxSize );
213 if ( isset( $params[
'targetlang'] ) && !$image->getMatchedLanguage( $params[
'targetlang'] ) ) {
214 unset( $params[
'targetlang'] );
228 public function doTransform( $image, $dstPath, $dstUrl, $params, $flags = 0 ) {
232 $clientWidth = $params[
'width'];
233 $clientHeight = $params[
'height'];
234 $physicalWidth = $params[
'physicalWidth'];
235 $physicalHeight = $params[
'physicalHeight'];
238 if ( $flags & self::TRANSFORM_LATER ) {
243 if ( isset( $metadata[
'error'] ) ) {
244 $err =
wfMessage(
'svg-long-error', $metadata[
'error'][
'message'] );
251 wfMessage(
'thumbnail_dest_directory' ) );
254 $srcPath = $image->getLocalRefPath();
255 if ( $srcPath ===
false ) {
257 sprintf(
'Thumbnail failed on %s: could not get local copy of "%s"',
261 $params[
'width'], $params[
'height'],
270 $lnPath =
"$tmpDir/" . basename( $srcPath );
271 $ok = mkdir( $tmpDir, 0771 );
274 sprintf(
'Thumbnail failed on %s: could not create temporary directory %s',
277 $params[
'width'], $params[
'height'],
278 wfMessage(
'thumbnail-temp-create' )->text()
281 $ok = symlink( $srcPath, $lnPath );
283 $cleaner =
new ScopedCallback(
function () use ( $tmpDir, $lnPath ) {
284 Wikimedia\suppressWarnings();
287 Wikimedia\restoreWarnings();
291 sprintf(
'Thumbnail failed on %s: could not link %s to %s',
294 $params[
'width'], $params[
'height'],
299 $status = $this->
rasterize( $lnPath, $dstPath, $physicalWidth, $physicalHeight,
$lang );
300 if ( $status ===
true ) {
318 public function rasterize( $srcPath, $dstPath, $width, $height,
$lang =
false ) {
326 if ( !is_callable( $func ) ) {
329 $err = $func( $srcPath,
336 $retval = (bool)$err;
340 [
'$path/',
'$width',
'$height',
'$input',
'$output' ],
344 Shell::escape( $srcPath ),
345 Shell::escape( $dstPath ) ],
350 if (
$lang !==
false ) {
351 $env[
'LANG'] =
$lang;
354 wfDebug( __METHOD__ .
": $cmd" );
359 if ( $retval != 0 || $removed ) {
368 $im =
new Imagick( $srcPath );
369 $im->setImageFormat(
'png' );
370 $im->setBackgroundColor(
'transparent' );
371 $im->setImageDepth( 8 );
373 if ( !$im->thumbnailImage( intval( $width ), intval( $height ),
false ) ) {
374 return 'Could not resize image';
376 if ( !$im->writeImage( $dstPath ) ) {
377 return "Could not write to $dstPath";
388 if ( $metadata ===
false &&
$file instanceof
File ) {
389 $metadata =
$file->getMetadata();
393 if ( isset( $metadata[
'width'] ) && isset( $metadata[
'height'] ) ) {
394 return [ $metadata[
'width'], $metadata[
'height'],
'SVG',
395 "width=\"{$metadata['width']}\" height=\"{$metadata['height']}\"" ];
397 return [ 0, 0,
'SVG',
"width=\"0\" height=\"0\"" ];
402 return [
'png',
'image/png' ];
418 if ( isset( $metadata[
'error'] ) ) {
419 return wfMessage(
'svg-long-error', $metadata[
'error'][
'message'] )->text();
425 $msg =
wfMessage(
'svg-long-desc-animated' );
430 $msg->numParams(
$file->getWidth(),
$file->getHeight() )->params( $size );
432 return $msg->parse();
445 $metadata += $svgReader->getMetadata();
446 }
catch ( Exception $e ) {
448 $metadata[
'error'] = [
449 'message' => $e->getMessage(),
450 'code' => $e->getCode()
452 wfDebug( __METHOD__ .
': ' . $e->getMessage() );
459 Wikimedia\suppressWarnings();
461 Wikimedia\restoreWarnings();
462 if ( isset( $unser[
'version'] ) && $unser[
'version'] == self::SVG_METADATA_VERSION ) {
475 if ( $meta ===
false ) {
478 if ( !isset( $meta[
'originalWidth'] ) ) {
487 $fields = [
'objectname',
'imagedescription' ];
502 $metadata =
$file->getMetadata();
507 if ( !$metadata || isset( $metadata[
'error'] ) ) {
520 foreach ( $metadata as $name => $value ) {
521 $tag = strtolower( $name );
522 if ( isset( self::$metaConversion[$tag] ) ) {
523 $tag = strtolower( self::$metaConversion[$tag] );
530 in_array( $tag, $visibleFields ) ?
'visible' :
'collapsed',
537 return $showMeta ? $result :
false;
546 if ( in_array( $name, [
'width',
'height' ] ) ) {
548 return ( $value > 0 );
549 } elseif ( $name ==
'lang' ) {
552 || !MediaWikiServices::getInstance()->getLanguageNameUtils()
553 ->isValidCode( $value )
572 if ( $code !==
'en' ) {
573 $lang =
'lang' . strtolower( $code ) .
'-';
575 if ( !isset( $params[
'width'] ) ) {
579 return "$lang{$params['width']}px";
584 if ( preg_match(
'/^lang([a-z]+(?:-[a-z]+)*)-(\d+)px$/i', $str, $m ) ) {
585 return [
'width' => array_pop( $m ),
'lang' => $m[1] ];
586 } elseif ( preg_match(
'/^(\d+)px$/', $str, $m ) ) {
587 return [
'width' => $m[1],
'lang' =>
'en' ];
594 return [
'img_lang' =>
'lang',
'img_width' =>
'width' ];
602 $scriptParams = [
'width' => $params[
'width'] ];
603 if ( isset( $params[
'lang'] ) ) {
604 $scriptParams[
'lang'] = $params[
'lang'];
607 return $scriptParams;
611 $metadata =
$file->getMetadata();
616 if ( !$metadata || isset( $metadata[
'error'] ) ) {
620 foreach ( $metadata as $name => $value ) {
621 $tag = strtolower( $name );
622 if ( $tag ===
'originalwidth' || $tag ===
'originalheight' ) {
627 if ( isset( self::$metaConversion[$tag] ) ) {
628 $tag = self::$metaConversion[$tag];
629 $stdMetadata[$tag] = $value;
unserialize( $serialized)
$wgSVGConverter
Pick a converter defined in $wgSVGConverters.
$wgSVGMaxSize
Don't scale a SVG larger than this.
$wgSVGConverterPath
If not in the executable PATH, specify the SVG converter path.
$wgSVGConverters
Scalable Vector Graphics (SVG) may be uploaded as images.
wfDebug( $text, $dest='all', array $context=[])
Sends a line to the debug log if enabled or, optionally, to a comment in output.
wfTempDir()
Tries to get the system directory for temporary files.
wfRandomString( $length=32)
Get a random string containing a number of pseudo-random hex characters.
wfHostname()
Get host name of the current machine, for use in error reporting.
wfShellExecWithStderr( $cmd, &$retval=null, $environ=[], $limits=[])
Execute a shell command, returning both stdout and stderr.
wfDebugLog( $logGroup, $text, $dest='all', array $context=[])
Send a line to a supplementary debug log file, if configured, or main debug log if not.
wfMkdirParents( $dir, $mode=null, $caller=null)
Make directory, and make all parent directories if they don't exist.
wfMessage( $key,... $params)
This is the function for getting translated interface messages.
Implements some public methods and some protected utility functions which are required by multiple ch...
Media handler abstract base class for images.
validateParam( $name, $value)
isVectorized( $file)
The material is vectorized and thus scaling is lossless.
normaliseParams( $image, &$params)
formatMetadata( $file, $context=false)
parseParamString( $str)
Parse a param string made with makeParamString back into an array.array|bool Array of parameters or f...
getMetadata( $file, $filename)
mustRender( $file)
True if handled types cannot be displayed directly in a browser but can be rendered.
getScriptParams( $params)
makeParamString( $params)
getCommonMetaArray(File $file)
Get an array of standard (FormatMetadata type) metadata values.
unpackMetadata( $metadata)
static array $metaConversion
A list of metadata tags that can be converted to the commonly used exif tags.
doTransform( $image, $dstPath, $dstUrl, $params, $flags=0)
getImageSize( $file, $path, $metadata=false)
getLanguageFromParams(array $params)
Determines render language from image parameters.
getAvailableLanguages(File $file)
Which languages (systemLanguage attribute) is supported.
getLongDesc( $file)
Subtitle for the image.
normaliseParamsInternal( $image, $params)
Code taken out of normaliseParams() for testability.
getMetadataType( $image)
Get a string describing the type of metadata, for display purposes.
getThumbType( $ext, $mime, $params=null)
Get the thumbnail extension and MIME type for a given source MIME type.
getDefaultRenderLanguage(File $file)
What language to render file in if none selected.
rasterize( $srcPath, $dstPath, $width, $height, $lang=false)
Transform an SVG file to PNG This function can be called outside of thumbnail contexts.
isEnabled()
False if the handler is disabled for all files Stable to override.
canAnimateThumbnail( $file)
We do not support making animated svg thumbnails.
visibleMetadataFields()
Get a list of metadata items which should be displayed when the metadata table is collapsed.
static rasterizeImagickExt( $srcPath, $dstPath, $width, $height)
getMatchedLanguage( $userPreferredLanguage, array $svgLanguages)
SVG's systemLanguage matching rules state: 'The systemLanguage attribute ... [e]valuates to "true" if...
const SVG_METADATA_VERSION
isMetadataValid( $image, $metadata)
Check if the metadata string is valid for this handler.
getParamMap()
Get an associative array mapping magic word IDs to parameter names.Will be used by the parser to iden...
Media transform output for images.
if(PHP_SAPI !='cli-server') if(!isset( $_SERVER['SCRIPT_FILENAME'])) $file
Item class for a filearchive table row.
if(!is_readable( $file)) $ext
if(!isset( $args[0])) $lang