diff options
author | Luke Shumaker <lukeshu@sbcglobal.net> | 2016-05-01 15:12:12 -0400 |
---|---|---|
committer | Luke Shumaker <lukeshu@sbcglobal.net> | 2016-05-01 15:12:12 -0400 |
commit | c9aa36da061816dee256a979c2ff8d2ee41824d9 (patch) | |
tree | 29f7002b80ee984b488bd047dbbd80b36bf892e9 /includes/media/SVGMetadataExtractor.php | |
parent | b4274e0e33eafb5e9ead9d949ebf031a9fb8363b (diff) | |
parent | d1ba966140d7a60cd5ae4e8667ceb27c1a138592 (diff) |
Merge branch 'archwiki'
# Conflicts:
# skins/ArchLinux.php
# skins/ArchLinux/archlogo.gif
Diffstat (limited to 'includes/media/SVGMetadataExtractor.php')
-rw-r--r-- | includes/media/SVGMetadataExtractor.php | 92 |
1 files changed, 71 insertions, 21 deletions
diff --git a/includes/media/SVGMetadataExtractor.php b/includes/media/SVGMetadataExtractor.php index 2e33bb98..2a1091d8 100644 --- a/includes/media/SVGMetadataExtractor.php +++ b/includes/media/SVGMetadataExtractor.php @@ -31,6 +31,7 @@ class SVGMetadataExtractor { static function getMetadata( $filename ) { $svg = new SVGReader( $filename ); + return $svg->getMetadata(); } } @@ -42,10 +43,19 @@ class SVGReader { const DEFAULT_WIDTH = 512; const DEFAULT_HEIGHT = 512; const NS_SVG = 'http://www.w3.org/2000/svg'; + const LANG_PREFIX_MATCH = 1; + const LANG_FULL_MATCH = 2; + /** @var null|XMLReader */ private $reader = null; + + /** @var bool */ private $mDebug = false; - private $metadata = Array(); + + /** @var array */ + private $metadata = array(); + private $languages = array(); + private $languagePrefixes = array(); /** * Constructor @@ -113,7 +123,7 @@ class SVGReader { } /** - * @return Array with the known metadata + * @return array Array with the known metadata */ public function getMetadata() { return $this->metadata; @@ -148,7 +158,9 @@ class SVGReader { $this->debug( "$tag" ); - if ( $isSVG && $tag == 'svg' && $type == XmlReader::END_ELEMENT && $this->reader->depth <= $exitDepth ) { + if ( $isSVG && $tag == 'svg' && $type == XmlReader::END_ELEMENT + && $this->reader->depth <= $exitDepth + ) { break; } elseif ( $isSVG && $tag == 'title' ) { $this->readField( $tag, 'title' ); @@ -164,10 +176,8 @@ class SVGReader { } elseif ( $tag !== '#text' ) { $this->debug( "Unhandled top-level XML tag $tag" ); - if ( !isset( $this->metadata['animated'] ) ) { - // Recurse into children of current tag, looking for animation. - $this->animateFilter( $tag ); - } + // Recurse into children of current tag, looking for animation and languages. + $this->animateFilterAndLang( $tag ); } // Goto next element, which is sibling of current (Skip children). @@ -176,14 +186,16 @@ class SVGReader { $this->reader->close(); + $this->metadata['translations'] = $this->languages + $this->languagePrefixes; + return true; } /** * Read a textelement from an element * - * @param string $name of the element that we are reading from - * @param string $metafield that we will fill with the result + * @param string $name Name of the element that we are reading from + * @param string $metafield Field that we will fill with the result */ private function readField( $name, $metafield = null ) { $this->debug( "Read field $metafield" ); @@ -192,7 +204,10 @@ class SVGReader { } $keepReading = $this->reader->read(); while ( $keepReading ) { - if ( $this->reader->localName == $name && $this->reader->namespaceURI == self::NS_SVG && $this->reader->nodeType == XmlReader::END_ELEMENT ) { + if ( $this->reader->localName == $name + && $this->reader->namespaceURI == self::NS_SVG + && $this->reader->nodeType == XmlReader::END_ELEMENT + ) { break; } elseif ( $this->reader->nodeType == XmlReader::TEXT ) { $this->metadata[$metafield] = trim( $this->reader->value ); @@ -204,7 +219,7 @@ class SVGReader { /** * Read an XML snippet from an element * - * @param string $metafield that we will fill with the result + * @param string $metafield Field that we will fill with the result * @throws MWException */ private function readXml( $metafield = null ) { @@ -212,21 +227,24 @@ class SVGReader { if ( !$metafield || $this->reader->nodeType != XmlReader::ELEMENT ) { return; } - // TODO: find and store type of xml snippet. metadata['metadataType'] = "rdf" + // @todo Find and store type of xml snippet. metadata['metadataType'] = "rdf" if ( method_exists( $this->reader, 'readInnerXML' ) ) { $this->metadata[$metafield] = trim( $this->reader->readInnerXML() ); } else { - throw new MWException( "The PHP XMLReader extension does not come with readInnerXML() method. Your libxml is probably out of date (need 2.6.20 or later)." ); + throw new MWException( "The PHP XMLReader extension does not come " . + "with readInnerXML() method. Your libxml is probably out of " . + "date (need 2.6.20 or later)." ); } $this->reader->next(); } /** - * Filter all children, looking for animate elements + * Filter all children, looking for animated elements. + * Also get a list of languages that can be targeted. * - * @param string $name of the element that we are reading from + * @param string $name Name of the element that we are reading from */ - private function animateFilter( $name ) { + private function animateFilterAndLang( $name ) { $this->debug( "animate filter for tag $name" ); if ( $this->reader->nodeType != XmlReader::ELEMENT ) { return; @@ -238,9 +256,38 @@ class SVGReader { $keepReading = $this->reader->read(); while ( $keepReading ) { if ( $this->reader->localName == $name && $this->reader->depth <= $exitDepth - && $this->reader->nodeType == XmlReader::END_ELEMENT ) { + && $this->reader->nodeType == XmlReader::END_ELEMENT + ) { break; - } elseif ( $this->reader->namespaceURI == self::NS_SVG && $this->reader->nodeType == XmlReader::ELEMENT ) { + } elseif ( $this->reader->namespaceURI == self::NS_SVG + && $this->reader->nodeType == XmlReader::ELEMENT + ) { + + $sysLang = $this->reader->getAttribute( 'systemLanguage' ); + if ( !is_null( $sysLang ) && $sysLang !== '' ) { + // See http://www.w3.org/TR/SVG/struct.html#SystemLanguageAttribute + $langList = explode( ',', $sysLang ); + foreach ( $langList as $langItem ) { + $langItem = trim( $langItem ); + if ( Language::isWellFormedLanguageTag( $langItem ) ) { + $this->languages[$langItem] = self::LANG_FULL_MATCH; + } + // Note, the standard says that any prefix should work, + // here we do only the initial prefix, since that will catch + // 99% of cases, and we are going to compare against fallbacks. + // This differs mildly from how the spec says languages should be + // handled, however it matches better how the MediaWiki language + // preference is generally handled. + $dash = strpos( $langItem, '-' ); + // Intentionally checking both !false and > 0 at the same time. + if ( $dash ) { + $itemPrefix = substr( $langItem, 0, $dash ); + if ( Language::isWellFormedLanguageTag( $itemPrefix ) ) { + $this->languagePrefixes[$itemPrefix] = self::LANG_PREFIX_MATCH; + } + } + } + } switch ( $this->reader->localName ) { case 'script': // Normally we disallow files with @@ -261,6 +308,7 @@ class SVGReader { } } + // @todo FIXME: Unused, remove? private function throwXmlError( $err ) { $this->debug( "FAILURE: $err" ); wfDebug( "SVGReader XML error: $err\n" ); @@ -272,10 +320,12 @@ class SVGReader { } } + // @todo FIXME: Unused, remove? private function warn( $data ) { wfDebug( "SVGReader: $data\n" ); } + // @todo FIXME: Unused, remove? private function notice( $data ) { wfDebug( "SVGReader WARN: $data\n" ); } @@ -333,8 +383,8 @@ class SVGReader { * http://www.w3.org/TR/SVG11/coords.html#UnitIdentifiers * * @param string $length CSS/SVG length. - * @param $viewportSize: Float optional scale for percentage units... - * @return float: length in pixels + * @param float|int $viewportSize Optional scale for percentage units... + * @return float Length in pixels */ static function scaleSVGUnit( $length, $viewportSize = 512 ) { static $unitLength = array( @@ -347,7 +397,7 @@ class SVGReader { 'em' => 16.0, // fake it? 'ex' => 12.0, // fake it? '' => 1.0, // "User units" pixels by default - ); + ); $matches = array(); if ( preg_match( '/^\s*(\d+(?:\.\d+)?)(em|ex|px|pt|pc|cm|mm|in|%|)\s*$/', $length, $matches ) ) { $length = floatval( $matches[1] ); |