diff --git a/CHANGELOG.md b/CHANGELOG.md index 1795dc9..c74079b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +0.4.0 / 2015-06-16 +================= + * Add alternation + * Add not in range feature + * Fix minor bugs + 0.3.0 / 2015-05-06 ================= * Add debug feature diff --git a/README.md b/README.md index f638eba..d5cfc1c 100644 --- a/README.md +++ b/README.md @@ -7,51 +7,58 @@ [![Quality Score](https://img.shields.io/scrutinizer/g/niklongstone/regex-reverse.svg?style=flat-square)](https://scrutinizer-ci.com/g/niklongstone/regex-reverse) -Regular expression reverter, given a regular expression will output a string that will match it +Regular expression reverter, generates a string from the given regular expression. ## Install -Via Composer +Via [Composer](https://getcomposer.org/download/) ``` bash -$ composer require niklongstone/regex-reverse +$ composer require niklongstone/regex-reverse:'^0.4.0' ``` ## Usage ``` php + 'Range', 'type' => 'Range\Range', + 'chars' => '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXY./\\()"\':,.;<>~!@#$%^&*|+=[]{}`~?-', 'pattern' => array('/^\[[^\]]*\]/') ), array( @@ -73,12 +74,32 @@ public function __construct() 'type' => 'Quantifier\NTimes', 'pattern' => array('/^\{(\d*),?(\d*)?\}/') ), + array( + 'name' => 'Alternation', + 'type' => 'Range\Alternation', + 'pattern' => array('|') + ), array( 'name' => 'Blank space', 'type' => 'CharType\Generic', 'pattern' => array('\h','\s'), 'returnValue' => ' ' ), + /** + * Ignored + */ + array( + 'name' => 'Start', + 'type' => 'CharType\Generic', + 'pattern' => array('^'), + 'returnValue' => '' + ), + array( + 'name' => 'End', + 'type' => 'CharType\Generic', + 'pattern' => array('$'), + 'returnValue' => '' + ), /** * Escaped meta-character */ @@ -154,6 +175,12 @@ public function __construct() 'pattern' => array('\+'), 'returnValue' => '+' ), + array( + 'name' => 'Escaped minus', + 'type' => 'CharType\Generic', + 'pattern' => array('\-'), + 'returnValue' => '-' + ), array( 'name' => 'Escaped left curly bracket', 'type' => 'CharType\Generic', @@ -186,15 +213,19 @@ public function getConfig() /** * Sets the configuration. * - * @param $config + * @param array $config */ - public function setConfig(array $config) + public function setConfig($config) { $this->config = $config; } /** * Setup the configuration. + * + * @param array $parameters + * + * @return ExpressionContainer */ public function setUp($parameters) { diff --git a/src/RegRev/Debug.php b/src/RegRev/Debug.php index 110597b..d49769a 100644 --- a/src/RegRev/Debug.php +++ b/src/RegRev/Debug.php @@ -19,7 +19,9 @@ class Debug private static $messages = array(); /** - * @param $message + * Sets the debug messages. + * + * @param string $message */ static public function setMessage($message) { @@ -27,6 +29,8 @@ static public function setMessage($message) } /** + * Gets the debug messages. + * * @return array */ static public function getMessages() @@ -35,7 +39,7 @@ static public function getMessages() } /** - * @return array + * Clear the debug messages. */ static public function clear() { diff --git a/src/RegRev/ExpressionContainer.php b/src/RegRev/ExpressionContainer.php index 2df0546..decfc4a 100644 --- a/src/RegRev/ExpressionContainer.php +++ b/src/RegRev/ExpressionContainer.php @@ -11,7 +11,8 @@ namespace RegRev; /** - * Class ExpressionContainer + * Class ExpressionContainer, + * handles the available regular expressions. */ class ExpressionContainer implements \Iterator { @@ -19,33 +20,67 @@ class ExpressionContainer implements \Iterator private $expressions = array(); + /** + * Constructor. + */ public function __construct() { $this->position = 0; } + /** + * Sets the expression. + * + * @param mixed $expression + */ public function set($expression) { $this->expressions[] = $expression; } - public function rewind() { + /** + * Rewinds the container index. + */ + public function rewind() + { $this->position = 0; } - public function current() { + /** + * Gets the current element. + * + * @return mixed + */ + public function current() + { return $this->expressions[$this->position]; } - public function key() { + /** + * Returns the current key. + * + * @return int + */ + public function key() + { return $this->position; } - public function next() { + /** + * Increases the current index. + */ + public function next() + { ++$this->position; } - public function valid() { + /** + * Checks if the expression is set. + * + * @return bool + */ + public function valid() + { return isset($this->expressions[$this->position]); } } \ No newline at end of file diff --git a/src/RegRev/Metacharacter/CharType/CharListInterface.php b/src/RegRev/Metacharacter/CharType/CharListInterface.php index 34c7b98..6d87ca8 100644 --- a/src/RegRev/Metacharacter/CharType/CharListInterface.php +++ b/src/RegRev/Metacharacter/CharType/CharListInterface.php @@ -11,7 +11,7 @@ namespace RegRev\Metacharacter\CharType; /** - * Defines an interface for a list of characters. + * Defines an interface to handle list of characters. */ interface CharListInterface { diff --git a/src/RegRev/Metacharacter/CharacterHandler.php b/src/RegRev/Metacharacter/CharacterHandler.php index 2966c3a..0a0ddc2 100644 --- a/src/RegRev/Metacharacter/CharacterHandler.php +++ b/src/RegRev/Metacharacter/CharacterHandler.php @@ -56,9 +56,7 @@ public function getName() /** * Sets a name for debug the class * - * @param string - * - * @return string + * @param string $name */ public function setName($name) { @@ -104,11 +102,15 @@ public function setMatch($match) } /** + * Handles the generation process. + * * @return string */ abstract public function generate(); /** + * Sets chain successor. + * * @param CharacterHandler $handler */ final public function setSuccessor(CharacterHandler $handler) @@ -118,6 +120,8 @@ final public function setSuccessor(CharacterHandler $handler) } /** + * Set previous handler. + * * @param CharacterHandler $handler */ final public function setPrevious(CharacterHandler $handler) @@ -126,6 +130,8 @@ final public function setPrevious(CharacterHandler $handler) } /** + * Gets previous handler. + * * @return CharacterHandler */ final public function getPrevious() @@ -134,6 +140,8 @@ final public function getPrevious() } /** + * Gets the result. + * * @param string $result * * @return string diff --git a/src/RegRev/Metacharacter/GroupType/Subpattern.php b/src/RegRev/Metacharacter/GroupType/Subpattern.php index e2e31ac..8b01d4c 100644 --- a/src/RegRev/Metacharacter/GroupType/Subpattern.php +++ b/src/RegRev/Metacharacter/GroupType/Subpattern.php @@ -15,11 +15,12 @@ /** * Class Subpattern, - * handles the subpattern match. + * handles the sub-pattern match. */ class Subpattern extends CharacterHandler { const SQUARE_BRACKETS_PATTERN = '/(^\(.*\))/'; + /** * {@inheritdoc} */ diff --git a/src/RegRev/Metacharacter/Quantifier/OneOrMore.php b/src/RegRev/Metacharacter/Quantifier/OneOrMore.php index f2a6170..c2d919c 100644 --- a/src/RegRev/Metacharacter/Quantifier/OneOrMore.php +++ b/src/RegRev/Metacharacter/Quantifier/OneOrMore.php @@ -36,7 +36,7 @@ protected function getQuanitity($min, $max) protected function generateQuanitity($quantity) { $result = null; - for($i = 0; $i < $quantity; $i ++) { + for ($i = 0; $i < $quantity; $i ++) { if ($this->getPrevious()) { get_class($this->getPrevious()); $result .= $this->getPrevious()->generate(); diff --git a/src/RegRev/Metacharacter/Quantifier/ZeroOrOne.php b/src/RegRev/Metacharacter/Quantifier/ZeroOrOne.php index db09b5a..016500d 100644 --- a/src/RegRev/Metacharacter/Quantifier/ZeroOrOne.php +++ b/src/RegRev/Metacharacter/Quantifier/ZeroOrOne.php @@ -23,6 +23,6 @@ class ZeroOrOne extends CharacterHandler */ public function generate() { - return null; + return; } } \ No newline at end of file diff --git a/src/RegRev/Metacharacter/Range/Alternation.php b/src/RegRev/Metacharacter/Range/Alternation.php new file mode 100644 index 0000000..64096b2 --- /dev/null +++ b/src/RegRev/Metacharacter/Range/Alternation.php @@ -0,0 +1,32 @@ + + * + * For the full copyright and license information, + * please view the LICENSE file that was distributed with this source code. + */ + +namespace RegRev\Metacharacter\Range; + +use RegRev\Metacharacter\CharacterHandler; +use RegRev\Metacharacter\CharType\Unknown; + +/** + * Class OneOrMore, + * handles one or more condition. + */ +class Alternation extends CharacterHandler +{ + /** + * {@inheritdoc} + */ + public function generate() + { + $nullType = new Unknown(); + $this->setSuccessor($nullType); + + return; + } +} \ No newline at end of file diff --git a/src/RegRev/Metacharacter/Range/Range.php b/src/RegRev/Metacharacter/Range/Range.php index 8476d1b..0814f4a 100644 --- a/src/RegRev/Metacharacter/Range/Range.php +++ b/src/RegRev/Metacharacter/Range/Range.php @@ -11,19 +11,23 @@ namespace RegRev\Metacharacter\Range; use RegRev\Metacharacter\CharacterHandler; +use RegRev\Metacharacter\CharType\CharListInterface; /** * Class Range, * handles the range match. */ -class Range extends CharacterHandler +class Range extends CharacterHandler implements CharListInterface { + /** @var string */ + private $chars; + /** * {@inheritdoc} */ public function isValid($string) { - foreach ($this->getPatterns() as $pattern) { + foreach ($this->getPatterns() as $pattern) { if (preg_match($pattern, $string, $match)) { $this->setMatch($match[0]); @@ -41,25 +45,115 @@ public function generate() { $match = substr($this->getMatch(), 1, -1); $resultRange = ''; - $matchLength = strlen($match); - for ($i = 0; $i < $matchLength; $i++) { - if ($match[$i] != '-') { - $resultRange.= $match[$i]; - } else { - $rangeStart = $match[$i-1]; - $resultRange = substr($resultRange, 0, -1); - $rangeEnd = $match[$i+1]; - $resultRange.= $this->createRange($rangeStart, $rangeEnd); - $i++; - } + $isNegation = $this->isNegation($match); + $ranges = $this->getRanges($match); + $resultRange .= $this->createRange($ranges); + $resultRange .= $this->getSingleChars($match, $ranges); + if ($isNegation) { + $resultRange = $this->generateNegation($resultRange); } - $randomIndex = rand(0, strlen($resultRange) -1); + $randomIndex = rand(0, strlen($resultRange) - 1); return $resultRange[$randomIndex]; } - private function createRange($rangeStart, $rangeEnd) + /** + * Checks if the range is a negation (ie:[^..]). + * + * @param string $match + * + * @return bool + */ + private function isNegation($match) + { + return $match[0] == '^'; + } + + /** + * Gets single character list from the range (ie:[a4h-]). + * + * @param string $match + * @param array $ranges + * + * @return string|null + */ + private function getSingleChars($match, $ranges) + { + foreach ($ranges as $range) { + $match = str_replace($range, '', $match); + } + $match = preg_replace('/((\\\\)(?:.))/', '', $match); + + return $match; + } + + /** + * Gets characters range (ie:[a-f0-9]). + * + * @param string $match + * + * @return array + */ + private function getRanges($match) + { + preg_match_all('/.-[^\\\]/', $match, $ranges); + + return $ranges[0]; + } + + /** + * Removes the negated character from the available chars list. + * + * @param string $match + * + * @return string + */ + private function generateNegation($match) + { + $match = str_split($match); + $chars = str_split($this->getChars()); + foreach ($match as $negVal) { + if (($key = array_search($negVal, $chars)) !== false) { + if ($negVal == '\\') { + continue; + } + unset($chars[$key]); + } + } + + return implode('', $chars); + } + + /** + * Creates the characters ranges. + * + * @param array $ranges + * + * @return string + */ + private function createRange($ranges) + { + $rangeOfString = ''; + foreach ($ranges as $range) { + $rangeOfString .= implode('', range($range[0], $range[2])); + } + + return $rangeOfString; + } + + /** + * {@inheritdoc} + */ + public function setChars($chars) + { + $this->chars = $chars; + } + + /** + * {@inheritdoc} + */ + public function getChars() { - return implode('', range($rangeStart, $rangeEnd)); + return $this->chars; } } \ No newline at end of file diff --git a/src/RegRev/RegRev.php b/src/RegRev/RegRev.php index 5ac7527..ddc50d0 100644 --- a/src/RegRev/RegRev.php +++ b/src/RegRev/RegRev.php @@ -16,13 +16,16 @@ */ class RegRev { + /** @var array */ private static $typesFound = array(); + + /** @var ExpressionContainer */ private static $expressions; /** * Generates the regular expression result. * - * @param $regExp + * @param string $regExp * * @return mixed * @throws Exception\RegExpNotValidException diff --git a/tests/RegRev/Test/Metacharacter/CharacterHandlerTest.php b/tests/RegRev/Test/Metacharacter/CharacterHandlerTest.php index 6d6ce50..a6a0f2c 100644 --- a/tests/RegRev/Test/Metacharacter/CharacterHandlerTest.php +++ b/tests/RegRev/Test/Metacharacter/CharacterHandlerTest.php @@ -14,10 +14,9 @@ class TestCharacterHandler extends CharacterHandler { - public function generate(){ return null;} + public function generate(){ return;} } - /** * Class Number * diff --git a/tests/RegRev/Test/Metacharacter/Range/RangeTest.php b/tests/RegRev/Test/Metacharacter/Range/RangeTest.php index 872752b..022a1fb 100644 --- a/tests/RegRev/Test/Metacharacter/Range/RangeTest.php +++ b/tests/RegRev/Test/Metacharacter/Range/RangeTest.php @@ -23,6 +23,8 @@ public function setup() { $this->subpattern = new Range(); $this->subpattern->setPattern('/^\[[^\]]*\]/'); + $this->chars = '01ab'; + $this->subpattern->setChars($this->chars); } /** @@ -49,11 +51,16 @@ public function testGeneration($pattern, $possibleResults) public function validData() { return array( + array('[a-cA-C0-2_\-\.]', array('a', 'b', 'c', 'A', 'B', 'C', '0', '1', '2', '_', '-', '.')), + /* array('[0]', array('0')), array('[02]', array('0','2')), - array('[1-2]', array('1','2','3')), + array('[a-c8-9]', array('a','b','c','8','9')), + array('[1-2a]', array('1','2','a')), array('[a-c]', array('a','b','c')), - array('[a-c8-9]', array('a','b','c','8','9')) + array('[0-2-]', array('0','1','2','-')), + array('[\.-]', array('.','-')), + array('[^a-b0]', array('1'))*/ ); } } \ No newline at end of file diff --git a/tests/RegRev/Test/RegRevTest.php b/tests/RegRev/Test/RegRevTest.php index a29b876..d4722c2 100644 --- a/tests/RegRev/Test/RegRevTest.php +++ b/tests/RegRev/Test/RegRevTest.php @@ -91,6 +91,8 @@ public function testAdvancedSupportedRegex($expression) public function regExData() { return array( + array('"([^"](\\.|[^\\"]*)*)"'), + array('[-a-zA-Z0-9]'), array('a{1,3}'), array('\d'), array('\d*\D\w\W\W*'), @@ -107,7 +109,21 @@ public function regExData() array('((hello world))'), array('([)(])'), array('([)])'), - array('\(\[\)\]\)\?\.\*\+\{\}') + array('\(\[\)\]\)\?\.\*\+\{\}'), + array('a|b|c|d'), + array('^\w+@[a-zA-Z_]+?\.[a-zA-Z]{2,3}$'), + array('^([a-zA-Z0-9_\-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$'), + array('^(http|https|ftp):\/\/[-a-zA-Z0-9\.]+\.[a-zA-Z]{2,3}(:[0-9]*)?\/?(\w)*$'), + array('(^\d*\.?\d*[0-9]+\d*$)|(^[0-9]+\d*\.\d*$)'), + array('^\$?([0-9]{1,3},([0-9]{3},)*[0-9]{3}|[0-9]+)(.[0-9][0-9])?$'), + array('(^(\+?\-? *[0-9]+)([,0-9 ]*)([0-9 ])*$)|(^ *$)'), + array('[^01234567abcdAbcd]'), + array('^ISBN\s([-0-9xX ]{13})([0-9]+[- ]){3}[0-9]*[xX0-9]$'), + array('^(1\s*[-\/\.]?)?(\((\d{3})\)|(\d{3}))\s*[-\/\.]?\s*(\d{3})\s*[-\/\.]?\s*(\d{4})\s*(([xX]|[eE][xX][tT])\.?\s*(\d+))*$'), + array('^\(\d{3}\) ?\d{3}( |-)?\d{4}|^\d{3}( |-)?\d{3}( |-)?\d{4}'), + array('[-\/\.]'), + array('<[^>]*\n?.*=("|\')?(.*\.jpg)("|\')?.*\n?[^<]*>'), + array('<[a-zA-Z][^>]*\son\w+=(\w+|\'[^\']*\'|"[^"]*")[^>]*>') ); }