mirror of
https://github.com/Respect/Validation.git
synced 2024-06-14 03:25:09 +02:00
Refactor "AbstractWrapper" class
This commit also creates `AbstractLocaleWrapper` to help creating locale-based rules.
This commit is contained in:
parent
550795c1e2
commit
aa7d84c3ea
59
library/Rules/AbstractLocaleWrapper.php
Normal file
59
library/Rules/AbstractLocaleWrapper.php
Normal file
|
@ -0,0 +1,59 @@
|
|||
<?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 function class_exists;
|
||||
use function mb_strtolower;
|
||||
use function sprintf;
|
||||
use function ucfirst;
|
||||
use Respect\Validation\Exceptions\ComponentException;
|
||||
|
||||
/**
|
||||
* Abstract class to help creating rules based on location.
|
||||
*
|
||||
* @author Henrique Moody <henriquemoody@gmail.com>
|
||||
*/
|
||||
abstract class AbstractLocaleWrapper extends AbstractWrapper
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $countryCode;
|
||||
|
||||
/**
|
||||
* Initializes the rule.
|
||||
*
|
||||
* @param string $countryCode
|
||||
*
|
||||
* @throws ComponentException When country is not supported.
|
||||
*/
|
||||
public function __construct(string $countryCode)
|
||||
{
|
||||
$normalized = ucfirst(mb_strtolower($countryCode));
|
||||
$className = sprintf('%s\\Locale\\%s%s', __NAMESPACE__, $normalized, $this->getSuffix());
|
||||
if (!class_exists($className)) {
|
||||
throw new ComponentException(sprintf('"%s" is not a supported country code', $countryCode));
|
||||
}
|
||||
|
||||
$this->countryCode = $countryCode;
|
||||
parent::__construct(new $className);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the class name based on the identifier.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
abstract protected function getSuffix(): string;
|
||||
}
|
|
@ -13,40 +13,60 @@ declare(strict_types=1);
|
|||
|
||||
namespace Respect\Validation\Rules;
|
||||
|
||||
use Respect\Validation\Exceptions\ComponentException;
|
||||
use Respect\Validation\Validatable;
|
||||
|
||||
/**
|
||||
* Abstract class to help on creating rules that wrap rules.
|
||||
*
|
||||
* @author Henrique Moody <henriquemoody@gmail.com>
|
||||
*/
|
||||
abstract class AbstractWrapper extends AbstractRule
|
||||
{
|
||||
protected $validatable;
|
||||
/**
|
||||
* @var Validatable
|
||||
*/
|
||||
private $validatable;
|
||||
|
||||
public function getValidatable()
|
||||
/**
|
||||
* Initializes the rule.
|
||||
*
|
||||
* @param Validatable $validatable
|
||||
*/
|
||||
public function __construct(Validatable $validatable)
|
||||
{
|
||||
if (!$this->validatable instanceof Validatable) {
|
||||
throw new ComponentException('There is no defined validatable');
|
||||
}
|
||||
|
||||
return $this->validatable;
|
||||
$this->validatable = $validatable;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function assert($input)
|
||||
{
|
||||
return $this->getValidatable()->assert($input);
|
||||
return $this->validatable->assert($input);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function check($input)
|
||||
{
|
||||
return $this->getValidatable()->check($input);
|
||||
return $this->validatable->check($input);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function validate($input)
|
||||
{
|
||||
return $this->getValidatable()->validate($input);
|
||||
return $this->validatable->validate($input);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setName($name)
|
||||
{
|
||||
$this->getValidatable()->setName($name);
|
||||
$this->validatable->setName($name);
|
||||
|
||||
return parent::setName($name);
|
||||
}
|
||||
|
|
|
@ -13,21 +13,13 @@ declare(strict_types=1);
|
|||
|
||||
namespace Respect\Validation\Rules;
|
||||
|
||||
use Respect\Validation\Exceptions\ComponentException;
|
||||
|
||||
class IdentityCard extends AbstractWrapper
|
||||
final class IdentityCard extends AbstractLocaleWrapper
|
||||
{
|
||||
public $countryCode;
|
||||
|
||||
public function __construct($countryCode)
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getSuffix(): string
|
||||
{
|
||||
$shortName = ucfirst(mb_strtolower($countryCode)).'IdentityCard';
|
||||
$className = __NAMESPACE__.'\\Locale\\'.$shortName;
|
||||
if (!class_exists($className)) {
|
||||
throw new ComponentException(sprintf('There is no support for identity cards from "%s"', $countryCode));
|
||||
}
|
||||
|
||||
$this->countryCode = $countryCode;
|
||||
$this->validatable = new $className();
|
||||
return 'IdentityCard';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,11 +20,6 @@ class Optional extends AbstractWrapper
|
|||
{
|
||||
use UndefinedHelper;
|
||||
|
||||
public function __construct(Validatable $rule)
|
||||
{
|
||||
$this->validatable = $rule;
|
||||
}
|
||||
|
||||
public function assert($input)
|
||||
{
|
||||
if ($this->isUndefined($input)) {
|
||||
|
|
|
@ -13,27 +13,21 @@ declare(strict_types=1);
|
|||
|
||||
namespace Respect\Validation\Rules;
|
||||
|
||||
use Respect\Validation\Exceptions\ComponentException;
|
||||
|
||||
/**
|
||||
* Validates country subdivision codes according to ISO 3166-2.
|
||||
*
|
||||
* @see http://en.wikipedia.org/wiki/ISO_3166-2
|
||||
* @see http://www.geonames.org/countries/
|
||||
*
|
||||
* @author Henrique Moody <henriquemoody@gmail.com>
|
||||
*/
|
||||
class SubdivisionCode extends AbstractWrapper
|
||||
final class SubdivisionCode extends AbstractLocaleWrapper
|
||||
{
|
||||
public $countryCode;
|
||||
|
||||
public function __construct($countryCode)
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getSuffix(): string
|
||||
{
|
||||
$shortName = ucfirst(mb_strtolower($countryCode)).'SubdivisionCode';
|
||||
$className = __NAMESPACE__.'\\Locale\\'.$shortName;
|
||||
if (!class_exists($className)) {
|
||||
throw new ComponentException(sprintf('"%s" is not a valid country code in ISO 3166-2', $countryCode));
|
||||
}
|
||||
|
||||
$this->countryCode = $countryCode;
|
||||
$this->validatable = new $className();
|
||||
return 'SubdivisionCode';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,22 +13,13 @@ declare(strict_types=1);
|
|||
|
||||
namespace Respect\Validation\Rules;
|
||||
|
||||
use Respect\Validation\Exceptions\ComponentException;
|
||||
|
||||
final class Vatin extends AbstractWrapper
|
||||
final class Vatin extends AbstractLocaleWrapper
|
||||
{
|
||||
public $countryCode;
|
||||
|
||||
public function __construct($countryCode)
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getSuffix(): string
|
||||
{
|
||||
$shortName = ucfirst(mb_strtolower($countryCode)).'Vatin';
|
||||
$className = __NAMESPACE__.'\\Locale\\'.$shortName;
|
||||
if (!class_exists($className)) {
|
||||
$message = sprintf('There is no support for VAT identification number from "%s"', $countryCode);
|
||||
throw new ComponentException($message);
|
||||
}
|
||||
|
||||
$this->countryCode = $countryCode;
|
||||
$this->validatable = new $className();
|
||||
return 'Vatin';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,40 +14,33 @@ declare(strict_types=1);
|
|||
namespace Respect\Validation\Rules;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use ReflectionObject;
|
||||
use Respect\Validation\Validatable;
|
||||
|
||||
class AbstractWrapperTest extends TestCase
|
||||
/**
|
||||
* @test core
|
||||
*
|
||||
* @covers \Respect\Validation\Rules\AbstractWrapper
|
||||
*
|
||||
* @author Henrique Moody <henriquemoody@gmail.com>
|
||||
*/
|
||||
final class AbstractWrapperTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @expectedException \Respect\Validation\Exceptions\ComponentException
|
||||
* @expectedExceptionMessage There is no defined validatable
|
||||
* @test
|
||||
*/
|
||||
public function testShouldThrowsAnExceptionWhenWrappedValidatableIsNotDefined(): void
|
||||
{
|
||||
$wrapper = $this->getMockForAbstractClass(AbstractWrapper::class);
|
||||
$wrapper->getValidatable();
|
||||
}
|
||||
|
||||
private function bindValidatable($wrapper, $validatable): void
|
||||
{
|
||||
$reflectionObject = new ReflectionObject($wrapper);
|
||||
$reflectionProperty = $reflectionObject->getProperty('validatable');
|
||||
$reflectionProperty->setAccessible(true);
|
||||
$reflectionProperty->setValue($wrapper, $validatable);
|
||||
}
|
||||
|
||||
public function testShouldReturnDefinedValidatable(): void
|
||||
public function shouldReturnDefinedValidatable(): void
|
||||
{
|
||||
$validatable = $this->createMock(Validatable::class);
|
||||
|
||||
$wrapper = $this->getMockForAbstractClass(AbstractWrapper::class);
|
||||
$this->bindValidatable($wrapper, $validatable);
|
||||
$wrapper = $this->getMockForAbstractClass(AbstractWrapper::class, [$validatable]);
|
||||
|
||||
self::assertSame($validatable, $wrapper->getValidatable());
|
||||
self::assertAttributeSame($validatable, 'validatable', $wrapper);
|
||||
}
|
||||
|
||||
public function testShouldUseWrappedToValidate(): void
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function shouldUseWrappedToValidate(): void
|
||||
{
|
||||
$input = 'Whatever';
|
||||
|
||||
|
@ -58,13 +51,15 @@ class AbstractWrapperTest extends TestCase
|
|||
->with($input)
|
||||
->will($this->returnValue(true));
|
||||
|
||||
$wrapper = $this->getMockForAbstractClass(AbstractWrapper::class);
|
||||
$this->bindValidatable($wrapper, $validatable);
|
||||
$wrapper = $this->getMockForAbstractClass(AbstractWrapper::class, [$validatable]);
|
||||
|
||||
self::assertTrue($wrapper->validate($input));
|
||||
}
|
||||
|
||||
public function testShouldUseWrappedToAssert(): void
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function shouldUseWrappedToAssert(): void
|
||||
{
|
||||
$input = 'Whatever';
|
||||
|
||||
|
@ -75,13 +70,15 @@ class AbstractWrapperTest extends TestCase
|
|||
->with($input)
|
||||
->will($this->returnValue(true));
|
||||
|
||||
$wrapper = $this->getMockForAbstractClass(AbstractWrapper::class);
|
||||
$this->bindValidatable($wrapper, $validatable);
|
||||
$wrapper = $this->getMockForAbstractClass(AbstractWrapper::class, [$validatable]);
|
||||
|
||||
self::assertTrue($wrapper->assert($input));
|
||||
}
|
||||
|
||||
public function testShouldUseWrappedToCheck(): void
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function shouldUseWrappedToCheck(): void
|
||||
{
|
||||
$input = 'Whatever';
|
||||
|
||||
|
@ -92,13 +89,15 @@ class AbstractWrapperTest extends TestCase
|
|||
->with($input)
|
||||
->will($this->returnValue(true));
|
||||
|
||||
$wrapper = $this->getMockForAbstractClass(AbstractWrapper::class);
|
||||
$this->bindValidatable($wrapper, $validatable);
|
||||
$wrapper = $this->getMockForAbstractClass(AbstractWrapper::class, [$validatable]);
|
||||
|
||||
self::assertTrue($wrapper->check($input));
|
||||
}
|
||||
|
||||
public function testShouldPassNameOnToWrapped(): void
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function shouldPassNameOnToWrapped(): void
|
||||
{
|
||||
$name = 'Whatever';
|
||||
|
||||
|
@ -109,8 +108,7 @@ class AbstractWrapperTest extends TestCase
|
|||
->with($name)
|
||||
->will($this->returnValue($validatable));
|
||||
|
||||
$wrapper = $this->getMockForAbstractClass(AbstractWrapper::class);
|
||||
$this->bindValidatable($wrapper, $validatable);
|
||||
$wrapper = $this->getMockForAbstractClass(AbstractWrapper::class, [$validatable]);
|
||||
|
||||
self::assertSame($wrapper, $wrapper->setName($name));
|
||||
}
|
||||
|
|
|
@ -52,14 +52,6 @@ class OptionalTest extends TestCase
|
|||
];
|
||||
}
|
||||
|
||||
public function testShouldAcceptInstanceOfValidatobleOnConstructor(): void
|
||||
{
|
||||
$validatable = $this->createMock(Validatable::class);
|
||||
$rule = new Optional($validatable);
|
||||
|
||||
self::assertSame($validatable, $rule->getValidatable());
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider providerForOptional
|
||||
*/
|
||||
|
|
|
@ -23,7 +23,7 @@ class SubdivisionCodeTest extends TestCase
|
|||
{
|
||||
/**
|
||||
* @expectedException \Respect\Validation\Exceptions\ComponentException
|
||||
* @expectedExceptionMessage "whatever" is not a valid country code in ISO 3166-2
|
||||
* @expectedExceptionMessage "whatever" is not a supported country code
|
||||
*/
|
||||
public function testShouldThrowsExceptionWhenInvalidFormat(): void
|
||||
{
|
||||
|
@ -32,7 +32,7 @@ class SubdivisionCodeTest extends TestCase
|
|||
|
||||
/**
|
||||
* @expectedException \Respect\Validation\Exceptions\ComponentException
|
||||
* @expectedExceptionMessage "JK" is not a valid country code in ISO 3166-2
|
||||
* @expectedExceptionMessage "JK" is not a supported country code
|
||||
*/
|
||||
public function testShouldNotAcceptWrongNamesOnConstructor(): void
|
||||
{
|
||||
|
@ -41,9 +41,10 @@ class SubdivisionCodeTest extends TestCase
|
|||
|
||||
public function testShouldDefineASubdivisionCodeFormatOnConstructor(): void
|
||||
{
|
||||
$countrySubdivision = new SubdivisionCode('US');
|
||||
$countryCode = 'US';
|
||||
$countrySubdivision = new SubdivisionCode($countryCode);
|
||||
|
||||
self::assertEquals('US', $countrySubdivision->countryCode);
|
||||
self::assertAttributeEquals($countryCode, 'countryCode', $countrySubdivision);
|
||||
}
|
||||
|
||||
public function providerForValidSubdivisionCodeInformation()
|
||||
|
|
|
@ -27,12 +27,12 @@ final class VatinTest extends TestCase
|
|||
$countryCode = 'PL';
|
||||
$rule = new Vatin($countryCode);
|
||||
|
||||
self::assertInstanceOf(Validatable::class, $rule->getValidatable());
|
||||
self::assertAttributeInstanceOf(Validatable::class, 'validatable', $rule);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \Respect\Validation\Exceptions\ComponentException
|
||||
* @expectedExceptionMessage There is no support for VAT identification number from "BR"
|
||||
* @expectedExceptionMessage "BR" is not a supported country code
|
||||
*/
|
||||
public function testShouldThrowAnExceptionWhenCountryCodeIsNotSupported(): void
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue