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

TemplateLoader.php

Zuletzt modifiziert: 02.04.2025, 15:04 - Dateigröße: 5.04 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 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]+;))', '&amp;', $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('&AMP;', '&amp;', $template)
201          );
202      }
203  }