Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -73,13 +73,16 @@ public function check(&$value, $schema = null, ?JsonPointer $path = null, $i = n
private function createPregMatchPattern(string $pattern): string
{
$replacements = [
// '\D' => '[^0-9]',
// '\d' => '[0-9]',
'\p{digit}' => '\p{Nd}',
// '\w' => '[A-Za-z0-9_]',
// '\W' => '[^A-Za-z0-9_]',
// '\s' => '[\s\x{200B}]' // Explicitly include zero width white space,
'\p{Letter}' => '\p{L}', // Map ECMA long property name to PHP (PCRE) Unicode property abbreviations
// PCRE with /u makes \d, \D, \w and \W Unicode aware, while ECMA-262 defines
// them over ASCII only, so they are narrowed back to their ECMA meaning.
'\\D' => '[^0-9]',
'\\d' => '[0-9]',
'\\w' => '[A-Za-z0-9_]',
'\\W' => '[^A-Za-z0-9_]',
'\\s' => '[\\s\\x{200B}]', // Explicitly include zero width white space
// PCRE rejects the ECMA long property names, so they are mapped to its abbreviations.
'\\p{digit}' => '\\p{Nd}',
'\\p{Letter}' => '\\p{L}',
];

$pattern = str_replace(
Expand Down
17 changes: 10 additions & 7 deletions src/JsonSchema/Constraints/Drafts/Draft06/PatternConstraint.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,13 +43,16 @@ public function check(&$value, $schema = null, ?JsonPointer $path = null, $i = n
private function createPregMatchPattern(string $pattern): string
{
$replacements = [
'\D' => '[^0-9]',
'\d' => '[0-9]',
'\p{digit}' => '[0-9]',
'\w' => '[A-Za-z0-9_]',
'\W' => '[^A-Za-z0-9_]',
'\s' => '[\s\x{200B}]', // Explicitly include zero width white space
'\p{Letter}' => '\p{L}', // Map ECMA long property name to PHP (PCRE) Unicode property abbreviations
// PCRE with /u makes \d, \D, \w and \W Unicode aware, while ECMA-262 defines
// them over ASCII only, so they are narrowed back to their ECMA meaning.
'\\D' => '[^0-9]',
'\\d' => '[0-9]',
'\\w' => '[A-Za-z0-9_]',
'\\W' => '[^A-Za-z0-9_]',
'\\s' => '[\\s\\x{200B}]', // Explicitly include zero width white space
// PCRE rejects the ECMA long property names, so they are mapped to its abbreviations.
'\\p{digit}' => '\\p{Nd}',
'\\p{Letter}' => '\\p{L}',
];

$pattern = str_replace(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,13 +52,16 @@ public function check(&$value, $schema = null, ?JsonPointer $path = null, $i = n
private function createPregMatchPattern(string $pattern): string
{
$replacements = [
// '\D' => '[^0-9]',
'\d' => '[0-9]',
'\p{digit}' => '[0-9]',
// '\w' => '[A-Za-z0-9_]',
// '\W' => '[^A-Za-z0-9_]',
// '\s' => '[\s\x{200B}]' // Explicitly include zero width white space
'\p{Letter}' => '\p{L}', // Map ECMA long property name to PHP (PCRE) Unicode property abbreviations
// PCRE with /u makes \d, \D, \w and \W Unicode aware, while ECMA-262 defines
// them over ASCII only, so they are narrowed back to their ECMA meaning.
'\\D' => '[^0-9]',
'\\d' => '[0-9]',
'\\w' => '[A-Za-z0-9_]',
'\\W' => '[^A-Za-z0-9_]',
'\\s' => '[\\s\\x{200B}]', // Explicitly include zero width white space
// PCRE rejects the ECMA long property names, so they are mapped to its abbreviations.
'\\p{digit}' => '\\p{Nd}',
'\\p{Letter}' => '\\p{L}',
];

$pattern = str_replace(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,13 +73,16 @@ public function check(&$value, $schema = null, ?JsonPointer $path = null, $i = n
private function createPregMatchPattern(string $pattern): string
{
$replacements = [
// '\D' => '[^0-9]',
// '\d' => '[0-9]',
'\p{digit}' => '\p{Nd}',
// '\w' => '[A-Za-z0-9_]',
// '\W' => '[^A-Za-z0-9_]',
// '\s' => '[\s\x{200B}]' // Explicitly include zero width white space,
'\p{Letter}' => '\p{L}', // Map ECMA long property name to PHP (PCRE) Unicode property abbreviations
// PCRE with /u makes \d, \D, \w and \W Unicode aware, while ECMA-262 defines
// them over ASCII only, so they are narrowed back to their ECMA meaning.
'\\D' => '[^0-9]',
'\\d' => '[0-9]',
'\\w' => '[A-Za-z0-9_]',
'\\W' => '[^A-Za-z0-9_]',
'\\s' => '[\\s\\x{200B}]', // Explicitly include zero width white space
// PCRE rejects the ECMA long property names, so they are mapped to its abbreviations.
'\\p{digit}' => '\\p{Nd}',
'\\p{Letter}' => '\\p{L}',
];

$pattern = str_replace(
Expand Down
17 changes: 10 additions & 7 deletions src/JsonSchema/Constraints/Drafts/Draft07/PatternConstraint.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,13 +43,16 @@ public function check(&$value, $schema = null, ?JsonPointer $path = null, $i = n
private function createPregMatchPattern(string $pattern): string
{
$replacements = [
'\D' => '[^0-9]',
'\d' => '[0-9]',
'\p{digit}' => '[0-9]',
'\w' => '[A-Za-z0-9_]',
'\W' => '[^A-Za-z0-9_]',
'\s' => '[\s\x{200B}]', // Explicitly include zero width white space
'\p{Letter}' => '\p{L}', // Map ECMA long property name to PHP (PCRE) Unicode property abbreviations
// PCRE with /u makes \d, \D, \w and \W Unicode aware, while ECMA-262 defines
// them over ASCII only, so they are narrowed back to their ECMA meaning.
'\\D' => '[^0-9]',
'\\d' => '[0-9]',
'\\w' => '[A-Za-z0-9_]',
'\\W' => '[^A-Za-z0-9_]',
'\\s' => '[\\s\\x{200B}]', // Explicitly include zero width white space
// PCRE rejects the ECMA long property names, so they are mapped to its abbreviations.
'\\p{digit}' => '\\p{Nd}',
'\\p{Letter}' => '\\p{L}',
];

$pattern = str_replace(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,13 +52,16 @@ public function check(&$value, $schema = null, ?JsonPointer $path = null, $i = n
private function createPregMatchPattern(string $pattern): string
{
$replacements = [
// '\D' => '[^0-9]',
'\d' => '[0-9]',
'\p{digit}' => '[0-9]',
// '\w' => '[A-Za-z0-9_]',
// '\W' => '[^A-Za-z0-9_]',
// '\s' => '[\s\x{200B}]' // Explicitly include zero width white space
'\p{Letter}' => '\p{L}', // Map ECMA long property name to PHP (PCRE) Unicode property abbreviations
// PCRE with /u makes \d, \D, \w and \W Unicode aware, while ECMA-262 defines
// them over ASCII only, so they are narrowed back to their ECMA meaning.
'\\D' => '[^0-9]',
'\\d' => '[0-9]',
'\\w' => '[A-Za-z0-9_]',
'\\W' => '[^A-Za-z0-9_]',
'\\s' => '[\\s\\x{200B}]', // Explicitly include zero width white space
// PCRE rejects the ECMA long property names, so they are mapped to its abbreviations.
'\\p{digit}' => '\\p{Nd}',
'\\p{Letter}' => '\\p{L}',
];

$pattern = str_replace(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,13 +73,16 @@ public function check(&$value, $schema = null, ?JsonPointer $path = null, $i = n
private function createPregMatchPattern(string $pattern): string
{
$replacements = [
// '\D' => '[^0-9]',
// '\d' => '[0-9]',
'\p{digit}' => '\p{Nd}',
// '\w' => '[A-Za-z0-9_]',
// '\W' => '[^A-Za-z0-9_]',
// '\s' => '[\s\x{200B}]' // Explicitly include zero width white space,
'\p{Letter}' => '\p{L}', // Map ECMA long property name to PHP (PCRE) Unicode property abbreviations
// PCRE with /u makes \d, \D, \w and \W Unicode aware, while ECMA-262 defines
// them over ASCII only, so they are narrowed back to their ECMA meaning.
'\\D' => '[^0-9]',
'\\d' => '[0-9]',
'\\w' => '[A-Za-z0-9_]',
'\\W' => '[^A-Za-z0-9_]',
'\\s' => '[\\s\\x{200B}]', // Explicitly include zero width white space
// PCRE rejects the ECMA long property names, so they are mapped to its abbreviations.
'\\p{digit}' => '\\p{Nd}',
'\\p{Letter}' => '\\p{L}',
];

$pattern = str_replace(
Expand Down
17 changes: 10 additions & 7 deletions src/JsonSchema/Constraints/Drafts/Draft2019/PatternConstraint.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,13 +43,16 @@ public function check(&$value, $schema = null, ?JsonPointer $path = null, $i = n
private function createPregMatchPattern(string $pattern): string
{
$replacements = [
'\D' => '[^0-9]',
'\d' => '[0-9]',
'\p{digit}' => '[0-9]',
'\w' => '[A-Za-z0-9_]',
'\W' => '[^A-Za-z0-9_]',
'\s' => '[\s\x{200B}]', // Explicitly include zero width white space
'\p{Letter}' => '\p{L}', // Map ECMA long property name to PHP (PCRE) Unicode property abbreviations
// PCRE with /u makes \d, \D, \w and \W Unicode aware, while ECMA-262 defines
// them over ASCII only, so they are narrowed back to their ECMA meaning.
'\\D' => '[^0-9]',
'\\d' => '[0-9]',
'\\w' => '[A-Za-z0-9_]',
'\\W' => '[^A-Za-z0-9_]',
'\\s' => '[\\s\\x{200B}]', // Explicitly include zero width white space
// PCRE rejects the ECMA long property names, so they are mapped to its abbreviations.
'\\p{digit}' => '\\p{Nd}',
'\\p{Letter}' => '\\p{L}',
];

$pattern = str_replace(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,13 +55,16 @@ public function check(&$value, $schema = null, ?JsonPointer $path = null, $i = n
private function createPregMatchPattern(string $pattern): string
{
$replacements = [
// '\D' => '[^0-9]',
'\d' => '[0-9]',
'\p{digit}' => '[0-9]',
// '\w' => '[A-Za-z0-9_]',
// '\W' => '[^A-Za-z0-9_]',
// '\s' => '[\s\x{200B}]' // Explicitly include zero width white space
'\p{Letter}' => '\p{L}', // Map ECMA long property name to PHP (PCRE) Unicode property abbreviations
// PCRE with /u makes \d, \D, \w and \W Unicode aware, while ECMA-262 defines
// them over ASCII only, so they are narrowed back to their ECMA meaning.
'\\D' => '[^0-9]',
'\\d' => '[0-9]',
'\\w' => '[A-Za-z0-9_]',
'\\W' => '[^A-Za-z0-9_]',
'\\s' => '[\\s\\x{200B}]', // Explicitly include zero width white space
// PCRE rejects the ECMA long property names, so they are mapped to its abbreviations.
'\\p{digit}' => '\\p{Nd}',
'\\p{Letter}' => '\\p{L}',
];

$pattern = str_replace(
Expand Down
54 changes: 54 additions & 0 deletions tests/Constraints/Draft06/EcmaPatternTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<?php

declare(strict_types=1);

namespace JsonSchema\Tests\Constraints\Draft06;

use JsonSchema\Constraints\Constraint;
use JsonSchema\Tests\Constraints\VeryBaseTestCase;
use JsonSchema\Validator;

/**
* ECMA-262 defines \d, \D, \w and \W over ASCII only, while PCRE makes them Unicode
* aware under the /u modifier. Patterns must keep their ECMA meaning.
*/
class EcmaPatternTest extends VeryBaseTestCase
{
/**
* @dataProvider provideNonAsciiCases
*/
public function testShorthandClassesKeepTheirAsciiOnlyEcmaMeaning(string $schema, string $data, bool $expectedToBeValid): void
{
$validator = new Validator();
$decodedData = json_decode($data);
$validator->validate($decodedData, json_decode($schema), Constraint::CHECK_MODE_STRICT);

self::assertSame($expectedToBeValid, $validator->isValid(), (string) json_encode($validator->getErrors()));
}

/**
* @return array<string, array{string, string, bool}>
*/
public static function provideNonAsciiCases(): array
{
$dialect = '"$schema": "http://json-schema.org/draft-06/schema#"';

return [
'ASCII digit matches \\d in patternProperties' => [
'{' . $dialect . ', "patternProperties": {"^\\\\d+$": {"type": "string"}}, "additionalProperties": false}',
'{"5": "ok"}',
true,
],
'Arabic-Indic digit does not match \\d in patternProperties' => [
'{' . $dialect . ', "patternProperties": {"^\\\\d+$": {"type": "string"}}, "additionalProperties": false}',
'{"٣": "ok"}',
false,
],
'accented letter does not match \\w in pattern' => [
'{' . $dialect . ', "type": "string", "pattern": "^\\\\w+$"}',
'"é"',
false,
],
];
}
}
54 changes: 54 additions & 0 deletions tests/Constraints/Draft07/EcmaPatternTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<?php

declare(strict_types=1);

namespace JsonSchema\Tests\Constraints\Draft07;

use JsonSchema\Constraints\Constraint;
use JsonSchema\Tests\Constraints\VeryBaseTestCase;
use JsonSchema\Validator;

/**
* ECMA-262 defines \d, \D, \w and \W over ASCII only, while PCRE makes them Unicode
* aware under the /u modifier. Patterns must keep their ECMA meaning.
*/
class EcmaPatternTest extends VeryBaseTestCase
{
/**
* @dataProvider provideNonAsciiCases
*/
public function testShorthandClassesKeepTheirAsciiOnlyEcmaMeaning(string $schema, string $data, bool $expectedToBeValid): void
{
$validator = new Validator();
$decodedData = json_decode($data);
$validator->validate($decodedData, json_decode($schema), Constraint::CHECK_MODE_STRICT);

self::assertSame($expectedToBeValid, $validator->isValid(), (string) json_encode($validator->getErrors()));
}

/**
* @return array<string, array{string, string, bool}>
*/
public static function provideNonAsciiCases(): array
{
$dialect = '"$schema": "http://json-schema.org/draft-07/schema#"';

return [
'ASCII digit matches \\d in patternProperties' => [
'{' . $dialect . ', "patternProperties": {"^\\\\d+$": {"type": "string"}}, "additionalProperties": false}',
'{"5": "ok"}',
true,
],
'Arabic-Indic digit does not match \\d in patternProperties' => [
'{' . $dialect . ', "patternProperties": {"^\\\\d+$": {"type": "string"}}, "additionalProperties": false}',
'{"٣": "ok"}',
false,
],
'accented letter does not match \\w in pattern' => [
'{' . $dialect . ', "type": "string", "pattern": "^\\\\w+$"}',
'"é"',
false,
],
];
}
}
54 changes: 54 additions & 0 deletions tests/Constraints/Draft2019/EcmaPatternTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<?php

declare(strict_types=1);

namespace JsonSchema\Tests\Constraints\Draft2019;

use JsonSchema\Constraints\Constraint;
use JsonSchema\Tests\Constraints\VeryBaseTestCase;
use JsonSchema\Validator;

/**
* ECMA-262 defines \d, \D, \w and \W over ASCII only, while PCRE makes them Unicode
* aware under the /u modifier. Patterns must keep their ECMA meaning.
*/
class EcmaPatternTest extends VeryBaseTestCase
{
/**
* @dataProvider provideNonAsciiCases
*/
public function testShorthandClassesKeepTheirAsciiOnlyEcmaMeaning(string $schema, string $data, bool $expectedToBeValid): void
{
$validator = new Validator();
$decodedData = json_decode($data);
$validator->validate($decodedData, json_decode($schema), Constraint::CHECK_MODE_STRICT);

self::assertSame($expectedToBeValid, $validator->isValid(), (string) json_encode($validator->getErrors()));
}

/**
* @return array<string, array{string, string, bool}>
*/
public static function provideNonAsciiCases(): array
{
$dialect = '"$schema": "https://json-schema.org/draft/2019-09/schema"';

return [
'ASCII digit matches \\d in patternProperties' => [
'{' . $dialect . ', "patternProperties": {"^\\\\d+$": {"type": "string"}}, "additionalProperties": false}',
'{"5": "ok"}',
true,
],
'Arabic-Indic digit does not match \\d in patternProperties' => [
'{' . $dialect . ', "patternProperties": {"^\\\\d+$": {"type": "string"}}, "additionalProperties": false}',
'{"٣": "ok"}',
false,
],
'accented letter does not match \\w in pattern' => [
'{' . $dialect . ', "type": "string", "pattern": "^\\\\w+$"}',
'"é"',
false,
],
];
}
}
Loading