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

Element.php

Zuletzt modifiziert: 01.05.2026, 11:26 - Dateigröße: 10.59 KiB


 001  <?php declare(strict_types=1);
 002   
 003  /**
 004  * @package   s9e\SweetDOM
 005  * @copyright Copyright (c) 2019-2021 The s9e authors
 006  * @license   http://www.opensource.org/licenses/mit-license.php The MIT License
 007  */
 008  namespace s9e\SweetDOM;
 009   
 010  use BadMethodCallException;
 011  use DOMElement;
 012  use DOMException;
 013  use DOMNode;
 014  use DOMNodeList;
 015  use DOMText;
 016   
 017  /**
 018  * @method self appendElement(string $nodeName, $text = '')
 019  * @method self appendElementSibling(string $nodeName, $text = '')
 020  * @method DOMText appendText(string $text)
 021  * @method DOMText appendTextSibling(string $text)
 022  * @method self appendXslApplyTemplates(string $select = null)
 023  * @method self appendXslApplyTemplatesSibling(string $select = null)
 024  * @method self appendXslAttribute(string $name, string $text = '')
 025  * @method self appendXslAttributeSibling(string $name, string $text = '')
 026  * @method self appendXslChoose()
 027  * @method self appendXslChooseSibling()
 028  * @method self appendXslComment(string $text = '')
 029  * @method self appendXslCommentSibling(string $text = '')
 030  * @method self appendXslCopyOf(string $select)
 031  * @method self appendXslCopyOfSibling(string $select)
 032  * @method self appendXslIf(string $test, string $text = '')
 033  * @method self appendXslIfSibling(string $test, string $text = '')
 034  * @method self appendXslOtherwise(string $text = '')
 035  * @method self appendXslOtherwiseSibling(string $text = '')
 036  * @method self appendXslText(string $text = '')
 037  * @method self appendXslTextSibling(string $text = '')
 038  * @method self appendXslValueOf(string $select)
 039  * @method self appendXslValueOfSibling(string $select)
 040  * @method self appendXslVariable(string $name, string $select = null)
 041  * @method self appendXslVariableSibling(string $name, string $select = null)
 042  * @method self appendXslWhen(string $test, string $text = '')
 043  * @method self appendXslWhenSibling(string $test, string $text = '')
 044  * @method self prependElement(string $nodeName, $text = '')
 045  * @method self prependElementSibling(string $nodeName, $text = '')
 046  * @method DOMText prependText(string $text)
 047  * @method DOMText prependTextSibling(string $text)
 048  * @method self prependXslApplyTemplates(string $select = null)
 049  * @method self prependXslApplyTemplatesSibling(string $select = null)
 050  * @method self prependXslAttribute(string $name, string $text = '')
 051  * @method self prependXslAttributeSibling(string $name, string $text = '')
 052  * @method self prependXslChoose()
 053  * @method self prependXslChooseSibling()
 054  * @method self prependXslComment(string $text = '')
 055  * @method self prependXslCommentSibling(string $text = '')
 056  * @method self prependXslCopyOf(string $select)
 057  * @method self prependXslCopyOfSibling(string $select)
 058  * @method self prependXslIf(string $test, string $text = '')
 059  * @method self prependXslIfSibling(string $test, string $text = '')
 060  * @method self prependXslOtherwise(string $text = '')
 061  * @method self prependXslOtherwiseSibling(string $text = '')
 062  * @method self prependXslText(string $text = '')
 063  * @method self prependXslTextSibling(string $text = '')
 064  * @method self prependXslValueOf(string $select)
 065  * @method self prependXslValueOfSibling(string $select)
 066  * @method self prependXslVariable(string $name, string $select = null)
 067  * @method self prependXslVariableSibling(string $name, string $select = null)
 068  * @method self prependXslWhen(string $test, string $text = '')
 069  * @method self prependXslWhenSibling(string $test, string $text = '')
 070  * @property Document $ownerDocument
 071  */
 072  class Element extends DOMElement
 073  {
 074      public function __call(string $name, array $arguments)
 075      {
 076          $name      = strtolower($name);
 077          $positions = [
 078              'append'         => 'beforeend',
 079              'appendsibling'  => 'afterend',
 080              'prepend'        => 'afterbegin',
 081              'prependsibling' => 'beforebegin'
 082          ];
 083   
 084          if (preg_match('(^(append|prepend)xsl(\\w+?)(sibling|)$)', $name, $m))
 085          {
 086              $localName = $m[2];
 087              $where     = $positions[$m[1] . $m[3]];
 088   
 089              return $this->insertXslElement($where, $localName, $arguments);
 090          }
 091          if (preg_match('(^(append|prepend)element(sibling|)$)', $name, $m))
 092          {
 093              $nodeName = $arguments[0];
 094              $text     = $arguments[1] ?? '';
 095              $where    = $positions[$m[1] . $m[2]];
 096   
 097              return $this->insertElement($where, $nodeName, $text);
 098          }
 099          if (preg_match('(^(append|prepend)text(sibling|)$)', $name, $m))
 100          {
 101              $text  = $arguments[0];
 102              $where = $positions[$m[1] . $m[2]];
 103   
 104              return $this->insertText($where, $text);
 105          }
 106   
 107          throw new BadMethodCallException;
 108      }
 109   
 110      /**
 111      * Evaluate and return the result of a given XPath expression using this element as context node
 112      *
 113      * @param  string  $expr XPath expression
 114      * @return mixed
 115      */
 116      public function evaluate(string $expr)
 117      {
 118          return $this->ownerDocument->evaluate($expr, $this);
 119      }
 120   
 121      /**
 122      * Evaluate and return the first element of a given XPath query using this element as context node
 123      *
 124      * @param  string       $expr XPath expression
 125      * @return DOMNode|null
 126      */
 127      public function firstOf(string $expr): ?DOMNode
 128      {
 129          return $this->ownerDocument->firstOf($expr, $this);
 130      }
 131   
 132      /**
 133      * Insert given element relative to this element's position
 134      *
 135      * @param  string     $where   One of 'beforebegin', 'afterbegin', 'beforeend', 'afterend'
 136      * @param  DOMElement $element
 137      * @return self
 138      */
 139      public function insertAdjacentElement(string $where, DOMElement $element): self
 140      {
 141          $this->insertAdjacentNode($where, $element);
 142   
 143          return $element;
 144      }
 145   
 146      /**
 147      * Insert given text relative to this element's position
 148      *
 149      * @param  string $where One of 'beforebegin', 'afterbegin', 'beforeend', 'afterend'
 150      * @param  string $text
 151      * @return void
 152      */
 153      public function insertAdjacentText(string $where, string $text): void
 154      {
 155          $this->insertText($where, $text);
 156      }
 157   
 158      /**
 159      * Insert given XML relative to this element's position
 160      *
 161      * @param  string $where One of 'beforebegin', 'afterbegin', 'beforeend', 'afterend'
 162      * @param  string $xml
 163      * @return void
 164      */
 165      public function insertAdjacentXML(string $where, string $xml): void
 166      {
 167          $fragment = $this->ownerDocument->createDocumentFragment();
 168          $fragment->appendXML($this->addMissingNamespaceDeclarations($xml));
 169   
 170          $this->insertAdjacentNode($where, $fragment);
 171      }
 172   
 173      /**
 174      * Evaluate and return the result of a given XPath query using this element as context node
 175      *
 176      * @param  string      $expr XPath expression
 177      * @return DOMNodeList
 178      */
 179      public function query(string $expr): DOMNodeList
 180      {
 181          return $this->ownerDocument->query($expr, $this);
 182      }
 183   
 184      /**
 185      * Remove this element from the document
 186      *
 187      * @return void
 188      */
 189      public function remove(): void
 190      {
 191          $this->parentOrThrow()->removeChild($this);
 192      }
 193   
 194      /**
 195      * Replace this element with given nodes/text
 196      *
 197      * @param  DOMNode|string $nodes
 198      * @return void
 199      */
 200      public function replaceWith(...$nodes): void
 201      {
 202          $parentNode = $this->parentOrThrow(new DOMException('No Modification Allowed Error', DOM_NO_MODIFICATION_ALLOWED_ERR));
 203   
 204          foreach ($nodes as $node)
 205          {
 206              if (!($node instanceof DOMNode))
 207              {
 208                  $node = $this->ownerDocument->createTextNode((string) $node);
 209              }
 210              $parentNode->insertBefore($node, $this);
 211          }
 212          $parentNode->removeChild($this);
 213      }
 214   
 215      /**
 216      * Add namespace declarations that may be missing in given XML
 217      *
 218      * @param  string $xml Original XML
 219      * @return string      Modified XML
 220      */
 221      protected function addMissingNamespaceDeclarations(string $xml): string
 222      {
 223          preg_match_all('(xmlns:\\K[-\\w]++(?==))', $xml, $m);
 224          $prefixes = array_flip($m[0]);
 225   
 226          return preg_replace_callback(
 227              '(<([-\\w]++):[^>]*?\\K\\s*/?>)',
 228              function ($m) use ($prefixes)
 229              {
 230                  $return = $m[0];
 231                  $prefix = $m[1];
 232                  if (!isset($prefixes[$prefix]))
 233                  {
 234                      $nsURI  = $this->lookupNamespaceURI($prefix);
 235                      $return = ' xmlns:' . $prefix . '="' . htmlspecialchars($nsURI, ENT_XML1) . '"' . $return;
 236                  }
 237   
 238                  return $return;
 239              },
 240              $xml
 241          );
 242      }
 243   
 244      /**
 245      * Insert given node relative to this element's position
 246      *
 247      * @param  string  $where One of 'beforebegin', 'afterbegin', 'beforeend', 'afterend'
 248      * @param  DOMNode $node
 249      * @return void
 250      */
 251      protected function insertAdjacentNode(string $where, DOMNode $node): void
 252      {
 253          switch (strtolower($where))
 254          {
 255              case 'afterbegin':
 256                  $this->insertBefore($node, $this->firstChild);
 257                  break;
 258   
 259              case 'afterend':
 260                  if (isset($this->parentNode))
 261                  {
 262                      $this->parentNode->insertBefore($node, $this->nextSibling);
 263                  }
 264                  break;
 265   
 266              case 'beforebegin':
 267                  if (isset($this->parentNode))
 268                  {
 269                      $this->parentNode->insertBefore($node, $this);
 270                  }
 271                  break;
 272   
 273              case 'beforeend':
 274                  $this->appendChild($node);
 275                  break;
 276   
 277              default:
 278                  throw new DOMException("'$where' is not one of 'beforebegin', 'afterbegin', 'beforeend', or 'afterend'", DOM_SYNTAX_ERR);
 279          }
 280      }
 281   
 282      /**
 283      * Create and insert an element at given position
 284      *
 285      * @param  string $where    One of 'beforebegin', 'afterbegin', 'beforeend', 'afterend'
 286      * @param  string $nodeName Element's nodeName
 287      * @param  string $text     Text content
 288      * @return self
 289      */
 290      protected function insertElement(string $where, string $nodeName, string $text): self
 291      {
 292          $text = htmlspecialchars($text, ENT_NOQUOTES);
 293          $pos  = strpos($nodeName, ':');
 294          if ($pos === false)
 295          {
 296              $element = $this->ownerDocument->createElement($nodeName, $text);
 297          }
 298          else
 299          {
 300              $prefix       = substr($nodeName, 0, $pos);
 301              $namespaceURI = $this->ownerDocument->lookupNamespaceURI($prefix);
 302              $element      = $this->ownerDocument->createElementNS($namespaceURI, $nodeName, $text);
 303          }
 304   
 305          return $this->insertAdjacentElement($where, $element);
 306      }
 307   
 308      /**
 309      * Insert given text relative to this element's position
 310      *
 311      * @param  string  $where One of 'beforebegin', 'afterbegin', 'beforeend', 'afterend'
 312      * @param  string  $text
 313      * @return DOMText
 314      */
 315      protected function insertText(string $where, string $text): DOMText
 316      {
 317          $node = $this->ownerDocument->createTextNode($text);
 318          $this->insertAdjacentNode($where, $node);
 319   
 320          return $node;
 321      }
 322   
 323      /**
 324      * Create and insert an XSL element at given position
 325      *
 326      * @param  string $where     One of 'beforebegin', 'afterbegin', 'beforeend', 'afterend'
 327      * @param  string $localName Element's localName
 328      * @param  array  $arguments Arguments passed to the Document::create* function
 329      * @return self
 330      */
 331      protected function insertXslElement(string $where, string $localName, array $arguments): self
 332      {
 333          $callback = [$this->ownerDocument, 'createXsl' . ucfirst($localName)];
 334          if (!is_callable($callback))
 335          {
 336              throw new BadMethodCallException;
 337          }
 338   
 339          $element = call_user_func_array($callback, $arguments);
 340   
 341          return $this->insertAdjacentElement($where, $element);
 342      }
 343   
 344      /**
 345      * Return this element's parent element if available, or throw an exception
 346      *
 347      * @param  DOMException $previous Previous exception
 348      * @return DOMNode
 349      */
 350      protected function parentOrThrow(DOMException $previous = null): DOMNode
 351      {
 352          if (isset($this->parentNode))
 353          {
 354              return $this->parentNode;
 355          }
 356   
 357          throw new DOMException('Not Found Error', DOM_NOT_FOUND_ERR, $previous);
 358      }
 359  }