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

TemplateLoader.php

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