From 430c066f7797328afe292dabde608f1b784a1ab6 Mon Sep 17 00:00:00 2001 From: Francois Zaninotto Date: Fri, 7 Nov 2014 09:05:12 +0100 Subject: [PATCH 1/2] Add regexify formatter --- src/Faker/Provider/Base.php | 73 ++++++++++++++++++++++++++++++++ test/Faker/Provider/BaseTest.php | 50 +++++++++++++++++++++- 2 files changed, 121 insertions(+), 2 deletions(-) diff --git a/src/Faker/Provider/Base.php b/src/Faker/Provider/Base.php index de61c8b49a..e5f2c0fa48 100644 --- a/src/Faker/Provider/Base.php +++ b/src/Faker/Provider/Base.php @@ -370,6 +370,79 @@ public static function asciify($string = '****') return preg_replace_callback('/\*/u', 'static::randomAscii', $string); } + /** + * Transforms a basic regular expression into a random string satisfying the expression. + * + * @example $faker->regexify('[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}'); // sm0@y8k96a.ej + * + * Regex delimiters '/.../' and begin/end markers '^...$' are ignored. + * + * Only supports a small subset of the regex syntax. For instance, + * unicode, negated classes, unbouned ranges, subpatterns, back references, + * assertions, recursive patterns, and comments are not supported. Escaping + * support is extremely fragile. + * + * This method is also VERY slow. Use it only when no other formatter + * can generate the fake data you want. For instance, prefer calling + * `$faker->email` rather than `regexify` with the previous regular + * expression. + * + * Also note than `bothify` can probably do most of what this method does, + * but much faster. For instance, for a dummy email generation, try + * `$faker->bothify('?????????@???.???')`. + * + * @see https://github.com/icomefromthenet/ReverseRegex for a more robust implementation + * + * @param string $regex A regular expression (delimiters are optional) + * @return string + */ + public static function regexify($regex = '') + { + // ditch the anchors + $regex = preg_replace('/^\/?\^?/', '', $regex); + $regex = preg_replace('/\$?\/?$/', '', $regex); + // All {2} become {2,2} + $regex = preg_replace('/\{(\d+)\}/', '{\1,\1}', $regex); + // Single-letter quantifiers (?, *, +) become bracket quantifiers ({0,1}, {0,rand}, {1, rand}) + $regex = preg_replace('/(?assertEquals('fooBar?', BaseProvider::asciify('fooBar?')); } - public function testNumerifyReturnsStringWithStarSignsReplacedByAsciiChars() + public function testAsciifyReturnsStringWithStarSignsReplacedByAsciiChars() { - $this->assertRegExp('/foo.Ba.r/', BaseProvider::numerify('foo*Ba*r')); + $this->assertRegExp('/foo.Ba.r/', BaseProvider::asciify('foo*Ba*r')); + } + + public function regexifyBasicDataProvider() + { + return array( + array('azeQSDF1234', 'azeQSDF1234', 'does not change non regex chars'), + array('foo(bar){1}', 'foobar', 'replaces regex characters'), + array('', '', 'supports empty string'), + array('/^foo(bar){1}$/', 'foobar', 'ignores regex delimiters') + ); + } + + /** + * @dataProvider regexifyBasicDataProvider + */ + public function testRegexifyBasicFeatures($input, $output, $message) + { + $this->assertEquals($output, BaseProvider::regexify($input), $message); + } + + public function regexifyDataProvider() + { + return array( + array('\d', 'numbers'), + array('\w', 'letters'), + array('(a|b)', 'alternation'), + array('[aeiou]', 'basic character class'), + array('[a-z]', 'character class range'), + array('[a-z1-9]', 'multiple character class range'), + array('a*b+c?', 'single character quantifiers'), + array('a{2}', 'brackets quantifiers'), + array('a{2,3}', 'min-max brackets quantifiers'), + array('[aeiou]{2,3}', 'brackets quantifiers on basic character class'), + array('[a-z]{2,3}', 'brackets quantifiers on character class range'), + array('(a|b){2,3}', 'brackets quantifiers on alternation'), + array('\.\*\?\+', 'escaped characters'), + array('[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}', 'complex regex') + ); + } + + /** + * @dataProvider regexifyDataProvider + */ + public function testRegexifySupportedRegexSyntax($pattern, $message) + { + $this->assertRegExp('/' . $pattern . '/', BaseProvider::regexify($pattern), 'Regexify supports ' . $message); } public function testOptionalReturnsProviderValueWhenCalledWithWeight1() From b7a0aeeedee473ce9487ff45a78e4373be4148f1 Mon Sep 17 00:00:00 2001 From: Francois Zaninotto Date: Fri, 7 Nov 2014 09:13:22 +0100 Subject: [PATCH 2/2] Fix regexify on PHP 5.3 --- src/Faker/Provider/Base.php | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Faker/Provider/Base.php b/src/Faker/Provider/Base.php index e5f2c0fa48..ee5b3a0056 100644 --- a/src/Faker/Provider/Base.php +++ b/src/Faker/Provider/Base.php @@ -405,23 +405,23 @@ public static function regexify($regex = '') $regex = preg_replace('/\{(\d+)\}/', '{\1,\1}', $regex); // Single-letter quantifiers (?, *, +) become bracket quantifiers ({0,1}, {0,rand}, {1, rand}) $regex = preg_replace('/(?