Skip to content

Commit

Permalink
Moving validation to metadata objects
Browse files Browse the repository at this point in the history
  • Loading branch information
mateuszsip committed Oct 24, 2018
1 parent 5a4a16e commit 08d35db
Show file tree
Hide file tree
Showing 32 changed files with 600 additions and 263 deletions.

This file was deleted.

51 changes: 0 additions & 51 deletions lib/Doctrine/Annotations/Assembler/Validator/TargetValidator.php

This file was deleted.

26 changes: 0 additions & 26 deletions lib/Doctrine/Annotations/Assembler/Validator/ValueValidator.php

This file was deleted.

18 changes: 10 additions & 8 deletions lib/Doctrine/Annotations/Constructor/Constructor.php
Expand Up @@ -4,10 +4,10 @@

namespace Doctrine\Annotations\Constructor;

use Doctrine\Annotations\Assembler\Validator\TargetValidator;
use Doctrine\Annotations\Assembler\Validator\ValueValidator;
use Doctrine\Annotations\Constructor\Instantiator\Instantiator;
use Doctrine\Annotations\Metadata\AnnotationMetadata;
use Doctrine\Annotations\Metadata\InvalidAnnotationValue;
use Doctrine\Annotations\Metadata\InvalidPropertyValue;
use Doctrine\Annotations\Parser\Scope;

final class Constructor
Expand All @@ -25,7 +25,7 @@ public function __construct(Instantiator $instantiator)
*/
public function construct(AnnotationMetadata $annotationMetadata, Scope $scope, iterable $parameters) : object
{
(new TargetValidator())->validate($annotationMetadata, $scope);
$annotationMetadata->validateTarget($scope);

foreach ($parameters as $propertyName => $propertyValue) {
if ($propertyName === '') {
Expand All @@ -36,11 +36,13 @@ public function construct(AnnotationMetadata $annotationMetadata, Scope $scope,
$propertyName = $annotationMetadata->getDefaultProperty()->getName();
}

(new ValueValidator())->validate(
$annotationMetadata,
$annotationMetadata->getProperties()[$propertyName],
$propertyValue
);
$propertyMetadata = $annotationMetadata->getProperties()[$propertyName];

try {
$propertyMetadata->validateValue($propertyValue);
} catch (InvalidPropertyValue $exception) {
throw InvalidAnnotationValue::new($annotationMetadata, $exception);
}
}

return $this->instantiator->instantiate($annotationMetadata, $parameters);
Expand Down
42 changes: 42 additions & 0 deletions lib/Doctrine/Annotations/Metadata/AnnotationMetadata.php
Expand Up @@ -4,6 +4,10 @@

namespace Doctrine\Annotations\Metadata;

use Doctrine\Annotations\Parser\Scope;
use ReflectionClass;
use ReflectionMethod;
use ReflectionProperty;
use function array_combine;
use function array_filter;
use function array_map;
Expand Down Expand Up @@ -79,4 +83,42 @@ public function getDefaultProperty() : ?PropertyMetadata
{
return $this->defaultProperty;
}

/**
* @return true
*
* @throws InvalidTarget
*/
public function validateTarget(Scope $scope) : bool
{
$target = $this->getTarget();

if ($target->all()) {
return true;
}

if ($scope->isNested()) {
if (! $target->annotation()) {
throw InvalidTarget::annotation($this);
}

return true;
}

$subject = $scope->getSubject();

if ($subject instanceof ReflectionClass && ! $target->class()) {
throw InvalidTarget::class($this);
}

if ($subject instanceof ReflectionProperty && ! $target->property()) {
throw InvalidTarget::property($this);
}

if ($subject instanceof ReflectionMethod && ! $target->method()) {
throw InvalidTarget::method($this);
}

return true;
}
}
Expand Up @@ -10,6 +10,7 @@
use Doctrine\Annotations\Assembler\Assembler;
use Doctrine\Annotations\Metadata\AnnotationMetadata;
use Doctrine\Annotations\Metadata\AnnotationTarget;
use Doctrine\Annotations\Metadata\Constraint\TypeConstraint;
use Doctrine\Annotations\Metadata\InternalAnnotations;
use Doctrine\Annotations\Metadata\PropertyMetadata;
use Doctrine\Annotations\Metadata\Reflection\ClassReflectionProvider;
Expand Down Expand Up @@ -158,7 +159,7 @@ private function assembleProperty(ReflectionProperty $property, bool $first) : P
if ($docBlock === false) {
return new PropertyMetadata(
$property->getName(),
new MixedType(),
new TypeConstraint(new MixedType()),
$first
);
}
Expand All @@ -175,6 +176,6 @@ private function assembleProperty(ReflectionProperty $property, bool $first) : P
$type = new UnionType($type, new NullType());
}

return new PropertyMetadata($property->getName(), $type, $first);
return new PropertyMetadata($property->getName(), new TypeConstraint($type), $first);
}
}
@@ -0,0 +1,28 @@
<?php

declare(strict_types=1);

namespace Doctrine\Annotations\Metadata\Constraint;

final class CompositeConstraint implements Constraint
{
/** @var Constraint[] */
private $constraints;

public function __construct(Constraint ...$constraints)
{
$this->constraints = $constraints;
}

/**
* @param mixed $value
*/
public function validate($value) : bool
{
foreach ($this->constraints as $constraint) {
$constraint->validate($value);
}

return true;
}
}
17 changes: 17 additions & 0 deletions lib/Doctrine/Annotations/Metadata/Constraint/Constraint.php
@@ -0,0 +1,17 @@
<?php

declare(strict_types=1);

namespace Doctrine\Annotations\Metadata\Constraint;

interface Constraint
{
/**
* @param mixed $value
*
* @return true
*
* @throws ConstraintNotFulfilled
*/
public function validate($value) : bool;
}
@@ -0,0 +1,17 @@
<?php

declare(strict_types=1);

namespace Doctrine\Annotations\Metadata\Constraint;

use Doctrine\Annotations\Metadata\ValidationException;
use Exception;
use Throwable;

abstract class ConstraintNotFulfilled extends Exception implements ValidationException
{
protected function __construct(string $message, ?Throwable $previous = null)
{
parent::__construct($message, 0, $previous);
}
}
33 changes: 33 additions & 0 deletions lib/Doctrine/Annotations/Metadata/Constraint/EnumConstraint.php
@@ -0,0 +1,33 @@
<?php

declare(strict_types=1);

namespace Doctrine\Annotations\Metadata\Constraint;

use function in_array;

final class EnumConstraint implements Constraint
{
/** @var mixed[] */
private $allowedValues;

/**
* @param mixed[] $allowedValues
*/
public function __construct(array $allowedValues)
{
$this->allowedValues = $allowedValues;
}

/**
* @param mixed $value
*/
public function validate($value) : bool
{
if (! in_array($value, $this->allowedValues)) {
throw InvalidValue::new($this->allowedValues, $value);
}

return true;
}
}
25 changes: 25 additions & 0 deletions lib/Doctrine/Annotations/Metadata/Constraint/InvalidType.php
@@ -0,0 +1,25 @@
<?php

declare(strict_types=1);

namespace Doctrine\Annotations\Metadata\Constraint;

use function sprintf;

final class InvalidType extends ConstraintNotFulfilled
{
/**
* @param mixed $value
*/
public static function new(string $typeDescription, $value) : self
{
// TODO: Describe value
return new self(
sprintf(
'Invalid value "%s" fo type %s.',
$value,
$typeDescription
)
);
}
}
28 changes: 28 additions & 0 deletions lib/Doctrine/Annotations/Metadata/Constraint/InvalidValue.php
@@ -0,0 +1,28 @@
<?php

declare(strict_types=1);

namespace Doctrine\Annotations\Metadata\Constraint;

use function gettype;
use function implode;
use function sprintf;

final class InvalidValue extends ConstraintNotFulfilled
{
/**
* @param mixed[] $allowedValues
* @param mixed $value
*/
public static function new(array $allowedValues, $value) : self
{
// TODO: Describe values
return new self(
sprintf(
'Invalid value "%s" for allowed values: "%s".',
gettype($value),
implode(',', $allowedValues)
)
);
}
}
@@ -0,0 +1,13 @@
<?php

declare(strict_types=1);

namespace Doctrine\Annotations\Metadata\Constraint;

final class MissingRequiredValue extends ConstraintNotFulfilled
{
public static function new() : self
{
return new self('Required value is null');
}
}

0 comments on commit 08d35db

Please sign in to comment.