Seditio Source
Root |
./othercms/phpBB3/vendor/s9e/sweetdom/src/Element.php
<?php declare(strict_types=1);

/**
* @package   s9e\SweetDOM
* @copyright Copyright (c) 2019-2020 The s9e authors
* @license   http://www.opensource.org/licenses/mit-license.php The MIT License
*/
namespace s9e\SweetDOM;

use
BadMethodCallException;
use
DOMElement;
use
DOMNode;
use
DOMNodeList;
use
InvalidArgumentException;

/**
* @method self appendXslApplyTemplates(string $select = null)
* @method self appendXslApplyTemplatesSibling(string $select = null)
* @method self appendXslAttribute(string $name, string $text = '')
* @method self appendXslAttributeSibling(string $name, string $text = '')
* @method self appendXslChoose()
* @method self appendXslChooseSibling()
* @method self appendXslComment(string $text = '')
* @method self appendXslCommentSibling(string $text = '')
* @method self appendXslCopyOf(string $select)
* @method self appendXslCopyOfSibling(string $select)
* @method self appendXslIf(string $test, string $text = '')
* @method self appendXslIfSibling(string $test, string $text = '')
* @method self appendXslOtherwise(string $text = '')
* @method self appendXslOtherwiseSibling(string $text = '')
* @method self appendXslText(string $text = '')
* @method self appendXslTextSibling(string $text = '')
* @method self appendXslValueOf(string $select)
* @method self appendXslValueOfSibling(string $select)
* @method self appendXslVariable(string $name, string $select = null)
* @method self appendXslVariableSibling(string $name, string $select = null)
* @method self appendXslWhen(string $test, string $text = '')
* @method self appendXslWhenSibling(string $test, string $text = '')
* @method self prependXslApplyTemplates(string $select = null)
* @method self prependXslApplyTemplatesSibling(string $select = null)
* @method self prependXslAttribute(string $name, string $text = '')
* @method self prependXslAttributeSibling(string $name, string $text = '')
* @method self prependXslChoose()
* @method self prependXslChooseSibling()
* @method self prependXslComment(string $text = '')
* @method self prependXslCommentSibling(string $text = '')
* @method self prependXslCopyOf(string $select)
* @method self prependXslCopyOfSibling(string $select)
* @method self prependXslIf(string $test, string $text = '')
* @method self prependXslIfSibling(string $test, string $text = '')
* @method self prependXslOtherwise(string $text = '')
* @method self prependXslOtherwiseSibling(string $text = '')
* @method self prependXslText(string $text = '')
* @method self prependXslTextSibling(string $text = '')
* @method self prependXslValueOf(string $select)
* @method self prependXslValueOfSibling(string $select)
* @method self prependXslVariable(string $name, string $select = null)
* @method self prependXslVariableSibling(string $name, string $select = null)
* @method self prependXslWhen(string $test, string $text = '')
* @method self prependXslWhenSibling(string $test, string $text = '')
*/
class Element extends DOMElement
{
    public function
__call(string $name, array $arguments)
    {
        if (
preg_match('(^(append|prepend)(xsl\\w+?)(sibling|)$)', strtolower($name), $m))
        {
           
$callback = [$this->ownerDocument, 'create' . $m[2]];
            if (
is_callable($callback))
            {
               
$element = call_user_func_array($callback, $arguments);
               
$where   = [
                   
'append'         => 'beforeend',
                   
'appendsibling'  => 'afterend',
                   
'prepend'        => 'afterbegin',
                   
'prependsibling' => 'beforebegin'
               
];

                return
$this->insertAdjacentElement($where[$m[1] . $m[3]], $element);
            }
        }

        throw new
BadMethodCallException;
    }

   
/**
    * Evaluate and return the result of a given XPath expression using this element as context node
    *
    * @param  string  $expr XPath expression
    * @return mixed
    */
   
public function evaluate(string $expr)
    {
        return
$this->ownerDocument->evaluate($expr, $this);
    }

   
/**
    * Evaluate and return the first element of a given XPath query using this element as context node
    *
    * @param  string       $expr XPath expression
    * @return DOMNode|null
    */
   
public function firstOf(string $expr): ?DOMNode
   
{
        return
$this->ownerDocument->firstOf($expr, $this);
    }

   
/**
    * Insert given element relative to this element's position
    *
    * @param  string $where   One of 'beforebegin', 'afterbegin', 'beforeend', 'afterend'
    * @param  self   $element
    * @return self
    */
   
public function insertAdjacentElement(string $where, self $element): self
   
{
       
$this->insertAdjacentNode($where, $element);

        return
$element;
    }

   
/**
    * Insert given text relative to this element's position
    *
    * @param  string $where One of 'beforebegin', 'afterbegin', 'beforeend', 'afterend'
    * @param  string $text
    * @return void
    */
   
public function insertAdjacentText(string $where, string $text): void
   
{
       
$this->insertAdjacentXML($where, htmlspecialchars($text, ENT_XML1));
    }

   
/**
    * Insert given XML relative to this element's position
    *
    * @param  string $where One of 'beforebegin', 'afterbegin', 'beforeend', 'afterend'
    * @param  string $xml
    * @return void
    */
   
public function insertAdjacentXML(string $where, string $xml): void
   
{
       
$fragment = $this->ownerDocument->createDocumentFragment();
       
$fragment->appendXML($this->addMissingNamespaceDeclarations($xml));

       
$this->insertAdjacentNode($where, $fragment);
    }

   
/**
    * Evaluate and return the result of a given XPath query using this element as context node
    *
    * @param  string      $expr XPath expression
    * @return DOMNodeList
    */
   
public function query(string $expr): DOMNodeList
   
{
        return
$this->ownerDocument->query($expr, $this);
    }

   
/**
    * Remove this element from the document
    *
    * @return void
    */
   
public function remove(): void
   
{
       
$this->parentNode->removeChild($this);
    }

   
/**
    * Replace this element with given nodes/text
    *
    * @param  DOMNode|string $nodes
    * @return void
    */
   
public function replaceWith(...$nodes): void
   
{
        foreach (
$nodes as $node)
        {
            if (!(
$node instanceof DOMNode))
            {
               
$node = $this->ownerDocument->createTextNode((string) $node);
            }
           
$this->parentNode->insertBefore($node, $this);
        }
       
$this->parentNode->removeChild($this);
    }

   
/**
    * Add namespace declarations that may be missing in given XML
    *
    * @param  string $xml Original XML
    * @return string      Modified XML
    */
   
protected function addMissingNamespaceDeclarations(string $xml): string
   
{
       
preg_match_all('(xmlns:\\K[-\\w]++(?==))', $xml, $m);
       
$prefixes = array_flip($m[0]);

        return
preg_replace_callback(
           
'(<([-\\w]++):[^>]*?\\K\\s*/?>)',
            function (
$m) use ($prefixes)
            {
               
$return = $m[0];
               
$prefix = $m[1];
                if (!isset(
$prefixes[$prefix]))
                {
                   
$nsURI  = $this->lookupNamespaceURI($prefix);
                   
$return = ' xmlns:' . $prefix . '="' . htmlspecialchars($nsURI, ENT_XML1) . '"' . $return;
                }

                return
$return;
            },
           
$xml
       
);
    }

   
/**
    * Insert given node relative to this element's position
    *
    * @param  string  $where One of 'beforebegin', 'afterbegin', 'beforeend', 'afterend'
    * @param  DOMNode $node
    * @return void
    */
   
protected function insertAdjacentNode(string $where, DOMNode $node): void
   
{
       
$where = strtolower($where);
        if (
$where === 'beforebegin')
        {
           
$this->parentNode->insertBefore($node, $this);
        }
        elseif (
$where === 'beforeend')
        {
           
$this->appendChild($node);
        }
        elseif (
$where === 'afterend')
        {
           
$this->parentNode->insertBefore($node, $this->nextSibling);
        }
        elseif (
$where === 'afterbegin')
        {
           
$this->insertBefore($node, $this->firstChild);
        }
        else
        {
            throw new
InvalidArgumentException;
        }
    }
}