[ Index ]

PHP Cross Reference of phpBB-3.3.0-deutsch

title

Body

[close]

/vendor/s9e/regexp-builder/src/ -> Serializer.php (source)

   1  <?php
   2  
   3  /**
   4  * @package   s9e\RegexpBuilder
   5  * @copyright Copyright (c) 2016-2018 The s9e Authors
   6  * @license   http://www.opensource.org/licenses/mit-license.php The MIT License
   7  */
   8  namespace s9e\RegexpBuilder;
   9  
  10  use s9e\RegexpBuilder\MetaCharacters;
  11  use s9e\RegexpBuilder\Output\OutputInterface;
  12  
  13  class Serializer
  14  {
  15      /**
  16      * @var Escaper
  17      */
  18      protected $escaper;
  19  
  20      /**
  21      * @var MetaCharacters
  22      */
  23      protected $meta;
  24  
  25      /**
  26      * @var OutputInterface
  27      */
  28      protected $output;
  29  
  30      /**
  31      * @param OutputInterface $output
  32      * @parm  MetaCharacters  $meta
  33      * @param Escaper         $escaper
  34      */
  35  	public function __construct(OutputInterface $output, MetaCharacters $meta, Escaper $escaper)
  36      {
  37          $this->escaper = $escaper;
  38          $this->meta    = $meta;
  39          $this->output  = $output;
  40      }
  41  
  42      /**
  43      * Serialize given strings into a regular expression
  44      *
  45      * @param  array[] $strings
  46      * @return string
  47      */
  48  	public function serializeStrings(array $strings)
  49      {
  50          $info         = $this->analyzeStrings($strings);
  51          $alternations = array_map([$this, 'serializeString'], $info['strings']);
  52          if (!empty($info['chars']))
  53          {
  54              // Prepend the character class to the list of alternations
  55              array_unshift($alternations, $this->serializeCharacterClass($info['chars']));
  56          }
  57  
  58          $expr = implode('|', $alternations);
  59          if ($this->needsParentheses($info))
  60          {
  61              $expr = '(?:' . $expr . ')';
  62          }
  63  
  64          return $expr . $info['quantifier'];
  65      }
  66  
  67      /**
  68      * Analyze given strings to determine how to serialize them
  69      *
  70      * The returned array may contains any of the following elements:
  71      *
  72      *  - (string) quantifier Either '' or '?'
  73      *  - (array)  chars      List of values from single-char strings
  74      *  - (array)  strings    List of multi-char strings
  75      *
  76      * @param  array[] $strings
  77      * @return array
  78      */
  79  	protected function analyzeStrings(array $strings)
  80      {
  81          $info = ['alternationsCount' => 0, 'quantifier' => ''];
  82          if ($strings[0] === [])
  83          {
  84              $info['quantifier'] = '?';
  85              unset($strings[0]);
  86          }
  87  
  88          $chars = $this->getChars($strings);
  89          if (count($chars) > 1)
  90          {
  91              ++$info['alternationsCount'];
  92              $info['chars'] = array_values($chars);
  93              $strings       = array_diff_key($strings, $chars);
  94          }
  95  
  96          $info['strings']            = array_values($strings);
  97          $info['alternationsCount'] += count($strings);
  98  
  99          return $info;
 100      }
 101  
 102      /**
 103      * Return the portion of strings that are composed of a single character
 104      *
 105      * @param  array[]
 106      * @return array   String key => value
 107      */
 108  	protected function getChars(array $strings)
 109      {
 110          $chars = [];
 111          foreach ($strings as $k => $string)
 112          {
 113              if ($this->isChar($string))
 114              {
 115                  $chars[$k] = $string[0];
 116              }
 117          }
 118  
 119          return $chars;
 120      }
 121  
 122      /**
 123      * Get the list of ranges that cover all given values
 124      *
 125      * @param  integer[] $values Ordered list of values
 126      * @return array[]           List of ranges in the form [start, end]
 127      */
 128  	protected function getRanges(array $values)
 129      {
 130          $i      = 0;
 131          $cnt    = count($values);
 132          $start  = $values[0];
 133          $end    = $start;
 134          $ranges = [];
 135          while (++$i < $cnt)
 136          {
 137              if ($values[$i] === $end + 1)
 138              {
 139                  ++$end;
 140              }
 141              else
 142              {
 143                  $ranges[] = [$start, $end];
 144                  $start = $end = $values[$i];
 145              }
 146          }
 147          $ranges[] = [$start, $end];
 148  
 149          return $ranges;
 150      }
 151  
 152      /**
 153      * Test whether given string represents a single character
 154      *
 155      * @param  array $string
 156      * @return bool
 157      */
 158  	protected function isChar(array $string)
 159      {
 160          return count($string) === 1 && is_int($string[0]) && MetaCharacters::isChar($string[0]);
 161      }
 162  
 163      /**
 164      * Test whether an expression is quantifiable based on the strings info
 165      *
 166      * @param  array $info
 167      * @return bool
 168      */
 169  	protected function isQuantifiable(array $info)
 170      {
 171          $strings = $info['strings'];
 172  
 173          return empty($strings) || $this->isSingleQuantifiableString($strings);
 174      }
 175  
 176      /**
 177      * Test whether a list of strings contains only one single quantifiable string
 178      *
 179      * @param  array[] $strings
 180      * @return bool
 181      */
 182  	protected function isSingleQuantifiableString(array $strings)
 183      {
 184          return count($strings) === 1 && count($strings[0]) === 1 && MetaCharacters::isQuantifiable($strings[0][0]);
 185      }
 186  
 187      /**
 188      * Test whether an expression needs parentheses based on the strings info
 189      *
 190      * @param  array $info
 191      * @return bool
 192      */
 193  	protected function needsParentheses(array $info)
 194      {
 195          return ($info['alternationsCount'] > 1 || ($info['quantifier'] && !$this->isQuantifiable($info)));
 196      }
 197  
 198      /**
 199      * Serialize a given list of values into a character class
 200      *
 201      * @param  integer[] $values
 202      * @return string
 203      */
 204  	protected function serializeCharacterClass(array $values)
 205      {
 206          $expr = '[';
 207          foreach ($this->getRanges($values) as list($start, $end))
 208          {
 209              $expr .= $this->serializeCharacterClassUnit($start);
 210              if ($end > $start)
 211              {
 212                  if ($end > $start + 1)
 213                  {
 214                      $expr .= '-';
 215                  }
 216                  $expr .= $this->serializeCharacterClassUnit($end);
 217              }
 218          }
 219          $expr .= ']';
 220  
 221          return $expr;
 222      }
 223  
 224      /**
 225      * Serialize a given value to be used in a character class
 226      *
 227      * @param  integer $value
 228      * @return string
 229      */
 230  	protected function serializeCharacterClassUnit($value)
 231      {
 232          return $this->serializeValue($value, 'escapeCharacterClass');
 233      }
 234  
 235      /**
 236      * Serialize an element from a string
 237      *
 238      * @param  array|integer $element
 239      * @return string
 240      */
 241  	protected function serializeElement($element)
 242      {
 243          return (is_array($element)) ? $this->serializeStrings($element) : $this->serializeLiteral($element);
 244      }
 245  
 246      /**
 247      * Serialize a given value to be used as a literal
 248      *
 249      * @param  integer $value
 250      * @return string
 251      */
 252  	protected function serializeLiteral($value)
 253      {
 254          return $this->serializeValue($value, 'escapeLiteral');
 255      }
 256  
 257      /**
 258      * Serialize a given string into a regular expression
 259      *
 260      * @param  array  $string
 261      * @return string
 262      */
 263  	protected function serializeString(array $string)
 264      {
 265          return implode('', array_map([$this, 'serializeElement'], $string));
 266      }
 267  
 268      /**
 269      * Serialize a given value
 270      *
 271      * @param  integer $value
 272      * @param  string  $escapeMethod
 273      * @return string
 274      */
 275  	protected function serializeValue($value, $escapeMethod)
 276      {
 277          return ($value < 0) ? $this->meta->getExpression($value) : $this->escaper->$escapeMethod($this->output->output($value));
 278      }
 279  }


Generated: Tue Apr 7 19:44:41 2020 Cross-referenced by PHPXref 0.7.1