StringUtils: Add a utility for checking if a string is a valid regex
authorDaimona Eaytoy <daimona.wiki@gmail.com>
Wed, 5 Sep 2018 14:20:13 +0000 (16:20 +0200)
committerDaimona Eaytoy <daimona.wiki@gmail.com>
Wed, 18 Sep 2019 09:46:29 +0000 (09:46 +0000)
There's no function to check if a string is a valid regex, and doing it
via preg_match requires error suppression, often performed with @. This
isn't however a good practice, and suppressing errors via functions is
not a one line solution. Adding an utility function would probably be a
benefit for several use cases (try to grep '@preg_match' for a few of
them).

Change-Id: I257a096319f1ec13441e9f745dcd22545fdd5cc6

includes/libs/StringUtils.php
tests/phpunit/includes/libs/StringUtilsTest.php

index 51d1081..19dd8fe 100644 (file)
@@ -1,4 +1,7 @@
 <?php
+
+use Wikimedia\AtEase\AtEase;
+
 /**
  * Methods to play with strings.
  *
@@ -340,4 +343,21 @@ class StringUtils {
                        return new ArrayIterator( explode( $separator, $subject ) );
                }
        }
+
+       /**
+        * Utility function to check if the given string is a valid regex. Avoids
+        * manually calling suppressWarnings and restoreWarnings, and provides a
+        * one-line solution without the need to use @.
+        *
+        * @since 1.34
+        * @param string $string The string you want to check being a valid regex
+        * @return bool
+        */
+       public static function isValidRegex( $string ) {
+               AtEase::suppressWarnings();
+               // @phan-suppress-next-line PhanParamSuspiciousOrder False positive
+               $isValid = preg_match( $string, '' );
+               AtEase::restoreWarnings();
+               return $isValid !== false;
+       }
 }
index fcfa53e..79d5788 100644 (file)
@@ -125,4 +125,28 @@ class StringUtilsTest extends PHPUnit\Framework\TestCase {
                        'noncharacters 2' => [ $PASS, "\xef\xbf\xbf" ],
                ];
        }
+
+       /**
+        * @param strin $input
+        * @param bool $expected
+        * @dataProvider provideRegexps
+        * @covers StringUtils::isValidRegex
+        */
+       public function testIsValidRegex( $input, $expected ) {
+               $this->assertSame( $expected, StringUtils::isValidRegex( $input ) );
+       }
+
+       /**
+        * Data provider for testValidRegex
+        */
+       public static function provideRegexps() {
+               return [
+                       [ 'foo', false ],
+                       [ '/foo/', true ],
+                       [ '//', true ],
+                       [ '/(foo/', false ],
+                       [ '!(f[o]{2})!', true ],
+                       [ '/foo\/', false ]
+               ];
+       }
 }