[ Index ]

PHP Cross Reference of phpBB-3.3.12-deutsch

title

Body

[close]

/vendor/s9e/sweetdom/src/ -> Element.php (source)

   1  <?php declare(strict_types=1);
   2  
   3  /**
   4  * @package   s9e\SweetDOM
   5  * @copyright Copyright (c) 2019-2021 The s9e authors
   6  * @license   http://www.opensource.org/licenses/mit-license.php The MIT License
   7  */
   8  namespace s9e\SweetDOM;
   9  
  10  use BadMethodCallException;
  11  use DOMElement;
  12  use DOMException;
  13  use DOMNode;
  14  use DOMNodeList;
  15  use DOMText;
  16  
  17  /**
  18  * @method self appendElement(string $nodeName, $text = '')
  19  * @method self appendElementSibling(string $nodeName, $text = '')
  20  * @method DOMText appendText(string $text)
  21  * @method DOMText appendTextSibling(string $text)
  22  * @method self appendXslApplyTemplates(string $select = null)
  23  * @method self appendXslApplyTemplatesSibling(string $select = null)
  24  * @method self appendXslAttribute(string $name, string $text = '')
  25  * @method self appendXslAttributeSibling(string $name, string $text = '')
  26  * @method self appendXslChoose()
  27  * @method self appendXslChooseSibling()
  28  * @method self appendXslComment(string $text = '')
  29  * @method self appendXslCommentSibling(string $text = '')
  30  * @method self appendXslCopyOf(string $select)
  31  * @method self appendXslCopyOfSibling(string $select)
  32  * @method self appendXslIf(string $test, string $text = '')
  33  * @method self appendXslIfSibling(string $test, string $text = '')
  34  * @method self appendXslOtherwise(string $text = '')
  35  * @method self appendXslOtherwiseSibling(string $text = '')
  36  * @method self appendXslText(string $text = '')
  37  * @method self appendXslTextSibling(string $text = '')
  38  * @method self appendXslValueOf(string $select)
  39  * @method self appendXslValueOfSibling(string $select)
  40  * @method self appendXslVariable(string $name, string $select = null)
  41  * @method self appendXslVariableSibling(string $name, string $select = null)
  42  * @method self appendXslWhen(string $test, string $text = '')
  43  * @method self appendXslWhenSibling(string $test, string $text = '')
  44  * @method self prependElement(string $nodeName, $text = '')
  45  * @method self prependElementSibling(string $nodeName, $text = '')
  46  * @method DOMText prependText(string $text)
  47  * @method DOMText prependTextSibling(string $text)
  48  * @method self prependXslApplyTemplates(string $select = null)
  49  * @method self prependXslApplyTemplatesSibling(string $select = null)
  50  * @method self prependXslAttribute(string $name, string $text = '')
  51  * @method self prependXslAttributeSibling(string $name, string $text = '')
  52  * @method self prependXslChoose()
  53  * @method self prependXslChooseSibling()
  54  * @method self prependXslComment(string $text = '')
  55  * @method self prependXslCommentSibling(string $text = '')
  56  * @method self prependXslCopyOf(string $select)
  57  * @method self prependXslCopyOfSibling(string $select)
  58  * @method self prependXslIf(string $test, string $text = '')
  59  * @method self prependXslIfSibling(string $test, string $text = '')
  60  * @method self prependXslOtherwise(string $text = '')
  61  * @method self prependXslOtherwiseSibling(string $text = '')
  62  * @method self prependXslText(string $text = '')
  63  * @method self prependXslTextSibling(string $text = '')
  64  * @method self prependXslValueOf(string $select)
  65  * @method self prependXslValueOfSibling(string $select)
  66  * @method self prependXslVariable(string $name, string $select = null)
  67  * @method self prependXslVariableSibling(string $name, string $select = null)
  68  * @method self prependXslWhen(string $test, string $text = '')
  69  * @method self prependXslWhenSibling(string $test, string $text = '')
  70  * @property Document $ownerDocument
  71  */
  72  class Element extends DOMElement
  73  {
  74  	public function __call(string $name, array $arguments)
  75      {
  76          $name      = strtolower($name);
  77          $positions = [
  78              'append'         => 'beforeend',
  79              'appendsibling'  => 'afterend',
  80              'prepend'        => 'afterbegin',
  81              'prependsibling' => 'beforebegin'
  82          ];
  83  
  84          if (preg_match('(^(append|prepend)xsl(\\w+?)(sibling|)$)', $name, $m))
  85          {
  86              $localName = $m[2];
  87              $where     = $positions[$m[1] . $m[3]];
  88  
  89              return $this->insertXslElement($where, $localName, $arguments);
  90          }
  91          if (preg_match('(^(append|prepend)element(sibling|)$)', $name, $m))
  92          {
  93              $nodeName = $arguments[0];
  94              $text     = $arguments[1] ?? '';
  95              $where    = $positions[$m[1] . $m[2]];
  96  
  97              return $this->insertElement($where, $nodeName, $text);
  98          }
  99          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  }


Generated: Sun Jun 23 12:25:44 2024 Cross-referenced by PHPXref 0.7.1