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 |
TemplateHelper.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 DOMAttr;
011 use DOMCharacterData;
012 use DOMDocument;
013 use DOMElement;
014 use DOMNode;
015 use DOMProcessingInstruction;
016 use DOMText;
017 use DOMXPath;
018
019 abstract class TemplateHelper
020 {
021 /**
022 * XSL namespace
023 */
024 const XMLNS_XSL = 'http://www.w3.org/1999/XSL/Transform';
025
026 /**
027 * Return a list of parameters in use in given XSL
028 *
029 * @param string $xsl XSL source
030 * @return array Alphabetically sorted list of unique parameter names
031 */
032 public static function getParametersFromXSL($xsl)
033 {
034 $paramNames = [];
035 $xpath = new DOMXPath(TemplateLoader::load($xsl));
036
037 // Start by collecting XPath expressions in XSL elements
038 $query = '//xsl:*/@match | //xsl:*/@select | //xsl:*/@test';
039 foreach ($xpath->query($query) as $attribute)
040 {
041 $expr = $attribute->value;
042 $paramNames += array_flip(self::getParametersFromExpression($attribute, $expr));
043 }
044
045 // Collect XPath expressions in attribute value templates
046 $query = '//*[namespace-uri() != "' . self::XMLNS_XSL . '"]/@*[contains(., "{")]';
047 foreach ($xpath->query($query) as $attribute)
048 {
049 foreach (AVTHelper::parse($attribute->value) as $token)
050 {
051 if ($token[0] === 'expression')
052 {
053 $expr = $token[1];
054 $paramNames += array_flip(self::getParametersFromExpression($attribute, $expr));
055 }
056 }
057 }
058
059 // Sort the parameter names and return them in a list
060 ksort($paramNames);
061
062 return array_keys($paramNames);
063 }
064
065 /**
066 * Highlight the source of a node inside of a template
067 *
068 * @param DOMNode $node Node to highlight
069 * @param string $prepend HTML to prepend
070 * @param string $append HTML to append
071 * @return string Template's source, as HTML
072 */
073 public static function highlightNode(DOMNode $node, $prepend, $append)
074 {
075 // Create a copy of the document that we can modify without side effects
076 $dom = $node->ownerDocument->cloneNode(true);
077 $dom->formatOutput = true;
078
079 $xpath = new DOMXPath($dom);
080 $node = $xpath->query($node->getNodePath())->item(0);
081
082 // Add a unique token to the node
083 $uniqid = uniqid('_');
084 if ($node instanceof DOMAttr)
085 {
086 $node->value = htmlspecialchars($node->value, ENT_NOQUOTES, 'UTF-8') . $uniqid;
087 }
088 elseif ($node instanceof DOMElement)
089 {
090 $node->setAttribute($uniqid, '');
091 }
092 elseif ($node instanceof DOMCharacterData || $node instanceof DOMProcessingInstruction)
093 {
094 $node->data .= $uniqid;
095 }
096
097 $docXml = TemplateLoader::innerXML($dom->documentElement);
098 $docXml = trim(str_replace("\n ", "\n", $docXml));
099
100 $nodeHtml = htmlspecialchars(trim($dom->saveXML($node)));
101 $docHtml = htmlspecialchars($docXml);
102
103 // Enclose the node's representation in our highlighting HTML
104 $html = str_replace($nodeHtml, $prepend . $nodeHtml . $append, $docHtml);
105
106 // Remove the unique token from HTML
107 $html = str_replace(' ' . $uniqid . '=""', '', $html);
108 $html = str_replace($uniqid, '', $html);
109
110 return $html;
111 }
112
113 /**
114 * Replace simple templates (in an array, in-place) with a common template
115 *
116 * In some situations, renderers can take advantage of multiple tags having the same template. In
117 * any configuration, there's almost always a number of "simple" tags that are rendered as an
118 * HTML element of the same name with no HTML attributes. For instance, the system tag "p" used
119 * for paragraphs, "B" tags used for "b" HTML elements, etc... This method replaces those
120 * templates with a common template that uses a dynamic element name based on the tag's name,
121 * either its nodeName or localName depending on whether the tag is namespaced, and normalized to
122 * lowercase using XPath's translate() function
123 *
124 * @param array<string> &$templates Associative array of [tagName => template]
125 * @param integer $minCount
126 * @return void
127 */
128 public static function replaceHomogeneousTemplates(array &$templates, $minCount = 3)
129 {
130 // Prepare the XPath expression used for the element's name
131 $expr = 'name()';
132
133 // Identify "simple" tags, whose template is one element of the same name. Their template
134 // can be replaced with a dynamic template shared by all the simple tags
135 $tagNames = [];
136 foreach ($templates as $tagName => $template)
137 {
138 // Generate the element name based on the tag's localName, lowercased
139 $elName = strtolower(preg_replace('/^[^:]+:/', '', $tagName));
140 if ($template === '<' . $elName . '><xsl:apply-templates/></' . $elName . '>')
141 {
142 $tagNames[] = $tagName;
143
144 // Use local-name() if any of the tags are namespaced
145 if (strpos($tagName, ':') !== false)
146 {
147 $expr = 'local-name()';
148 }
149 }
150 }
151
152 // We only bother replacing their template if there are at least $minCount simple tags.
153 // Otherwise it only makes the stylesheet bigger
154 if (count($tagNames) < $minCount)
155 {
156 return;
157 }
158
159 // Generate a list of uppercase characters from the tags' names
160 $chars = preg_replace('/[^A-Z]+/', '', count_chars(implode('', $tagNames), 3));
161 if ($chars > '')
162 {
163 $expr = 'translate(' . $expr . ",'" . $chars . "','" . strtolower($chars) . "')";
164 }
165
166 // Prepare the common template
167 $template = '<xsl:element name="{' . $expr . '}"><xsl:apply-templates/></xsl:element>';
168
169 // Replace the templates
170 foreach ($tagNames as $tagName)
171 {
172 $templates[$tagName] = $template;
173 }
174 }
175
176 /**
177 * Get a list of parameters from given XPath expression
178 *
179 * @param DOMNode $node Context node
180 * @param string $expr XPath expression
181 * @return string[]
182 */
183 protected static function getParametersFromExpression(DOMNode $node, $expr)
184 {
185 $varNames = XPathHelper::getVariables($expr);
186 $paramNames = [];
187 $xpath = new DOMXPath($node->ownerDocument);
188 foreach ($varNames as $name)
189 {
190 // Test whether this is the name of a local variable
191 $query = 'ancestor-or-self::*/preceding-sibling::xsl:variable[@name="' . $name . '"]';
192 if (!$xpath->query($query, $node)->length)
193 {
194 $paramNames[] = $name;
195 }
196 }
197
198 return $paramNames;
199 }
200 }