/** * Run validator to validate column * * A validator could be: * 1. a ValidationKit validator, * 2. a closure * 3. a function name * * The validation result must be returned as in following format: * * boolean (valid or invalid, true or false) * * array( boolean valid , string message ) * * ValidationKit\ValidationMessage object. * * This method returns * * (object) { * valid: boolean valid or invalid * field: string field name * message: * } */ protected function _validateColumn(RuntimeColumn $column, $val, array $args) { // check for requried columns if ($column->required && ($val === '' || $val === NULL)) { return array('valid' => false, 'message' => sprintf(_('Field %s is required.'), $column->getLabel()), 'field' => $column->name); } // XXX: migrate this method to runtime column if ($validator = $column->validator) { if (is_callable($validator)) { $ret = call_user_func($validator, $val, $args, $this); if (is_bool($ret)) { return array('valid' => $ret, 'message' => 'Validation failed.', 'field' => $column->name); } elseif (is_array($ret)) { return array('valid' => $ret[0], 'message' => $ret[1], 'field' => $column->name); } else { throw new Exception('Wrong validation result format, Please returns (valid,message) or (valid)'); } } else { if (is_string($validator) && is_a($validator, 'ValidationKit\\Validator', true)) { // it's a ValidationKit\Validator $validator = $column->validatorArgs ? new $validator($column->get('validatorArgs')) : new $validator(); $ret = $validator->validate($val); $msgs = $validator->getMessages(); $msg = isset($msgs[0]) ? $msgs[0] : 'Validation failed.'; return array('valid' => $ret, 'message' => $msg, 'field' => $column->name); } else { throw new Exception("Unsupported validator"); } } } if ($val && $column->validValues) { if ($validValues = $column->getValidValues($this, $args)) { // sort by index if (isset($validValues[0]) && !in_array($val, $validValues)) { return array('valid' => false, 'message' => sprintf("%s is not a valid value for %s", $val, $column->name), 'field' => $column->name); } else { $values = array_values($validValues); foreach ($values as &$v) { if (is_array($v)) { $v = array_values($v); } } if (!in_array($val, $values)) { return array('valid' => false, 'message' => sprintf(_("%s is not a valid value for %s"), $val, $column->name), 'field' => $column->name); } } } } }
/** * Translate LazyRecord RuntimeColumn to ActionKit param object. * * @param RuntimeColumn $column * @param BaseModel $record * @return Param; */ public static function toParam(RuntimeColumn $column, BaseModel $record = null, Action $action = null) { $name = $column->name; $param = new Param($name, $action); if ($column->isa) { $param->isa($column->isa); } // Convert notNull to required // required() is basically the same as notNull but provides extra // software validation. // When creating records, the primary key with auto-increment support is not required. // However when updating records, the primary key is required for updating the existing record.. if ($column->notNull) { if ($action && $column->primary) { if ($action instanceof CreateRecordAction) { // autoIncrement is not defined, then it requires the input value. if ($column->autoIncrement) { $param->required = false; } else { $param->required = true; } } else { if ($action instanceof UpdateRecordAction || $action instanceof DeleteRecordAction) { // primary key column is required to update/delete records. $param->required = true; } } } else { $param->required = true; } } foreach ($column->attributes as $k => $v) { // if the model column validator is not compatible with action validator if ($k === 'validator' || $v instanceof Raw) { continue; } $param->{$k} = $v; } // if we got record, load the value from it. if ($record) { // $val = $record->{$name}; // $val = $val instanceof BaseModel ? $val->dataKeyValue() : $val; $val = $record->getValue($name); $param->value = $val; // XXX: should get default value (from column definition) // default value is only used in create action. } else { $default = $column->getDefaultValue(); if (!$default instanceof Raw) { $param->value = $default; } } // convert related collection model to validValues if ($param->refer && !$param->validValues) { if (class_exists($param->refer, true)) { $referClass = $param->refer; // it's a `has many`-like relationship if (is_subclass_of($referClass, 'LazyRecord\\BaseCollection', true)) { $collection = new $referClass(); $options = array(); foreach ($collection as $item) { $label = method_exists($item, 'dataLabel') ? $item->dataLabel() : $item->id; $options[$label] = $item->dataKeyValue(); } $param->validValues = $options; } elseif (is_subclass_of($referClass, 'LazyRecord\\BaseModel', true)) { // it's a `belongs-to`-like relationship $class = $referClass . 'Collection'; $collection = new $class(); $options = array(); foreach ($collection as $item) { $label = method_exists($item, 'dataLabel') ? $item->dataLabel() : $item->id; $options[$label] = $item->dataKeyValue(); } $param->validValues = $options; } elseif (is_subclass_of($referClass, 'LazyRecord\\Schema\\DeclareSchema', true)) { $schema = new $referClass(); $collection = $schema->newCollection(); $options = array(); foreach ($collection as $item) { $label = method_exists($item, 'dataLabel') ? $item->dataLabel() : $item->id; $options[$label] = $item->dataKeyValue(); } $param->validValues = $options; } else { throw new Exception('Unsupported refer type'); } } elseif ($relation = $record->getSchema()->getRelation($param->refer)) { // so it's a relationship reference // TODO: implement this throw new Exception('Unsupported refer type'); } } // Convert column type to param type. // copy widget attributes if ($column->widgetClass) { $param->widgetClass = $column->widgetClass; } if ($column->widgetAttributes) { $param->widgetAttributes = $column->widgetAttributes; } if ($column->immutable) { $param->widgetAttributes['readonly'] = 'readonly'; } if ($column->renderAs) { $param->renderAs($column->renderAs); } elseif ($param->validValues || $param->validPairs || $param->optionValues) { $param->renderAs('SelectInput'); } elseif ($param->name === 'id') { $param->renderAs('HiddenInput'); } else { // guess input widget from data type $typeMapping = array('date' => 'DateInput', 'datetime' => 'DateTimeInput', 'text' => 'TextareaInput'); if (isset($typeMapping[$param->type])) { $param->renderAs($typeMapping[$param->type]); } else { $param->renderAs('TextInput'); } } return $param; }