'asko@bien.ee']; * $rules = ['email' => 'required|email']; * $hird = new Hird($fields, $rules); * * if ($hird->fails()) { * return $hird->errors(); * } * ``` * * @author Asko Nomm */ class Hird { private array $errors = []; private array $validators = []; public function __construct( private array $fields, private array $rules, ) { $this->registerDefaultValidators(); } /** * Registers the default, built-in validators. * * @return void */ private function registerDefaultValidators(): void { $this->registerValidator('len', (new LenValidator)); $this->registerValidator('email', (new EmailValidator)); $this->registerValidator('required', (new RequiredValidator)); } /** * Registers a validator to a `$ruleName`. * * @param string $ruleName * @param Validator $validator * @return void */ public function registerValidator(string $ruleName, Validator $validator): void { $this->validators[$ruleName] = $validator; } /** * Removes a validator assigned to the `$ruleName`. * * @param string $ruleName * @return void */ public function removeValidator(string $ruleName): void { unset($this->validators[$ruleName]); } /** * Runs `$this->rules` over `$this->fields` to construct * potential errors that will be stored as an array of strings * in `$this->errors`. * * @return void */ public function validate(): void { foreach ($this->rules as $field => $rule) { $value = isset($this->fields[$field]) ? $this->fields[$field] : ''; foreach (explode('|', $rule) as $item) { if (str_contains($item, ':')) { $itemParts = explode(':', $item); $name = $itemParts[0]; $modifier = implode(':', array_slice($itemParts, 1, count($itemParts) - 1, true)); if (!$this->validators[$name]->validate($field, $value, $modifier)) { $this->errors[] = $this->validators[$name]->composeError($field, $modifier); } } else { if (!$this->validators[$item]->validate($field, $value)) { $this->errors[] = $this->validators[$item]->composeError($field); } } } } } /** * Returns a boolean `true` if there have been any errors. * Returns `false` otherwise. * * @return boolean */ public function fails(): bool { $this->validate(); return count($this->errors) !== 0; } /** * Returns an array of strings where each string * is a single error that happened during validation. * * @return array */ public function errors(): array { return $this->errors; } /** * If errors are present, returns the first one. * Otherwise returns an empty string. * * @return string */ public function firstError(): string { if (count($this->errors) > 0) { return $this->errors[0]; } return ''; } }