Verzeichnisstruktur phpBB-3.3.15
- Veröffentlicht
- 28.08.2024
So funktioniert es
|
Auf das letzte Element klicken. Dies geht jeweils ein Schritt zurück |
Auf das Icon klicken, dies öffnet das Verzeichnis. Nochmal klicken schließt das Verzeichnis. |
|
(Beispiel Datei-Icons)
|
Auf das Icon klicken um den Quellcode anzuzeigen |
TemplateLoader.php
001 <?php
002
003 /**
004 * @package s9e\TextFormatter
005 * @copyright Copyright (c) 2010-2022 The s9e authors
006 * @license http://www.opensource.org/licenses/mit-license.php The MIT License
007 */
008 namespace s9e\TextFormatter\Configurator\Helpers;
009
010 use DOMDocument;
011 use DOMElement;
012 use DOMXPath;
013 use RuntimeException;
014
015 abstract class TemplateLoader
016 {
017 /**
018 * XSL namespace
019 */
020 const XMLNS_XSL = 'http://www.w3.org/1999/XSL/Transform';
021
022 /**
023 * Get the XML content of an element
024 *
025 * @private
026 *
027 * @param DOMElement $element
028 * @return string
029 */
030 public static function innerXML(DOMElement $element)
031 {
032 // Serialize the XML then remove the outer element
033 $xml = $element->ownerDocument->saveXML($element);
034 $pos = 1 + strpos($xml, '>');
035 $len = strrpos($xml, '<') - $pos;
036
037 // If the template is empty, return an empty string
038 return ($len < 1) ? '' : substr($xml, $pos, $len);
039 }
040
041 /**
042 * Load a template as an xsl:template node
043 *
044 * Will attempt to load it as XML first, then as HTML as a fallback. Either way, an xsl:template
045 * node is returned
046 *
047 * @param string $template
048 * @return DOMDocument
049 */
050 public static function load($template)
051 {
052 $dom = self::loadAsXML($template) ?: self::loadAsXML(self::fixEntities($template));
053 if ($dom)
054 {
055 return $dom;
056 }
057
058 // If the template contains an XSL element, abort now. Otherwise, try reparsing it as HTML
059 if (strpos($template, '<xsl:') !== false)
060 {
061 $error = libxml_get_last_error();
062
063 throw new RuntimeException('Invalid XSL: ' . $error->message);
064 }
065
066 return self::loadAsHTML($template);
067 }
068
069 /**
070 * Serialize a loaded template back into a string
071 *
072 * NOTE: removes the root node created by load()
073 *
074 * @param DOMDocument $dom
075 * @return string
076 */
077 public static function save(DOMDocument $dom)
078 {
079 $xml = self::innerXML($dom->documentElement);
080 if (strpos($xml, 'xmlns:xsl') !== false)
081 {
082 $xml = preg_replace('((<[^>]+?) xmlns:xsl="' . self::XMLNS_XSL . '")', '$1', $xml);
083 }
084
085 return $xml;
086 }
087
088 /**
089 * Replace HTML entities and unescaped ampersands in given template
090 *
091 * @param string $template
092 * @return string
093 */
094 protected static function fixEntities($template)
095 {
096 $template = self::replaceEntities($template);
097 $template = preg_replace('(&(?!quot;|amp;|apos;|lt;|gt;|#\\d+;|#x[A-Fa-f0-9]+;))', '&', $template);
098
099 return $template;
100 }
101
102 /**
103 * Load given HTML template in a DOM document
104 *
105 * @param string $template Original template
106 * @return DOMDocument
107 */
108 protected static function loadAsHTML($template)
109 {
110 $template = self::replaceCDATA($template);
111 $template = self::replaceEntities($template);
112
113 $dom = new DOMDocument;
114 $html = '<?xml version="1.0" encoding="utf-8" ?><html><body><div>' . $template . '</div></body></html>';
115
116 $useErrors = libxml_use_internal_errors(true);
117 $dom->loadHTML($html, LIBXML_NSCLEAN);
118 self::removeInvalidAttributes($dom);
119 libxml_use_internal_errors($useErrors);
120
121 // Now dump the thing as XML then reload it with the proper root element
122 $xml = '<?xml version="1.0" encoding="utf-8" ?><xsl:template xmlns:xsl="' . self::XMLNS_XSL . '">' . self::innerXML($dom->documentElement->firstChild->firstChild) . '</xsl:template>';
123
124 $useErrors = libxml_use_internal_errors(true);
125 $dom->loadXML($xml, LIBXML_NSCLEAN);
126 libxml_use_internal_errors($useErrors);
127
128 return $dom;
129 }
130
131 /**
132 * Load given XSL template in a DOM document
133 *
134 * @param string $template Original template
135 * @return bool|DOMDocument DOMDocument on success, FALSE otherwise
136 */
137 protected static function loadAsXML($template)
138 {
139 $xml = '<?xml version="1.0" encoding="utf-8" ?><xsl:template xmlns:xsl="' . self::XMLNS_XSL . '">' . $template . '</xsl:template>';
140
141 $useErrors = libxml_use_internal_errors(true);
142 $dom = new DOMDocument;
143 $success = $dom->loadXML($xml, LIBXML_NOCDATA | LIBXML_NSCLEAN);
144 self::removeInvalidAttributes($dom);
145 libxml_use_internal_errors($useErrors);
146
147 return ($success) ? $dom : false;
148 }
149
150 /**
151 * Remove attributes with an invalid name from given DOM document
152 *
153 * @param DOMDocument $dom
154 * @return void
155 */
156 protected static function removeInvalidAttributes(DOMDocument $dom)
157 {
158 $xpath = new DOMXPath($dom);
159 foreach ($xpath->query('//@*') as $attribute)
160 {
161 if (!preg_match('(^(?:[-\\w]+:)?(?!\\d)[-\\w]+$)D', $attribute->nodeName))
162 {
163 $attribute->parentNode->removeAttributeNode($attribute);
164 }
165 }
166 }
167
168 /**
169 * Replace CDATA sections in given template
170 *
171 * @param string $template Original template
172 * @return string Modified template
173 */
174 protected static function replaceCDATA($template)
175 {
176 return preg_replace_callback(
177 '(<!\\[CDATA\\[(.*?)\\]\\]>)',
178 function ($m)
179 {
180 return htmlspecialchars($m[1]);
181 },
182 $template
183 );
184 }
185
186 /**
187 * Replace known HTML entities
188 *
189 * @param string $template
190 * @return string
191 */
192 protected static function replaceEntities(string $template): string
193 {
194 return preg_replace_callback(
195 '(&(?!quot;|amp;|apos;|lt;|gt;)\\w+;)',
196 function ($m)
197 {
198 return html_entity_decode($m[0], ENT_HTML5 | ENT_NOQUOTES, 'UTF-8');
199 },
200 str_replace('&', '&', $template)
201 );
202 }
203 }