initial commit
This commit is contained in:
commit
0db3e92ee6
59 changed files with 3384 additions and 0 deletions
181
src/DomainObjects/Validation/AbstractValidator.php
Normal file
181
src/DomainObjects/Validation/AbstractValidator.php
Normal file
|
|
@ -0,0 +1,181 @@
|
|||
<?php declare(strict_types=1);
|
||||
|
||||
namespace VeruA\DomainObjects\Validation;
|
||||
|
||||
use VeruA\Log;
|
||||
use VeruA\DomainObjects\DomainObject;
|
||||
use VeruA\DomainObjects\ValueObjects\Value;
|
||||
use VeruA\DomainObjects\Validation\ResultCollection;
|
||||
|
||||
/**
|
||||
* Validator is a singleton base class for classes validating DomainObjects.
|
||||
*/
|
||||
abstract class AbstractValidator implements Validator
|
||||
{
|
||||
use Log;
|
||||
|
||||
/**
|
||||
* Needs to be declared in every childclass
|
||||
* @var callable[] A list of tests used to validate domainObjects dataTypes, indexed by fieldname
|
||||
*/
|
||||
protected $validators = [];
|
||||
|
||||
/**
|
||||
* Stores the single instance of Validator.
|
||||
* @var Validator
|
||||
* @abstract Needs to be redeclared in every child class
|
||||
*/
|
||||
protected static AbstractValidator $instance;
|
||||
|
||||
private bool $validatorsLoaded = false;
|
||||
|
||||
/**
|
||||
* Implement constructor in childclasses and assign the validator functions to using setValidators()
|
||||
* All sub-classes should have protected constructors.
|
||||
*/
|
||||
protected abstract function __construct();
|
||||
|
||||
// getValidators() {{{
|
||||
/**
|
||||
* Returns the validator functions.
|
||||
*/
|
||||
public function getValidators()
|
||||
{
|
||||
return $this->validators;
|
||||
} // }}}
|
||||
|
||||
// setValidators() {{{
|
||||
/**
|
||||
* Sets the validator functions.
|
||||
*/
|
||||
protected function setValidators($tests)
|
||||
{
|
||||
$parentClass = get_parent_class($this);
|
||||
$parentTests = [];
|
||||
|
||||
if ($parentClass !== false && $parentClass !== AbstractValidator::class)
|
||||
{
|
||||
$parentTests = $parentClass::getInstance()->getValidators();
|
||||
}
|
||||
$this->validators = array_merge($parentTests, $tests);
|
||||
} // }}}
|
||||
|
||||
// addValidator() {{{
|
||||
/**
|
||||
* Dynamically add a validator function
|
||||
* @param string $field The DomainObject Field to validate
|
||||
* @param callable $validator The Validator function to use
|
||||
* @param string $validatorIndex The internal index used to store the validator function. Use this to
|
||||
* remove or overwrite the validator
|
||||
*/
|
||||
public function addValidator(string $field, callable $validator, ?string $validatorIndex=null)
|
||||
{
|
||||
if (!isset($this->validators[$field])) $this->validators[$field] = [];
|
||||
$this->validators[$field][$validatorIndex] = $validator;
|
||||
} // }}}
|
||||
|
||||
// removeValidator() {{{
|
||||
/**
|
||||
* Dynamiocally remove a validator function
|
||||
*/
|
||||
public function removeValidator(string $field, $validatorIndex=null)
|
||||
{
|
||||
if (isset($validatorIndex))
|
||||
{
|
||||
unset($this->validators[$field][$validatorIndex]);
|
||||
} else
|
||||
{
|
||||
unset($this->validators[$field]);
|
||||
}
|
||||
} // }}}
|
||||
|
||||
// getInstance() {{{
|
||||
/**
|
||||
* Returnst the instances of the validator, instantiates a new one if there isn't one already.
|
||||
* @return Validator
|
||||
*/
|
||||
public static function getInstance(): Validator
|
||||
{
|
||||
if (!isset(static::$instance)) {
|
||||
static::$instance = new static();
|
||||
}
|
||||
|
||||
assert(
|
||||
array_column(
|
||||
(new \ReflectionClass(static::$instance))
|
||||
->getProperties(\ReflectionProperty::IS_STATIC | \ReflectionProperty::IS_PROTECTED),
|
||||
'class', 'name'
|
||||
)['instance'] === get_class(static::$instance),
|
||||
new \Exception('$instance has to be redeclared in '.get_class(static::$instance))
|
||||
);
|
||||
|
||||
return static::$instance;
|
||||
} // }}}
|
||||
|
||||
// validate() {{{
|
||||
/**
|
||||
* Validates a DomainObject.
|
||||
* @param DomainObject $domainObject
|
||||
* @return ResultCollection|bool returns true if validations passed a ResultCollection otherwise
|
||||
*/
|
||||
public function validate(Validatable $domainObject)
|
||||
{
|
||||
$this->loadDefaultValidators($domainObject);
|
||||
|
||||
$rc = new ResultCollection((new \ReflectionClass($domainObject))->getShortName());
|
||||
$passed = true;
|
||||
|
||||
// Validate properties
|
||||
foreach ($this->validators as $col => $validators)
|
||||
{
|
||||
if (!isset($domainObject->$col)) {
|
||||
$this->log()->notice('DomainObject '.get_class($domainObject)." has no field '$col'");
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
$valueObject = $domainObject->getValueObjectOf($col);
|
||||
foreach ($validators as $test)
|
||||
{
|
||||
if (true !== ($result = $test($valueObject))) {
|
||||
$rc->$col = $result;
|
||||
$passed = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (\OutOfRangeException $e) {
|
||||
self::log()->notice('Field not set', ['name' => $col]);
|
||||
}
|
||||
}
|
||||
|
||||
return $passed ?: $rc;
|
||||
} // }}}
|
||||
|
||||
// loadDefaultValidators() {{{
|
||||
/**
|
||||
* load vaildators defined in ValueObjects.
|
||||
* Defined as Default and as such meaning always used. An example is the EAN13 ValueObject
|
||||
* which always validates checksum and length
|
||||
*/
|
||||
private function loadDefaultValidators(DomainObject $domainObject)
|
||||
{
|
||||
if (! $this->validatorsLoaded)
|
||||
{
|
||||
foreach ($domainObject->dataTypes() as $col => $dt)
|
||||
{
|
||||
if (is_subclass_of($dt, Value::class) && !empty($validators = ($dt)::defaultValidators()))
|
||||
{
|
||||
if (!isset($this->validators[$col])) $this->validators[$col] = [];
|
||||
|
||||
$this->validators[$col] = array_merge($this->validators[$col], $validators);
|
||||
}
|
||||
}
|
||||
self::log()->debug('Registered Validators', $this->validators);
|
||||
|
||||
$this->validatorsLoaded = true;
|
||||
}
|
||||
} // }}}
|
||||
}
|
||||
|
||||
/* jEdit buffer local properties {{{
|
||||
* :folding=explicit:collapseFolds=1:
|
||||
}}}*/
|
||||
Loading…
Add table
Add a link
Reference in a new issue