Verzeichnisstruktur phpBB-3.3.16


Veröffentlicht
27.04.2026

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: 01.05.2026, 11:28 - 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  }