Projekt

Obecné

Profil

Stáhnout (13.9 KB) Statistiky
| Větev: | Tag: | Revize:
<?php defined('SYSPATH') or die('No direct script access.');
/**
* FORGE base input library.
*
* $Id: Form_Input.php 1923 2008-02-05 14:49:08Z Shadowhand $
*
* @package Forge
* @author Kohana Team
* @copyright (c) 2007-2008 Kohana Team
* @license http://kohanaphp.com/license.html
*
* @method Form_Input rules(string $rules)
* @method Form_Input name(string $name)
* @method Form_Input type(string $type)
* @method Form_Input class(string $class)
* @method Form_Input value(string $value)
*/
class Form_Input
{

// Input method
public $method;
// Element data
protected $data = array
(
'type' => 'text',
'class' => 'textbox',
'value' => ''
);
// Protected data keys
protected $protect = array();
// Validation rules, matches, and callbacks
protected $rules = array();
protected $matches = array();
protected $callbacks = array();
// Validation check
protected $is_valid;
// Errors
protected $errors = array();
protected $error_messages = array();

/**
* Sets the input element name.
*/
public function __construct($name)
{
$this->data['name'] = $name;
$this->data['label'] = __(utf8::ucfirst(inflector::humanize($name))).':';
}

/**
* Sets form attributes, or return rules.
*
* @return Form_Input
*/
public function __call($method, $args)
{
if ($method == 'rules')
{
if (empty($args))
return $this->rules;

// Set rules and action
$rules = $args[0];
$action = substr($rules, 0, 1);

if (in_array($action, array('-', '+', '=')))
{
// Remove the action from the rules
$rules = substr($rules, 1);
}
else
{
// Default action is append
$action = '';
}

$this->add_rules(explode('|', $rules), $action);
}
elseif ($method == 'name')
{
// Do nothing. The name should stay static once it is set.
}
else
{
$this->data[$method] = $args[0];
}

return $this;
}

/**
* Returns form attributes.
*
* @param string attribute name
* @return string
*/
public function __get($key)
{
if (isset($this->data[$key]))
{
return $this->data[$key];
}
}

/**
* Sets a form element that this element must match the value of.
*
* @chainable
* @param object another Forge input
* @return Form_Input
*/
public function matches($input)
{
if (!in_array($input, $this->matches, TRUE))
{
$this->matches[] = $input;
}

return $this;
}

/**
* Sets a callback method as a rule for this input.
*
* @chainable
* @param callback
* @return Form_Input
*/
public function callback($callback)
{
if (!in_array($callback, $this->callbacks, TRUE))
{
$this->callbacks[] = $callback;
}

return $this;
}

/**
* Sets name
*
* @param mixed $val
* @return Form_Input
*/
public function name($val = NULL)
{
if ($val === NULL)
{
return $this->data['name'];
}
else
{
$this->data['name'] = $val;
return $this;
}
}

/**
* Sets or returns the input label.
*
* @chainable
* @param string label to set
* @return Form_Input
*/
public function label($val = NULL)
{
if ($val === NULL)
{
if (isset($this->data['name']) AND isset($this->data['label']))
{
return form::label($this->data['name'], $this->data['label']);
}
return FALSE;
}
else
{
if ($val === TRUE)
{
$this->data['label'] = utf8::ucwords(inflector::humanize($this->name));
}
else if (!preg_match('/<.*>/', $val))
{
$val = __($val);
if (!($this instanceof Form_Checkbox) &&
strstr($val, ':') === FALSE)
{
$val .= ':';
}
$this->data['label'] = $val;
}
else
{
$this->data['label'] = $val;
}
return $this;
}
}

/**
* Sets help
*
* @param string $val
* @return Form_Input
*/
public function help($val = NULL)
{
if ($val === NULL)
{
if (isset($this->data['help']))
return $this->data['help'];
}
else
{
// is there any HTML tag in label?
if (!preg_match('/<.*>/', $val))
{ // no => than translate!
$val = help::hint($val);
}
$this->data['help'] = $val;
return $this;
}
}

/**
* Sets script
*
* @param string $type
* @param string $val
* @return Form_Input
*/
public function script($type, $val = NULL)
{
if ($val === NULL)
{
if (isset($this->data[$type]))
return $this->data[$type];
}
else
{
$this->data[$type] = $val;
return $this;
}
}

/**
* Set or return the error message.
*
* @chainable
* @param string error message
* @return Form_Input
*/
public function message($val = NULL)
{
if ($val === NULL)
{
if (isset($this->data['message']))
return $this->data['message'];
}
else
{
$this->data['message'] = $val;
return $this;
}
}

/**
* Runs validation and returns the element HTML.
*
* @return string
*/
public function html()
{
// Make sure validation runs
$this->validate();

return $this->html_element();
}

/**
* Returns the form input HTML.
*
* @return string
*/
protected function html_element()
{
$data = $this->data;

unset($data['label']);
unset($data['message']);
unset($data['help']);
unset($data['autocomplete']);

// array with aliases of validation function
$alias = array('numeric' => 'number');

// convert to array
$data['class'] = array($data['class']);

foreach ($this->rules as $rule)
{
if ($rule == 'required')
$data['class'][] = 'required';
else if (substr($rule, 0, 6) == 'valid_')
{
$arr = explode('_', $rule);
array_shift($arr);
$rule = implode('_', $arr);

$rule = (isset($alias[$rule])) ? $alias[$rule] : $rule;

$data['class'][] = $rule;
}
else
{
if (preg_match("/length\[([0-9]+),([0-9]+)\]/", $rule, $matches))
{
$data['minlength'] = $matches[1];
$data['maxlength'] = $matches[2];
}
}
}

foreach ($this->callbacks as $callback)
{
$callback = $callback[1];
if (substr($callback, 0, 6) == 'valid_')
{
$arr = explode('_', $callback);
array_shift($arr);
$callback = implode('_', $arr);

$callback = (isset($alias[$callback])) ? $alias[$callback] : $callback;

$data['class'][] = $callback;
}
}

$data['class'] = implode(' ', $data['class']);

return form::input($data);
}

/**
* Replace, remove, or append rules.
*
* @param array rules to change
* @param string action to use: replace, remove, append
*/
protected function add_rules(array $rules, $action)
{
if ($action === '=')
{
// Just replace the rules
$this->rules = $rules;
return;
}

foreach ($rules as $rule)
{
if ($action === '-')
{
if (($key = array_search($rule, $this->rules)) !== FALSE)
{
// Remove the rule
unset($this->rules[$key]);
}
}
else
{
if (!in_array($rule, $this->rules))
{
if ($action == '+')
{
array_unshift($this->rules, $rule);
}
else
{
$this->rules[] = $rule;
}
}
}
}
}

/**
* Add an error to the input.
*
* @chainable
* @return object
*/
public function add_error($key, $val)
{
if (!isset($this->errors[$key]))
{
$this->errors[$key] = $val;
}

return $this;
}

/**
* Set or return the error messages.
*
* @chainable
* @param string|array failed validation function, or an array of messages
* @param string error message
* @return object|array
*/
public function error_messages($func = NULL, $message = NULL)
{
// Set custom error messages
if (!empty($func))
{
if (is_array($func))
{
// Replace all
$this->error_messages = $func;
}
else
{
if (empty($message))
{
// Single error, replaces all others
$this->error_messages = $func;
}
else
{
// Add custom error
$this->error_messages[$func] = $message;
}
}
return $this;
}

// Make sure validation runs
is_null($this->is_valid) and $this->validate();

// Return single error
if (!is_array($this->error_messages) AND !empty($this->errors))
return array($this->error_messages);

$messages = array();
foreach ($this->errors as $func => $args)
{
if (is_string($args))
{
$error = $args;
}
else
{
// Force args to be an array
$args = is_array($args) ? $args : array();

// Add the label or name to the beginning of the args
array_unshift($args, $this->label ? utf8::strtolower($this->label) : $this->name);

if (isset($this->error_messages[$func]))
{
// Use custom error message
$error = vsprintf($this->error_messages[$func], $args);
}
else
{
// Get the proper i18n entry, very hacky but it works
switch ($func)
{
case 'valid_url':
case 'valid_email':
case 'valid_ip':
// Fetch an i18n error message
$error = Kohana::lang('validation.' . $func, $args);
break;
case 'valid_suffix':
$error = Kohana::lang('validation.valid_suffix', $args);
break;
case substr($func, 0, 6) === 'valid_':
// Strip 'valid_' from func name
$func = (substr($func, 0, 6) === 'valid_') ? substr($func, 6) : $func;
case 'alpha':
case 'alpha_dash':
case 'digit':
case 'numeric':
// i18n strings have to be inserted into valid_type
$args[] = Kohana::lang('validation.' . $func);
$error = Kohana::lang('validation.valid_type', $args);
break;
default:
$error = Kohana::lang('validation.' . $func, $args);
}
}
}

// Add error to list
$messages[] = $error;
}

return $messages;
}

/**
* Get the global input value.
*
* @return string|bool
*/
protected function input_value()
{
static $input, $method;

if ($input === NULL)
{
// Load the Input library
$input = new Input;
}

// Fetch the method for this object
$method = $this->method;

if (func_num_args() > 0)
{
$name = func_get_arg(0);

if (preg_match("/^([^\[]+)(\[([0-9]?)\])+$/", $name, $matches))
{
$name = $matches[1];
if ($matches[3] == '')
return $input->$method($name);
$value = $input->$method($name);
return (isset($value[$matches[3]])) ? $value[$matches[3]] : '';
}

return $input->$method($name);
}
else
return $input->$method();
}

/**
* Load the value of the input, if form data is present.
*
* @return void
*/
protected function load_value()
{
if (is_bool($this->is_valid))
return;

if ($name = $this->name)
{
// Load POSTed value, but only for named inputs
$this->data['value'] = $this->input_value($name);
}

if (is_string($this->data['value']))
{
// Trim string values
$this->data['value'] = trim($this->data['value']);
}
}

/**
* Validate this input based on the set rules.
*
* @return bool
*/
public function validate()
{
// Validation has already run
if (is_bool($this->is_valid))
return $this->is_valid;

// No data to validate
if ($this->input_value() == FALSE)
return $this->is_valid = FALSE;
// Load the submitted value
$this->load_value();
// No rules to validate
if (count($this->rules) == 0 AND count($this->matches) == 0 AND count($this->callbacks) == 0)
return $this->is_valid = TRUE;

if (!empty($this->rules))
{
foreach ($this->rules as $rule)
{
if (($offset = strpos($rule, '[')) !== FALSE)
{
// Get the args
$args = preg_split('/, ?/', trim(substr($rule, $offset), '[]'));

// Remove the args from the rule
$rule = substr($rule, 0, $offset);
}

if (substr($rule, 0, 6) === 'valid_' AND method_exists('valid', substr($rule, 6)))
{
$func = substr($rule, 6);

if ($this->value AND !valid::$func($this->value))
{
$this->errors[$rule] = TRUE;
}
}
elseif (method_exists($this, 'rule_' . $rule))
{
// The rule function is always prefixed with rule_
$rule = 'rule_' . $rule;

if (isset($args))
{
// Manually call up to 2 args for speed
switch (count($args))
{
case 1:
$this->$rule($args[0]);
break;
case 2:
$this->$rule($args[0], $args[1]);
break;
default:
call_user_func_array(array($this, $rule), $args);
break;
}
}
else
{
// Just call the rule
$this->$rule();
}

// Prevent args from being re-used
unset($args);
}
else
{
throw new Kohana_Exception('validation.invalid_rule', $rule);
}

// Stop when an error occurs
if (!empty($this->errors))
break;
}
}

if (!empty($this->matches))
{
foreach ($this->matches as $input)
{
if ($this->value != $input->value)
{
// Field does not match
$this->errors['matches'] = array($input->name);
break;
}
}
}

if (!empty($this->callbacks))
{
foreach ($this->callbacks as $callback)
{
call_user_func($callback, $this);

// Stop when an error occurs
if (!empty($this->errors))
break;
}
}

// If there are errors, validation failed
return $this->is_valid = empty($this->errors);
}

/**
* Chceck if value is GPS coordinate if it is not empty
*
* @author Ondřej Fibich
*/
protected function rule_gps()
{
if ($this->value)
{
if (preg_match("/^[0-9]+\.[0-9]+$/", strval($this->value)) == 0)
{
if (!gps::is_valid_degrees_coordinate(strval($this->value)))
{
$this->errors['gps'] = TRUE;
}
}
}
}

/**
* Validate required.
*/
protected function rule_required()
{
if ($this->value == FALSE)
{
$this->errors['required'] = TRUE;
}
}

/**
* Validate length.
*/
protected function rule_length($min, $max = NULL)
{
// Get the length, return if zero
if (($length = strlen($this->value)) === 0)
return;

if ($max == NULL)
{
if ($length != $min)
{
$this->errors['exact_length'] = array($min);
}
}
else
{
if ($length < $min)
{
$this->errors['min_length'] = array($min);
}
elseif ($length > $max)
{
$this->errors['max_length'] = array($max);
}
}
}

}

// End Form Input
(9-9/14)