* @file
* @ingroup Media
*/
+use Wikimedia\ScopedCallback;
/**
* Handler for SVG images.
if ( isset( $metadata['translations'] ) ) {
foreach ( $metadata['translations'] as $lang => $langType ) {
if ( $langType === SVGReader::LANG_FULL_MATCH ) {
- $langList[] = $lang;
+ $langList[] = strtolower( $lang );
}
}
}
}
- return $langList;
+ return array_unique( $langList );
}
/**
- * What language to render file in if none selected.
+ * SVG's systemLanguage matching rules state:
+ * 'The `systemLanguage` attribute ... [e]valuates to "true" if one of the languages indicated
+ * by user preferences exactly equals one of the languages given in the value of this parameter,
+ * or if one of the languages indicated by user preferences exactly equals a prefix of one of
+ * the languages given in the value of this parameter such that the first tag character
+ * following the prefix is "-".'
*
- * @param File $file
- * @return string Language code.
+ * Return the first element of $svgLanguages that matches $userPreferredLanguage
+ *
+ * @see https://www.w3.org/TR/SVG/struct.html#SystemLanguageAttribute
+ * @param string $userPreferredLanguage
+ * @param array $svgLanguages
+ * @return string|null
+ */
+ public function getMatchedLanguage( $userPreferredLanguage, array $svgLanguages ) {
+ foreach ( $svgLanguages as $svgLang ) {
+ if ( strcasecmp( $svgLang, $userPreferredLanguage ) === 0 ) {
+ return $svgLang;
+ }
+ $trimmedSvgLang = $svgLang;
+ while ( strpos( $trimmedSvgLang, '-' ) !== false ) {
+ $trimmedSvgLang = substr( $trimmedSvgLang, 0, strrpos( $trimmedSvgLang, '-' ) );
+ if ( strcasecmp( $trimmedSvgLang, $userPreferredLanguage ) === 0 ) {
+ return $svgLang;
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * What language to render file in if none selected
+ *
+ * @param File $file Language code
+ * @return string
*/
public function getDefaultRenderLanguage( File $file ) {
return 'en';
/**
* @param File $image
- * @param array $params
+ * @param array &$params
* @return bool
*/
function normaliseParams( $image, &$params ) {
$metadata = $this->unpackMetadata( $image->getMetadata() );
if ( isset( $metadata['error'] ) ) { // sanity check
- $err = wfMessage( 'svg-long-error', $metadata['error']['message'] )->text();
+ $err = wfMessage( 'svg-long-error', $metadata['error']['message'] );
return new MediaTransformError( 'thumbnail_error', $clientWidth, $clientHeight, $err );
}
if ( !wfMkdirParents( dirname( $dstPath ), null, __METHOD__ ) ) {
return new MediaTransformError( 'thumbnail_error', $clientWidth, $clientHeight,
- wfMessage( 'thumbnail_dest_directory' )->text() );
+ wfMessage( 'thumbnail_dest_directory' ) );
}
$srcPath = $image->getLocalRefPath();
return new MediaTransformError( 'thumbnail_error',
$params['width'], $params['height'],
- wfMessage( 'filemissing' )->text()
+ wfMessage( 'filemissing' )
);
}
// https://git.gnome.org/browse/librsvg/commit/?id=f01aded72c38f0e18bc7ff67dee800e380251c8e
$tmpDir = wfTempDir() . '/svg_' . wfRandomString( 24 );
$lnPath = "$tmpDir/" . basename( $srcPath );
- $ok = mkdir( $tmpDir, 0771 ) && symlink( $srcPath, $lnPath );
+ $ok = mkdir( $tmpDir, 0771 );
+ if ( !$ok ) {
+ wfDebugLog( 'thumbnail',
+ sprintf( 'Thumbnail failed on %s: could not create temporary directory %s',
+ wfHostname(), $tmpDir ) );
+ return new MediaTransformError( 'thumbnail_error',
+ $params['width'], $params['height'],
+ wfMessage( 'thumbnail-temp-create' )->text()
+ );
+ }
+ $ok = symlink( $srcPath, $lnPath );
/** @noinspection PhpUnusedLocalVariableInspection */
$cleaner = new ScopedCallback( function () use ( $tmpDir, $lnPath ) {
MediaWiki\suppressWarnings();
wfHostname(), $lnPath, $srcPath ) );
return new MediaTransformError( 'thumbnail_error',
$params['width'], $params['height'],
- wfMessage( 'thumbnail-temp-create' )->text()
+ wfMessage( 'thumbnail-temp-create' )
);
}
}
/**
- * @param File $file
+ * @param File|FSFile $file
* @param string $path Unused
* @param bool|array $metadata
* @return array
*/
function getImageSize( $file, $path, $metadata = false ) {
- if ( $metadata === false ) {
+ if ( $metadata === false && $file instanceof File ) {
$metadata = $file->getMetadata();
}
$metadata = $this->unpackMetadata( $metadata );
}
/**
- * @param File $file
+ * @param File|FSFile $file
* @param string $filename
* @return string Serialised metadata
*/
return ( $value > 0 );
} elseif ( $name == 'lang' ) {
// Validate $code
- if ( $value === '' || !Language::isValidBuiltInCode( $value ) ) {
+ if ( $value === '' || !Language::isValidCode( $value ) ) {
wfDebug( "Invalid user language code\n" );
return false;
public function makeParamString( $params ) {
$lang = '';
if ( isset( $params['lang'] ) && $params['lang'] !== 'en' ) {
- $params['lang'] = strtolower( $params['lang'] );
- $lang = "lang{$params['lang']}-";
+ $lang = 'lang' . strtolower( $params['lang'] ) . '-';
}
if ( !isset( $params['width'] ) ) {
return false;
public function parseParamString( $str ) {
$m = false;
- if ( preg_match( '/^lang([a-z]+(?:-[a-z]+)*)-(\d+)px$/', $str, $m ) ) {
+ if ( preg_match( '/^lang([a-z]+(?:-[a-z]+)*)-(\d+)px$/i', $str, $m ) ) {
return [ 'width' => array_pop( $m ), 'lang' => $m[1] ];
} elseif ( preg_match( '/^(\d+)px$/', $str, $m ) ) {
return [ 'width' => $m[1], 'lang' => 'en' ];