Make properties of "AbstractRelated" private

Following what is happening with pretty much every class in this
library, this commit will make the public properties of
"AbstractRelated" private.

Because other objects use some of those public properties, this commit
will also implement a couple of methods in "AbstractRelated" so they can
access the values they need.

This commit will also remove the method "decision" that makes dynamic
calls to "assert()," "check()," and "validate()" methods.

Signed-off-by: Henrique Moody <henriquemoody@gmail.com>
This commit is contained in:
Henrique Moody 2019-05-05 16:22:44 +02:00
parent 541fea9d7b
commit 051866f75a
No known key found for this signature in database
GPG key ID: 221E9281655813A6
9 changed files with 63 additions and 258 deletions

View file

@ -16,7 +16,6 @@ namespace Respect\Validation\Rules;
use Respect\Validation\Exceptions\NestedValidationException;
use Respect\Validation\Exceptions\ValidationException;
use Respect\Validation\Validatable;
use function is_null;
use function is_scalar;
/**
@ -30,17 +29,17 @@ abstract class AbstractRelated extends AbstractRule
/**
* @var bool
*/
public $mandatory = true;
private $mandatory = true;
/**
* @var mixed
*/
public $reference = '';
private $reference;
/**
* @var Validatable|null
*/
public $validator;
private $rule;
/**
* @param mixed $input
@ -57,20 +56,33 @@ abstract class AbstractRelated extends AbstractRule
/**
* @param mixed $reference
*/
public function __construct($reference, ?Validatable $validator = null, bool $mandatory = true)
public function __construct($reference, ?Validatable $rule = null, bool $mandatory = true)
{
if (is_scalar($reference)) {
$this->setName((string) $reference);
if ($validator && !$validator->getName()) {
$validator->setName((string) $reference);
if ($rule && !$rule->getName()) {
$rule->setName((string) $reference);
}
}
$this->reference = $reference;
$this->validator = $validator;
$this->rule = $rule;
$this->mandatory = $mandatory;
}
/**
* @return mixed
*/
public function getReference()
{
return $this->reference;
}
public function isMandatory(): bool
{
return $this->mandatory;
}
/**
* {@inheritDoc}
*/
@ -78,8 +90,8 @@ abstract class AbstractRelated extends AbstractRule
{
parent::setName($name);
if ($this->validator instanceof Validatable) {
$this->validator->setName($name);
if ($this->rule instanceof Validatable) {
$this->rule->setName($name);
}
return $this;
@ -95,8 +107,12 @@ abstract class AbstractRelated extends AbstractRule
throw $this->reportError($input, ['hasReference' => false]);
}
if ($this->rule === null || !$hasReference) {
return;
}
try {
$this->decision('assert', $hasReference, $input);
$this->rule->assert($this->getReferenceValue($input));
} catch (ValidationException $validationException) {
/** @var NestedValidationException $nestedValidationException */
$nestedValidationException = $this->reportError($this->reference, ['hasReference' => true]);
@ -116,7 +132,11 @@ abstract class AbstractRelated extends AbstractRule
throw $this->reportError($input, ['hasReference' => false]);
}
$this->decision('check', $hasReference, $input);
if ($this->rule === null || !$hasReference) {
return;
}
$this->rule->check($this->getReferenceValue($input));
}
/**
@ -129,16 +149,10 @@ abstract class AbstractRelated extends AbstractRule
return false;
}
return $this->decision('validate', $hasReference, $input);
}
if ($this->rule === null || !$hasReference) {
return true;
}
/**
* @param mixed $input
*/
private function decision(string $type, bool $hasReference, $input): bool
{
return (!$this->mandatory && !$hasReference)
|| (is_null($this->validator)
|| $this->validator->$type($this->getReferenceValue($input)));
return $this->rule->validate($this->getReferenceValue($input));
}
}

View file

@ -28,9 +28,9 @@ use function property_exists;
*/
final class Attribute extends AbstractRelated
{
public function __construct(string $reference, ?Validatable $validator = null, bool $mandatory = true)
public function __construct(string $reference, ?Validatable $rule = null, bool $mandatory = true)
{
parent::__construct($reference, $validator, $mandatory);
parent::__construct($reference, $rule, $mandatory);
}
/**
@ -40,7 +40,7 @@ final class Attribute extends AbstractRelated
*/
public function getReferenceValue($input)
{
$propertyMirror = new ReflectionProperty($input, $this->reference);
$propertyMirror = new ReflectionProperty($input, (string) $this->getReference());
$propertyMirror->setAccessible(true);
return $propertyMirror->getValue($input);
@ -51,6 +51,6 @@ final class Attribute extends AbstractRelated
*/
public function hasReference($input): bool
{
return is_object($input) && property_exists($input, $this->reference);
return is_object($input) && property_exists($input, (string) $this->getReference());
}
}

View file

@ -29,12 +29,13 @@ final class Key extends AbstractRelated
/**
* @param mixed $reference
*/
public function __construct($reference, ?Validatable $referenceValidator = null, bool $mandatory = true)
public function __construct($reference, ?Validatable $rule = null, bool $mandatory = true)
{
if (!is_scalar($reference) || $reference === '') {
throw new ComponentException('Invalid array key name');
}
parent::__construct($reference, $referenceValidator, $mandatory);
parent::__construct($reference, $rule, $mandatory);
}
/**
@ -42,7 +43,7 @@ final class Key extends AbstractRelated
*/
public function getReferenceValue($input)
{
return $input[$this->reference];
return $input[$this->getReference()];
}
/**
@ -50,6 +51,6 @@ final class Key extends AbstractRelated
*/
public function hasReference($input): bool
{
return is_array($input) && array_key_exists($this->reference, $input);
return is_array($input) && array_key_exists($this->getReference(), $input);
}
}

View file

@ -53,7 +53,7 @@ final class KeyNested extends AbstractRelated
*/
private function getReferencePieces(): array
{
return explode('.', rtrim((string) $this->reference, '.'));
return explode('.', rtrim((string) $this->getReference(), '.'));
}
/**
@ -65,7 +65,7 @@ final class KeyNested extends AbstractRelated
private function getValueFromArray(array $array, $key)
{
if (!array_key_exists($key, $array)) {
$message = sprintf('Cannot select the key %s from the given array', $this->reference);
$message = sprintf('Cannot select the key %s from the given array', $this->getReference());
throw new ComponentException($message);
}
@ -80,7 +80,7 @@ final class KeyNested extends AbstractRelated
private function getValueFromArrayAccess(ArrayAccess $array, $key)
{
if (!$array->offsetExists($key)) {
$message = sprintf('Cannot select the key %s from the given array', $this->reference);
$message = sprintf('Cannot select the key %s from the given array', $this->getReference());
throw new ComponentException($message);
}
@ -97,7 +97,7 @@ final class KeyNested extends AbstractRelated
private function getValueFromObject($object, string $property)
{
if (empty($property) || !property_exists($object, $property)) {
$message = sprintf('Cannot select the property %s from the given object', $this->reference);
$message = sprintf('Cannot select the property %s from the given object', $this->getReference());
throw new ComponentException($message);
}
@ -124,7 +124,7 @@ final class KeyNested extends AbstractRelated
return $this->getValueFromObject($value, $key);
}
$message = sprintf('Cannot select the property %s from the given data', $this->reference);
$message = sprintf('Cannot select the property %s from the given data', $this->getReference());
throw new ComponentException($message);
}
@ -134,7 +134,7 @@ final class KeyNested extends AbstractRelated
public function getReferenceValue($input)
{
if (is_scalar($input)) {
$message = sprintf('Cannot select the %s in the given data', $this->reference);
$message = sprintf('Cannot select the %s in the given data', $this->getReference());
throw new ComponentException($message);
}

View file

@ -74,7 +74,7 @@ final class KeySet extends AbstractWrapper
*/
private function getKeyReference(Key $rule)
{
return $rule->reference;
return $rule->getReference();
}
/**
@ -87,11 +87,11 @@ final class KeySet extends AbstractWrapper
}
foreach ($this->keyRules as $keyRule) {
if (!array_key_exists($keyRule->reference, $input) && $keyRule->mandatory) {
if (!array_key_exists($keyRule->getReference(), $input) && $keyRule->isMandatory()) {
return false;
}
unset($input[$keyRule->reference]);
unset($input[$keyRule->getReference()]);
}
return count($input) == 0;

View file

@ -1,213 +0,0 @@
<?php
/*
* This file is part of Respect/Validation.
*
* (c) Alexandre Gomes Gaigalas <alexandre@gaigalas.net>
*
* For the full copyright and license information, please view the "LICENSE.md"
* file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Respect\Validation\Rules;
use Respect\Validation\Test\TestCase;
use Respect\Validation\Validatable;
/**
* @covers \Respect\Validation\Rules\AbstractRelated
*
* @author Emmerson Siqueira <emmersonsiqueira@gmail.com>
* @author Gabriel Caruso <carusogabriel34@gmail.com>
* @author Henrique Moody <henriquemoody@gmail.com>
*/
final class AbstractRelatedTest extends TestCase
{
/**
* @return string[][]
*/
public function providerForOperations(): array
{
return [
['validate'],
];
}
/**
* @test
*/
public function constructionOfAbstractRelatedClass(): void
{
$validatableMock = $this->createMock(Validatable::class);
$relatedRuleMock = $this->getMockForAbstractClass(AbstractRelated::class, ['foo', $validatableMock]);
self::assertEquals('foo', $relatedRuleMock->getName());
self::assertEquals('foo', $relatedRuleMock->reference);
self::assertTrue($relatedRuleMock->mandatory);
self::assertInstanceOf(Validatable::class, $relatedRuleMock->validator);
}
/**
* @dataProvider providerForOperations
*
* @test
*/
public function operationsShouldReturnTrueWhenReferenceValidatesItsValue(string $method): void
{
$validatableMock = $this->createMock(Validatable::class);
$validatableMock->expects(self::any())
->method($method)
->will(self::returnValue(true));
$relatedRuleMock = $this->getMockForAbstractClass(AbstractRelated::class, ['foo', $validatableMock]);
$relatedRuleMock->expects(self::any())
->method('hasReference')
->will(self::returnValue(true));
self::assertTrue($relatedRuleMock->$method('foo'));
}
/**
* @test
*/
public function validateShouldReturnFalseWhenIsMandatoryAndThereIsNoReference(): void
{
$relatedRuleMock = $this->getMockForAbstractClass(AbstractRelated::class, ['foo']);
$relatedRuleMock->expects(self::any())
->method('hasReference')
->will(self::returnValue(false));
self::assertFalse($relatedRuleMock->validate('foo'));
}
/**
* @test
*/
public function shouldAcceptReferenceOnConstructor(): void
{
$reference = 'something';
$abstractMock = $this
->getMockBuilder(AbstractRelated::class)
->setConstructorArgs([$reference])
->getMock();
self::assertSame($reference, $abstractMock->reference);
}
/**
* @test
*/
public function shouldBeMandatoryByDefault(): void
{
$abstractMock = $this
->getMockBuilder(AbstractRelated::class)
->setConstructorArgs(['something'])
->getMock();
self::assertTrue($abstractMock->mandatory);
}
/**
* @test
*/
public function shouldAcceptReferenceAndRuleOnConstructor(): void
{
$ruleMock = $this->createMock(Validatable::class);
$abstractMock = $this
->getMockBuilder(AbstractRelated::class)
->setConstructorArgs(['something', $ruleMock])
->getMock();
self::assertSame($ruleMock, $abstractMock->validator);
}
/**
* @test
*/
public function shouldDefineRuleNameAsReferenceWhenRuleDoesNotHaveName(): void
{
$reference = 'something';
$ruleMock = $this->createMock(Validatable::class);
$ruleMock
->expects(self::at(0))
->method('getName')
->will(self::returnValue(null));
$ruleMock
->expects(self::at(1))
->method('setName')
->with($reference);
$abstractMock = $this
->getMockBuilder(AbstractRelated::class)
->setConstructorArgs(['something', $ruleMock])
->getMock();
self::assertSame($ruleMock, $abstractMock->validator);
}
/**
* @test
*/
public function shouldNotDefineRuleNameAsReferenceWhenRuleDoesHaveName(): void
{
$ruleMock = $this->createMock(Validatable::class);
$ruleMock
->expects(self::at(0))
->method('getName')
->will(self::returnValue('something else'));
$ruleMock
->expects(self::never())
->method('setName');
$abstractMock = $this
->getMockBuilder(AbstractRelated::class)
->setConstructorArgs(['something', $ruleMock])
->getMock();
self::assertSame($ruleMock, $abstractMock->validator);
}
/**
* @test
*/
public function shouldAcceptMandatoryFlagOnConstructor(): void
{
$mandatory = false;
$abstractMock = $this
->getMockBuilder(AbstractRelated::class)
->setConstructorArgs(['something', $this->createMock(Validatable::class), $mandatory])
->getMock();
self::assertFalse($abstractMock->mandatory);
}
/**
* @test
*/
public function shouldDefineChildNameWhenDefiningTheNameOfTheParent(): void
{
$name = 'My new name';
$ruleMock = $this->createMock(Validatable::class);
$ruleMock
->expects(self::at(0))
->method('getName')
->will(self::returnValue('something else'));
$ruleMock
->expects(self::at(1))
->method('setName')
->with($name);
$this
->getMockBuilder(AbstractRelated::class)
->setConstructorArgs(['something', $ruleMock])
->getMock();
$ruleMock->setName($name);
}
}

View file

@ -18,8 +18,9 @@ use Respect\Validation\Validatable;
use stdClass;
/**
* @group rule
* @covers \Respect\Validation\Exceptions\AttributeException
* @group rule
*
* @covers \Respect\Validation\Rules\AbstractRelated
* @covers \Respect\Validation\Rules\Attribute
*
* @author Alexandre Gomes Gaigalas <alexandre@gaigalas.net>

View file

@ -19,8 +19,9 @@ use Respect\Validation\Validatable;
use stdClass;
/**
* @group rule
* @covers \Respect\Validation\Exceptions\KeyNestedException
* @group rule
*
* @covers \Respect\Validation\Rules\AbstractRelated
* @covers \Respect\Validation\Rules\KeyNested
*
* @author Alexandre Gomes Gaigalas <alexandre@gaigalas.net>

View file

@ -17,8 +17,9 @@ use Respect\Validation\Test\TestCase;
use Throwable;
/**
* @group rule
* @covers \Respect\Validation\Exceptions\KeyException
* @group rule
*
* @covers \Respect\Validation\Rules\AbstractRelated
* @covers \Respect\Validation\Rules\Key
*
* @author Alexandre Gomes Gaigalas <alexandre@gaigalas.net>