Code Coverage |
||||||||||
Classes and Traits |
Functions and Methods |
Lines |
||||||||
Total | |
100.00% |
1 / 1 |
|
100.00% |
15 / 15 |
CRAP | |
100.00% |
86 / 86 |
Field | |
100.00% |
1 / 1 |
|
100.00% |
15 / 15 |
43 | |
100.00% |
86 / 86 |
__construct | |
100.00% |
1 / 1 |
3 | |
100.00% |
7 / 7 |
|||
required | |
100.00% |
1 / 1 |
1 | |
100.00% |
2 / 2 |
|||
isRequired | |
100.00% |
1 / 1 |
1 | |
100.00% |
1 / 1 |
|||
appendFilter | |
100.00% |
1 / 1 |
1 | |
100.00% |
1 / 1 |
|||
prependFilter | |
100.00% |
1 / 1 |
1 | |
100.00% |
1 / 1 |
|||
addFilter | |
100.00% |
1 / 1 |
3 | |
100.00% |
7 / 7 |
|||
addFiltersFromArray | |
100.00% |
1 / 1 |
3 | |
100.00% |
6 / 6 |
|||
appendValidator | |
100.00% |
1 / 1 |
1 | |
100.00% |
1 / 1 |
|||
prependValidator | |
100.00% |
1 / 1 |
1 | |
100.00% |
1 / 1 |
|||
addValidator | |
100.00% |
1 / 1 |
3 | |
100.00% |
7 / 7 |
|||
addValidatorsFromArray | |
100.00% |
1 / 1 |
3 | |
100.00% |
6 / 6 |
|||
addFilterOrValidator | |
100.00% |
1 / 1 |
7 | |
100.00% |
14 / 14 |
|||
filter | |
100.00% |
1 / 1 |
6 | |
100.00% |
14 / 14 |
|||
validate | |
100.00% |
1 / 1 |
8 | |
100.00% |
17 / 17 |
|||
getErrors | |
100.00% |
1 / 1 |
1 | |
100.00% |
1 / 1 |
<?php | |
namespace Verja; | |
use Verja\Exception\FilterNotFound; | |
use Verja\Exception\InvalidValue; | |
use Verja\Exception\NotFound; | |
use Verja\Exception\ValidatorNotFound; | |
class Field | |
{ | |
/** @var FilterInterface[] */ | |
protected $filters = []; | |
/** @var ValidatorInterface[] */ | |
protected $validators = []; | |
/** @var array */ | |
protected $filterCache = []; | |
/** @var array */ | |
protected $validationCache = []; | |
/** @var array */ | |
protected $errors; | |
/** @var bool */ | |
protected $required = false; | |
/** @var bool */ | |
protected $filterFailed = false; | |
/** | |
* Field constructor. | |
* | |
* Adds filters and validators given in $definitions in the exact order. | |
* | |
* @param array $definitions | |
*/ | |
public function __construct(array $definitions = []) | |
{ | |
$p = array_search('required', $definitions); | |
if ($p !== false) { | |
array_splice($definitions, $p, 1); | |
$this->required(); | |
} | |
foreach ($definitions as $definition) { | |
$this->addFilterOrValidator($definition); | |
} | |
} | |
/** | |
* Set required flag | |
* | |
* @param bool $required | |
* @return $this | |
*/ | |
public function required($required = true) | |
{ | |
$this->required = $required; | |
return $this; | |
} | |
/** | |
* @return bool | |
*/ | |
public function isRequired() | |
{ | |
return $this->required; | |
} | |
/** | |
* Append $filter to the list of filters | |
* | |
* @param FilterInterface|string $filter | |
* @return $this | |
*/ | |
public function appendFilter($filter) | |
{ | |
return $this->addFilter($filter, false); | |
} | |
/** | |
* Prepend $filter to the list of filters | |
* | |
* @param FilterInterface|string $filter | |
* @return $this | |
*/ | |
public function prependFilter($filter) | |
{ | |
return $this->addFilter($filter, true); | |
} | |
/** | |
* Add $filter to the list of filters | |
* | |
* Appends by default prepends when $prepend == true | |
* | |
* @param FilterInterface|string $filter | |
* @param bool $prepend | |
* @return $this | |
*/ | |
public function addFilter($filter, $prepend = false) | |
{ | |
$filter = Filter::getFilter($filter); | |
if (count($this->filterCache) > 0) { | |
$this->filterCache = []; | |
} | |
if ($prepend) { | |
array_unshift($this->filters, $filter->assign($this)); | |
} else { | |
array_push($this->filters, $filter->assign($this)); | |
} | |
return $this; | |
} | |
/** | |
* Add Filters from $filterDefinitions | |
* | |
* Returns an array of Classes that where not found. | |
* | |
* @param array $filterDefinitions | |
* @return array | |
*/ | |
public function addFiltersFromArray(array $filterDefinitions) | |
{ | |
$notFound = []; | |
foreach ($filterDefinitions as $filterDefinition) { | |
try { | |
$this->addFilter($filterDefinition); | |
} catch (FilterNotFound $exception) { | |
$notFound[$exception->getFilter()] = $filterDefinition; | |
} | |
} | |
return $notFound; | |
} | |
/** | |
* Append $validator to the list of validators | |
* | |
* @param ValidatorInterface|string $validator | |
* @return $this | |
*/ | |
public function appendValidator($validator) | |
{ | |
return $this->addValidator($validator, false); | |
} | |
/** | |
* Prepend $validator to the list of validators | |
* | |
* @param ValidatorInterface|string $validator | |
* @return $this | |
*/ | |
public function prependValidator($validator) | |
{ | |
return $this->addValidator($validator, true); | |
} | |
/** | |
* Add $validator to the list of filters | |
* | |
* Appends by default prepends when $prepend == true | |
* | |
* @param ValidatorInterface|string|callable $validator | |
* @param bool $prepend | |
* @return $this | |
*/ | |
public function addValidator($validator, $prepend = false) | |
{ | |
$validator = Validator::getValidator($validator); | |
if (count($this->validationCache) > 0) { | |
$this->validationCache = []; | |
} | |
if ($prepend) { | |
array_unshift($this->validators, $validator->assign($this)); | |
} else { | |
array_push($this->validators, $validator->assign($this)); | |
} | |
return $this; | |
} | |
/** | |
* Add Filters from $validatorDefinitions | |
* | |
* Returns an array of Classes that where not found. | |
* | |
* @param array $validatorDefinitions | |
* @return array | |
*/ | |
public function addValidatorsFromArray(array $validatorDefinitions) | |
{ | |
$notFound = []; | |
foreach ($validatorDefinitions as $validatorDefinition) { | |
try { | |
$this->addValidator($validatorDefinition, false); | |
} catch (ValidatorNotFound $exception) { | |
$notFound[$exception->getValidator()] = $validatorDefinition; | |
} | |
} | |
return $notFound; | |
} | |
/** | |
* Add a filter or validator | |
* | |
* @param FilterInterface|ValidatorInterface|string $definition | |
* @return $this | |
* @throws NotFound | |
*/ | |
public function addFilterOrValidator($definition) | |
{ | |
if ($definition instanceof FilterInterface) { | |
$this->addFilter($definition); | |
} elseif ($definition instanceof ValidatorInterface) { | |
$this->addValidator($definition); | |
} elseif (is_callable($definition) && !is_string($definition)) { | |
$this->addValidator($definition); | |
} else { | |
try { | |
$this->addFilter($definition); | |
} catch (FilterNotFound $exception) { | |
try { | |
$this->addValidator($definition); | |
} catch (ValidatorNotFound $exception) { | |
throw new NotFound(sprintf( | |
'No filter or validator named \'%s\' found', | |
$exception->getValidator() | |
)); | |
} | |
} | |
} | |
return $this; | |
} | |
/** | |
* Filter $value with predefined filters | |
* | |
* Some filters may need context pass it with $context. | |
* | |
* @param mixed $value | |
* @param array $context | |
* @return mixed | |
*/ | |
public function filter($value, array $context = []) | |
{ | |
try { | |
$hash = md5(serialize([$value, $context])); | |
if (isset($this->filterCache[$hash])) { | |
return $this->filterCache[$hash]; | |
} | |
} catch (\Exception $exception) { | |
} | |
$this->filterFailed = false; | |
foreach ($this->filters as $filter) { | |
try { | |
$value = $filter->filter($value, $context); | |
} catch (InvalidValue $e) { | |
$this->filterFailed = true; | |
$this->errors = $e->errors; | |
break; | |
} | |
} | |
if (isset($hash)) { | |
$this->filterCache[$hash] = $value; | |
} | |
return $value; | |
} | |
/** | |
* Validate $value with predefined validators | |
* | |
* Some validators may need context pass it with $context. | |
* | |
* @param mixed $value | |
* @param array $context | |
* @return bool | |
*/ | |
public function validate($value, array $context = []) | |
{ | |
$filtered = $this->filter($value, $context); | |
if ($this->filterFailed) { | |
return false; | |
} | |
try { | |
$hash = md5(serialize([$filtered, $context])); | |
if (isset($this->validationCache[$hash])) { | |
return $this->validationCache[$hash]; | |
} | |
} catch (\Exception $exception) { | |
// we catch the exception when the value or context can not be serialized | |
} | |
$valid = true; | |
$this->errors = []; | |
foreach ($this->validators as $validator) { | |
if (!$validator->validate($filtered, $context)) { | |
$valid = false; | |
if ($error = $validator->getError()) { | |
$this->errors[] = $error; | |
} | |
} | |
} | |
if (isset($hash)) { | |
$this->validationCache[$hash] = $valid; | |
} | |
return $valid; | |
} | |
/** | |
* @return Error[] | |
*/ | |
public function getErrors() | |
{ | |
return $this->errors; | |
} | |
} |