--- /dev/null
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Finder\Expression;
+
+@trigger_error('The '.__NAMESPACE__.'\Regex class is deprecated since version 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
+
+/**
+ * @author Jean-François Simon <contact@jfsimon.fr>
+ */
+class Regex implements ValueInterface
+{
+ const START_FLAG = '^';
+ const END_FLAG = '$';
+ const BOUNDARY = '~';
+ const JOKER = '.*';
+ const ESCAPING = '\\';
+
+ /**
+ * @var string
+ */
+ private $pattern;
+
+ /**
+ * @var array
+ */
+ private $options;
+
+ /**
+ * @var bool
+ */
+ private $startFlag;
+
+ /**
+ * @var bool
+ */
+ private $endFlag;
+
+ /**
+ * @var bool
+ */
+ private $startJoker;
+
+ /**
+ * @var bool
+ */
+ private $endJoker;
+
+ /**
+ * @param string $expr
+ *
+ * @return self
+ *
+ * @throws \InvalidArgumentException
+ */
+ public static function create($expr)
+ {
+ if (preg_match('/^(.{3,}?)([imsxuADU]*)$/', $expr, $m)) {
+ $start = substr($m[1], 0, 1);
+ $end = substr($m[1], -1);
+
+ if (
+ ($start === $end && !preg_match('/[*?[:alnum:] \\\\]/', $start))
+ || ($start === '{' && $end === '}')
+ || ($start === '(' && $end === ')')
+ ) {
+ return new self(substr($m[1], 1, -1), $m[2], $end);
+ }
+ }
+
+ throw new \InvalidArgumentException('Given expression is not a regex.');
+ }
+
+ /**
+ * @param string $pattern
+ * @param string $options
+ * @param string $delimiter
+ */
+ public function __construct($pattern, $options = '', $delimiter = null)
+ {
+ if (null !== $delimiter) {
+ // removes delimiter escaping
+ $pattern = str_replace('\\'.$delimiter, $delimiter, $pattern);
+ }
+
+ $this->parsePattern($pattern);
+ $this->options = $options;
+ }
+
+ /**
+ * @return string
+ */
+ public function __toString()
+ {
+ return $this->render();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function render()
+ {
+ return self::BOUNDARY
+ .$this->renderPattern()
+ .self::BOUNDARY
+ .$this->options;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function renderPattern()
+ {
+ return ($this->startFlag ? self::START_FLAG : '')
+ .($this->startJoker ? self::JOKER : '')
+ .str_replace(self::BOUNDARY, '\\'.self::BOUNDARY, $this->pattern)
+ .($this->endJoker ? self::JOKER : '')
+ .($this->endFlag ? self::END_FLAG : '');
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function isCaseSensitive()
+ {
+ return !$this->hasOption('i');
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getType()
+ {
+ return Expression::TYPE_REGEX;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function prepend($expr)
+ {
+ $this->pattern = $expr.$this->pattern;
+
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function append($expr)
+ {
+ $this->pattern .= $expr;
+
+ return $this;
+ }
+
+ /**
+ * @param string $option
+ *
+ * @return bool
+ */
+ public function hasOption($option)
+ {
+ return false !== strpos($this->options, $option);
+ }
+
+ /**
+ * @param string $option
+ *
+ * @return $this
+ */
+ public function addOption($option)
+ {
+ if (!$this->hasOption($option)) {
+ $this->options .= $option;
+ }
+
+ return $this;
+ }
+
+ /**
+ * @param string $option
+ *
+ * @return $this
+ */
+ public function removeOption($option)
+ {
+ $this->options = str_replace($option, '', $this->options);
+
+ return $this;
+ }
+
+ /**
+ * @param bool $startFlag
+ *
+ * @return $this
+ */
+ public function setStartFlag($startFlag)
+ {
+ $this->startFlag = $startFlag;
+
+ return $this;
+ }
+
+ /**
+ * @return bool
+ */
+ public function hasStartFlag()
+ {
+ return $this->startFlag;
+ }
+
+ /**
+ * @param bool $endFlag
+ *
+ * @return $this
+ */
+ public function setEndFlag($endFlag)
+ {
+ $this->endFlag = (bool) $endFlag;
+
+ return $this;
+ }
+
+ /**
+ * @return bool
+ */
+ public function hasEndFlag()
+ {
+ return $this->endFlag;
+ }
+
+ /**
+ * @param bool $startJoker
+ *
+ * @return $this
+ */
+ public function setStartJoker($startJoker)
+ {
+ $this->startJoker = $startJoker;
+
+ return $this;
+ }
+
+ /**
+ * @return bool
+ */
+ public function hasStartJoker()
+ {
+ return $this->startJoker;
+ }
+
+ /**
+ * @param bool $endJoker
+ *
+ * @return $this
+ */
+ public function setEndJoker($endJoker)
+ {
+ $this->endJoker = (bool) $endJoker;
+
+ return $this;
+ }
+
+ /**
+ * @return bool
+ */
+ public function hasEndJoker()
+ {
+ return $this->endJoker;
+ }
+
+ /**
+ * @param array $replacement
+ *
+ * @return $this
+ */
+ public function replaceJokers($replacement)
+ {
+ $replace = function ($subject) use ($replacement) {
+ $subject = $subject[0];
+ $replace = 0 === substr_count($subject, '\\') % 2;
+
+ return $replace ? str_replace('.', $replacement, $subject) : $subject;
+ };
+
+ $this->pattern = preg_replace_callback('~[\\\\]*\\.~', $replace, $this->pattern);
+
+ return $this;
+ }
+
+ /**
+ * @param string $pattern
+ */
+ private function parsePattern($pattern)
+ {
+ if ($this->startFlag = self::START_FLAG === substr($pattern, 0, 1)) {
+ $pattern = substr($pattern, 1);
+ }
+
+ if ($this->startJoker = self::JOKER === substr($pattern, 0, 2)) {
+ $pattern = substr($pattern, 2);
+ }
+
+ if ($this->endFlag = (self::END_FLAG === substr($pattern, -1) && self::ESCAPING !== substr($pattern, -2, -1))) {
+ $pattern = substr($pattern, 0, -1);
+ }
+
+ if ($this->endJoker = (self::JOKER === substr($pattern, -2) && self::ESCAPING !== substr($pattern, -3, -2))) {
+ $pattern = substr($pattern, 0, -2);
+ }
+
+ $this->pattern = $pattern;
+ }
+}