Seditio Source
Root |
./othercms/phpBB3/vendor/s9e/text-formatter/src/Configurator/TemplateChecks/AbstractXSLSupportCheck.php
<?php declare(strict_types=1);

/**
* @package   s9e\TextFormatter
* @copyright Copyright (c) 2010-2021 The s9e authors
* @license   http://www.opensource.org/licenses/mit-license.php The MIT License
*/
namespace s9e\TextFormatter\Configurator\TemplateChecks;

use
DOMElement;
use
DOMXPath;
use
RuntimeException;
use
s9e\TextFormatter\Configurator\Helpers\AVTHelper;
use
s9e\TextFormatter\Configurator\Items\Tag;
use
s9e\TextFormatter\Configurator\TemplateCheck;

abstract class
AbstractXSLSupportCheck extends TemplateCheck
{
   
/**
    * @var string[] List of supported XSL elements (local name only)
    */
   
protected $supportedElements = [];

   
/**
    * @var string[] List of supported XPath functions
    */
   
protected $supportedFunctions = [];

   
/**
    * @var string[] List of supported XPath operators
    */
   
protected $supportedOperators = ['and', 'div', 'mod', 'or'];

   
/**
    * Check for elements not supported by the PHP renderer
    *
    * @param DOMElement $template <xsl:template/> node
    * @param Tag        $tag      Tag this template belongs to
    */
   
public function check(DOMElement $template, Tag $tag): void
   
{
       
$this->checkXslElements($template);
       
$this->checkXPathExpressions($template);
    }

   
/**
    * Check given XPath expression
    */
   
protected function checkXPathExpression(string $expr): void
   
{
       
preg_match_all('("[^"]*+"|\'[^\']*+\'|((?:[a-z]++-)*+[a-z]++)(?=\\s*\\())', $expr, $m);
        foreach (
array_filter($m[1]) as $funcName)
        {
            if (!
in_array($funcName, $this->supportedFunctions, true)
             && !
in_array($funcName, $this->supportedOperators, true))
            {
                throw new
RuntimeException('XPath function ' . $funcName . '() is not supported');
            }
        }
    }

   
/**
    * Check all XPath expressions in given template
    */
   
protected function checkXPathExpressions(DOMElement $template): void
   
{
        foreach (
$this->getXPathExpressions($template) as $expr)
        {
           
$this->checkXPathExpression($expr);
        }
    }

   
/**
    * Check all XSL elements in given template
    */
   
protected function checkXslElements(DOMElement $template): void
   
{
       
$xpath = new DOMXPath($template->ownerDocument);
       
$nodes = $xpath->query('/xsl:template//xsl:*');
        foreach (
$nodes as $node)
        {
            if (!
in_array($node->localName, $this->supportedElements, true))
            {
                throw new
RuntimeException('xsl:' . $node->localName . ' elements are not supported');
            }

           
$methodName = 'checkXsl' . str_replace(' ', '', ucwords(str_replace('-', ' ', $node->localName))) . 'Element';
            if (
method_exists($this, $methodName))
            {
               
$this->$methodName($node);
            }
        }
    }

   
/**
    * Return all XPath expressions in given template
    */
   
protected function getXPathExpressions(DOMElement $template): array
    {
       
$exprs = [];
       
$xpath = new DOMXPath($template->ownerDocument);

       
$query = '//xsl:*/@name | //*[namespace-uri() != "' . self::XMLNS_XSL . '"]/@*[contains(., "{")]';
        foreach (
$xpath->query($query) as $attribute)
        {
            foreach (
AVTHelper::parse($attribute->value) as [$type, $content])
            {
                if (
$type === 'expression')
                {
                   
$exprs[] = $content;
                }
            }
        }

       
$query = '//xsl:*/@select | //xsl:*/@test';
        foreach (
$xpath->query($query) as $attribute)
        {
           
$exprs[] = $attribute->value;
        }

        return
$exprs;
    }
}