Skip to content

Commit 0dcca11

Browse files
authored
Merge pull request #3 from DutchCodingCompany/feature/attribute-rule
Add attribute rule
2 parents 987de07 + 4abe3e1 commit 0dcca11

File tree

6 files changed

+124
-24
lines changed

6 files changed

+124
-24
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
# Changelog
22

3+
## 2.1.0 - 2025-08-05
4+
- Add `JsonSchemaAttributeRule`
5+
36
## 2.0.0 - 2025-08-05
47
- Modernize code
58
- Drop support for laravel 10.x

README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,9 @@ composer require dutchcodingcompany/laravel-json-schema
1414

1515
## Usage
1616
1. Create a json schema in the schema directory, eg. `storage/app/schema/example.json`
17-
2. Reference the schema in the validator: `new \DutchCodingCompany\LaravelJsonSchema\Rules\JsonSchemaRule('example')`
17+
2. Reference the schema in the validator using one of the rules:
18+
- `new \DutchCodingCompany\LaravelJsonSchema\Rules\JsonSchemaRule('example')`
19+
- `new \DutchCodingCompany\LaravelJsonSchema\Rules\JsonSchemaAttributeRule('type', TypeEnum::class)` (be careful to validate the attribute `type` in this case)
1820

1921
To customize the schema directory, use environment variable `JSON_SCHEMA_DIRECTORY` or publish the config file.
2022

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<?php
2+
3+
namespace DutchCodingCompany\LaravelJsonSchema\Contracts;
4+
5+
interface JsonSchemaNameProvider
6+
{
7+
public function getSchemaName(): string;
8+
}

src/Rules/BaseRule.php

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
<?php
2+
3+
namespace DutchCodingCompany\LaravelJsonSchema\Rules;
4+
5+
use Closure;
6+
use DutchCodingCompany\LaravelJsonSchema\Contracts\JsonSchemaValidator;
7+
use Illuminate\Container\Container;
8+
use Illuminate\Contracts\Validation\ValidationRule;
9+
10+
abstract class BaseRule implements ValidationRule
11+
{
12+
protected JsonSchemaValidator $schemaValidator;
13+
14+
/**
15+
* @param bool $detailedMessage wether of not to include the details of what failed
16+
* @param \DutchCodingCompany\LaravelJsonSchema\Contracts\JsonSchemaValidator|null $schemaValidator custom repository, otherwise resolved from the service container
17+
*/
18+
public function __construct(
19+
protected bool $detailedMessage = true,
20+
JsonSchemaValidator | null $schemaValidator = null,
21+
) {
22+
$this->schemaValidator = $schemaValidator ?? Container::getInstance()->make(JsonSchemaValidator::class);
23+
}
24+
25+
/**
26+
* Run the validation rule.
27+
*/
28+
public function validate(string $attribute, mixed $value, Closure $fail): void
29+
{
30+
$result = $this->schemaValidator->validate($this->determineSchemaName(), $value);
31+
32+
if ($result->failed()) {
33+
$fail($this->detailedMessage
34+
? 'json-schema::messages.detailed-error-message'
35+
: 'json-schema::messages.error-message'
36+
)->translate([
37+
'attribute' => $attribute,
38+
'details' => $result->getMessage() ?? '',
39+
]);
40+
}
41+
}
42+
43+
abstract protected function determineSchemaName(): string;
44+
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
<?php
2+
3+
namespace DutchCodingCompany\LaravelJsonSchema\Rules;
4+
5+
use DutchCodingCompany\LaravelJsonSchema\Contracts\JsonSchemaNameProvider;
6+
use DutchCodingCompany\LaravelJsonSchema\Contracts\JsonSchemaValidator;
7+
use Illuminate\Contracts\Validation\DataAwareRule;
8+
use InvalidArgumentException;
9+
10+
class JsonSchemaAttributeRule extends BaseRule implements DataAwareRule
11+
{
12+
/**
13+
* All of the data under validation.
14+
*
15+
* @var array<string, mixed>
16+
*/
17+
protected $data = [];
18+
19+
/**
20+
* @param string $attribute from with other attribute to retrieve the schema name
21+
* @param class-string<\BackedEnum&\DutchCodingCompany\LaravelJsonSchema\Contracts\JsonSchemaNameProvider>|null $enum which enum to cast the schema name into (if applicable)
22+
*/
23+
public function __construct(
24+
protected string $attribute,
25+
protected ?string $enum = null,
26+
protected bool $detailedMessage = true,
27+
JsonSchemaValidator | null $schemaValidator = null,
28+
) {
29+
parent::__construct($detailedMessage, $schemaValidator);
30+
}
31+
32+
/**
33+
* Set the data under validation.
34+
*
35+
* @param array<string, mixed> $data
36+
*/
37+
public function setData(array $data): static
38+
{
39+
$this->data = $data;
40+
41+
return $this;
42+
}
43+
44+
protected function determineSchemaName(): string
45+
{
46+
$schemaName = data_get($this->data, $this->attribute);
47+
48+
if ($this->enum !== null) {
49+
$enum = ($this->enum)::tryFrom($schemaName);
50+
51+
if ($enum instanceof JsonSchemaNameProvider) {
52+
return $enum->getSchemaName();
53+
}
54+
}
55+
56+
if (is_string($schemaName)) {
57+
return $schemaName;
58+
}
59+
60+
throw new InvalidArgumentException('Cannot determine schema name from attribute "'.$this->attribute.'"');
61+
}
62+
}

src/Rules/JsonSchemaRule.php

Lines changed: 4 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -4,41 +4,22 @@
44

55
use Closure;
66
use DutchCodingCompany\LaravelJsonSchema\Contracts\JsonSchemaValidator;
7-
use Illuminate\Container\Container;
8-
use Illuminate\Contracts\Validation\ValidationRule;
97

10-
class JsonSchemaRule implements ValidationRule
8+
class JsonSchemaRule extends BaseRule
119
{
12-
protected JsonSchemaValidator $schemaValidator;
13-
1410
/**
1511
* @param string $schema name of the schema to validate
16-
* @param bool $detailedMessage wether of not to include the details of what failed
17-
* @param \DutchCodingCompany\LaravelJsonSchema\Contracts\JsonSchemaValidator|null $schemaValidator custom repository, otherwise resolved from the service container
1812
*/
1913
public function __construct(
2014
protected string $schema,
2115
protected bool $detailedMessage = true,
2216
JsonSchemaValidator | null $schemaValidator = null,
2317
) {
24-
$this->schemaValidator = $schemaValidator ?? Container::getInstance()->make(JsonSchemaValidator::class);
18+
parent::__construct($detailedMessage, $schemaValidator);
2519
}
2620

27-
/**
28-
* Run the validation rule.
29-
*/
30-
public function validate(string $attribute, mixed $value, Closure $fail): void
21+
protected function determineSchemaName(): string
3122
{
32-
$result = $this->schemaValidator->validate($this->schema, $value);
33-
34-
if ($result->failed()) {
35-
$fail($this->detailedMessage
36-
? 'json-schema::messages.detailed-error-message'
37-
: 'json-schema::messages.error-message'
38-
)->translate([
39-
'attribute' => $attribute,
40-
'details' => $result->getMessage() ?? '',
41-
]);
42-
}
23+
return $this->schema;
4324
}
4425
}

0 commit comments

Comments
 (0)