[ Index ]

PHP Cross Reference of phpBB-3.2.11-deutsch

title

Body

[close]

/vendor/s9e/text-formatter/src/Plugins/Preg/ -> Configurator.php (source)

   1  <?php
   2  
   3  /*
   4  * @package   s9e\TextFormatter
   5  * @copyright Copyright (c) 2010-2019 The s9e Authors
   6  * @license   http://www.opensource.org/licenses/mit-license.php The MIT License
   7  */
   8  namespace s9e\TextFormatter\Plugins\Preg;
   9  use DOMAttr;
  10  use DOMText;
  11  use DOMXPath;
  12  use Exception;
  13  use InvalidArgumentException;
  14  use s9e\TextFormatter\Configurator\Helpers\RegexpParser;
  15  use s9e\TextFormatter\Configurator\Helpers\TemplateHelper;
  16  use s9e\TextFormatter\Configurator\Items\Regexp;
  17  use s9e\TextFormatter\Configurator\Items\Tag;
  18  use s9e\TextFormatter\Configurator\JavaScript\RegexpConvertor;
  19  use s9e\TextFormatter\Configurator\Validators\TagName;
  20  use s9e\TextFormatter\Plugins\ConfiguratorBase;
  21  class Configurator extends ConfiguratorBase
  22  {
  23      protected $captures;
  24      protected $collection = [];
  25      protected $delimiter;
  26      protected $modifiers;
  27      protected $references;
  28      protected $referencesRegexp = '((?<!\\\\)(?:\\\\\\\\)*\\K(?:[$\\\\]\\d+|\\$\\{\\d+\\}))S';
  29  	public function asConfig()
  30      {
  31          if (!\count($this->collection))
  32              return;
  33          $pregs = [];
  34          foreach ($this->collection as $_ca164be8)
  35          {
  36              list($tagName, $regexp, $passthroughIdx) = $_ca164be8;
  37              $captures = RegexpParser::getCaptureNames($regexp);
  38              $pregs[]  = [$tagName, new Regexp($regexp, \true), $passthroughIdx, $captures];
  39          }
  40          return ['generics' => $pregs];
  41      }
  42  	public function getJSHints()
  43      {
  44          $hasPassthrough = \false;
  45          foreach ($this->collection as $_ca164be8)
  46          {
  47              list($tagName, $regexp, $passthroughIdx) = $_ca164be8;
  48              if ($passthroughIdx)
  49              {
  50                  $hasPassthrough = \true;
  51                  break;
  52              }
  53          }
  54          return ['PREG_HAS_PASSTHROUGH' => $hasPassthrough];
  55      }
  56  	public function match($regexp, $tagName)
  57      {
  58          $tagName        = TagName::normalize($tagName);
  59          $passthroughIdx = 0;
  60          $this->parseRegexp($regexp);
  61          foreach ($this->captures as $i => $capture)
  62          {
  63              if (!$this->isCatchAll($capture['expr']))
  64                  continue;
  65              $passthroughIdx = $i;
  66          }
  67          $this->collection[] = [$tagName, $regexp, $passthroughIdx];
  68      }
  69  	public function replace($regexp, $template, $tagName = \null)
  70      {
  71          if (!isset($tagName))
  72              $tagName = 'PREG_' . \strtoupper(\dechex(\crc32($regexp)));
  73          $this->parseRegexp($regexp);
  74          $this->parseTemplate($template);
  75          $passthroughIdx = $this->getPassthroughCapture();
  76          if ($passthroughIdx)
  77              $this->captures[$passthroughIdx]['passthrough'] = \true;
  78          $regexp   = $this->fixUnnamedCaptures($regexp);
  79          $template = $this->convertTemplate($template, $passthroughIdx);
  80          $this->collection[] = [$tagName, $regexp, $passthroughIdx];
  81          return $this->createTag($tagName, $template);
  82      }
  83  	protected function addAttribute(Tag $tag, $attrName)
  84      {
  85          $isUrl = \false;
  86          $exprs = [];
  87          foreach ($this->captures as $key => $capture)
  88          {
  89              if ($capture['name'] !== $attrName)
  90                  continue;
  91              $exprs[] = $capture['expr'];
  92              if (isset($this->references['asUrl'][$key]))
  93                  $isUrl = \true;
  94          }
  95          $exprs = \array_unique($exprs);
  96          $regexp = $this->delimiter . '^';
  97          $regexp .= (\count($exprs) === 1) ? $exprs[0] : '(?:' . \implode('|', $exprs) . ')';
  98          $regexp .= '$' . $this->delimiter . 'D' . $this->modifiers;
  99          $attribute = $tag->attributes->add($attrName);
 100          $filter = $this->configurator->attributeFilters['#regexp'];
 101          $filter->setRegexp($regexp);
 102          $attribute->filterChain[] = $filter;
 103          if ($isUrl)
 104          {
 105              $filter = $this->configurator->attributeFilters['#url'];
 106              $attribute->filterChain[] = $filter;
 107          }
 108      }
 109  	protected function convertTemplate($template, $passthroughIdx)
 110      {
 111          $template = TemplateHelper::replaceTokens(
 112              $template,
 113              $this->referencesRegexp,
 114              function ($m, $node) use ($passthroughIdx)
 115              {
 116                  $key = (int) \trim($m[0], '\\${}');
 117                  if ($key === 0)
 118                      return ['expression', '.'];
 119                  if ($key === $passthroughIdx && $node instanceof DOMText)
 120                      return ['passthrough'];
 121                  if (isset($this->captures[$key]['name']))
 122                      return ['expression', '@' . $this->captures[$key]['name']];
 123                  return ['literal', ''];
 124              }
 125          );
 126          $template = TemplateHelper::replaceTokens(
 127              $template,
 128              '(\\\\+[0-9${\\\\])',
 129              function ($m)
 130              {
 131                  return ['literal', \stripslashes($m[0])];
 132              }
 133          );
 134          return $template;
 135      }
 136  	protected function createTag($tagName, $template)
 137      {
 138          $tag = new Tag;
 139          foreach ($this->captures as $key => $capture)
 140          {
 141              if (!isset($capture['name']))
 142                  continue;
 143              $attrName = $capture['name'];
 144              if (isset($tag->attributes[$attrName]))
 145                  continue;
 146              $this->addAttribute($tag, $attrName);
 147          }
 148          $tag->template = $template;
 149          $this->configurator->templateNormalizer->normalizeTag($tag);
 150          $this->configurator->templateChecker->checkTag($tag);
 151          return $this->configurator->tags->add($tagName, $tag);
 152      }
 153  	protected function fixUnnamedCaptures($regexp)
 154      {
 155          $keys = [];
 156          foreach ($this->references['anywhere'] as $key)
 157          {
 158              $capture = $this->captures[$key];
 159              if (!$key || isset($capture['name']))
 160                  continue;
 161              if (isset($this->references['asUrl'][$key]) || !isset($capture['passthrough']))
 162                  $keys[] = $key;
 163          }
 164          \rsort($keys);
 165          foreach ($keys as $key)
 166          {
 167              $name   = '_' . $key;
 168              $pos    = $this->captures[$key]['pos'];
 169              $regexp = \substr_replace($regexp, "?'" . $name . "'", 2 + $pos, 0);
 170              $this->captures[$key]['name'] = $name;
 171          }
 172          return $regexp;
 173      }
 174  	protected function getPassthroughCapture()
 175      {
 176          $passthrough = 0;
 177          foreach ($this->references['inText'] as $key)
 178          {
 179              if (!$this->isCatchAll($this->captures[$key]['expr']))
 180                  continue;
 181              if ($passthrough)
 182              {
 183                  $passthrough = 0;
 184                  break;
 185              }
 186              $passthrough = (int) $key;
 187          }
 188          return $passthrough;
 189      }
 190  	protected function getRegexpInfo($regexp)
 191      {
 192          if (@\preg_match_all($regexp, '') === \false)
 193              throw new InvalidArgumentException('Invalid regexp');
 194          return RegexpParser::parse($regexp);
 195      }
 196  	protected function isCatchAll($expr)
 197      {
 198          return (bool) \preg_match('(^\\.[*+]\\??$)D', $expr);
 199      }
 200  	protected function parseRegexp($regexp)
 201      {
 202          $this->captures = [['name' => \null, 'expr' => \null]];
 203          $regexpInfo = $this->getRegexpInfo($regexp);
 204          $this->delimiter = $regexpInfo['delimiter'];
 205          $this->modifiers = \str_replace('D', '', $regexpInfo['modifiers']);
 206          foreach ($regexpInfo['tokens'] as $token)
 207          {
 208              if ($token['type'] !== 'capturingSubpatternStart')
 209                  continue;
 210              $this->captures[] = [
 211                  'pos'    => $token['pos'],
 212                  'name'   => (isset($token['name'])) ? $token['name'] : \null,
 213                  'expr'   => $token['content']
 214              ];
 215          }
 216      }
 217  	protected function parseTemplate($template)
 218      {
 219          $this->references = [
 220              'anywhere' => [],
 221              'asUrl'    => [],
 222              'inText'   => []
 223          ];
 224          \preg_match_all($this->referencesRegexp, $template, $matches);
 225          foreach ($matches[0] as $match)
 226          {
 227              $key = \trim($match, '\\${}');
 228              $this->references['anywhere'][$key] = $key;
 229          }
 230          $dom   = TemplateHelper::loadTemplate($template);
 231          $xpath = new DOMXPath($dom);
 232          foreach ($xpath->query('//text()') as $node)
 233          {
 234              \preg_match_all($this->referencesRegexp, $node->textContent, $matches);
 235              foreach ($matches[0] as $match)
 236              {
 237                  $key = \trim($match, '\\${}');
 238                  $this->references['inText'][$key] = $key;
 239              }
 240          }
 241          foreach (TemplateHelper::getURLNodes($dom) as $node)
 242              if ($node instanceof DOMAttr
 243               && \preg_match('(^(?:[$\\\\]\\d+|\\$\\{\\d+\\}))', \trim($node->value), $m))
 244              {
 245                  $key = \trim($m[0], '\\${}');
 246                  $this->references['asUrl'][$key] = $key;
 247              }
 248          $this->removeUnknownReferences();
 249      }
 250  	protected function removeUnknownReferences()
 251      {
 252          foreach ($this->references as &$references)
 253              $references = \array_intersect_key($references, $this->captures);
 254      }
 255  }


Generated: Wed Nov 11 20:33:01 2020 Cross-referenced by PHPXref 0.7.1