/WDB/Validation/ColumnValidator.php
https://bitbucket.org/rejem/wheeldb · PHP · 168 lines · 119 code · 10 blank · 39 comment · 27 complexity · 8cab131ec62913ada426fc5cd95d7514 MD5 · raw file
- <?php
- namespace WDB\Validation;
- use WDB,
- WDB\Exception;
- /**
- * @property-read ColumnValidationError[] $errors
- * @author Richard Ejem <richard(at)ejem.cz>
- * @package WDB
- */
- final class ColumnValidator implements iValidator
- {
- /**@var array*/
- private $errors;
- //WDB\Event\iEventListener implementation
- /**
- * Validate passed record.
- *
- * @param WDB\Wrapper\Record $record
- * @return bool
- * @throws WDB\Exception\BadArgument
- */
- public function raise(WDB\Wrapper\iRecord $record = NULL)
- {
- if ($record === NULL) throw new Exception\BadArgument("Validator event raise() method needs"
- . " WDB\Wrapper\iRecord as a raise argument");
- $this->errors = array();
- foreach ($record->getTable()->getColumns() as $column)
- {
- $this->validateColumn($column, $record);
- }
- $record->addValidationErrors($this->errors);
- return $this->success();
- }
- //WDB\Event\iEventListener end
- /**
- * Returns true if last validation was successful.
- *
- * @return bool
- */
- public function success()
- {
- return count($this->errors) == 0;
- }
- //TODO create structure for errors
- /**
- * Returns list of validation errors occured
- *
- * @return array
- */
- public function getErrors()
- {
- return $this->errors;
- }
- //iValidator implementation
- public function fetchValidatorData(WDB\Wrapper\iRecord $record, &$data)
- {
- $columns = $record->getTable()->getColumns();
- foreach ($data['columns'] as $key=>&$c)
- {
- if (isset($columns[$key]) && $columns[$key]->getRules() !== NULL)
- {
- $c['ColumnValidator'] = $columns[$key]->getRules()->toArray();
- }
- }
- }
- //iValidator end
- /**
- * If condition is false, adds a message to this->errors based on currently validated column and rule.
- *
- * @param bool $condition
- */
- private function assert(WDB\Wrapper\iColumn $column, $rule, WDB\Wrapper\Field $field, $condition)
- {
- if (!$condition)
- {
- $rules = $column->getRules();
- $err = $rules[$rule]['message'];
- $this->errors[] = array('message'=>$err, 'column'=>$column);
- $field->addValidationError($err);
- }
- }
- /**
- * Validates current column by class private variables (column, field).
- *
- * @throws WDB\Exception\BadArgument
- */
- private function validateColumn(WDB\Wrapper\iColumn $column, WDB\Wrapper\iRecord $record)
- {
- $value = $record[$column->getName()];
- $columns = $record->getTable()->getColumns();
- $c = $column;
- $f = $record->getField($column->getName());
- //column is empty and not required - skip some validation
- if ($value === NULL && empty($column->rules[ColumnRules::REQUIRED])) return;
- $isEmpty = (($value === NULL || $value === '') && empty($column->rules[ColumnRules::REQUIRED]));
- foreach ($column->rules as $id=>$rule)
- {
- $r = $id;
- $special = FALSE;
- if (is_array($value) || is_object($value))
- {
- $special = TRUE;
- if (!in_array($id, array(ColumnRules::REQUIRED, ColumnRules::EQUALTO, ColumnRules::CALLBACK))) continue;
- }
- switch ($id)
- {
- case ColumnRules::REQUIRED:
- $this->assert($c,$r,$f,($value !== '' && $value !== NULL && $value !== FALSE && $value !== array()));
- break;
- case ColumnRules::INTEGER:
- $this->assert($c,$r,$f,preg_match('~[+-]?[0-9]+~', trim($value)));
- break;
- case ColumnRules::FLOAT:
- $this->assert($c,$r,$f,is_numeric(trim($value)));
- break;
- case ColumnRules::MINLENGTH:
- $this->assert($c,$r,$f,strlen($value) >= $rule['argument']);
- break;
- case ColumnRules::MAXLENGTH:
- $this->assert($c,$r,$f,strlen($value) <= $rule['argument']);
- break;
- case ColumnRules::MINVALUE:
- $this->assert($c,$r,$f,is_numeric($value) && bccomp($value, $rule['argument']) >= 0);
- break;
- case ColumnRules::MAXVALUE:
- $this->assert($c,$r,$f,is_numeric($value) && bccomp($value, $rule['argument']) <= 0);
- break;
- case ColumnRules::PATTERN:
- $this->assert($c,$r,$f,$isEmpty || preg_match($rule['argument'], $value));
- break;
- case ColumnRules::EQUALTO:
- if (!isset($record[$rule['argument']]))
- {
- throw new Exception\BadArgument("field {$rule['argument']} tested for equality with {$column->getName()} was not found");
- }
- $this->assert($c,$r,$f,$value == $record[$rule['argument']]);
- break;
- case ColumnRules::CALLBACK:
- if (!$rule['argument'] instanceof WDB\Utils\Caller && !is_callable($rule['argument']))
- {
- throw new Exception\BadArgument("Validation rule with custom callback need the callback to be an instance of \WDB\Utils\Caller");
- }
- if ($rule['argument'] instanceof WDB\Utils\Caller)
- {
- $rule['argument']->arguments['value'] = $value;
- $this->assert($c,$r,$f,$isEmpty || $rule['argument']($value));
- }
- else
- {
- $this->assert($c,$r,$f,$isEmpty || call_user_func($rule['argument'], $value));
- }
- break;
- default:
- throw new Exception\BadArgument("unknown validation rule #$id");
- }
- }
- }
- }