Skip to content

Commit

Permalink
Merge pull request #3 from mschindler83/validation-extension
Browse files Browse the repository at this point in the history
Validation feature and fixes
  • Loading branch information
mschindler83 authored Feb 19, 2020
2 parents 971fda0 + baf2736 commit 722cc4b
Show file tree
Hide file tree
Showing 5 changed files with 158 additions and 6 deletions.
12 changes: 8 additions & 4 deletions ArrayAccess/ArrayAccess.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ public static function createWithJsonSchemaValidation($value, string $jsonSchema
$result = (new Validator())->schemaValidation(\json_decode(\json_encode($value)), $schema, 10);

if (!$result->isValid()) {
throw ArrayAccessFailed::jsonSchemaValidationFailed(...$result->getErrors());
throw ArrayAccessValidationFailed::withValidationErrors(...$result->getErrors());
}

return new self($value);
Expand All @@ -63,15 +63,19 @@ public static function newFromDotAnnotation(DotAnnotation ...$dotAnnotations): s
return new self($newArray);
}

public function writeAtPath($value, ...$path): self
public function writeAtPath($value, string ...$path): self
{
$pointer = &$this->data;
$instance = new self($this->data);

$path = empty($path) ? [0] : $path;

$pointer = &$instance->data;
foreach ($path as $key) {
$pointer = &$pointer[$key];
}
$pointer = $value;

return new self($this->data);
return $instance;
}

public function hasPath(...$path): bool
Expand Down
44 changes: 44 additions & 0 deletions ArrayAccess/ArrayAccessValidationFailed.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<?php
declare(strict_types=1);

namespace Mschindler83\ArrayAccess;

use Opis\JsonSchema\ValidationError;

class ArrayAccessValidationFailed extends \RuntimeException
{
private array $errors;

private ArrayAccess $errorMapping;

public static function withValidationErrors(ValidationError ...$errors): self
{
$messages = \array_map(
function(ValidationError $error) {
return \sprintf(
'Error: [%s], Data pointer: [%s]',
$error->keyword(),
\implode(', ', $error->dataPointer()),
);
},
$errors
);

$instance = new self(
\sprintf('Json schema validation failed: %s', \implode(', ', $messages))
);

$instance->errors = $errors;
$instance->errorMapping = ArrayAccess::create([]);
foreach ($errors as $error) {
$instance->errorMapping = $instance->errorMapping->writeAtPath((string) $error->keyword(), ...$error->dataPointer());
}

return $instance;
}

public function errorMapping(): ArrayAccess
{
return $this->errorMapping;
}
}
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,9 @@ JSON schema: <json-schema.json>
}
```

If validation fails, an `ArrayAccessValidationFailed` exception will be thrown.
You can get an `ArrayAccess` object of validation errors by calling the method `errorMapping()` on the exception.

### Access values
```
$array = [
Expand Down
71 changes: 69 additions & 2 deletions Tests/ArrayAccess/ArrayAccessTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
use BadMethodCallException;
use Mschindler83\ArrayAccess\ArrayAccess;
use Mschindler83\ArrayAccess\ArrayAccessFailed;
use Mschindler83\ArrayAccess\ArrayAccessValidationFailed;
use Mschindler83\ArrayAccess\DotAnnotation\SimpleDotAnnotation;
use PHPUnit\Framework\TestCase;

Expand Down Expand Up @@ -48,7 +49,7 @@ public function it_validates_with_json_schema_validator(): void
*/
public function it_raises_an_exception_on_failed_json_schema_validation(): void
{
$this->expectException(ArrayAccessFailed::class);
$this->expectException(ArrayAccessValidationFailed::class);
$this->expectExceptionMessage('Json schema validation failed: Error: [minLength], Data pointer: [key1], Error: [type], Data pointer: [key2], Error: [additionalProperties], Data pointer: []');

$data = [
Expand Down Expand Up @@ -155,21 +156,87 @@ public function it_can_write_at_path(): void
];

$access = ArrayAccess::create($testArray);
$newAccess = $access->writeAtPath('new-value', 'Foo', 'Bar', 'New');
$access = $access->writeAtPath('new-value', 'Foo', 'Bar', 'New');
$access = $access->writeAtPath('new-value-2', 'Foo', 'Bar', 'New-2');

static::assertSame(
[
'Foo' => [
'Bar' => [
'Baz' => 'Buz',
'New' => 'new-value',
'New-2' => 'new-value-2',
],
],
],
$access->data()
);
}

/**
* @test
*/
public function it_can_write_value_at_single_path(): void
{
$access = ArrayAccess::create([]);
$newAccess = $access->writeAtPath('new-value', 'Foo');

static::assertSame('new-value', $newAccess->string('Foo'));
}

/**
* @test
*/
public function it_can_write_empty_array(): void
{
$access = ArrayAccess::create([]);
$access = $access->writeAtPath([], '0');

static::assertSame([], $access->array(0));
}

/**
* @test
*/
public function it_can_write_at_path_on_empty_access(): void
{
$access = ArrayAccess::create([]);
$newAccess = $access->writeAtPath('new-value', 'Foo', 'Bar', 'New');

static::assertSame(
[
'Foo' => [
'Bar' => [
'New' => 'new-value',
],
],
],
$newAccess->data()
);
}

/**
* @test
*/
public function it_writes_on_zero_index_if_empty_path_provided(): void
{
$access = ArrayAccess::create([]);
$access = $access->writeAtPath('foo');

static::assertSame(['foo'], $access->data());
}

/**
* @test
*/
public function it_writes_null_value_on_zero_index(): void
{
$access = ArrayAccess::create([]);
$access = $access->writeAtPath(null);

static::assertSame([0 => null], $access->data());
}

/**
* @test
*/
Expand Down
34 changes: 34 additions & 0 deletions Tests/ArrayAccess/ArrayAccessValidationFailedTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php
declare(strict_types=1);

namespace Mschindler83\Tests\ArrayAccess;

use Mschindler83\ArrayAccess\ArrayAccessValidationFailed;
use Opis\JsonSchema\ValidationError;
use PHPUnit\Framework\TestCase;

class ArrayAccessValidationFailedTest extends TestCase
{
/**
* @test
*/
public function it_can_return_errors(): void
{
$error1 = new ValidationError(null, ['e1dp1', 'e1dp2'], [], false, 'kw1');
$error2 = new ValidationError(null, ['e2dp1', 'e2dp2'], [], false, 'kw2');

$exception = ArrayAccessValidationFailed::withValidationErrors($error1, $error2);

static::assertSame(
[
'e1dp1' => [
'e1dp2' => 'kw1'
],
'e2dp1' => [
'e2dp2' => 'kw2'
],
],
$exception->errorMapping()->data()
);
}
}

0 comments on commit 722cc4b

Please sign in to comment.