Skip to content

Commit bf51cde

Browse files
committed
feat: Add content validation support
1 parent b0030d1 commit bf51cde

File tree

4 files changed

+64
-1
lines changed

4 files changed

+64
-1
lines changed

src/JsonSchema/ConstraintError.php

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,8 @@ class ConstraintError extends Enum
5858
public const PROPERTY_NAMES = 'propertyNames';
5959
public const TYPE = 'type';
6060
public const UNIQUE_ITEMS = 'uniqueItems';
61+
public const CONTENT_MEDIA_TYPE = 'contentMediaType';
62+
public const CONTENT_ENCODING = 'contentEncoding';
6163

6264
/**
6365
* @return string
@@ -115,7 +117,9 @@ public function getMessage()
115117
self::PROPERTIES_MAX => 'Must contain no more than %d properties',
116118
self::PROPERTY_NAMES => 'Property name %s is invalid',
117119
self::TYPE => '%s value found, but %s is required',
118-
self::UNIQUE_ITEMS => 'There are no duplicates allowed in the array'
120+
self::UNIQUE_ITEMS => 'There are no duplicates allowed in the array',
121+
self::CONTENT_MEDIA_TYPE => 'Value is not valid with content media type',
122+
self::CONTENT_ENCODING => 'Value is not valid with content encoding',
119123
];
120124

121125
if (!isset($messages[$name])) {
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace JsonSchema\Constraints\Drafts\Draft07;
6+
7+
use JsonSchema\ConstraintError;
8+
use JsonSchema\Constraints\ConstraintInterface;
9+
use JsonSchema\Constraints\Factory;
10+
use JsonSchema\Entity\ErrorBagProxy;
11+
use JsonSchema\Entity\JsonPointer;
12+
use JsonSchema\Tool\DeepComparer;
13+
14+
class ContentConstraint implements ConstraintInterface
15+
{
16+
use ErrorBagProxy;
17+
18+
public function __construct(?Factory $factory = null)
19+
{
20+
$this->initialiseErrorBag($factory ?: new Factory());
21+
}
22+
23+
public function check(&$value, $schema = null, ?JsonPointer $path = null, $i = null): void
24+
{
25+
if (!property_exists($schema, 'contentMediaType') && !property_exists($schema, 'contentEncoding')) {
26+
return;
27+
}
28+
if (! is_string($value)) {
29+
return;
30+
}
31+
32+
$decodedValue = $value;
33+
34+
if (property_exists($schema, 'contentEncoding')) {
35+
if ($schema->contentEncoding === 'base64') {
36+
if (!preg_match('/^[A-Za-z0-9+\/=]+$/', $decodedValue)) {
37+
$this->addError(ConstraintError::CONTENT_ENCODING(), $path, ['contentEncoding' => $schema->contentEncoding]);
38+
return;
39+
}
40+
$decodedValue = base64_decode($decodedValue);
41+
}
42+
}
43+
44+
if (property_exists($schema, 'contentMediaType')) {
45+
if ($schema->contentMediaType === 'application/json') {
46+
json_decode($decodedValue, false);
47+
if (json_last_error() === JSON_ERROR_NONE) {
48+
return;
49+
}
50+
}
51+
52+
$this->addError(ConstraintError::CONTENT_MEDIA_TYPE(), $path, ['contentMediaType' => $schema->contentMediaType]);
53+
54+
}
55+
56+
}
57+
}

src/JsonSchema/Constraints/Drafts/Draft07/Draft07Constraint.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ public function check(&$value, $schema = null, ?JsonPointer $path = null, $i = n
6565
$this->checkForKeyword('multipleOf', $value, $schema, $path, $i);
6666
$this->checkForKeyword('format', $value, $schema, $path, $i);
6767
$this->checkForKeyword('pattern', $value, $schema, $path, $i);
68+
$this->checkForKeyword('content', $value, $schema, $path, $i);
6869
}
6970

7071
/**

src/JsonSchema/Constraints/Drafts/Draft07/Factory.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,5 +43,6 @@ class Factory extends \JsonSchema\Constraints\Factory
4343
'properties' => PropertiesConstraint::class,
4444
'items' => ItemsConstraint::class,
4545
'ref' => RefConstraint::class,
46+
'content' => ContentConstraint::class,
4647
];
4748
}

0 commit comments

Comments
 (0)