This repository has been archived on 2021-04-26. You can view files and clone it, but cannot push or open issues or pull requests.
gallery3-debian/modules/forge/libraries/Form_Input.php

555 lines
10 KiB
PHP

<?php defined("SYSPATH") or die("No direct script access.");
/**
* FORGE base input library.
*
* $Id: Form_Input.php 3326 2008-08-09 21:24:30Z Shadowhand $
*
* @package Forge
* @author Kohana Team
* @copyright (c) 2007-2008 Kohana Team
* @license http://kohanaphp.com/license.html
*/
class Form_Input_Core {
// 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;
}
/**
* Sets form attributes, or return rules.
*/
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 object
*/
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 object
*/
public function callback($callback)
{
if ( ! in_array($callback, $this->callbacks, TRUE))
{
$this->callbacks[] = $callback;
}
return $this;
}
/**
* Sets or returns the input label.
*
* @chainable
* @param string label to set
* @return string|object
*/
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
{
$this->data['label'] = ($val === TRUE) ? utf8::ucwords(inflector::humanize($this->name)) : $val;
return $this;
}
}
/**
* Set or return the error message.
*
* @chainable
* @param string error message
* @return strong|object
*/
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 render()
{
// 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']);
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 ? mb_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 = 'validation.'.$func;
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[] = 'validation.'.$func;
$error = 'validation.valid_type';
break;
default:
$error = 'validation.'.$func;
}
}
}
// Add error to list
$messages[] = $error;
}
return $messages;
}
/**
* Get the global input value.
*
* @return string|bool
*/
protected function input_value($name = array())
{
// Get the Input instance
$input = Input::instance();
// Fetch the method for this object
$method = $this->method;
return $input->$method($name, NULL);
}
/**
* 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->label ? mb_strtolower($input->label) : $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);
}
/**
* Validate required.
*/
protected function rule_required()
{
if ($this->value === '' OR $this->value === NULL)
{
$this->errors['required'] = TRUE;
}
}
/**
* Validate length.
*/
protected function rule_length($min, $max = NULL)
{
// Get the length, return if zero
if (($length = mb_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