├── .gitignore ├── .travis.yml ├── Example.php ├── LICENSE ├── README.md ├── composer.json ├── phpunit.xml.dist ├── src ├── Entity │ └── Expression.php ├── Parser │ ├── MethodParser.php │ └── MethodParserInterface.php ├── VerbalExpressions.php └── VerbalExpressionsScenario.php └── tests ├── Parser └── MethodParserTest.php ├── VerbalExpressionsScenarioTest.php └── VerbalExpressionsTest.php /.gitignore: -------------------------------------------------------------------------------- 1 | # General Ignores 2 | /vendor 3 | composer.lock 4 | /phpunit/ 5 | # IDEs 6 | .idea/ 7 | /nbproject/ 8 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: php 2 | php: 3 | - '5.4' 4 | - '5.5' 5 | - '5.6' 6 | - '7.0' 7 | - '7.1' 8 | - '7.2' 9 | - nightly 10 | matrix: 11 | include: 12 | - php: "5.3" 13 | dist: precise 14 | git: 15 | #there should rarely be a need to clone 50 deep, so this is just reducing build-time 16 | depth: 5 17 | before_script: 18 | # no need to provide coverage more than once and no need for the speedbump otherwise 19 | - if [[ ${TRAVIS_PHP_VERSION:0:3} != "7.1" ]]; then phpenv config-rm xdebug.ini || true ; fi 20 | # no need to test formatting more than once and php_codesniffer does not work with older php 21 | - if [[ ${TRAVIS_PHP_VERSION:0:3} != "5.6" ]]; then composer remove --dev squizlabs/php_codesniffer ; fi 22 | - composer install 23 | script: 24 | # since it's disabled otherwise... 25 | - if [[ ${TRAVIS_PHP_VERSION:0:3} == "5.6" ]]; then composer check-style ; fi 26 | - composer test 27 | -------------------------------------------------------------------------------- /Example.php: -------------------------------------------------------------------------------- 1 | startOfLine() 13 | ->then("http") 14 | ->maybe("s") 15 | ->then("://") 16 | ->maybe("www.") 17 | ->anythingBut(" ") 18 | ->endOfLine(); 19 | 20 | if ($regex->test("http://github.com")) { 21 | echo "valid url". '
'; 22 | } else { 23 | echo "invalid url". '
'; 24 | } 25 | 26 | if (preg_match($regex, 'http://github.com')) { 27 | echo 'valid url'; 28 | } else { 29 | echo 'invalid url'; 30 | } 31 | 32 | echo "
". $regex->getRegex() ."
"; 33 | 34 | echo $regex->clean(array("modifiers" => "m", "replaceLimit" => 4)) 35 | ->find(' ') 36 | ->replace("This is a small test http://somesite.com and some more text.", "-"); 37 | 38 | 39 | echo "
"; 40 | 41 | // limit 42 | echo $regex ->clean(array("modifiers" => "m")) 43 | ->startOfLine() 44 | ->anyOf("abc") 45 | ->anythingBut(" ") 46 | ->limit(1) 47 | ->withAnyCase() 48 | ->replace("Abracadabra is a nice word", "Ba"); 49 | 50 | echo "
"; 51 | 52 | 53 | 54 | echo $regex ->clean(array("modifiers" => "gm")) 55 | ->add("\b") 56 | ->word() 57 | ->limit(2, 3) 58 | ->add("\b") 59 | ->replace("test abc ab abcd", "*"); 60 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2013 jehna 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Build Status](https://travis-ci.org/VerbalExpressions/PHPVerbalExpressions.svg)](https://travis-ci.org/VerbalExpressions/PHPVerbalExpressions) 2 | 3 | ## PHPVerbalExpressions 4 | - ported from [VerbalExpressions](https://github.com/VerbalExpressions/JSVerbalExpressions) 5 | 6 | VerbalExpressions is a PHP library that helps to construct hard regular expressions. 7 | 8 | ## Installation 9 | The project supports Composer so you have to install [Composer](http://getcomposer.org/doc/00-intro.md#installation-nix) first, before project setup. 10 | 11 | ```sh 12 | $ composer require verbalexpressions/php-verbal-expressions:dev-master 13 | ``` 14 | 15 | ## Examples 16 | 17 | ```php 18 | startOfLine() 26 | ->then("http") 27 | ->maybe("s") 28 | ->then("://") 29 | ->maybe("www.") 30 | ->anythingBut(" ") 31 | ->endOfLine(); 32 | 33 | 34 | if ($regex->test("http://github.com")) { 35 | echo "valid url". '
'; 36 | } else { 37 | echo "invalid url". '
'; 38 | } 39 | 40 | if (preg_match($regex, 'http://github.com')) { 41 | echo 'valid url'; 42 | } else { 43 | echo 'invalid url'; 44 | } 45 | 46 | 47 | echo "
". $regex->getRegex() ."
"; 48 | 49 | echo $regex->clean(array("modifiers" => "m", "replaceLimit" => 4)) 50 | ->find(' ') 51 | ->replace("This is a small test http://somesite.com and some more text.", "-"); 52 | 53 | ``` 54 | 55 | More examples are available in the following files: 56 | 57 | - [Example.php](Example.php) 58 | - [VerbalExpressionsTest.php](tests/VerbalExpressionsTest.php) 59 | 60 | ### Business readable language expression definition 61 | ```PHP 62 | $definition = 'start, then "http", maybe "s", then "://", maybe "www.", anything but " ", end'; 63 | $regex = new VerbalExpressionsScenario($definition); 64 | ``` 65 | 66 | ## Methods list 67 | 68 | Name|Description|Usage 69 | :---|:---|:--- 70 | add| add values to the expression| add('abc') 71 | startOfLine| mark expression with ^| startOfLine(false) 72 | endOfLine| mark the expression with $|endOfLine() 73 | then|add a string to the expression| add('foo') 74 | find| alias for then| find('foo') 75 | maybe| define a string that might appear once or not| maybe('.com') 76 | anything| accept any string| anything() 77 | anythingBut| accept any string but the specified char| anythingBut(',') 78 | something| accept any non-empty string| something() 79 | somethingBut| anything non-empty except for these chars| somethingBut('a') 80 | replace| shorthand for preg_replace()| replace($source, $val) 81 | lineBreak| match \r \n|lineBreak() 82 | br|shorthand for lineBreak| br() 83 | tab|match tabs \t |tab() 84 | word|match \w+|word() 85 | anyOf| any of the listed chars| anyOf('abc') 86 | any| shorthand for anyOf| any('abc') 87 | range| adds a range to the expression|range(a,z,0,9) 88 | withAnyCase| match case default case sensitive|withAnyCase() 89 | stopAtFirst|toggles the g modifiers|stopAtFirst() 90 | addModifier| add a modifier|addModifier('g') 91 | removeModifier| remove a mofier|removeModifier('g') 92 | searchOneLine| Toggles m modifier|searchOneLine() 93 | multiple|adds the multiple modifier| multiple('*') 94 | _or|wraps the expression in an `or` with the provided value|_or('bar') 95 | limit|adds char limit|limit(1,3) 96 | test| performs a preg_match| test('valid@email.com') 97 | 98 | For all the above method (except `test`) you could use the `VerbalExpressionsScenario`. 99 | 100 | ## Other Implementations 101 | You can see an up to date list of all ports on [VerbalExpressions.github.io](http://VerbalExpressions.github.io). 102 | - [Javascript](https://github.com/jehna/VerbalExpressions) 103 | - [Ruby](https://github.com/VerbalExpressions/RubyVerbalExpressions) 104 | - [C#](https://github.com/VerbalExpressions/CSharpVerbalExpressions) 105 | - [Python](https://github.com/VerbalExpressions/PythonVerbalExpressions) 106 | - [Java](https://github.com/VerbalExpressions/JavaVerbalExpressions) 107 | - [C++](https://github.com/VerbalExpressions/CppVerbalExpressions) 108 | 109 | ## Building the project and running the tests 110 | The project supports Composer so you have to install [Composer](https://getcomposer.org/doc/00-intro.md#installation-nix) first before project setup. 111 | 112 | curl -sS https://getcomposer.org/installer | php 113 | php composer.phar install --dev 114 | ln -s vendor/phpunit/phpunit/phpunit.php phpunit 115 | ./phpunit 116 | 117 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "verbalexpressions/php-verbal-expressions", 3 | "license": "MIT", 4 | "type": "project", 5 | "description": "PHP Regular expressions made easy", 6 | "require": { 7 | "php": ">=5.3" 8 | }, 9 | "require-dev": { 10 | "phpunit/phpunit": "* >=4", 11 | "squizlabs/php_codesniffer": "^3.1" 12 | }, 13 | "minimum-stability": "stable", 14 | "autoload": { 15 | "psr-4": { 16 | "VerbalExpressions\\PHPVerbalExpressions\\": "src/" 17 | } 18 | }, 19 | "autoload-dev": { 20 | "psr-4": { 21 | "VerbalExpressions\\PHPVerbalExpressions\\Tests\\": "tests/" 22 | } 23 | }, 24 | "scripts": { 25 | "test": "vendor/bin/phpunit", 26 | "check-style": "phpcs -p --standard=PSR2 --runtime-set ignore_errors_on_exit 1 --runtime-set ignore_warnings_on_exit 1 src tests", 27 | "fix-style": "phpcbf -p --standard=PSR2 --runtime-set ignore_errors_on_exit 1 --runtime-set ignore_warnings_on_exit 1 src tests" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /phpunit.xml.dist: -------------------------------------------------------------------------------- 1 | 2 | 15 | 16 | 17 | ./tests/ 18 | 19 | 20 | 21 | 22 | 23 | ./src 24 | 25 | 26 | 27 | 28 | 29 | 34 | 39 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /src/Entity/Expression.php: -------------------------------------------------------------------------------- 1 | 10 | */ 11 | class Expression 12 | { 13 | /** 14 | * @var string 15 | */ 16 | private $name; 17 | 18 | /** 19 | * @var mixed 20 | */ 21 | private $arguments; 22 | 23 | /** 24 | * @param string $name 25 | * @param null $arguments 26 | */ 27 | public function __construct($name, $arguments = null) 28 | { 29 | $this->name = $name; 30 | $this->arguments = $arguments; 31 | } 32 | 33 | /** 34 | * Returns the expression's arguments. 35 | * 36 | * @return mixed 37 | */ 38 | public function getArguments() 39 | { 40 | return $this->arguments; 41 | } 42 | 43 | /** 44 | * Returns the expression's name. 45 | * 46 | * @return string 47 | */ 48 | public function getName() 49 | { 50 | return $this->name; 51 | } 52 | } -------------------------------------------------------------------------------- /src/Parser/MethodParser.php: -------------------------------------------------------------------------------- 1 | 11 | */ 12 | class MethodParser implements MethodParserInterface 13 | { 14 | const ANYTHING = 'anything'; 15 | const ANYTHING_BUT = 'anythingBut'; 16 | const SOMETHING = 'something'; 17 | const SOMETHING_BUT = 'somethingBut'; 18 | const END_OF_LINE = 'endOfLine'; 19 | const FIND = 'find'; 20 | const MAYBE = 'maybe'; 21 | const START_OF_LINE = 'startOfLine'; 22 | const THEN = 'then'; 23 | const ANY = 'any'; 24 | const ANY_OF = 'anyOf'; 25 | const BR = 'br'; 26 | const LINE_BREAK = 'lineBreak'; 27 | const RANGE = 'rangeBridge'; 28 | const TAB = 'tab'; 29 | const WORD = 'word'; 30 | const WITH_ANY_CASE = 'withAnyCase'; 31 | const STOP_AT_FIRST = 'stopAtFirst'; 32 | const SEARCH_ONE_LINE = 'searchOneLine'; 33 | const REPLACE = 'replaceBridge'; 34 | const ADD = 'add'; 35 | const LIMIT = 'limit'; 36 | const MULTIPLE = 'multiple'; 37 | const ADD_MODIFIER = 'addModifier'; 38 | const REMOVE_MODIFIER = 'removeModifier'; 39 | const _OR = '_or'; 40 | 41 | /** 42 | * @param string $scenarioString 43 | * @return null 44 | */ 45 | public function parse($scenarioString) 46 | { 47 | $definitions = $this->getDefinitions(); 48 | foreach ($definitions as $key => $val) { 49 | if (preg_match('/'.$key.'/i', $scenarioString)) { 50 | return $val; 51 | } 52 | } 53 | 54 | return null; 55 | } 56 | 57 | /** 58 | * @return array 59 | */ 60 | private function getDefinitions() 61 | { 62 | return array( 63 | 'anythingbut' => self::ANYTHING_BUT, 64 | 'somethingbut' => self::SOMETHING_BUT, 65 | 'something but' => self::SOMETHING_BUT, 66 | 'something' => self::SOMETHING, 67 | 'anything but' => self::ANYTHING_BUT, 68 | 'anything' => self::ANYTHING, 69 | 'end' => self::END_OF_LINE, 70 | 'end of line' => self::END_OF_LINE, 71 | 'endofline' => self::END_OF_LINE, 72 | 'find' => self::FIND, 73 | 'maybe' => self::MAYBE, 74 | 'start' => self::START_OF_LINE, 75 | 'startofline' => self::START_OF_LINE, 76 | 'start of line' => self::START_OF_LINE, 77 | 'then' => self::THEN, 78 | 'anyof' => self::ANY_OF, 79 | 'any of' => self::ANY_OF, 80 | 'linebreak' => self::LINE_BREAK, 81 | 'line break' => self::LINE_BREAK, 82 | 'br' => self::BR, 83 | 'range' => self::RANGE, 84 | 'tab' => self::TAB, 85 | 'word' => self::WORD, 86 | 'withanycase' => self::WITH_ANY_CASE, 87 | 'with any case' => self::WITH_ANY_CASE, 88 | 'any case' => self::WITH_ANY_CASE, 89 | 'any' => self::ANY, 90 | 'stopatfirst' => self::STOP_AT_FIRST, 91 | 'stop at first' => self::STOP_AT_FIRST, 92 | 'stop first' => self::STOP_AT_FIRST, 93 | 'searchoneline' => self::SEARCH_ONE_LINE, 94 | 'search one line' => self::SEARCH_ONE_LINE, 95 | 'replace' => self::REPLACE, 96 | 'add modifier' => self::ADD_MODIFIER, 97 | 'addmodifier' => self::ADD_MODIFIER, 98 | 'add' => self::ADD, 99 | 'remove modifier' => self::REMOVE_MODIFIER, 100 | 'removemodifier' => self::REMOVE_MODIFIER, 101 | 'limit' => self::LIMIT, 102 | 'multiple' => self::MULTIPLE, 103 | 'or' => self::_OR 104 | ); 105 | } 106 | } -------------------------------------------------------------------------------- /src/Parser/MethodParserInterface.php: -------------------------------------------------------------------------------- 1 | 12 | */ 13 | interface MethodParserInterface 14 | { 15 | /** 16 | * Parses a single declaration feature 17 | * and return the relative VerbalExpression method name. 18 | * 19 | * @param $singleFeatures 20 | * 21 | * @return string|null 22 | */ 23 | public function parse($singleFeatures); 24 | } -------------------------------------------------------------------------------- /src/VerbalExpressions.php: -------------------------------------------------------------------------------- 1 | source .= $this->lastAdded = $value; 46 | 47 | return $this; 48 | } 49 | 50 | /** 51 | * Start of Line 52 | * 53 | * Mark the expression to start at the beginning of the line. 54 | * 55 | * @access public 56 | * @param boolean $enable Enables or disables the line starting. Default value: true 57 | * @return VerbalExpressions 58 | */ 59 | public function startOfLine($enable = true) 60 | { 61 | $this->prefixes = $enable ? '^' : ''; 62 | 63 | return $this; 64 | } 65 | 66 | /** 67 | * End of line 68 | * 69 | * Mark the expression to end at the last character of the line. 70 | * 71 | * @access public 72 | * @param boolean $enable Enables or disables the line ending. Default value: true 73 | * @return VerbalExpressions 74 | */ 75 | public function endOfLine($enable = true) 76 | { 77 | $this->suffixes = $enable ? '$' : ''; 78 | 79 | return $this; 80 | } 81 | 82 | /** 83 | * Then 84 | * 85 | * Add a string to the expression 86 | * 87 | * @access public 88 | * @param string $value The string to be looked for 89 | * @return VerbalExpressions 90 | */ 91 | public function then($value) 92 | { 93 | return $this->add('(?:' . self::sanitize($value) . ')'); 94 | } 95 | 96 | /** 97 | * Find 98 | * 99 | * Alias for then() 100 | * 101 | * @access public 102 | * @param string $value The string to be looked for 103 | * @return VerbalExpressions 104 | */ 105 | public function find($value) 106 | { 107 | return $this->then($value); 108 | } 109 | 110 | /** 111 | * Maybe 112 | * 113 | * Add a string to the expression that might appear once (or not). 114 | * 115 | * @access public 116 | * @param string $value The string to be looked for 117 | * @return VerbalExpressions 118 | */ 119 | public function maybe($value) 120 | { 121 | return $this->add('(?:' . self::sanitize($value) . ')?'); 122 | } 123 | 124 | /** 125 | * Anything 126 | * 127 | * Accept any string 128 | * 129 | * @access public 130 | * @return VerbalExpressions 131 | */ 132 | public function anything() 133 | { 134 | return $this->add('(?:.*)'); 135 | } 136 | 137 | /** 138 | * AnythingBut 139 | * 140 | * Anything but this chars 141 | * 142 | * @access public 143 | * @param string $value The unaccepted chars 144 | * @return VerbalExpressions 145 | */ 146 | public function anythingBut($value) 147 | { 148 | return $this->add('(?:[^' . self::sanitize($value) . ']*)'); 149 | } 150 | 151 | /** 152 | * Something 153 | * 154 | * Accept any non-empty string 155 | * 156 | * @access public 157 | * @return VerbalExpressions 158 | */ 159 | public function something() 160 | { 161 | return $this->add('(?:.+)'); 162 | } 163 | 164 | /** 165 | * Anything but 166 | * 167 | * Anything non-empty except for these chars 168 | * 169 | * @access public 170 | * @param string $value The unaccepted chars 171 | * @return VerbalExpressions 172 | */ 173 | public function somethingBut($value) 174 | { 175 | return $this->add('(?:[^' . self::sanitize($value) . ']+)'); 176 | } 177 | 178 | /** 179 | * Preg Replace 180 | * 181 | * Shorthand for preg_replace() 182 | * 183 | * @access public 184 | * @param string $source the string that will be affected(subject) 185 | * @param string $value the replacement 186 | * @return VerbalExpressions 187 | */ 188 | public function replace($source, $value) 189 | { 190 | // php doesn't have g modifier so we remove it if it's there and we remove limit param 191 | if (strpos($this->modifiers, 'g') !== false) { 192 | $this->modifiers = str_replace('g', '', $this->modifiers); 193 | 194 | return preg_replace($this->getRegex(), $value, $source); 195 | } 196 | 197 | return preg_replace($this->getRegex(), $value, $source, $this->replaceLimit); 198 | } 199 | 200 | /** 201 | * Line break 202 | * 203 | * Match line break 204 | * 205 | * @access public 206 | * @return VerbalExpressions 207 | */ 208 | public function lineBreak() 209 | { 210 | return $this->add('(?:\\n|(\\r\\n))'); 211 | } 212 | 213 | /** 214 | * Line break 215 | * 216 | * Shorthand for lineBreak 217 | * 218 | * @access public 219 | * @return VerbalExpressions 220 | */ 221 | public function br() 222 | { 223 | return $this->lineBreak(); 224 | } 225 | 226 | /** 227 | * Tabs 228 | * 229 | * Match tabs. 230 | * 231 | * @access public 232 | * @return VerbalExpressions 233 | */ 234 | public function tab() 235 | { 236 | return $this->add('\\t'); 237 | } 238 | 239 | /** 240 | * Alpha Numeric 241 | * 242 | * Match any alpha numeric 243 | * 244 | * @access public 245 | * @return VerbalExpressions 246 | */ 247 | public function word() 248 | { 249 | return $this->add('\\w+'); 250 | } 251 | 252 | /** 253 | * Digit 254 | * 255 | * Match any digit 256 | * 257 | * @access public 258 | * @return VerbalExpressions 259 | */ 260 | public function digit() 261 | { 262 | return $this->add('\\d'); 263 | } 264 | 265 | /** 266 | * List Chars 267 | * 268 | * Any of the listed chars 269 | * 270 | * @access public 271 | * @param string $value The chars looked for 272 | * @return VerbalExpressions 273 | */ 274 | public function anyOf($value) 275 | { 276 | return $this->add('[' . $value . ']'); 277 | } 278 | 279 | /** 280 | * Alias 281 | * 282 | * Shorthand for anyOf 283 | * 284 | * @access public 285 | * @param string $value The chars looked for 286 | * @return VerbalExpressions 287 | */ 288 | public function any($value) 289 | { 290 | return $this->anyOf($value); 291 | } 292 | 293 | /** 294 | * Add a range 295 | * 296 | * Adds a range to our expression ex: range(a,z) => a-z, range(a,z,0,9) => a-z0-9 297 | * 298 | * @access public 299 | * @return VerbalExpressions 300 | * @throws \InvalidArgumentException 301 | */ 302 | public function range() 303 | { 304 | $args = func_get_args(); 305 | $arg_num = count($args); 306 | 307 | if ($arg_num%2 != 0) { 308 | throw new \InvalidArgumentException('Number of args must be even', 1); 309 | } 310 | 311 | $value = '['; 312 | 313 | for ($i = 0; $i < $arg_num;) { 314 | $value .= self::sanitize($args[$i++]) . '-' . self::sanitize($args[$i++]); 315 | } 316 | 317 | $value .= ']'; 318 | 319 | return $this->add($value); 320 | } 321 | 322 | /** 323 | * Add a modifier 324 | * 325 | * Adds a modifier 326 | * 327 | * @access public 328 | * @param string $modifier 329 | * @return VerbalExpressions 330 | */ 331 | public function addModifier($modifier) 332 | { 333 | if (strpos($this->modifiers, $modifier) === false) { 334 | $this->modifiers .= $modifier; 335 | } 336 | 337 | return $this; 338 | } 339 | 340 | /** 341 | * Remove Modifier 342 | * 343 | * Removes a modifier 344 | * 345 | * @access public 346 | * @param string $modifier 347 | * @return VerbalExpressions 348 | */ 349 | public function removeModifier($modifier) 350 | { 351 | $this->modifiers = str_replace($modifier, '', $modifier); 352 | 353 | return $this; 354 | } 355 | 356 | /** 357 | * Case Sensitivity 358 | * 359 | * Match case insensitive or sensitive based on $enable value 360 | * 361 | * @access public 362 | * @param boolean $enable Enables or disables case sensitive. Default true 363 | * @return VerbalExpressions 364 | */ 365 | public function withAnyCase($enable = true) 366 | { 367 | return $enable ? $this->addModifier('i') : $this->removeModifier('i'); 368 | } 369 | 370 | /** 371 | * Stop At First 372 | * 373 | * Toggles g modifier 374 | * 375 | * @access public 376 | * @param boolean $enable Enables or disables g modifier. Default true 377 | * @return VerbalExpressions 378 | */ 379 | public function stopAtFirst($enable = true) 380 | { 381 | return $enable ? $this->addModifier('g') : $this->removeModifier('g'); 382 | } 383 | 384 | /** 385 | * SearchOneLine 386 | * 387 | * Toggles m modifier 388 | * 389 | * @access public 390 | * @param boolean $enable Enables or disables m modifier. Default true 391 | * @return VerbalExpressions 392 | */ 393 | public function searchOneLine($enable = true) 394 | { 395 | return $enable ? $this->addModifier('m') : $this->removeModifier('m'); 396 | } 397 | 398 | /** 399 | * Multiple 400 | * 401 | * Adds the multiple modifier at the end of your expression 402 | * 403 | * @access public 404 | * @param string $value Your expression 405 | * @return VerbalExpressions 406 | */ 407 | public function multiple($value) 408 | { 409 | $value = self::sanitize($value); 410 | 411 | $last = substr($value, -1); 412 | 413 | if ($last !== '+' && $last !== '*') { 414 | $value .= '+'; 415 | } 416 | 417 | return $this->add($value); 418 | } 419 | 420 | /** 421 | * OR 422 | * 423 | * Wraps the current expression in an `or` with $value 424 | * Notice: OR is a reserved keyword in PHP, so this method is prefixed with "_" 425 | * 426 | * @access public 427 | * @param string $value new expression 428 | * @return VerbalExpressions 429 | */ 430 | public function _or($value) 431 | { 432 | if (strpos($this->prefixes, '(') === false) { 433 | $this->prefixes .= '(?:'; 434 | } 435 | 436 | if (strpos($this->suffixes, ')') === false) { 437 | $this->suffixes .= ')'; 438 | } 439 | 440 | $this->add(')|(?:'); 441 | 442 | if ($value) { 443 | $this->add($value); 444 | } 445 | 446 | return $this; 447 | } 448 | 449 | /** 450 | * Object to string 451 | * 452 | * PHP Magic method to return a string representation of the object. 453 | * 454 | * @access public 455 | * @return string 456 | */ 457 | public function __toString() 458 | { 459 | return $this->getRegex(); 460 | } 461 | 462 | /** 463 | * Get the Expression 464 | * 465 | * Creates the final regex. 466 | * 467 | * @access public 468 | * @return string The final regex 469 | */ 470 | public function getRegex() 471 | { 472 | return '/' . $this->prefixes . $this->source . $this->suffixes . '/' . $this->modifiers; 473 | } 474 | 475 | /** 476 | * Test 477 | * 478 | * Tests the match of a string to the current regex 479 | * 480 | * @access public 481 | * @param string $value The string to be tested 482 | * @return boolean true if it's a match 483 | */ 484 | public function test($value) 485 | { 486 | // php doesn't have g modifier so we remove it if it's there and call preg_match_all() 487 | if (strpos($this->modifiers, 'g') !== false) { 488 | $this->modifiers = str_replace('g', '', $this->modifiers); 489 | $matches = array();//because it's not optional in <5.4 490 | return preg_match_all($this->getRegex(), $value, $matches); 491 | } 492 | 493 | return (bool) preg_match($this->getRegex(), $value); 494 | } 495 | 496 | /** 497 | * Clean 498 | * 499 | * Deletes the current regex for a fresh start 500 | * 501 | * @access public 502 | * @param array $options 503 | * @return VerbalExpressions 504 | */ 505 | public function clean(array $options = array()) 506 | { 507 | $options = array_merge( 508 | array( 509 | 'prefixes' => '', 510 | 'source' => '', 511 | 'suffixes' => '', 512 | 'modifiers' => 'gm', 513 | 'replaceLimit' => '1' 514 | ), 515 | $options 516 | ); 517 | $this->prefixes = $options['prefixes']; 518 | $this->source = $options['source']; 519 | $this->suffixes = $options['suffixes']; 520 | $this->modifiers = $options['modifiers']; // default to global multi line matching 521 | $this->replaceLimit = $options['replaceLimit']; // default to global multi line matching 522 | 523 | return $this; 524 | } 525 | 526 | /** 527 | * Limit 528 | * 529 | * Adds char limit to the last added expression. 530 | * If $max is less then $min the limit will be: At least $min chars {$min,} 531 | * If $max is 0 the limit will be: exactly $min chars {$min} 532 | * If $max bigger then $min the limit will be: at least $min but not more then $max {$min, $max} 533 | * 534 | * @access public 535 | * @param integer $min 536 | * @param integer $max 537 | * @return VerbalExpressions 538 | */ 539 | public function limit($min, $max = 0) 540 | { 541 | if ($max == 0) { 542 | $value = '{' . $min . '}'; 543 | } elseif ($max < $min) { 544 | $value = '{' . $min . ',}'; 545 | } else { 546 | $value = '{' . $min . ',' . $max . '}'; 547 | } 548 | 549 | // check if the expression has * or + for the last expression 550 | if (preg_match('/\*|\+/', $this->lastAdded)) { 551 | $l = 1; 552 | $this->source = strrev(str_replace(array('+', '*'), strrev($value), strrev($this->source), $l)); 553 | 554 | return $this; 555 | } 556 | 557 | return $this->add($value); 558 | } 559 | } 560 | -------------------------------------------------------------------------------- /src/VerbalExpressionsScenario.php: -------------------------------------------------------------------------------- 1 | 15 | */ 16 | class VerbalExpressionsScenario extends VerbalExpressions 17 | { 18 | 19 | /** 20 | * @var string 21 | */ 22 | private $methodDelimiter; 23 | 24 | /** 25 | * @var string 26 | */ 27 | private $argumentDelimiter; 28 | 29 | /** 30 | * @var MethodParser 31 | */ 32 | private $methodParser; 33 | 34 | /** 35 | * @param string $scenario 36 | * @param string $methodDelimiter 37 | * @param string $argumentDelimiter 38 | * @param null|MethodParserInterface $methodParser 39 | * 40 | * @return VerbalExpressionsScenario 41 | */ 42 | public function __construct($scenario, $methodDelimiter = ', ', $argumentDelimiter = '"', $methodParser = null) 43 | { 44 | if (null == $methodParser || !$methodParser instanceof MethodParserInterface) { 45 | $this->methodParser = new MethodParser(); 46 | } 47 | $this->methodDelimiter = $methodDelimiter; 48 | $this->argumentDelimiter = $argumentDelimiter; 49 | $parsedScenario = $this->parseScenario($scenario); 50 | 51 | return $this->runScenario($parsedScenario); 52 | } 53 | 54 | /** 55 | * @param string $scenarioString 56 | * 57 | * @return array 58 | */ 59 | private function parseScenario($scenarioString) 60 | { 61 | $parsedScenario = array(); 62 | $scenarios = explode($this->methodDelimiter, $scenarioString); 63 | foreach ($scenarios as $scenario) { 64 | $arguments = null; 65 | $scenarioElement = explode($this->argumentDelimiter, $scenario); 66 | if (isset($scenarioElement[1])) { 67 | $arguments = $scenarioElement[1]; 68 | } 69 | $parsedScenario[] = new Expression($this->methodParser->parse($scenarioElement[0]), $arguments); 70 | } 71 | 72 | return $parsedScenario; 73 | } 74 | 75 | /** 76 | * @param array $parsedScenario 77 | * 78 | * @return VerbalExpressions 79 | */ 80 | private function runScenario($parsedScenario) 81 | { 82 | foreach ($parsedScenario as $expression) { 83 | call_user_func_array(array($this, $expression->getName()), array($expression->getArguments())); 84 | } 85 | 86 | return $this; 87 | } 88 | 89 | /** 90 | * @param null $range 91 | * 92 | * @return VerbalExpressions 93 | * @throws \InvalidArgumentException 94 | */ 95 | public function rangeBridge($range = null) 96 | { 97 | $range = explode(",", $range); 98 | call_user_func_array(array($this, 'range'), $range); 99 | } 100 | 101 | /** 102 | * @param array $arguments 103 | */ 104 | public function replaceBridge($arguments) 105 | { 106 | call_user_func(array($this, 'replace'), $arguments[0], $arguments[1]); 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /tests/Parser/MethodParserTest.php: -------------------------------------------------------------------------------- 1 | 12 | */ 13 | class MethodParserTest extends TestCase 14 | { 15 | private $methodParser; 16 | 17 | public function setUp() 18 | { 19 | $this->methodParser = new MethodParser(); 20 | } 21 | 22 | public function testParseWithEmptyText() 23 | { 24 | $this->assertNull($this->methodParser->parse('')); 25 | } 26 | 27 | /** 28 | * @dataProvider methodsList 29 | */ 30 | public function testParse($text, $expected) 31 | { 32 | $this->assertEquals($expected, $this->methodParser->parse($text)); 33 | } 34 | 35 | public function methodsList() 36 | { 37 | return array( 38 | array('anythingBut', MethodParser::ANYTHING_BUT), 39 | array('anything But', MethodParser::ANYTHING_BUT), 40 | array('somethingBut', MethodParser::SOMETHING_BUT), 41 | array('something but', MethodParser::SOMETHING_BUT), 42 | array('something', MethodParser::SOMETHING), 43 | array('anything but', MethodParser::ANYTHING_BUT), 44 | array('anything', MethodParser::ANYTHING), 45 | array('end', MethodParser::END_OF_LINE), 46 | array('find', MethodParser::FIND), 47 | array('maybe', MethodParser::MAYBE), 48 | array('start', MethodParser::START_OF_LINE), 49 | array('then', MethodParser::THEN), 50 | array('any', MethodParser::ANY), 51 | array('anyof', MethodParser::ANY_OF), 52 | array('any of', MethodParser::ANY_OF), 53 | array('br', MethodParser::BR), 54 | array('linebreak', MethodParser::LINE_BREAK), 55 | array('line break', MethodParser::LINE_BREAK), 56 | array('range', MethodParser::RANGE), 57 | array('tab', MethodParser::TAB), 58 | array('word', MethodParser::WORD), 59 | array('withanycase', MethodParser::WITH_ANY_CASE), 60 | array('with any case', MethodParser::WITH_ANY_CASE), 61 | array('any case', MethodParser::WITH_ANY_CASE), 62 | array('stopatfirst', MethodParser::STOP_AT_FIRST), 63 | array('stop at first', MethodParser::STOP_AT_FIRST), 64 | array('stop first', MethodParser::STOP_AT_FIRST), 65 | array('searchoneline', MethodParser::SEARCH_ONE_LINE), 66 | array('search one line', MethodParser::SEARCH_ONE_LINE), 67 | array('add modifier', MethodParser::ADD_MODIFIER), 68 | array('remove modifier', MethodParser::REMOVE_MODIFIER), 69 | array('replace', MethodParser::REPLACE), 70 | array('add', MethodParser::ADD), 71 | array('limit', MethodParser::LIMIT), 72 | array('multiple', MethodParser::MULTIPLE), 73 | array('or', MethodParser::_OR) 74 | ); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /tests/VerbalExpressionsScenarioTest.php: -------------------------------------------------------------------------------- 1 | assertEquals($expectation, (string)$reg, sprintf('The expected result "%s" is wrongly generated by the expression "%s"', $expectation, $expression)); 16 | } 17 | 18 | public function expressionProvider() 19 | { 20 | return array( 21 | array('start, then "http", range "a,z,1,2", end', '/(?:http)[a-z1-2]/m'), 22 | array('start, anythingBut "http", maybe "zed", end', '/(?:[^http]*)(?:zed)?/m'), 23 | array('start, any "foo", br, linebreak, tab, end', '/[foo](?:\n|(\r\n))(?:\n|(\r\n))\t/m'), 24 | array('start, any "http", br, end', '/[http](?:\n|(\r\n))/m'), 25 | array('start, anyOf "12", then "foo", end', '/[12](?:foo)/m'), 26 | array('start, anything, word, end', '/(?:.*)\w+/m'), 27 | array('start, then "foo", withAnyCase, end', '/(?:foo)/'), 28 | array('start, then "foo", stopAtFirst, searchOneLINE, end', '/(?:foo)/'), 29 | array('start, then "foo", or "bar", end', '/(?:(?:foo))|(?:bar/m'), 30 | array('start, word, limit "3", end', '/\w{3}/m'), 31 | array('start, find "foo", replace "foo,bar", end', '/(?:foo)/m'), 32 | array('start, then "abc", multiple "2", end', '/(?:abc)2+/m'), 33 | array('start, then "abc", add "something", end', '/(?:abc)something/m'), 34 | array('something', '/(?:.+)/m'), 35 | ); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /tests/VerbalExpressionsTest.php: -------------------------------------------------------------------------------- 1 | buildUrlPattern($regex); 18 | 19 | $this->assertTrue($regex->test($url)); 20 | 21 | 22 | $regex = new VerbalExpressions(); 23 | $this->buildUrlPatternAliased($regex); 24 | 25 | $this->assertTrue($regex->test($url)); 26 | } 27 | 28 | public static function provideValidUrls() 29 | { 30 | return array( 31 | array('http://github.com'), 32 | array('http://www.github.com'), 33 | array('https://github.com'), 34 | array('https://www.github.com'), 35 | array('https://github.com/blog'), 36 | array('https://foobar.github.com') 37 | ); 38 | } 39 | 40 | /** 41 | * @dataProvider provideInvalidUrls 42 | * @group functional 43 | */ 44 | public function testShouldFailWithInvalidUrls($url) 45 | { 46 | $regex = new VerbalExpressions(); 47 | $this->buildUrlPattern($regex); 48 | 49 | $this->assertFalse($regex->test($url)); 50 | } 51 | 52 | public static function provideInvalidUrls() 53 | { 54 | return array( 55 | array(' http://github.com'), 56 | array('foo'), 57 | array('htps://github.com'), 58 | array('http:/github.com'), 59 | array('https://github.com /blog'), 60 | ); 61 | } 62 | 63 | protected function buildUrlPattern(VerbalExpressions $regex) 64 | { 65 | return $regex->startOfLine() 66 | ->then("http") 67 | ->maybe("s") 68 | ->then("://") 69 | ->maybe("www.") 70 | ->anythingBut(" ") 71 | ->endOfLine(); 72 | } 73 | 74 | protected function buildUrlPatternAliased(VerbalExpressions $regex) 75 | { 76 | return $regex->startOfLine() 77 | ->find("http") 78 | ->maybe("s") 79 | ->find("://") 80 | ->maybe("www.") 81 | ->anythingBut(" ") 82 | ->endOfLine(); 83 | } 84 | 85 | 86 | public function testTest() 87 | { 88 | $regex = new VerbalExpressions(); 89 | $regex->find('regex'); 90 | 91 | $this->assertTrue($regex->test('testing regex string')); 92 | $this->assertFalse($regex->test('testing string')); 93 | 94 | $regex->stopAtFirst(); 95 | 96 | $this->assertEquals(1, $regex->test('testing regex string')); 97 | $this->assertFalse($regex->test('testing string')); 98 | } 99 | 100 | /** 101 | * @depends testTest 102 | */ 103 | public function testThenAfterStartOfLine() 104 | { 105 | $regex = new VerbalExpressions(); 106 | $regex->startOfLine() 107 | ->then('a') 108 | ->endOfLine(); 109 | 110 | $this->assertTrue($regex->test('a')); 111 | $this->assertFalse($regex->test('ba')); 112 | } 113 | 114 | public function testThenSomewhere() 115 | { 116 | $regex = new VerbalExpressions(); 117 | $regex->startOfLine(false) 118 | ->then('a') 119 | ->endOfLine(false); 120 | 121 | $this->assertTrue($regex->test('a')); 122 | $this->assertTrue($regex->test('ba')); 123 | } 124 | 125 | /** 126 | * @dataProvider provideAnything 127 | */ 128 | public function testAnything($needle) 129 | { 130 | $regex = new VerbalExpressions(); 131 | $regex->startOfLine() 132 | ->anything() 133 | ->endOfLine(); 134 | 135 | $this->assertTrue($regex->test($needle)); 136 | } 137 | 138 | public static function provideAnything() 139 | { 140 | return array( 141 | array('a'), 142 | array('foo'), 143 | array('bar'), 144 | array('!'), 145 | array(' dfs fdslf sdlfk '), 146 | array('t ( - _ - t )'), 147 | ); 148 | } 149 | 150 | public function testAnythingBut() 151 | { 152 | $regex = new VerbalExpressions(); 153 | $regex->startOfLine() 154 | ->anythingBut('a') 155 | ->endOfLine(); 156 | 157 | $this->assertTrue($regex->test('bcdefg h I A')); 158 | $this->assertFalse($regex->test('a')); 159 | $this->assertFalse($regex->test('fooa')); 160 | } 161 | 162 | public function testAnythingButQuote() 163 | { 164 | $regex = new VerbalExpressions(); 165 | $regex->startOfLine() 166 | ->anythingBut('[') 167 | ->endOfLine(); 168 | 169 | $this->assertTrue($regex->test('abcd')); 170 | $this->assertTrue($regex->test('ab\cd')); 171 | $this->assertFalse($regex->test('ab[cd')); 172 | $this->assertFalse($regex->test('[')); 173 | $this->assertFalse($regex->test('[')); 174 | $this->assertFalse($regex->test('\[')); 175 | } 176 | 177 | public function testSomething() 178 | { 179 | $regex = new VerbalExpressions(); 180 | $regex->startOfLine() 181 | ->something() 182 | ->endOfLine(); 183 | 184 | $this->assertTrue($regex->test('foobar')); 185 | $this->assertTrue($regex->test('foobar!')); 186 | $this->assertTrue($regex->test('foo bar')); 187 | $this->assertFalse($regex->test('')); 188 | } 189 | 190 | public function testSomethingBut() 191 | { 192 | $regex = new VerbalExpressions(); 193 | $regex->startOfLine() 194 | ->somethingBut('a') 195 | ->endOfLine(); 196 | 197 | $this->assertTrue($regex->test('foobr')); 198 | $this->assertTrue($regex->test('foobr!')); 199 | $this->assertTrue($regex->test('foo br')); 200 | $this->assertFalse($regex->test('a')); 201 | $this->assertFalse($regex->test('bar')); 202 | $this->assertFalse($regex->test('foo bar')); 203 | $this->assertFalse($regex->test('')); 204 | } 205 | 206 | public function testBr() 207 | { 208 | $regex = new VerbalExpressions(); 209 | $regex->startOfLine() 210 | ->something() 211 | ->br() 212 | ->something() 213 | ->endOfLine(); 214 | 215 | $this->assertTrue($regex->test("foo\nbar")); 216 | $this->assertFalse($regex->test("foo bar")); 217 | } 218 | 219 | public function testLineBreak() 220 | { 221 | $regex = new VerbalExpressions(); 222 | $regex->startOfLine() 223 | ->something() 224 | ->lineBreak() 225 | ->something() 226 | ->endOfLine(); 227 | 228 | $this->assertTrue($regex->test("foo\nbar")); 229 | $this->assertFalse($regex->test("foo bar")); 230 | } 231 | 232 | public function testTab() 233 | { 234 | $regex = new VerbalExpressions(); 235 | $regex->startOfLine() 236 | ->something() 237 | ->tab() 238 | ->something() 239 | ->endOfLine(); 240 | 241 | $this->assertTrue($regex->test("foo\tbar")); 242 | $this->assertFalse($regex->test("foo bar")); 243 | } 244 | 245 | public function testWord() 246 | { 247 | $regex = new VerbalExpressions(); 248 | $regex->startOfLine() 249 | ->word() 250 | ->endOfLine(); 251 | 252 | $this->assertTrue($regex->test('abcdefghijklmnopqrstuvwxyz0123456789_')); 253 | $this->assertTrue($regex->test('ABCDEFGHIJKLMNOPQRSTUVWXYZ')); 254 | $this->assertTrue($regex->test('a_c')); 255 | $this->assertFalse($regex->test('a-b')); 256 | $this->assertFalse($regex->test('a b')); 257 | $this->assertFalse($regex->test('a!b')); 258 | } 259 | 260 | 261 | public function testDigit() 262 | { 263 | $regex = new VerbalExpressions(); 264 | $regex->digit(); 265 | 266 | $this->assertTrue($regex->test('0123456789')); 267 | 268 | foreach (str_split('ABCDEFGHIJKLMNOPQRSTUVWXYZ_-@,./%*') as $char) { 269 | $this->assertFalse($regex->test($char), 'Should not match digit ('.$char.')'); 270 | } 271 | } 272 | 273 | public function testAny() 274 | { 275 | $regex = new VerbalExpressions(); 276 | $regex->startOfLine() 277 | ->any('a1M') 278 | ->endOfLine(); 279 | 280 | $this->assertTrue($regex->test('a')); 281 | $this->assertTrue($regex->test('1')); 282 | $this->assertTrue($regex->test('M')); 283 | $this->assertFalse($regex->test('b')); 284 | $this->assertFalse($regex->test('')); 285 | $this->assertFalse($regex->test(' ')); 286 | } 287 | 288 | public function testAnyOf() 289 | { 290 | $regex = new VerbalExpressions(); 291 | $regex->startOfLine() 292 | ->anyOf('a1M') 293 | ->endOfLine(); 294 | 295 | $this->assertTrue($regex->test('a')); 296 | $this->assertTrue($regex->test('1')); 297 | $this->assertTrue($regex->test('M')); 298 | $this->assertFalse($regex->test('b')); 299 | $this->assertFalse($regex->test('')); 300 | $this->assertFalse($regex->test(' ')); 301 | } 302 | 303 | 304 | public function testGetRegex() 305 | { 306 | $regex = new VerbalExpressions(); 307 | $regex->startOfLine() 308 | ->range(0, 9, 'a', 'z', 'A', 'Z') 309 | ->multiple(''); 310 | 311 | $this->assertEquals('/^[0-9a-zA-Z]+/m', $regex->getRegex()); 312 | $this->assertEquals('/^[0-9a-zA-Z]+/m', $regex->__toString()); 313 | $this->assertEquals('/^[0-9a-zA-Z]+/m', (string)$regex); 314 | $this->assertEquals('/^[0-9a-zA-Z]+/m', $regex . ''); 315 | } 316 | 317 | /** 318 | * @depends testGetRegex 319 | */ 320 | public function testGetRegexMultiple() 321 | { 322 | $regex = new VerbalExpressions(); 323 | $regex->startOfLine() 324 | ->multiple('regex'); 325 | 326 | $this->assertEquals('/^regex+/m', $regex->getRegex()); 327 | } 328 | 329 | /** 330 | * @expectedException InvalidArgumentException 331 | */ 332 | public function testRangeThrowsException() 333 | { 334 | $regex = new VerbalExpressions(); 335 | $regex->range(1, 2, 3); 336 | } 337 | 338 | /** 339 | * @depends testGetRegex 340 | */ 341 | public function testRangeLowercase() 342 | { 343 | $lowercaseAlpha = new VerbalExpressions(); 344 | $lowercaseAlpha->range('a', 'z') 345 | ->multiple(''); 346 | 347 | $lowercaseAlpha_all = new VerbalExpressions(); 348 | $lowercaseAlpha_all->startOfLine() 349 | ->range('a', 'z') 350 | ->multiple('') 351 | ->endOfLine(); 352 | 353 | $this->assertEquals('/[a-z]+/m', $lowercaseAlpha->getRegex()); 354 | $this->assertEquals('/^[a-z]+$/m', $lowercaseAlpha_all->getRegex()); 355 | 356 | $this->assertTrue($lowercaseAlpha->test('a')); 357 | $this->assertFalse($lowercaseAlpha->test('A')); 358 | $this->assertTrue($lowercaseAlpha->test('alphabet')); 359 | $this->assertTrue($lowercaseAlpha->test('Alphabet')); 360 | $this->assertFalse($lowercaseAlpha_all->test('Alphabet')); 361 | } 362 | 363 | /** 364 | * @depends testGetRegex 365 | */ 366 | public function testRangeUppercase() 367 | { 368 | $uppercaseAlpha = new VerbalExpressions(); 369 | $uppercaseAlpha->range('A', 'Z') 370 | ->multiple(''); 371 | 372 | $uppercaseAlpha_all = new VerbalExpressions(); 373 | $uppercaseAlpha_all->startOfLine() 374 | ->range('A', 'Z') 375 | ->multiple('') 376 | ->endOfLine(); 377 | 378 | $this->assertEquals('/[A-Z]+/m', $uppercaseAlpha->getRegex()); 379 | $this->assertEquals('/^[A-Z]+$/m', $uppercaseAlpha_all->getRegex()); 380 | 381 | $this->assertTrue($uppercaseAlpha->test('A')); 382 | $this->assertFalse($uppercaseAlpha->test('a')); 383 | $this->assertFalse($uppercaseAlpha->test('alphabet')); 384 | $this->assertTrue($uppercaseAlpha->test('Alphabet')); 385 | $this->assertTrue($uppercaseAlpha->test('ALPHABET')); 386 | $this->assertFalse($uppercaseAlpha_all->test('Alphabet')); 387 | $this->assertTrue($uppercaseAlpha_all->test('ALPHABET')); 388 | } 389 | 390 | /** 391 | * @depends testGetRegex 392 | */ 393 | public function testRangeNumerical() 394 | { 395 | $zeroToNine = new VerbalExpressions(); 396 | $zeroToNine->range(0, 9) 397 | ->multiple(''); 398 | 399 | $zeroToNine_all = new VerbalExpressions(); 400 | $zeroToNine_all->startOfLine() 401 | ->range(0, 9) 402 | ->multiple('') 403 | ->endOfLine(); 404 | 405 | $this->assertEquals('/[0-9]+/m', $zeroToNine->getRegex()); 406 | $this->assertEquals('/^[0-9]+$/m', $zeroToNine_all->getRegex()); 407 | 408 | $this->assertFalse($zeroToNine->test('alphabet')); 409 | $this->assertTrue($zeroToNine->test(0)); 410 | $this->assertTrue($zeroToNine->test('0')); 411 | $this->assertTrue($zeroToNine->test(123)); 412 | $this->assertTrue($zeroToNine->test('123')); 413 | $this->assertTrue($zeroToNine->test(1.23)); 414 | $this->assertTrue($zeroToNine->test('1.23')); 415 | $this->assertFalse($zeroToNine_all->test(1.23)); 416 | $this->assertFalse($zeroToNine_all->test('1.23')); 417 | $this->assertTrue($zeroToNine->test('£123')); 418 | $this->assertFalse($zeroToNine_all->test('£123')); 419 | } 420 | 421 | /** 422 | * @depends testGetRegex 423 | */ 424 | public function testRangeHexadecimal() 425 | { 426 | $hexadecimal = new VerbalExpressions(); 427 | $hexadecimal->startOfLine() 428 | ->range(0, 9, 'a', 'f') 429 | ->multiple('') 430 | ->endOfLine(); 431 | 432 | $this->assertEquals('/^[0-9a-f]+$/m', $hexadecimal->getRegex()); 433 | 434 | $this->assertFalse($hexadecimal->test('alphabet')); 435 | $this->assertTrue($hexadecimal->test('deadbeef')); 436 | $this->assertTrue($hexadecimal->test(md5(''))); 437 | $this->assertTrue($hexadecimal->test(sha1(''))); 438 | } 439 | 440 | /** 441 | * @depends testRangeHexadecimal 442 | */ 443 | public function testRangeMd5() 444 | { 445 | $md5 = new VerbalExpressions(); 446 | $md5->startOfLine() 447 | ->range(0, 9, 'a', 'f') 448 | ->limit(32) 449 | ->endOfLine(); 450 | 451 | $this->assertEquals('/^[0-9a-f]{32}$/m', $md5->getRegex()); 452 | 453 | $this->assertFalse($md5->test('alphabet')); 454 | $this->assertFalse($md5->test('deadbeef')); 455 | $this->assertTrue($md5->test(md5(''))); 456 | $this->assertFalse($md5->test(sha1(''))); 457 | } 458 | 459 | /* 460 | * @depends testRangeHexadecimal 461 | */ 462 | public function testRangeSha1() 463 | { 464 | $sha1 = new VerbalExpressions(); 465 | $sha1->startOfLine() 466 | ->range(0, 9, 'a', 'f') 467 | ->limit(40) 468 | ->endOfLine(); 469 | 470 | $this->assertEquals('/^[0-9a-f]{40}$/m', $sha1->getRegex()); 471 | 472 | $this->assertFalse($sha1->test('alphabet')); 473 | $this->assertFalse($sha1->test('deadbeef')); 474 | $this->assertFalse($sha1->test(md5(''))); 475 | $this->assertTrue($sha1->test(sha1(''))); 476 | } 477 | 478 | /** 479 | * @depends testGetRegex 480 | */ 481 | public function testRemoveModifier() 482 | { 483 | $regex = new VerbalExpressions(); 484 | $regex->range('a', 'z'); 485 | 486 | $this->assertEquals('/[a-z]/m', $regex->getRegex()); 487 | 488 | $regex->removeModifier('m'); 489 | 490 | $this->assertEquals('/[a-z]/', $regex->getRegex()); 491 | } 492 | 493 | /** 494 | * @depends testRemoveModifier 495 | */ 496 | public function testWithAnyCase() 497 | { 498 | $regex = new VerbalExpressions(); 499 | $regex->range('a', 'z') 500 | ->searchOneLine(false) 501 | ->withAnyCase(); 502 | 503 | $this->assertEquals('/[a-z]/i', $regex->getRegex()); 504 | 505 | $regex->withAnyCase(false); 506 | 507 | $this->assertEquals('/[a-z]/', $regex->getRegex()); 508 | } 509 | 510 | /** 511 | * @depends testGetRegex 512 | */ 513 | public function testOr() 514 | { 515 | $regex = new VerbalExpressions(); 516 | $regex->find('foo') 517 | ->_or('bar'); 518 | 519 | $this->assertTrue($regex->test('foo')); 520 | $this->assertTrue($regex->test('bar')); 521 | $this->assertFalse($regex->test('baz')); 522 | $this->assertTrue($regex->test('food')); 523 | 524 | $this->assertEquals('/(?:(?:foo))|(?:bar)/m', $regex->getRegex()); 525 | } 526 | 527 | /** 528 | * @depends testGetRegex 529 | * @todo fix VerbalExpressions::clean() so it matches initial state 530 | */ 531 | public function testClean() 532 | { 533 | $regex = new VerbalExpressions(); 534 | $regex->removeModifier('m') 535 | ->stopAtFirst() 536 | ->searchOneLine(); 537 | 538 | $regex_at_start = $regex->getRegex(); 539 | $regex->find('something') 540 | ->add('else') 541 | ->_or('another'); 542 | 543 | $this->assertNotEquals($regex_at_start, $regex->getRegex()); 544 | 545 | $regex->clean(); 546 | 547 | $this->assertEquals($regex_at_start, $regex->getRegex()); 548 | } 549 | 550 | /** 551 | * @depends testGetRegex 552 | */ 553 | public function testLimit() 554 | { 555 | $regex = new VerbalExpressions(); 556 | 557 | $regex->add('a') 558 | ->limit(1); 559 | $this->assertEquals('/a{1}/m', $regex->getRegex()); 560 | 561 | $regex->add('b') 562 | ->limit(2, 1); 563 | $this->assertEquals('/a{1}b{2,}/m', $regex->getRegex()); 564 | 565 | $regex->add('c') 566 | ->limit(3, 4); 567 | $this->assertEquals('/a{1}b{2,}c{3,4}/m', $regex->getRegex()); 568 | 569 | $regex->multiple('d'); 570 | $this->assertEquals('/a{1}b{2,}c{3,4}d+/m', $regex->getRegex()); 571 | 572 | $regex->limit(5, 6); 573 | $this->assertEquals('/a{1}b{2,}c{3,4}d{5,6}/m', $regex->getRegex()); 574 | } 575 | 576 | /** 577 | * @depends testGetRegex 578 | */ 579 | public function testReplace() 580 | { 581 | $regex = new VerbalExpressions(); 582 | $regex->add('foo'); 583 | 584 | $this->assertEquals('/foo/m', $regex->getRegex()); 585 | $this->assertEquals('bazbarfoo', $regex->replace('foobarfoo', 'baz')); 586 | 587 | $regex->stopAtFirst(); 588 | 589 | $this->assertEquals('/foo/mg', $regex->getRegex()); 590 | $this->assertEquals('bazbarbaz', $regex->replace('foobarfoo', 'baz')); 591 | } 592 | } 593 | --------------------------------------------------------------------------------