ffcd25220b7c7a032b66f1803d52d9fa633f35e9
[Packages/TYPO3.CMS.git] / typo3 / sysext / frontend / Classes / ContentObject / ScalableVectorGraphicsContentObject.php
1 <?php
2 namespace TYPO3\CMS\Frontend\ContentObject;
3
4 /*
5 * This file is part of the TYPO3 CMS project.
6 *
7 * It is free software; you can redistribute it and/or modify it under
8 * the terms of the GNU General Public License, either version 2
9 * of the License, or any later version.
10 *
11 * For the full copyright and license information, please read the
12 * LICENSE.txt file that was distributed with this source code.
13 *
14 * The TYPO3 project - inspiring people to share!
15 */
16
17 use TYPO3\CMS\Core\Utility\GeneralUtility;
18 use TYPO3\CMS\Core\Utility\PathUtility;
19
20 /**
21 * Contains RESTORE_REGISTER class object.
22 */
23 class ScalableVectorGraphicsContentObject extends AbstractContentObject
24 {
25 /**
26 * Rendering the cObject, SVG
27 *
28 * @param array $conf Array of TypoScript properties
29 * @return string
30 */
31 public function render($conf = []) : string
32 {
33 $renderMode = isset($conf['renderMode.'])
34 ? $this->cObj->stdWrap($conf['renderMode'], $conf['renderMode.'])
35 : $conf['renderMode'];
36
37 if ($renderMode === 'inline') {
38 return $this->renderInline($conf);
39 }
40
41 return $this->renderObject($conf);
42 }
43
44 /**
45 * @param array $conf
46 *
47 * @return string
48 */
49 protected function renderInline(array $conf) : string
50 {
51 $src = $this->resolveAbsoluteSourcePath($conf);
52 list($width, $height, $isDefaultWidth, $isDefaultHeight) = $this->getDimensions($conf);
53
54 $content = '';
55 if (file_exists($src)) {
56 $svgContent = file_get_contents($src);
57 $svgContent = preg_replace('/<script[\s\S]*?>[\s\S]*?<\/script>/i', '', $svgContent);
58 // Disables the functionality to allow external entities to be loaded when parsing the XML, must be kept
59 $previousValueOfEntityLoader = libxml_disable_entity_loader();
60 $svgElement = simplexml_load_string($svgContent);
61 libxml_disable_entity_loader($previousValueOfEntityLoader);
62
63 $domXml = dom_import_simplexml($svgElement);
64 if (!$isDefaultWidth) {
65 $domXml->setAttribute('width', $width);
66 }
67 if (!$isDefaultHeight) {
68 $domXml->setAttribute('height', $height);
69 }
70 // remove xml version tag
71 $content = $domXml->ownerDocument->saveXML($domXml->ownerDocument->documentElement);
72 } else {
73 $value = isset($conf['value.']) ? $this->cObj->stdWrap($conf['value'], $conf['value.']) : $conf['value'];
74 if (!empty($value)) {
75 $content = [];
76 $content[] = '<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="' . (int)$width . '" height="' . (int)$height . '">';
77 $content[] = $value;
78 $content[] = '</svg>';
79 $content = implode(LF, $content);
80 }
81 }
82 return $content;
83 }
84
85 /**
86 * Render the SVG as <object> tag
87 * @param array $conf
88 *
89 * @return string
90 */
91 protected function renderObject(array $conf) : string
92 {
93 $src = $this->resolveAbsoluteSourcePath($conf);
94 list($width, $height) = $this->getDimensions($conf);
95
96 $src = $src === '' ? null : PathUtility::getAbsoluteWebPath($src);
97
98 $value = isset($conf['value.']) ? $this->cObj->stdWrap($conf['value'], $conf['value.']) : $conf['value'];
99 $noscript = isset($conf['noscript.']) ? $this->cObj->stdWrap($conf['noscript'], $conf['noscript.']) : $conf['noscript'];
100
101 // @deprecated since TYPO3 v9, will be removed in TYPO3 v10 - see method usages
102 if (!empty($conf['noscript.']) || !empty($conf['noscript'])) {
103 GeneralUtility::deprecationLog('The option "noscript" of the SVG content object has been deprecated in v9 and will be remove in v10.');
104 }
105 if (!empty($conf['value.']) || !empty($conf['value'])) {
106 GeneralUtility::deprecationLog('The option "value" without setting renderMode=inline of the SVG content object has been deprecated in v9 and will be remove in v10.');
107 }
108
109 $content = [];
110 if ($src) {
111 $content[] = '<!--[if IE]>';
112 $content[] = ' <object src="' . htmlspecialchars($src) . '" classid="image/svg+xml" width="' . (int)$width . '" height="' . (int)$height . '">';
113 $content[] = '<![endif]-->';
114 $content[] = '<!--[if !IE]>-->';
115 $content[] = ' <object data="' . htmlspecialchars($src) . '" type="image/svg+xml" width="' . (int)$width . '" height="' . (int)$height . '">';
116 $content[] = '<!--<![endif]-->';
117 $content[] = $noscript;
118 $content[] = '</object>';
119 } else {
120 // @deprecated since TYPO3 v9, will be removed in TYPO3 v10 - see method usages
121 $content[] = '<script type="image/svg+xml">';
122 $content[] = ' <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="' . (int)$width . '" height="' . (int)$height . '">';
123 $content[] = $value;
124 $content[] = ' </svg>';
125 $content[] = '</script>';
126 $content[] = '<noscript>';
127 $content[] = $noscript;
128 $content[] = '</noscript>';
129 }
130 $content = implode(LF, $content);
131 if (isset($conf['stdWrap.'])) {
132 $content = $this->cObj->stdWrap($content, $conf['stdWrap.']);
133 }
134 return $content;
135 }
136
137 /**
138 * @param array $conf
139 *
140 * @return string
141 */
142 protected function resolveAbsoluteSourcePath(array $conf) : string
143 {
144 $src = isset($conf['src.']) ? $this->cObj->stdWrap($conf['src'], $conf['src.']) : $conf['src'];
145 return GeneralUtility::getFileAbsFileName($src);
146 }
147
148 /**
149 * @param array $conf
150 *
151 * @return array
152 */
153 protected function getDimensions(array $conf) : array
154 {
155 $isDefaultWidth = false;
156 $isDefaultHeight = false;
157 $width = isset($conf['width.']) ? $this->cObj->stdWrap($conf['width'], $conf['width.']) : $conf['width'];
158 $height = isset($conf['height.']) ? $this->cObj->stdWrap($conf['height'], $conf['height.']) : $conf['height'];
159
160 if (empty($width)) {
161 $isDefaultWidth = true;
162 $width = 600;
163 }
164 if (empty($height)) {
165 $isDefaultHeight = true;
166 $height = 400;
167 }
168
169 return [$width, $height, $isDefaultWidth, $isDefaultHeight];
170 }
171 }