[ Index ]

PHP Cross Reference of phpBB-3.3.14-deutsch

title

Body

[close]

/vendor/s9e/text-formatter/src/Configurator/RendererGenerators/PHP/ -> XPathConvertor.php (source)

   1  <?php
   2  
   3  /**
   4  * @package   s9e\TextFormatter
   5  * @copyright Copyright (c) 2010-2022 The s9e authors
   6  * @license   http://www.opensource.org/licenses/mit-license.php The MIT License
   7  */
   8  namespace s9e\TextFormatter\Configurator\RendererGenerators\PHP;
   9  
  10  use RuntimeException;
  11  use s9e\TextFormatter\Configurator\RecursiveParser;
  12  use s9e\TextFormatter\Configurator\RendererGenerators\PHP\XPathConvertor\Convertors\BooleanFunctions;
  13  use s9e\TextFormatter\Configurator\RendererGenerators\PHP\XPathConvertor\Convertors\BooleanOperators;
  14  use s9e\TextFormatter\Configurator\RendererGenerators\PHP\XPathConvertor\Convertors\Comparisons;
  15  use s9e\TextFormatter\Configurator\RendererGenerators\PHP\XPathConvertor\Convertors\Core;
  16  use s9e\TextFormatter\Configurator\RendererGenerators\PHP\XPathConvertor\Convertors\Math;
  17  use s9e\TextFormatter\Configurator\RendererGenerators\PHP\XPathConvertor\Convertors\MultiByteStringManipulation;
  18  use s9e\TextFormatter\Configurator\RendererGenerators\PHP\XPathConvertor\Convertors\PHP80Functions;
  19  use s9e\TextFormatter\Configurator\RendererGenerators\PHP\XPathConvertor\Convertors\SingleByteStringFunctions;
  20  use s9e\TextFormatter\Configurator\RendererGenerators\PHP\XPathConvertor\Convertors\SingleByteStringManipulation;
  21  
  22  class XPathConvertor
  23  {
  24      /**
  25      * @var array Array of togglable PHP features ("mbstring" and "php80")
  26      */
  27      public $features;
  28  
  29      /**
  30      * @var RecursiveParser
  31      */
  32      protected $parser;
  33  
  34      /**
  35      * Constructor
  36      */
  37  	public function __construct(RecursiveParser $parser = null)
  38      {
  39          $this->features = [
  40              'mbstring' => extension_loaded('mbstring'),
  41              'php80'    => version_compare(PHP_VERSION, '8.0', '>=')
  42          ];
  43          if (isset($parser))
  44          {
  45              $this->parser = $parser;
  46          }
  47      }
  48  
  49      /**
  50      * Convert an XPath expression (used in a condition) into PHP code
  51      *
  52      * This method is similar to convertXPath() but it selectively replaces some simple conditions
  53      * with the corresponding DOM method for performance reasons
  54      *
  55      * @param  string $expr XPath expression
  56      * @return string       PHP code
  57      */
  58  	public function convertCondition($expr)
  59      {
  60          // Replace @attr with boolean(@attr) in boolean expressions
  61          $expr = preg_replace(
  62              '((^|(?<!\\bboolean)\\(\\s*|\\b(?:and|or)\\s*)([\\(\\s]*)([$@][-\\w]+|@\\*)([\\)\\s]*)(?=$|\\s+(?:and|or)))',
  63              '$1$2boolean($3)$4',
  64              trim($expr)
  65          );
  66  
  67          // Replace not(boolean(@attr)) with not(@attr)
  68          $expr = preg_replace(
  69              '(not\\(boolean\\(([$@][-\\w]+)\\)\\))',
  70              'not($1)',
  71              $expr
  72          );
  73  
  74          try
  75          {
  76              return $this->getParser()->parse($expr)['value'];
  77          }
  78          catch (RuntimeException $e)
  79          {
  80              // Do nothing
  81          }
  82  
  83          // If the condition does not seem to contain a relational expression, or start with a
  84          // function call, we wrap it inside of a boolean() call
  85          if (!preg_match('([=<>]|\\bor\\b|\\band\\b|^[-\\w]+\\s*\\()', $expr))
  86          {
  87              $expr = 'boolean(' . $expr . ')';
  88          }
  89  
  90          return '$this->xpath->evaluate(' . $this->exportXPath($expr) . ',$node)';
  91      }
  92  
  93      /**
  94      * Convert an XPath expression (used as value) into PHP code
  95      *
  96      * @param  string $expr XPath expression
  97      * @return string       PHP code
  98      */
  99  	public function convertXPath($expr)
 100      {
 101          $expr = trim($expr);
 102          try
 103          {
 104              return $this->getParser()->parse($expr)['value'];
 105          }
 106          catch (RuntimeException $e)
 107          {
 108              // Do nothing
 109          }
 110  
 111          // Make sure the expression evaluates as a string
 112          if (!preg_match('(^[-\\w]*s(?:late|pace|tring)[-\\w]*\\()', $expr))
 113          {
 114              $expr = 'string(' . $expr . ')';
 115          }
 116  
 117          return '$this->xpath->evaluate(' . $this->exportXPath($expr) . ',$node)';
 118      }
 119  
 120      /**
 121      * Export an XPath expression as PHP with special consideration for XPath variables
 122      *
 123      * Will return PHP source representing the XPath expression, with special consideration for XPath
 124      * variables which are returned as a method call to XPath::export()
 125      *
 126      * @param  string $expr XPath expression
 127      * @return string       PHP representation of the expression
 128      */
 129  	protected function exportXPath($expr)
 130      {
 131          $phpTokens = [];
 132          foreach ($this->tokenizeXPathForExport($expr) as [$type, $content])
 133          {
 134              $methodName  = 'exportXPath' . $type;
 135              $phpTokens[] = $this->$methodName($content);
 136          }
 137  
 138          return implode('.', $phpTokens);
 139      }
 140  
 141      /**
 142      * Convert a "current()" XPath expression to its PHP source representation
 143      *
 144      * @return string
 145      */
 146  	protected function exportXPathCurrent()
 147      {
 148          return '$node->getNodePath()';
 149      }
 150  
 151      /**
 152      * Convert a fragment of an XPath expression to its PHP source representation
 153      *
 154      * @param  string $fragment
 155      * @return string
 156      */
 157  	protected function exportXPathFragment($fragment)
 158      {
 159          return var_export($fragment, true);
 160      }
 161  
 162      /**
 163      * Convert an XSLT parameter to its PHP source representation
 164      *
 165      * @param  string $param Parameter, including the leading $
 166      * @return string
 167      */
 168  	protected function exportXPathParam($param)
 169      {
 170          $paramName = ltrim($param, '$');
 171  
 172          return '$this->getParamAsXPath(' . var_export($paramName, true) . ')';
 173      }
 174  
 175      /**
 176      * Generate and return the a parser with the default set of matchers
 177      *
 178      * @return RecursiveParser
 179      */
 180  	protected function getDefaultParser()
 181      {
 182          $parser     = new RecursiveParser;
 183          $matchers   = [];
 184          $matchers[] = new SingleByteStringFunctions($parser);
 185          $matchers[] = new BooleanFunctions($parser);
 186          $matchers[] = new BooleanOperators($parser);
 187          $matchers[] = new Comparisons($parser);
 188          $matchers[] = new Core($parser);
 189          $matchers[] = new Math($parser);
 190          if (!empty($this->features['mbstring']))
 191          {
 192              $matchers[] = new MultiByteStringManipulation($parser);
 193          }
 194          $matchers[] = new SingleByteStringManipulation($parser);
 195          if (!empty($this->features['php80']))
 196          {
 197              $matchers[] = new PHP80Functions($parser);
 198          }
 199  
 200          $parser->setMatchers($matchers);
 201  
 202          return $parser;
 203      }
 204  
 205      /**
 206      * Return (and if necessary, create) the cached instance of the XPath parser
 207      *
 208      * @return RecursiveParser
 209      */
 210  	protected function getParser(): RecursiveParser
 211      {
 212          if (!isset($this->parser))
 213          {
 214              $this->parser = $this->getDefaultParser();
 215          }
 216  
 217          return $this->parser;
 218      }
 219  
 220      /**
 221      * Tokenize an XPath expression for use in PHP
 222      *
 223      * @param  string $expr XPath expression
 224      * @return array
 225      */
 226  	protected function tokenizeXPathForExport($expr)
 227      {
 228          $tokenExprs = [
 229              '(*:Current)\\bcurrent\\(\\)',
 230              '(*:Param)\\$\\w+',
 231              '(*:Fragment)(?:"[^"]*"|\'[^\']*\'|(?!current\\(\\)|\\$\\w).)++'
 232          ];
 233          preg_match_all('(' . implode('|', $tokenExprs) . ')s', $expr, $matches, PREG_SET_ORDER);
 234  
 235          $tokens = [];
 236          foreach ($matches as $m)
 237          {
 238              $tokens[] = [$m['MARK'], $m[0]];
 239          }
 240  
 241          return $tokens;
 242      }
 243  }


Generated: Mon Nov 25 19:05:08 2024 Cross-referenced by PHPXref 0.7.1