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.
Auf den Verzeichnisnamen klicken, dies zeigt nur das Verzeichnis mit Inhalt an

(Beispiel Datei-Icons)

Auf das Icon klicken um den Quellcode anzuzeigen

TemplateHelper.php

Zuletzt modifiziert: 02.04.2025, 15:04 - Dateigröße: 6.01 KiB


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 . '=&quot;&quot;', '', $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  }