Skip to content

Commit

Permalink
Merge pull request #46 from ckdot/master
Browse files Browse the repository at this point in the history
Keep inner exceptions if oneOf or anyOf fails
  • Loading branch information
scaytrase authored Jan 22, 2020
2 parents 16b0e9e + 1418a09 commit d28ede2
Show file tree
Hide file tree
Showing 4 changed files with 118 additions and 7 deletions.
41 changes: 41 additions & 0 deletions src/Schema/Exception/NotEnoughValidSchemas.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?php

declare(strict_types=1);

namespace League\OpenAPIValidation\Schema\Exception;

use Throwable;

class NotEnoughValidSchemas extends KeywordMismatch
{
/** @var Throwable[] */
protected $innerExceptions = [];

/**
* @param mixed $data
* @param Throwable[] $innerExceptions
*
* @return self
*/
public static function fromKeywordWithInnerExceptions(
string $keyword,
$data,
array $innerExceptions,
?string $message = null
) : KeywordMismatch {
$instance = new self('Keyword validation failed: ' . $message, 0);
$instance->keyword = $keyword;
$instance->data = $data;
$instance->innerExceptions = $innerExceptions;

return $instance;
}

/**
* @return Throwable[]
*/
public function innerExceptions() : array
{
return $this->innerExceptions;
}
}
41 changes: 41 additions & 0 deletions src/Schema/Exception/TooManyValidSchemas.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?php

declare(strict_types=1);

namespace League\OpenAPIValidation\Schema\Exception;

use cebe\openapi\spec\Schema;

class TooManyValidSchemas extends KeywordMismatch
{
/** @var Schema[] */
protected $validSchemas = [];

/**
* @param mixed $data
* @param Schema[] $validSchemas
*
* @return self
*/
public static function fromKeywordWithValidSchemas(
string $keyword,
$data,
array $validSchemas,
?string $message = null
) : KeywordMismatch {
$instance = new self('Keyword validation failed: ' . $message, 0);
$instance->keyword = $keyword;
$instance->data = $data;
$instance->validSchemas = $validSchemas;

return $instance;
}

/**
* @return Schema[]
*/
public function validSchemas() : array
{
return $this->validSchemas;
}
}
12 changes: 10 additions & 2 deletions src/Schema/Keywords/AnyOf.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use League\OpenAPIValidation\Schema\BreadCrumb;
use League\OpenAPIValidation\Schema\Exception\InvalidSchema;
use League\OpenAPIValidation\Schema\Exception\KeywordMismatch;
use League\OpenAPIValidation\Schema\Exception\NotEnoughValidSchemas;
use League\OpenAPIValidation\Schema\Exception\SchemaMismatch;
use League\OpenAPIValidation\Schema\SchemaValidator;
use Respect\Validation\Exceptions\ExceptionInterface;
Expand Down Expand Up @@ -51,17 +52,24 @@ public function validate($data, array $anyOf) : void
throw InvalidSchema::becauseDefensiveSchemaValidationFailed($e);
}

$innerExceptions = [];

foreach ($anyOf as $schema) {
$schemaValidator = new SchemaValidator($this->validationDataType);
try {
$schemaValidator->validate($data, $schema, $this->dataBreadCrumb);

return;
} catch (SchemaMismatch $e) {
// that did not match... its ok
$innerExceptions[] = $e;
}
}

throw KeywordMismatch::fromKeyword('anyOf', $data, 'Data must match at least one schema');
throw NotEnoughValidSchemas::fromKeywordWithInnerExceptions(
'anyOf',
$data,
$innerExceptions,
'Data must match at least one schema'
);
}
}
31 changes: 26 additions & 5 deletions src/Schema/Keywords/OneOf.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,13 @@
use League\OpenAPIValidation\Schema\BreadCrumb;
use League\OpenAPIValidation\Schema\Exception\InvalidSchema;
use League\OpenAPIValidation\Schema\Exception\KeywordMismatch;
use League\OpenAPIValidation\Schema\Exception\NotEnoughValidSchemas;
use League\OpenAPIValidation\Schema\Exception\SchemaMismatch;
use League\OpenAPIValidation\Schema\Exception\TooManyValidSchemas;
use League\OpenAPIValidation\Schema\SchemaValidator;
use Respect\Validation\Exceptions\ExceptionInterface;
use Respect\Validation\Validator;
use function count;
use function sprintf;

class OneOf extends BaseKeyword
Expand Down Expand Up @@ -53,19 +56,37 @@ public function validate($data, array $oneOf) : void
}

// Validate against all schemas
$matchedCount = 0;
$schemaValidator = new SchemaValidator($this->validationDataType);
$innerExceptions = [];
$validSchemas = [];

foreach ($oneOf as $schema) {
try {
$schemaValidator->validate($data, $schema, $this->dataBreadCrumb);
$matchedCount++;
$validSchemas[] = $schema;
} catch (SchemaMismatch $e) {
// that did not match... its ok
$innerExceptions[] = $e;
}
}

if ($matchedCount !== 1) {
throw KeywordMismatch::fromKeyword('oneOf', $data, sprintf('Data must match exactly one schema, but matched %d', $matchedCount));
if (count($validSchemas) === 1) {
return;
}

if (count($validSchemas) < 1) {
throw NotEnoughValidSchemas::fromKeywordWithInnerExceptions(
'oneOf',
$data,
$innerExceptions,
'Data must match exactly one schema, but matched none'
);
}

throw TooManyValidSchemas::fromKeywordWithValidSchemas(
'oneOf',
$data,
$validSchemas,
sprintf('Data must match exactly one schema, but matched %d', count($validSchemas))
);
}
}

0 comments on commit d28ede2

Please sign in to comment.