[FEATURE] Allow inline rendering for SVG content object 85/53685/7
authorFrank Naegler <frank.naegler@typo3.org>
Sat, 12 Aug 2017 10:37:06 +0000 (12:37 +0200)
committerAndreas Fernandez <typo3@scripting-base.de>
Wed, 16 Aug 2017 08:30:13 +0000 (10:30 +0200)
This patch add a new setting to allow inline rendering of SVG files.

Resolves: #82091
Releases: master
Change-Id: I1321964f2a2f0dcbb6cad4f4d2229c379b7f9e87
Reviewed-on: https://review.typo3.org/53685
Tested-by: TYPO3com <no-reply@typo3.com>
Reviewed-by: Wouter Wolters <typo3@wouterwolters.nl>
Reviewed-by: Josef Glatz <josef.glatz@typo3.org>
Reviewed-by: Joerg Boesche <typo3@joergboesche.de>
Tested-by: Joerg Boesche <typo3@joergboesche.de>
Reviewed-by: Andreas Fernandez <typo3@scripting-base.de>
Tested-by: Andreas Fernandez <typo3@scripting-base.de>
typo3/sysext/core/Documentation/Changelog/master/Feature-82091-AllowInlineRenderingInSVGContentObject.rst [new file with mode: 0644]
typo3/sysext/frontend/Classes/ContentObject/ScalableVectorGraphicsContentObject.php

diff --git a/typo3/sysext/core/Documentation/Changelog/master/Feature-82091-AllowInlineRenderingInSVGContentObject.rst b/typo3/sysext/core/Documentation/Changelog/master/Feature-82091-AllowInlineRenderingInSVGContentObject.rst
new file mode 100644 (file)
index 0000000..a12ff85
--- /dev/null
@@ -0,0 +1,28 @@
+.. include:: ../../Includes.txt
+
+==============================================================
+Feature: #82091 - Allow inline rendering in SVG content object
+==============================================================
+
+See :issue:`82091`
+
+Description
+===========
+
+The SVG content object supports a new option to render a SVG file as :html:``<svg>`` tag.
+The new setting :typoscript:``renderMode`` can be set to ``inline`` to render an inline version of the SVG file.
+
+.. code-block:: typoscript
+
+   page.10 = SVG
+   page.10 {
+      renderMode = inline
+      src = fileadmin/foo.svg
+   }
+
+Impact
+======
+
+SVG can now be rendered as :html:``<svg>`` tag.
+
+.. index:: Frontend, TypoScript
index 4fc66a0..720eb6d 100644 (file)
@@ -23,9 +23,53 @@ class ScalableVectorGraphicsContentObject extends AbstractContentObject
      * Rendering the cObject, SVG
      *
      * @param array $conf Array of TypoScript properties
-     * @return string Empty string (the cObject only sets internal data!)
+     * @return string
      */
-    public function render($conf = [])
+    public function render($conf = []) : string
+    {
+        $renderMode = isset($conf['renderMode.'])
+            ? $this->cObj->stdWrap($conf['renderMode'], $conf['renderMode.'])
+            : $conf['renderMode'];
+
+        if ($renderMode === 'inline') {
+            return $this->renderInline($conf);
+        }
+
+        return $this->renderObject($conf);
+    }
+
+    /**
+     * @param array $conf
+     *
+     * @return string
+     */
+    protected function renderInline(array $conf) : string
+    {
+        $src = isset($conf['src.']) ? $this->cObj->stdWrap($conf['src'], $conf['src.']) : $conf['src'];
+
+        if (!file_exists($src)) {
+            return '';
+        }
+
+        $svgContent = file_get_contents($src);
+        $svgContent = preg_replace('/<script[\s\S]*?>[\s\S]*?<\/script>/i', '', $svgContent);
+        // Disables the functionality to allow external entities to be loaded when parsing the XML, must be kept
+        $previousValueOfEntityLoader = libxml_disable_entity_loader(true);
+        $svgElement = simplexml_load_string($svgContent);
+        libxml_disable_entity_loader($previousValueOfEntityLoader);
+
+        // remove xml version tag
+        $domXml = dom_import_simplexml($svgElement);
+        return $domXml->ownerDocument->saveXML($domXml->ownerDocument->documentElement);
+    }
+
+    /**
+     * Render the SVG as <object> tag
+     * @param array $conf
+     *
+     * @return string
+     */
+    protected function renderObject(array $conf) : string
     {
         $width = isset($conf['width.']) ? $this->cObj->stdWrap($conf['width'], $conf['width.']) : $conf['width'];
         if (!$width) {
@@ -39,36 +83,31 @@ class ScalableVectorGraphicsContentObject extends AbstractContentObject
         if (!$src) {
             $src = null;
         }
+
         $value = isset($conf['value.']) ? $this->cObj->stdWrap($conf['value'], $conf['value.']) : $conf['value'];
         $noscript = isset($conf['noscript.']) ? $this->cObj->stdWrap($conf['noscript'], $conf['noscript.']) : $conf['noscript'];
-        if ($src) {
-            $content = '
-
-                                       <!--[if IE]>
-                                       <object src="' . $src . '" classid="image/svg+xml" width="' . $width . '" height="' . $height . '">
-                                       <![endif]-->
-                                       <!--[if !IE]>-->
-                                       <object data="' . $src . '" type="image/svg+xml" width="' . $width . '" height="' . $height . '">
-                                       <!--<![endif]-->
-                                       ' . $noscript . '
-                                       </object>
 
-                       ';
+        $content = [];
+        if ($src) {
+            $content[] = '<!--[if IE]>';
+            $content[] = '  <object src="' . htmlspecialchars($src) . '" classid="image/svg+xml" width="' . (int)$width . '" height="' . (int)$height . '">';
+            $content[] = '<![endif]-->';
+            $content[] = '<!--[if !IE]>-->';
+            $content[] = '  <object data="' . htmlspecialchars($src) . '" type="image/svg+xml" width="' . (int)$width . '" height="' . (int)$height . '">';
+            $content[] = '<!--<![endif]-->';
+            $content[] = $noscript;
+            $content[] = '</object>';
         } else {
-            $content = '
-                               <script type="image/svg+xml">
-                                       <svg xmlns="http://www.w3.org/2000/svg"
-                                       xmlns:xlink="http://www.w3.org/1999/xlink"
-                                       width="' . $width . '"
-                                       height="' . $height . '">
-                       ' . $value . '
-                               </svg>
-                               </script>
-                               <noscript>
-                       ' . $noscript . '
-                               </noscript>
-                       ';
+            $content[] = '<script type="image/svg+xml">';
+            $content[] = '  <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="' . (int)$width . '" height="' . (int)$height . '">';
+            $content[] = $value;
+            $content[] = '  </svg>';
+            $content[] = '</script>';
+            $content[] = '<noscript>';
+            $content[] = $noscript;
+            $content[] = '</noscript>';
         }
+        $content = implode(LF, $content);
         if (isset($conf['stdWrap.'])) {
             $content = $this->cObj->stdWrap($content, $conf['stdWrap.']);
         }