public function validate(EntityInterface $entity, array $options = [])
{
$v = new \Valitron\Validator($entity->data());
// Run beforeValidate to know whether or not we can continue
if (false === $this->eventEmitter()->emit('beforeValidate', [$entity, $this, $v])) {
return false;
}
// Check validation rules on each feild
$uniqueWhere = [];
foreach ($this->fields() as $field => $fieldAttrs) {
// Required field
if (isset($fieldAttrs['required']) && true === $fieldAttrs['required'] || $fieldAttrs['primary'] === true && $fieldAttrs['autoincrement'] === false) {
$v->rule('required', $field);
}
// Unique field
if ($entity->isNew() && isset($fieldAttrs['unique']) && !empty($fieldAttrs['unique']) && $entity->{$field} !== null) {
if (is_string($fieldAttrs['unique'])) {
// Named group
$fieldKeyName = $fieldAttrs['unique'];
$uniqueWhere[$fieldKeyName][$field] = $entity->{$field};
} else {
$uniqueWhere[$field] = $entity->{$field};
}
}
// Run only if field required
if ($entity->{$field} !== null || $fieldAttrs['required'] === true) {
// Field with 'options'
if (isset($fieldAttrs['options']) && is_array($fieldAttrs['options'])) {
$v->rule('in', $field, $fieldAttrs['options']);
}
// Valitron validation rules
if (isset($fieldAttrs['validation']) && is_array($fieldAttrs['validation'])) {
foreach ($fieldAttrs['validation'] as $rule => $ruleName) {
$params = [];
if (is_string($rule)) {
$params = (array) $ruleName;
$ruleName = $rule;
}
$params = array_merge([$ruleName, $field], $params);
call_user_func_array([$v, 'rule'], $params);
}
}
}
}
// Unique validation
if (!empty($uniqueWhere)) {
foreach ($uniqueWhere as $field => $value) {
if (!is_array($value)) {
$value = [$field => $value];
}
$value = $this->convertToDatabaseValues($entity, $value);
if (!in_array(null, $value, true) && $this->first($value) !== false) {
$entity->error($field, "" . ucwords(str_replace('_', ' ', $field)) . " '" . implode('-', $value) . "' is already taken.");
}
}
}
if (!$v->validate()) {
$entity->errors($v->errors(), false);
}
//Relations validation
if (isset($options['relations']) && $options['relations'] === true) {
$this->validateRelations($entity);
}
// Run afterValidate to run additional/custom validations
if (false === $this->eventEmitter()->emit('afterValidate', [$entity, $this, $v])) {
return false;
}
// Return error result
return !$entity->hasErrors();
}