Validate regex in string pattern and object patternProperties
[MAILPOET-4195]
This commit is contained in:
@@ -87,4 +87,12 @@ abstract class Schema {
|
||||
protected function getReservedKeywords(): array {
|
||||
return rest_get_allowed_schema_keywords();
|
||||
}
|
||||
|
||||
protected function validatePattern(string $pattern): void {
|
||||
$escaped = str_replace('#', '\\#', $pattern);
|
||||
$regex = "#$escaped#u";
|
||||
if (@preg_match($regex, '') === false) {
|
||||
throw new InvalidStateException("Invalid regular expression '$regex'");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -35,12 +35,12 @@ class ObjectSchema extends Schema {
|
||||
* @param array<string, Schema> $properties
|
||||
*/
|
||||
public function patternProperties(array $properties): self {
|
||||
return $this->updateSchemaProperty('patternProperties', array_map(
|
||||
function (Schema $property) {
|
||||
return $property->toArray();
|
||||
},
|
||||
$properties
|
||||
));
|
||||
$patternProperties = [];
|
||||
foreach ($properties as $key => $value) {
|
||||
$this->validatePattern($key);
|
||||
$patternProperties[$key] = $value->toArray();
|
||||
}
|
||||
return $this->updateSchemaProperty('patternProperties', $patternProperties);
|
||||
}
|
||||
|
||||
public function minProperties(int $value): self {
|
||||
|
@@ -23,6 +23,7 @@ class StringSchema extends Schema {
|
||||
* See: https://developer.wordpress.org/rest-api/extending-the-rest-api/schema/#pattern
|
||||
*/
|
||||
public function pattern(string $pattern): self {
|
||||
$this->validatePattern($pattern);
|
||||
return $this->updateSchemaProperty('pattern', $pattern);
|
||||
}
|
||||
|
||||
|
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace MailPoet\Validator\Schema;
|
||||
|
||||
use MailPoet\InvalidStateException;
|
||||
use MailPoet\Validator\Schema;
|
||||
use MailPoetUnitTest;
|
||||
|
||||
@@ -104,6 +105,11 @@ class ObjectSchemaTest extends MailPoetUnitTest {
|
||||
'{"type":"object","patternProperties":{"^number-[0-9]+":{"type":"number"},"^string-[0-9]+":{"type":"string"}}}',
|
||||
$object->toString()
|
||||
);
|
||||
|
||||
$this->assertInvalidPatternProperty(['\\' => $this->getNumberSchemaMock()], "Invalid regular expression '#\\#u'");
|
||||
$this->assertInvalidPatternProperty(['\\#' => $this->getStringSchemaMock()], "Invalid regular expression '#\\\\##u'");
|
||||
$this->assertInvalidPatternProperty(['[' => $this->getNumberSchemaMock()], "Invalid regular expression '#[#u'");
|
||||
$this->assertInvalidPatternProperty(['[0-9' => $this->getStringSchemaMock()], "Invalid regular expression '#[0-9#u'");
|
||||
}
|
||||
|
||||
public function testMinProperties(): void {
|
||||
@@ -174,4 +180,15 @@ class ObjectSchemaTest extends MailPoetUnitTest {
|
||||
protected $schema = ['type' => 'string'];
|
||||
};
|
||||
}
|
||||
|
||||
private function assertInvalidPatternProperty(array $properties, string $message): void {
|
||||
try {
|
||||
(new ObjectSchema())->patternProperties($properties);
|
||||
} catch (InvalidStateException $e) {
|
||||
$this->assertSame($message, $e->getMessage());
|
||||
return;
|
||||
}
|
||||
$class = InvalidStateException::class;
|
||||
$this->fail("Exception '$class' with message '$message' was not thrown.");
|
||||
}
|
||||
}
|
||||
|
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace MailPoet\Validator\Schema;
|
||||
|
||||
use MailPoet\InvalidStateException;
|
||||
use MailPoetUnitTest;
|
||||
|
||||
class StringSchemaTest extends MailPoetUnitTest {
|
||||
@@ -27,6 +28,11 @@ class StringSchemaTest extends MailPoetUnitTest {
|
||||
$string = (new StringSchema())->pattern('[0-9]+');
|
||||
$this->assertSame(['type' => 'string', 'pattern' => '[0-9]+'], $string->toArray());
|
||||
$this->assertSame('{"type":"string","pattern":"[0-9]+"}', $string->toString());
|
||||
|
||||
$this->assertInvalidPattern('\\', "Invalid regular expression '#\\#u'");
|
||||
$this->assertInvalidPattern('\\#', "Invalid regular expression '#\\\\##u'");
|
||||
$this->assertInvalidPattern('[', "Invalid regular expression '#[#u'");
|
||||
$this->assertInvalidPattern('[0-9', "Invalid regular expression '#[0-9#u'");
|
||||
}
|
||||
|
||||
public function testFormat(): void {
|
||||
@@ -88,4 +94,15 @@ class StringSchemaTest extends MailPoetUnitTest {
|
||||
$this->assertNotSame($string->formatUri(), $string);
|
||||
$this->assertNotSame($string->formatUuid(), $string);
|
||||
}
|
||||
|
||||
private function assertInvalidPattern(string $pattern, string $message): void {
|
||||
try {
|
||||
(new StringSchema())->pattern($pattern);
|
||||
} catch (InvalidStateException $e) {
|
||||
$this->assertSame($message, $e->getMessage());
|
||||
return;
|
||||
}
|
||||
$class = InvalidStateException::class;
|
||||
$this->fail("Exception '$class' with message '$message' was not thrown.");
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user