Browse code

Implement svg_inline insert tag

Benjamin Roth authored on26/10/2023 14:54:53
Showing1 changed files
... ...
@@ -10,51 +10,134 @@
10 10
 
11 11
 namespace EsalesMedia\ContentHelperBundle\EventListener;
12 12
 
13
+use Contao\FilesModel;
14
+use Contao\Validator;
13 15
 
14 16
 class InsertTagsListener
15 17
 {
16 18
     public function onReplaceInsertTags($tag)
17 19
     {
18
-        $strId = '';
19
-        $strPrefix = 'ico';
20
-        $template = '<svg class="%s %s"><use xlink:href="#%s"></use></svg>';
21
-        $elements = explode('::', $tag);
20
+        $elements = explode('::', $tag,2);
21
+        $insertTag = array_shift($elements);
22 22
 
23
-        if ($elements[0] == 'svg')
24
-        {
25
-            if ($elements[2])
23
+        if (strtolower($insertTag) === 'svg_inline') {
24
+            if (isset($elements[0]) && $elements[0])
26 25
             {
27
-                $strPrefix =  $elements[2];
28
-                if (isset($elements[3])) {
29
-                  $strId = $elements[3];
26
+                $fragments = explode(':', $elements[0]);
27
+                $strFile = $fragments[0];
28
+                $strId = null;
29
+                $strClass = null;
30
+                if (isset($fragments[1]))
31
+                {
32
+                    $strClass = $fragments[1];
33
+                }
34
+                if (isset($fragments[2]))
35
+                {
36
+                    $strId = $fragments[2];
30 37
                 }
31
-            }
32
-            if ($elements[1])
33
-            {
34
-                $strClasses = '';
35
-                $arrClasses = explode(':', $elements[1]);
36
-                $strClass = array_shift($arrClasses);
37 38
 
38
-                $strSvgId = $strPrefix.'-'.$strClass;
39
-                $strClasses = $strSvgId;
39
+                if (Validator::isUuid($strFile))
40
+                {
41
+                    // Handle UUIDs
42
+                    $objFile = FilesModel::findByUuid($strFile);
40 43
 
41
-                foreach ($arrClasses as $class)
44
+                    if ($objFile === null)
45
+                    {
46
+                        return '';
47
+                    }
48
+
49
+                    $strFile = $objFile->path;
50
+                }
51
+                elseif (is_numeric($strFile))
42 52
                 {
43
-                    $classFragments = explode(' ', $class);
44
-                    foreach ($classFragments as $classFragment)
53
+                    // Handle numeric IDs (see #4805)
54
+                    $objFile = FilesModel::findByPk($strFile);
55
+
56
+                    if ($objFile === null)
45 57
                     {
46
-                        $strClasses .= ' ' . $classFragment;
58
+                        return '';
47 59
                     }
60
+
61
+                    $strFile = $objFile->path;
62
+                }
63
+                elseif (Validator::isInsecurePath($strFile))
64
+                {
65
+                    throw new \RuntimeException('Invalid path ' . $strFile);
66
+                }
67
+                elseif (($objFile = FilesModel::findByPath($strFile)) !== null)
68
+                {
69
+                    $strFile = $objFile->path;
70
+                } else {
71
+                    return '';
48 72
                 }
49 73
 
50
-                if ($strId)
74
+                return $this->print_svg($strFile,$strClass,$strId);
75
+            }
76
+        }
77
+
78
+        if (strtolower($insertTag) === 'svg_use')
79
+        {
80
+            if (isset($elements[0]) && $elements[0])
81
+            {
82
+                $strId = '';
83
+                $strPrefix = 'ico';
84
+                $template = '<svg class="%s %s"><use xlink:href="#%s"></use></svg>';
85
+                $fragments = explode(':', $elements[0]);
86
+
87
+                if (isset($fragments[1]))
51 88
                 {
52
-                    $template = '<svg id="'.$strId.'" class="%s %s"><use xlink:href="#%s"></use></svg>';
89
+                    $strPrefix = $fragments[1];
90
+                    if (isset($fragments[2]))
91
+                    {
92
+                        $strId = $fragments[2];
93
+                    }
94
+                }
95
+                if (isset($fragments[0]))
96
+                {
97
+                    $strClasses = '';
98
+                    $arrClasses = explode(':', $fragments[0]);
99
+                    $strClass = array_shift($arrClasses);
100
+
101
+                    $strSvgId = $strPrefix . '-' . $strClass;
102
+                    $strClasses = $strSvgId;
103
+
104
+                    foreach ($arrClasses as $class)
105
+                    {
106
+                        $classFragments = explode(' ', $class);
107
+                        foreach ($classFragments as $classFragment)
108
+                        {
109
+                            $strClasses .= ' ' . $classFragment;
110
+                        }
111
+                    }
112
+
113
+                    if ($strId)
114
+                    {
115
+                        $template = '<svg id="' . $strId . '" class="%s %s"><use xlink:href="#%s"></use></svg>';
116
+                    }
117
+                    return sprintf($template, $strPrefix, $strClasses, $strSvgId);
53 118
                 }
54
-                return sprintf($template,$strPrefix,$strClasses,$strSvgId);
55 119
             }
56 120
         }
57 121
 
58
-      return false;
122
+        return false;
123
+    }
124
+
125
+    protected function print_svg($svgPath, ?string $strClass=null, ?string$strId=null){
126
+        $iconfile = new \DOMDocument();
127
+        $iconfile->load($svgPath);
128
+        if (($svg = $iconfile->getElementsByTagName('svg')->item(0)))
129
+        {
130
+            if ($strClass) {
131
+                if (($embClass = $svg->getAttribute('class')))
132
+                {
133
+                    $strClass = $embClass. ' ' . $strClass;
134
+                }
135
+                $svg->setAttribute('class', $strClass);
136
+            }
137
+            if ($strId){
138
+                $svg->setAttribute('id', $strId);
139
+            }
140
+            return $iconfile->saveHTML($svg);
141
+        }
59 142
     }
60 143
 }