diff --git a/src/Model/Validator/PatternPropertiesValidator.php b/src/Model/Validator/PatternPropertiesValidator.php index 9a065c4..470b6ef 100644 --- a/src/Model/Validator/PatternPropertiesValidator.php +++ b/src/Model/Validator/PatternPropertiesValidator.php @@ -64,7 +64,7 @@ public function __construct( DIRECTORY_SEPARATOR . 'Validator' . DIRECTORY_SEPARATOR . 'PatternProperties.phptpl', [ 'patternHash' => $this->key, - 'pattern' => "/{$this->pattern}/", + 'pattern' => base64_encode('/' . addcslashes($this->pattern, '/') . '/'), 'validationProperty' => $this->validationProperty, 'generatorConfiguration' => $schemaProcessor->getGeneratorConfiguration(), 'viewHelper' => new RenderHelper($schemaProcessor->getGeneratorConfiguration()), diff --git a/src/PropertyProcessor/Property/BaseProcessor.php b/src/PropertyProcessor/Property/BaseProcessor.php index b11d4ea..65eda43 100644 --- a/src/PropertyProcessor/Property/BaseProcessor.php +++ b/src/PropertyProcessor/Property/BaseProcessor.php @@ -168,7 +168,9 @@ protected function addPatternPropertiesValidator(JsonSchema $propertySchema): vo } foreach ($json['patternProperties'] as $pattern => $schema) { - if (@preg_match("/$pattern/", '') === false) { + $escapedPattern = addcslashes($pattern, '/'); + + if (@preg_match("/$escapedPattern/", '') === false) { throw new SchemaException( "Invalid pattern '$pattern' for pattern property in file {$propertySchema->getFile()}" ); diff --git a/src/SchemaProcessor/PostProcessor/Internal/ExtendObjectPropertiesMatchingPatternPropertiesPostProcessor.php b/src/SchemaProcessor/PostProcessor/Internal/ExtendObjectPropertiesMatchingPatternPropertiesPostProcessor.php index 8083528..2ddc964 100644 --- a/src/SchemaProcessor/PostProcessor/Internal/ExtendObjectPropertiesMatchingPatternPropertiesPostProcessor.php +++ b/src/SchemaProcessor/PostProcessor/Internal/ExtendObjectPropertiesMatchingPatternPropertiesPostProcessor.php @@ -43,7 +43,7 @@ public function getCode(PropertyInterface $property, bool $batchUpdate = false): { $json = $this->schema->getJsonSchema()->getJson(); // A batch update must execute the base validators to check the integrity of the object. - // Consequently the schema hook must not add validation code in that places. + // Consequently, the schema hook must not add validation code in that places. if ($batchUpdate || !isset($json['patternProperties'])) { return ''; } @@ -51,7 +51,7 @@ public function getCode(PropertyInterface $property, bool $batchUpdate = false): $matchesAnyPattern = false; foreach (array_keys($json['patternProperties']) as $pattern) { - if (preg_match("/{$pattern}/", $property->getName())) { + if (preg_match('/' . addcslashes($pattern, '/') . '/', $property->getName())) { $matchesAnyPattern = true; } } @@ -107,8 +107,11 @@ function (Validator $validator): bool { /** @var PatternPropertiesValidator $patternPropertiesValidator */ foreach ($patternPropertiesValidators as $patternPropertiesValidator) { - if (!preg_match("/{$patternPropertiesValidator->getPattern()}/", $property->getName()) || - !isset( + if (!preg_match( + '/' . addcslashes($patternPropertiesValidator->getPattern(), '/') . '/', + $property->getName() + ) + || !isset( $schema->getJsonSchema()->getJson() ['patternProperties'] [$patternPropertiesValidator->getPattern()] diff --git a/src/SchemaProcessor/PostProcessor/Internal/PatternPropertiesPostProcessor.php b/src/SchemaProcessor/PostProcessor/Internal/PatternPropertiesPostProcessor.php index c664989..a2f631d 100644 --- a/src/SchemaProcessor/PostProcessor/Internal/PatternPropertiesPostProcessor.php +++ b/src/SchemaProcessor/PostProcessor/Internal/PatternPropertiesPostProcessor.php @@ -53,7 +53,7 @@ public function process(Schema $schema, GeneratorConfiguration $generatorConfigu $schema->getProperties(), function (array $carry, PropertyInterface $property) use ($schemaProperties, $validator): array { if (in_array($property->getName(), $schemaProperties) && - preg_match("/{$validator->getPattern()}/", $property->getName()) + preg_match('/' . addcslashes($validator->getPattern(), '/') . '/', $property->getName()) ) { $carry[] = $property; } diff --git a/src/Templates/Validator/PatternProperties.phptpl b/src/Templates/Validator/PatternProperties.phptpl index 016d258..c947890 100644 --- a/src/Templates/Validator/PatternProperties.phptpl +++ b/src/Templates/Validator/PatternProperties.phptpl @@ -7,7 +7,7 @@ foreach ($properties as $propertyKey => $value) { try { - if (!preg_match("{{ pattern }}", $propertyKey)) { + if (!preg_match(base64_decode('{{ pattern }}'), $propertyKey)) { continue; } diff --git a/tests/Basic/PatternPropertiesTest.php b/tests/Basic/PatternPropertiesTest.php index d298702..91e5cdb 100644 --- a/tests/Basic/PatternPropertiesTest.php +++ b/tests/Basic/PatternPropertiesTest.php @@ -21,7 +21,7 @@ public function testInvalidPatternThrowsAnException(): void $this->expectException(SchemaException::class); $this->expectExceptionMessageMatches("/Invalid pattern 'ab\[c' for pattern property in file .*\.json/"); - $this->generateClassFromFile('InvalidPattern.json'); + $this->generateClassFromFileTemplate('PatternProperty.json', ['ab[c']); } /** @@ -85,4 +85,15 @@ public function testMultipleTransformingFiltersForPatternPropertiesAndObjectProp $this->generateClassFromFile('MultipleTransformingFilters.json'); } + + /** + * https://github.com/wol-soft/php-json-schema-model-generator/issues/65 + */ + public function testPatternEscaping(): void + { + $className = $this->generateClassFromFileTemplate('PatternProperty.json', ['a/(b|c)']); + $object = new $className(['a/b' => 'Hello']); + + $this->assertSame(['a/b' => 'Hello'], $object->getRawModelDataInput()); + } } diff --git a/tests/Schema/PatternPropertiesTest/InvalidPattern.json b/tests/Schema/PatternPropertiesTest/PatternProperty.json similarity index 85% rename from tests/Schema/PatternPropertiesTest/InvalidPattern.json rename to tests/Schema/PatternPropertiesTest/PatternProperty.json index 2bdd2d7..776a4fb 100644 --- a/tests/Schema/PatternPropertiesTest/InvalidPattern.json +++ b/tests/Schema/PatternPropertiesTest/PatternProperty.json @@ -1,7 +1,7 @@ { "type": "object", "patternProperties": { - "ab[c": { + "%s": { "type": "string" } }