/horde-3.3.13/lib/Horde/Form.php
PHP | 4908 lines | 3112 code | 652 blank | 1144 comment | 469 complexity | f4355879d9388b0d21ca68251e904d7e MD5 | raw file
Possible License(s): LGPL-2.0
Large files files are truncated, but you can click here to view the full file
- <?php
- /**
- * @package Horde_Form
- */
- /** String */
- include_once 'Horde/String.php';
- /**
- * Horde_Form Master Class.
- *
- * The Horde_Form:: package provides form rendering, validation, and
- * other functionality for the Horde Application Framework.
- *
- * $Horde: framework/Form/Form.php,v 1.306.2.81 2012/02/03 15:17:31 jan Exp $
- *
- * Copyright 2001-2007 Robert E. Coyle <robertecoyle@hotmail.com>
- * Copyright 2001-2009 The Horde Project (http://www.horde.org/)
- *
- * See the enclosed file COPYING for license information (LGPL). If you
- * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
- *
- * @author Robert E. Coyle <robertecoyle@hotmail.com>
- * @author Chuck Hagenbuch <chuck@horde.org>
- * @since Horde 3.0
- * @package Horde_Form
- */
- class Horde_Form {
- var $_name = '';
- var $_title = '';
- var $_extra = '';
- var $_vars;
- var $_submit = array();
- var $_reset = false;
- var $_errors = array();
- var $_submitted = null;
- var $_sections = array();
- var $_open_section = null;
- var $_currentSection = array();
- var $_variables = array();
- var $_hiddenVariables = array();
- var $_useFormToken = true;
- var $_autofilled = false;
- var $_enctype = null;
- var $_help = false;
- function Horde_Form(&$vars, $title = '', $name = null)
- {
- if (empty($name)) {
- $name = String::lower(get_class($this));
- }
- $this->_vars = &$vars;
- $this->_title = $title;
- $this->_name = $name;
- }
- function __construct($vars, $title = '', $name = null)
- {
- $this->Horde_Form($vars, $title, $name);
- }
- function &singleton($form, &$vars, $title = '', $name = null)
- {
- static $instances = array();
- $signature = serialize(array($form, $vars, $title, $name));
- if (!isset($instances[$signature])) {
- if (class_exists($form)) {
- $instances[$signature] = new $form($vars, $title, $name);
- } else {
- $instances[$signature] = new Horde_Form($vars, $title, $name);
- }
- }
- return $instances[$signature];
- }
- function setVars(&$vars)
- {
- $this->_vars = &$vars;
- }
- function getTitle()
- {
- return $this->_title;
- }
- function setTitle($title)
- {
- $this->_title = $title;
- }
- function getExtra()
- {
- return $this->_extra;
- }
- function setExtra($extra)
- {
- $this->_extra = $extra;
- }
- function getName()
- {
- return $this->_name;
- }
- /**
- * Sets or gets whether the form should be verified by tokens.
- * Tokens are used to verify that a form is only submitted once.
- *
- * @param boolean $token If specified, sets whether to use form tokens.
- *
- * @return boolean Whether form tokens are being used.
- */
- function useToken($token = null)
- {
- if (!is_null($token)) {
- $this->_useFormToken = $token;
- }
- return $this->_useFormToken;
- }
- /**
- * Get the renderer for this form, either a custom renderer or the
- * standard one.
- *
- * To use a custom form renderer, your form class needs to
- * override this function:
- * <code>
- * function &getRenderer()
- * {
- * $r = new CustomFormRenderer();
- * return $r;
- * }
- * </code>
- *
- * ... where CustomFormRenderer is the classname of the custom
- * renderer class, which should extend Horde_Form_Renderer.
- *
- * @param array $params A hash of renderer-specific parameters.
- *
- * @return object Horde_Form_Renderer The form renderer.
- */
- function &getRenderer($params = array())
- {
- require_once 'Horde/Form/Renderer.php';
- $renderer = new Horde_Form_Renderer($params);
- return $renderer;
- }
- function &getType($type, $params = array())
- {
- $type_class = 'Horde_Form_Type_' . $type;
- if (!class_exists($type_class)) {
- require_once 'PEAR.php';
- Horde::fatal(PEAR::raiseError(sprintf('Nonexistant class "%s" for field type "%s"', $type_class, $type)), __FILE__, __LINE__);
- }
- $type_ob = new $type_class();
- if (!$params) {
- $params = array();
- }
- call_user_func_array(array(&$type_ob, 'init'), $params);
- return $type_ob;
- }
- function setSection($section = '', $desc = '', $image = '', $expanded = true)
- {
- $this->_currentSection = $section;
- if (!count($this->_sections) && !$this->getOpenSection()) {
- $this->setOpenSection($section);
- }
- $this->_sections[$section]['desc'] = $desc;
- $this->_sections[$section]['expanded'] = $expanded;
- $this->_sections[$section]['image'] = $image;
- }
- function getSectionDesc($section)
- {
- return $this->_sections[$section]['desc'];
- }
- function getSectionImage($section)
- {
- return $this->_sections[$section]['image'];
- }
- function setOpenSection($section)
- {
- $this->_vars->set('__formOpenSection', $section);
- }
- function getOpenSection()
- {
- return $this->_vars->get('__formOpenSection');
- }
- function getSectionExpandedState($section, $boolean = false)
- {
- if ($boolean) {
- /* Only the boolean value is required. */
- return $this->_sections[$section]['expanded'];
- }
- /* Need to return the values for use in styles. */
- if ($this->_sections[$section]['expanded']) {
- return 'block';
- } else {
- return 'none';
- }
- }
- /**
- * TODO
- */
- function &addVariable($humanName, $varName, $type, $required,
- $readonly = false, $description = null,
- $params = array())
- {
- return $this->insertVariableBefore(null, $humanName, $varName, $type,
- $required, $readonly, $description,
- $params);
- }
- /**
- * TODO
- */
- function &insertVariableBefore($before, $humanName, $varName, $type,
- $required, $readonly = false,
- $description = null, $params = array())
- {
- $type = &$this->getType($type, $params);
- $var = new Horde_Form_Variable($humanName, $varName, $type,
- $required, $readonly, $description);
- /* Set the form object reference in the var. */
- $var->setFormOb($this);
- if ($var->getTypeName() == 'enum' &&
- !strlen($type->getPrompt()) &&
- count($var->getValues()) == 1) {
- $vals = array_keys($var->getValues());
- $this->_vars->add($var->varName, $vals[0]);
- $var->_autofilled = true;
- } elseif ($var->getTypeName() == 'file' ||
- $var->getTypeName() == 'image') {
- $this->_enctype = 'multipart/form-data';
- }
- if (empty($this->_currentSection)) {
- $this->_currentSection = '__base';
- }
- if (is_null($before)) {
- $this->_variables[$this->_currentSection][] = &$var;
- } else {
- $num = 0;
- while (isset($this->_variables[$this->_currentSection][$num]) &&
- $this->_variables[$this->_currentSection][$num]->getVarName() != $before) {
- $num++;
- }
- if (!isset($this->_variables[$this->_currentSection][$num])) {
- $this->_variables[$this->_currentSection][] = &$var;
- } else {
- $this->_variables[$this->_currentSection] = array_merge(
- array_slice($this->_variables[$this->_currentSection], 0, $num),
- array(&$var),
- array_slice($this->_variables[$this->_currentSection], $num));
- }
- }
- return $var;
- }
- /**
- * Removes a variable from the form.
- *
- * As only variables can be passed by reference, you need to call this
- * method this way if want to pass a variable name:
- * <code>
- * $form->removeVariable($var = 'varname');
- * </code>
- *
- * @param Horde_Form_Variable|string $var Either the variable's name or
- * the variable to remove from the
- * form.
- *
- * @return boolean True if the variable was found (and deleted).
- */
- function removeVariable(&$var)
- {
- foreach (array_keys($this->_variables) as $section) {
- foreach (array_keys($this->_variables[$section]) as $i) {
- if ((is_a($var, 'Horde_Form_Variable') && $this->_variables[$section][$i] === $var) ||
- ($this->_variables[$section][$i]->getVarName() == $var)) {
- // Slice out the variable to be removed.
- $this->_variables[$this->_currentSection] = array_merge(
- array_slice($this->_variables[$this->_currentSection], 0, $i),
- array_slice($this->_variables[$this->_currentSection], $i + 1));
- return true;
- }
- }
- }
- return false;
- }
- /**
- * TODO
- */
- function &addHidden($humanName, $varName, $type, $required,
- $readonly = false, $description = null,
- $params = array())
- {
- $type = &$this->getType($type, $params);
- $var = new Horde_Form_Variable($humanName, $varName, $type,
- $required, $readonly, $description);
- $var->hide();
- $this->_hiddenVariables[] = &$var;
- return $var;
- }
- function &getVariables($flat = true, $withHidden = false)
- {
- if ($flat) {
- $vars = array();
- foreach ($this->_variables as $section) {
- foreach ($section as $var) {
- $vars[] = $var;
- }
- }
- if ($withHidden) {
- foreach ($this->_hiddenVariables as $var) {
- $vars[] = $var;
- }
- }
- return $vars;
- } else {
- return $this->_variables;
- }
- }
- function setButtons($submit, $reset = false)
- {
- if ($submit === true || is_null($submit) || empty($submit)) {
- /* Default to 'Submit'. */
- $submit = array(_("Submit"));
- } elseif (!is_array($submit)) {
- /* Default to array if not passed. */
- $submit = array($submit);
- }
- /* Only if $reset is strictly true insert default 'Reset'. */
- if ($reset === true) {
- $reset = _("Reset");
- }
- $this->_submit = $submit;
- $this->_reset = $reset;
- }
- function appendButtons($submit)
- {
- if (!is_array($submit)) {
- $submit = array($submit);
- }
- $this->_submit = array_merge($this->_submit, $submit);
- }
- function preserveVarByPost(&$vars, $varname, $alt_varname = '')
- {
- $value = $vars->getExists($varname, $wasset);
- /* If an alternate name is given under which to preserve use that. */
- if ($alt_varname) {
- $varname = $alt_varname;
- }
- if ($wasset) {
- $this->_preserveVarByPost($varname, $value);
- }
- }
- /**
- * @access private
- */
- function _preserveVarByPost($varname, $value)
- {
- if (is_array($value)) {
- foreach ($value as $id => $val) {
- $this->_preserveVarByPost($varname . '[' . $id . ']', $val);
- }
- } else {
- $varname = htmlspecialchars($varname);
- $value = htmlspecialchars($value);
- printf('<input type="hidden" name="%s" value="%s" />' . "\n",
- $varname,
- $value);
- }
- }
- function open(&$renderer, &$vars, $action, $method = 'get', $enctype = null)
- {
- if (is_null($enctype) && !is_null($this->_enctype)) {
- $enctype = $this->_enctype;
- }
- $renderer->open($action, $method, $this->_name, $enctype);
- $renderer->listFormVars($this);
- if (!empty($this->_name)) {
- $this->_preserveVarByPost('formname', $this->_name);
- }
- if ($this->_useFormToken) {
- require_once 'Horde/Token.php';
- $token = Horde_Token::generateId($this->_name);
- $_SESSION['horde_form_secrets'][$token] = true;
- $this->_preserveVarByPost($this->_name . '_formToken', $token);
- }
- /* Loop through vars and check for any special cases to preserve. */
- $variables = $this->getVariables();
- foreach ($variables as $var) {
- /* Preserve value if change has to be tracked. */
- if ($var->getOption('trackchange')) {
- $varname = $var->getVarName();
- $this->preserveVarByPost($vars, $varname, '__old_' . $varname);
- }
- }
- foreach ($this->_hiddenVariables as $var) {
- $this->preserveVarByPost($vars, $var->getVarName());
- }
- }
- function close($renderer)
- {
- $renderer->close();
- }
- /**
- * Renders the form for editing.
- *
- * @param Horde_Form_Renderer $renderer A renderer instance, optional
- * since Horde 3.2.
- * @param Variables $vars A Variables instance, optional
- * since Horde 3.2.
- * @param string $action The form action (url).
- * @param string $method The form method, usually either
- * 'get' or 'post'.
- * @param string $enctype The form encoding type. Determined
- * automatically if null.
- * @param boolean $focus Focus the first form field?
- */
- function renderActive($renderer = null, $vars = null, $action = '',
- $method = 'get', $enctype = null, $focus = true)
- {
- if (is_null($renderer)) {
- $renderer = $this->getRenderer();
- }
- if (is_null($vars)) {
- $vars = $this->_vars;
- }
- if (is_null($enctype) && !is_null($this->_enctype)) {
- $enctype = $this->_enctype;
- }
- $renderer->open($action, $method, $this->getName(), $enctype);
- $renderer->listFormVars($this);
- if (!empty($this->_name)) {
- $this->_preserveVarByPost('formname', $this->_name);
- }
- if ($this->_useFormToken) {
- require_once 'Horde/Token.php';
- $token = Horde_Token::generateId($this->_name);
- $_SESSION['horde_form_secrets'][$token] = true;
- $this->_preserveVarByPost($this->_name . '_formToken', $token);
- }
- if (count($this->_sections)) {
- $this->_preserveVarByPost('__formOpenSection', $this->getOpenSection());
- }
- /* Loop through vars and check for any special cases to
- * preserve. */
- $variables = $this->getVariables();
- foreach ($variables as $var) {
- /* Preserve value if change has to be tracked. */
- if ($var->getOption('trackchange')) {
- $varname = $var->getVarName();
- $this->preserveVarByPost($vars, $varname, '__old_' . $varname);
- }
- }
- foreach ($this->_hiddenVariables as $var) {
- $this->preserveVarByPost($vars, $var->getVarName());
- }
- $renderer->beginActive($this->getTitle(), $this->getExtra());
- $renderer->renderFormActive($this, $vars);
- $renderer->submit($this->_submit, $this->_reset);
- $renderer->end();
- $renderer->close($focus);
- }
- /**
- * Renders the form for displaying.
- *
- * @param Horde_Form_Renderer $renderer A renderer instance, optional
- * since Horde 3.2.
- * @param Variables $vars A Variables instance, optional
- * since Horde 3.2.
- */
- function renderInactive($renderer = null, $vars = null)
- {
- if (is_null($renderer)) {
- $renderer = $this->getRenderer();
- }
- if (is_null($vars)) {
- $vars = $this->_vars;
- }
- $renderer->_name = $this->_name;
- $renderer->beginInactive($this->getTitle(), $this->getExtra());
- $renderer->renderFormInactive($this, $vars);
- $renderer->end();
- }
- function preserve($vars)
- {
- if ($this->_useFormToken) {
- require_once 'Horde/Token.php';
- $token = Horde_Token::generateId($this->_name);
- $_SESSION['horde_form_secrets'][$token] = true;
- $this->_preserveVarByPost($this->_name . '_formToken', $token);
- }
- $variables = $this->getVariables();
- foreach ($variables as $var) {
- $varname = $var->getVarName();
- /* Save value of individual components. */
- switch ($var->getTypeName()) {
- case 'passwordconfirm':
- case 'emailconfirm':
- $this->preserveVarByPost($vars, $varname . '[original]');
- $this->preserveVarByPost($vars, $varname . '[confirm]');
- break;
- case 'monthyear':
- $this->preserveVarByPost($vars, $varname . '[month]');
- $this->preserveVarByPost($vars, $varname . '[year]');
- break;
- case 'monthdayyear':
- $this->preserveVarByPost($vars, $varname . '[month]');
- $this->preserveVarByPost($vars, $varname . '[day]');
- $this->preserveVarByPost($vars, $varname . '[year]');
- break;
- }
- $this->preserveVarByPost($vars, $varname);
- }
- foreach ($this->_hiddenVariables as $var) {
- $this->preserveVarByPost($vars, $var->getVarName());
- }
- }
- function unsetVars(&$vars)
- {
- foreach ($this->getVariables() as $var) {
- $vars->remove($var->getVarName());
- }
- }
- /**
- * Validates the form, checking if it really has been submitted by calling
- * isSubmitted() and if true does any onSubmit() calls for variable types
- * in the form. The _submitted variable is then rechecked.
- *
- * @param Variables $vars A Variables instance, optional since Horde
- * 3.2.
- * @param boolean $canAutofill Can the form be valid without being
- * submitted?
- *
- * @return boolean True if the form is valid.
- */
- function validate($vars = null, $canAutoFill = false)
- {
- if (is_null($vars)) {
- $vars = $this->_vars;
- }
- /* Get submitted status. */
- if ($this->isSubmitted() || $canAutoFill) {
- /* Form was submitted or can autofill; check for any variable
- * types' onSubmit(). */
- $this->onSubmit($vars);
- /* Recheck submitted status. */
- if (!$this->isSubmitted() && !$canAutoFill) {
- return false;
- }
- } else {
- /* Form has not been submitted; return false. */
- return false;
- }
- $message = '';
- $this->_autofilled = true;
- if ($this->_useFormToken) {
- global $conf;
- require_once 'Horde/Token.php';
- if (isset($conf['token'])) {
- /* If there is a configured token system, set it up. */
- $tokenSource = &Horde_Token::singleton($conf['token']['driver'], Horde::getDriverConfig('token', $conf['token']['driver']));
- } else {
- /* Default to the file system if no config. */
- $tokenSource = &Horde_Token::singleton('file');
- }
- $passedToken = $vars->get($this->_name . '_formToken');
- if (!empty($passedToken) && !$tokenSource->verify($passedToken)) {
- $this->_errors['_formToken'] = _("This form has already been processed.");
- }
- if (empty($_SESSION['horde_form_secrets'][$passedToken])) {
- $this->_errors['_formSecret'] = _("Required secret is invalid - potentially malicious request.");
- }
- }
- foreach ($this->getVariables() as $var) {
- $this->_autofilled = $var->_autofilled && $this->_autofilled;
- if (!$var->validate($vars, $message)) {
- $this->_errors[$var->getVarName()] = $message;
- }
- }
- if ($this->_autofilled) {
- unset($this->_errors['_formToken']);
- }
- foreach ($this->_hiddenVariables as $var) {
- if (!$var->validate($vars, $message)) {
- $this->_errors[$var->getVarName()] = $message;
- }
- }
- return $this->isValid();
- }
- function clearValidation()
- {
- $this->_errors = array();
- }
- function getError($var)
- {
- if (is_a($var, 'Horde_Form_Variable')) {
- $name = $var->getVarName();
- } else {
- $name = $var;
- }
- return isset($this->_errors[$name]) ? $this->_errors[$name] : null;
- }
- function setError($var, $message)
- {
- if (is_a($var, 'Horde_Form_Variable')) {
- $name = $var->getVarName();
- } else {
- $name = $var;
- }
- $this->_errors[$name] = $message;
- }
- function clearError($var)
- {
- if (is_a($var, 'Horde_Form_Variable')) {
- $name = $var->getVarName();
- } else {
- $name = $var;
- }
- unset($this->_errors[$name]);
- }
- function isValid()
- {
- return ($this->_autofilled || count($this->_errors) == 0);
- }
- function execute()
- {
- Horde::logMessage('Warning: Horde_Form::execute() called, should be overridden', __FILE__, __LINE__, PEAR_LOG_DEBUG);
- }
- /**
- * Fetch the field values of the submitted form.
- *
- * @param Variables $vars A Variables instance, optional since Horde 3.2.
- * @param array $info Array to be filled with the submitted field
- * values.
- */
- function getInfo($vars, &$info)
- {
- if (is_null($vars)) {
- $vars = $this->_vars;
- }
- $this->_getInfoFromVariables($this->getVariables(), $vars, $info);
- $this->_getInfoFromVariables($this->_hiddenVariables, $vars, $info);
- }
- /**
- * Fetch the field values from a given array of variables.
- *
- * @access private
- *
- * @param array $variables An array of Horde_Form_Variable objects to
- * fetch from.
- * @param object $vars The Variables object.
- * @param array $info The array to be filled with the submitted
- * field values.
- */
- function _getInfoFromVariables($variables, &$vars, &$info)
- {
- foreach ($variables as $var) {
- if ($var->isArrayVal()) {
- $var->getInfo($vars, $values);
- if (is_array($values)) {
- $varName = str_replace('[]', '', $var->getVarName());
- foreach ($values as $i => $val) {
- $info[$i][$varName] = $val;
- }
- }
- } else {
- require_once 'Horde/Array.php';
- if (Horde_Array::getArrayParts($var->getVarName(), $base, $keys)) {
- if (!isset($info[$base])) {
- $info[$base] = array();
- }
- $pointer = &$info[$base];
- while (count($keys)) {
- $key = array_shift($keys);
- if (!isset($pointer[$key])) {
- $pointer[$key] = array();
- }
- $pointer = &$pointer[$key];
- }
- $var->getInfo($vars, $pointer);
- } else {
- $var->getInfo($vars, $info[$var->getVarName()]);
- }
- }
- }
- }
- function hasHelp()
- {
- return $this->_help;
- }
- /**
- * Determines if this form has been submitted or not. If the class
- * var _submitted is null then it will check for the presence of
- * the formname in the form variables.
- *
- * Other events can explicitly set the _submitted variable to
- * false to indicate a form submit but not for actual posting of
- * data (eg. onChange events to update the display of fields).
- *
- * @return boolean True or false indicating if the form has been
- * submitted.
- */
- function isSubmitted()
- {
- if (is_null($this->_submitted)) {
- if ($this->_vars->get('formname') == $this->getName()) {
- $this->_submitted = true;
- } else {
- $this->_submitted = false;
- }
- }
- return $this->_submitted;
- }
- /**
- * Checks if there is anything to do on the submission of the form by
- * looping through each variable's onSubmit() function.
- *
- * @param Horde_Variables $vars
- */
- function onSubmit(&$vars)
- {
- /* Loop through all vars and check if there's anything to do on
- * submit. */
- $variables = $this->getVariables();
- foreach ($variables as $var) {
- $var->type->onSubmit($var, $vars);
- /* If changes to var being tracked don't register the form as
- * submitted if old value and new value differ. */
- if ($var->getOption('trackchange')) {
- $varname = $var->getVarName();
- if (!is_null($vars->get('formname')) &&
- $vars->get($varname) != $vars->get('__old_' . $varname)) {
- $this->_submitted = false;
- }
- }
- }
- }
- /**
- * Explicitly sets the state of the form submit.
- *
- * An event can override the automatic determination of the submit state
- * in the isSubmitted() function.
- *
- * @param boolean $state Whether to set the state of the form as being
- * submitted.
- */
- function setSubmitted($state = true)
- {
- $this->_submitted = $state;
- }
- }
- /**
- * Horde_Form_Type Class
- *
- * @author Robert E. Coyle <robertecoyle@hotmail.com>
- * @package Horde_Form
- */
- class Horde_Form_Type {
- function Horde_Form_Type()
- {
- }
- function getProperty($property)
- {
- $prop = '_' . $property;
- return isset($this->$prop) ? $this->$prop : null;
- }
- function __get($property)
- {
- return $this->getProperty($property);
- }
- function setProperty($property, $value)
- {
- $prop = '_' . $property;
- $this->$prop = $value;
- }
- function __set($property, $value)
- {
- return $this->setProperty($property, $value);
- }
- function init()
- {
- }
- function onSubmit()
- {
- }
- function isValid(&$var, &$vars, $value, &$message)
- {
- $message = '<strong>Error:</strong> Horde_Form_Type::isValid() called - should be overridden<br />';
- return false;
- }
- function getTypeName()
- {
- return str_replace('horde_form_type_', '', String::lower(get_class($this)));
- }
- function getValues()
- {
- return null;
- }
- function getInfo(&$vars, &$var, &$info)
- {
- $info = $var->getValue($vars);
- }
- }
- class Horde_Form_Type_spacer extends Horde_Form_Type {
- function isValid(&$var, &$vars, $value, &$message)
- {
- return true;
- }
- /**
- * Return info about field type.
- */
- function about()
- {
- return array('name' => _("Spacer"));
- }
- }
- class Horde_Form_Type_header extends Horde_Form_Type {
- function isValid(&$var, &$vars, $value, &$message)
- {
- return true;
- }
- /**
- * Return info about field type.
- */
- function about()
- {
- return array('name' => _("Header"));
- }
- }
- class Horde_Form_Type_description extends Horde_Form_Type {
- function isValid(&$var, &$vars, $value, &$message)
- {
- return true;
- }
- /**
- * Return info about field type.
- */
- function about()
- {
- return array('name' => _("Description"));
- }
- }
- /**
- * Simply renders its raw value in both active and inactive rendering.
- */
- class Horde_Form_Type_html extends Horde_Form_Type {
- function isValid(&$var, &$vars, $value, &$message)
- {
- return true;
- }
- /**
- * Return info about field type.
- */
- function about()
- {
- return array('name' => _("HTML"));
- }
- }
- class Horde_Form_Type_number extends Horde_Form_Type {
- var $_fraction;
- function init($fraction = null)
- {
- $this->_fraction = $fraction;
- }
- function isValid(&$var, &$vars, $value, &$message)
- {
- if ($var->isRequired() && empty($value) && ((string)(double)$value !== $value)) {
- $message = _("This field is required.");
- return false;
- } elseif (empty($value)) {
- return true;
- }
- /* If matched, then this is a correct numeric value. */
- if (preg_match($this->_getValidationPattern(), $value)) {
- return true;
- }
- $message = _("This field must be a valid number.");
- return false;
- }
- function _getValidationPattern()
- {
- static $pattern = '';
- if (!empty($pattern)) {
- return $pattern;
- }
- /* Get current locale information. */
- $linfo = NLS::getLocaleInfo();
- /* Build the pattern. */
- $pattern = '(-)?';
- /* Only check thousands separators if locale has any. */
- if (!empty($linfo['mon_thousands_sep'])) {
- /* Regex to check for correct thousands separators (if any). */
- $pattern .= '((\d+)|((\d{0,3}?)([' . $linfo['mon_thousands_sep'] . ']\d{3})*?))';
- } else {
- /* No locale thousands separator, check for only digits. */
- $pattern .= '(\d+)';
- }
- /* If no decimal point specified default to dot. */
- if (empty($linfo['mon_decimal_point'])) {
- $linfo['mon_decimal_point'] = '.';
- }
- /* Regex to check for correct decimals (if any). */
- if (empty($this->_fraction)) {
- $fraction = '*';
- } else {
- $fraction = '{0,' . $this->_fraction . '}';
- }
- $pattern .= '([' . $linfo['mon_decimal_point'] . '](\d' . $fraction . '))?';
- /* Put together the whole regex pattern. */
- $pattern = '/^' . $pattern . '$/';
- return $pattern;
- }
- function getInfo(&$vars, &$var, &$info)
- {
- $value = $vars->get($var->getVarName());
- $linfo = NLS::getLocaleInfo();
- $value = str_replace($linfo['mon_thousands_sep'], '', $value);
- $info = str_replace($linfo['mon_decimal_point'], '.', $value);
- }
- /**
- * Return info about field type.
- */
- function about()
- {
- return array('name' => _("Number"));
- }
- }
- class Horde_Form_Type_int extends Horde_Form_Type {
- function isValid(&$var, &$vars, $value, &$message)
- {
- if ($var->isRequired() && empty($value) && ((string)(int)$value !== $value)) {
- $message = _("This field is required.");
- return false;
- }
- if (empty($value) || preg_match('/^[0-9]+$/', $value)) {
- return true;
- }
- $message = _("This field may only contain integers.");
- return false;
- }
- /**
- * Return info about field type.
- */
- function about()
- {
- return array('name' => _("Integer"));
- }
- }
- class Horde_Form_Type_octal extends Horde_Form_Type {
- function isValid(&$var, &$vars, $value, &$message)
- {
- if ($var->isRequired() && empty($value) && ((string)(int)$value !== $value)) {
- $message = _("This field is required.");
- return false;
- }
- if (empty($value) || preg_match('/^[0-7]+$/', $value)) {
- return true;
- }
- $message = _("This field may only contain octal values.");
- return false;
- }
- /**
- * Return info about field type.
- */
- function about()
- {
- return array('name' => _("Octal"));
- }
- }
- class Horde_Form_Type_intlist extends Horde_Form_Type {
- function isValid(&$var, &$vars, $value, &$message)
- {
- if (empty($value) && $var->isRequired()) {
- $message = _("This field is required.");
- return false;
- }
- if (empty($value) || preg_match('/^[0-9 ,]+$/', $value)) {
- return true;
- }
- $message = _("This field must be a comma or space separated list of integers");
- return false;
- }
- /**
- * Return info about field type.
- */
- function about()
- {
- return array('name' => _("Integer list"));
- }
- }
- class Horde_Form_Type_text extends Horde_Form_Type {
- var $_regex;
- var $_size;
- var $_maxlength;
- /**
- * The initialisation function for the text variable type.
- *
- * @access private
- *
- * @param string $regex Any valid PHP PCRE pattern syntax that
- * needs to be matched for the field to be
- * considered valid. If left empty validity
- * will be checked only for required fields
- * whether they are empty or not.
- * If using this regex test it is advisable
- * to enter a description for this field to
- * warn the user what is expected, as the
- * generated error message is quite generic
- * and will not give any indication where
- * the regex failed.
- * @param integer $size The size of the input field.
- * @param integer $maxlength The max number of characters.
- */
- function init($regex = '', $size = 40, $maxlength = null)
- {
- $this->_regex = $regex;
- $this->_size = $size;
- $this->_maxlength = $maxlength;
- }
- function isValid(&$var, &$vars, $value, &$message)
- {
- $valid = true;
- if (!empty($this->_maxlength) && String::length($value) > $this->_maxlength) {
- $valid = false;
- $message = sprintf(_("Value is over the maximum length of %d."), $this->_maxlength);
- } elseif ($var->isRequired() && empty($this->_regex)) {
- $valid = strlen(trim($value)) > 0;
- if (!$valid) {
- $message = _("This field is required.");
- }
- } elseif (!empty($this->_regex)) {
- $valid = preg_match($this->_regex, $value);
- if (!$valid) {
- $message = _("You must enter a valid value.");
- }
- }
- return $valid;
- }
- function getSize()
- {
- return $this->_size;
- }
- function getMaxLength()
- {
- return $this->_maxlength;
- }
- /**
- * Return info about field type.
- */
- function about()
- {
- return array(
- 'name' => _("Text"),
- 'params' => array(
- 'regex' => array('label' => _("Regex"),
- 'type' => 'text'),
- 'size' => array('label' => _("Size"),
- 'type' => 'int'),
- 'maxlength' => array('label' => _("Maximum length"),
- 'type' => 'int')));
- }
- }
- class Horde_Form_Type_stringlist extends Horde_Form_Type_text {
- /**
- * Return info about field type.
- */
- function about()
- {
- return array(
- 'name' => _("String list"),
- 'params' => array(
- 'regex' => array('label' => _("Regex"),
- 'type' => 'text'),
- 'size' => array('label' => _("Size"),
- 'type' => 'int'),
- 'maxlength' => array('label' => _("Maximum length"),
- 'type' => 'int')),
- );
- }
- }
- /**
- * @since Horde 3.3
- */
- class Horde_Form_Type_stringarray extends Horde_Form_Type_stringlist {
- function getInfo(&$vars, &$var, &$info)
- {
- $info = array_map('trim', explode(',', $vars->get($var->getVarName())));
- }
- /**
- * Return info about field type.
- */
- function about()
- {
- return array(
- 'name' => _("String list returning an array"),
- 'params' => array(
- 'regex' => array('label' => _("Regex"),
- 'type' => 'text'),
- 'size' => array('label' => _("Size"),
- 'type' => 'int'),
- 'maxlength' => array('label' => _("Maximum length"),
- 'type' => 'int')),
- );
- }
- }
- /**
- * @since Horde 3.2
- */
- class Horde_Form_Type_phone extends Horde_Form_Type {
- function isValid(&$var, &$vars, $value, &$message)
- {
- if (!strlen(trim($value))) {
- if ($var->isRequired()) {
- $message = _("This field is required.");
- return false;
- }
- } elseif (!preg_match('/^\+?[\d()\-\/. ]*$/', $value)) {
- $message = _("You must enter a valid phone number, digits only with an optional '+' for the international dialing prefix.");
- return false;
- }
- return true;
- }
- /**
- * Return info about field type.
- */
- function about()
- {
- return array('name' => _("Phone number"));
- }
- }
- class Horde_Form_Type_cellphone extends Horde_Form_Type_phone {
- /**
- * Return info about field type.
- */
- function about()
- {
- return array('name' => _("Mobile phone number"));
- }
- }
- class Horde_Form_Type_ipaddress extends Horde_Form_Type_text {
- function isValid(&$var, &$vars, $value, &$message)
- {
- $valid = true;
- if (strlen(trim($value)) > 0) {
- $ip = explode('.', $value);
- $valid = (count($ip) == 4);
- if ($valid) {
- foreach ($ip as $part) {
- if (!is_numeric($part) ||
- $part > 255 ||
- $part < 0) {
- $valid = false;
- break;
- }
- }
- }
- if (!$valid) {
- $message = _("Please enter a valid IP address.");
- }
- } elseif ($var->isRequired()) {
- $valid = false;
- $message = _("This field is required.");
- }
- return $valid;
- }
- /**
- * Return info about field type.
- */
- function about()
- {
- return array('name' => _("IP address"));
- }
- }
- class Horde_Form_Type_longtext extends Horde_Form_Type_text {
- var $_rows;
- var $_cols;
- var $_helper = array();
- function init($rows = 8, $cols = 80, $helper = array())
- {
- if (!is_array($helper)) {
- $helper = array($helper);
- }
- $this->_rows = $rows;
- $this->_cols = $cols;
- $this->_helper = $helper;
- }
- function getRows()
- {
- return $this->_rows;
- }
- function getCols()
- {
- return $this->_cols;
- }
- function hasHelper($option = '')
- {
- if (empty($option)) {
- /* No option specified, check if any helpers have been
- * activated. */
- return !empty($this->_helper);
- } elseif (empty($this->_helper)) {
- /* No helpers activated at all, return false. */
- return false;
- } else {
- /* Check if given helper has been activated. */
- return in_array($option, $this->_helper);
- }
- }
- /**
- * Return info about field type.
- */
- function about()
- {
- return array(
- 'name' => _("Long text"),
- 'params' => array(
- 'rows' => array('label' => _("Number of rows"),
- 'type' => 'int'),
- 'cols' => array('label' => _("Number of columns"),
- 'type' => 'int'),
- 'helper' => array('label' => _("Helpers"),
- 'type' => 'stringarray')));
- }
- }
- class Horde_Form_Type_countedtext extends Horde_Form_Type_longtext {
- var $_chars;
- function init($rows = null, $cols = null, $chars = 1000)
- {
- parent::init($rows, $cols);
- $this->_chars = $chars;
- }
- function isValid(&$var, &$vars, $value, &$message)
- {
- $valid = true;
- $length = String::length(trim($value));
- if ($var->isRequired() && $length <= 0) {
- $valid = false;
- $message = _("This field is required.");
- } elseif ($length > $this->_chars) {
- $valid = false;
- $message = sprintf(ngettext("There are too many characters in this field. You have entered %d character; ", "There are too many characters in this field. You have entered %d characters; ", $length), $length)
- . sprintf(_("you must enter less than %d."), $this->_chars);
- }
- return $valid;
- }
- function getChars()
- {
- return $this->_chars;
- }
- /**
- * Return info about field type.
- */
- function about()
- {
- return array(
- 'name' => _("Counted text"),
- 'params' => array(
- 'rows' => array('label' => _("Number of rows"),
- 'type' => 'int'),
- 'cols' => array('label' => _("Number of columns"),
- 'type' => 'int'),
- 'chars' => array('label' => _("Number of characters"),
- 'type' => 'int')));
- }
- }
- class Horde_Form_Type_address extends Horde_Form_Type_longtext {
- function parse($address)
- {
- $info = array();
- $aus_state_regex = '(?:ACT|NSW|NT|QLD|SA|TAS|VIC|WA)';
- if (preg_match('/(?s)(.*?)(?-s)\r?\n(?:(.*?)\s+)?((?:A[BL]|B[ABDHLNRST]?|C[ABFHMORTVW]|D[ADEGHLNTY]|E[CHNX]?|F[KY]|G[LUY]?|H[ADGPRSUX]|I[GMPV]|JE|K[ATWY]|L[ADELNSU]?|M[EKL]?|N[EGNPRW]?|O[LX]|P[AEHLOR]|R[GHM]|S[AEGKLMNOPRSTWY]?|T[ADFNQRSW]|UB|W[ACDFNRSV]?|YO|ZE)\d(?:\d|[A-Z])? \d[A-Z]{2})/', $address, $addressParts)) {
- /* UK postcode detected. */
- $info = array('country' => 'uk', 'zip' => $addressParts[3]);
- if (!empty($addressParts[1])) {
- $info['street'] = $addressParts[1];
- }
- if (!empty($addressParts[2])) {
- $info['city'] = $addressParts[2];
- }
- } elseif (preg_match('/\b' . $aus_state_regex . '\b/', $address)) {
- /* Australian state detected. */
- /* Split out the address, line-by-line. */
- $addressLines = preg_split('/\r?\n/', $address);
- $info = array('country' => 'au');
- for ($i = 0; $i < count($addressLines); $i++) {
- /* See if it's the street number & name. */
- if (preg_match('/(\d+\s*\/\s*)?(\d+|\d+[a-zA-Z])\s+([a-zA-Z ]*)/', $addressLines[$i], $lineParts)) {
- $info['street'] = $addressLines[$i];
- $info['streetNumber'] = $lineParts[2];
- $info['streetName'] = $lineParts[3];
- }
- /* Look for "Suburb, State". */
- if (preg_match('/([a-zA-Z ]*),?\s+(' . $aus_state_regex . ')/', $addressLines[$i], $lineParts)) {
- $info['city'] = $lineParts[1];
- $info['state'] = $lineParts[2];
- }
- /* Look for "State <4 digit postcode>". */
- if (preg_match('/(' . $aus_state_regex . ')\s+(\d{4})/', $addressLines[$i], $lineParts)) {
- $info['state'] = $lineParts[1];
- $info['zip'] = $lineParts[2];
- }
- }
- } elseif (preg_match('/(?s)(.*?)(?-s)\r?\n(.*)\s*,\s*(\w+)\.?\s+(\d+|[a-zA-Z]\d[a-zA-Z]\s?\d[a-zA-Z]\d)/', $address, $addressParts)) {
- /* American/Canadian address style. */
- $info = array('country' => 'us');
- if (!empty($addressParts[4]) &&
- preg_match('|[a-zA-Z]\d[a-zA-Z]\s?\d[a-zA-Z]\d|', $addressParts[4])) {
- $info['country'] = 'ca';
- }
- if (!empty($addressParts[1])) {
- $info['street'] = $addressParts[1];
- }
- if (!empty($addressParts[2])) {
- $info['city'] = $addressParts[2];
- }
- if (!empty($addressParts[3])) {
- $info['state'] = $addressParts[3];
- }
- if (!empty($addressParts[4])) {
- $info['zip'] = $addressParts[4];
- }
- } elseif (preg_match('/(?:(?s)(.*?)(?-s)(?:\r?\n|,\s*))?(?:([A-Z]{1,3})-)?(\d{4,5})\s+(.*)(?:\r?\n(.*))?/i', $address, $addressParts)) {
- /* European address style. */
- $info = array();
- if (!empty($addressParts[1])) {
- $info['street'] = $addressParts[1];
- }
- if (!empty($addressParts[2])) {
- include 'Horde/NLS/carsigns.php';
- $country = array_search(String::upper($addressParts[2]), $carsigns);
- if ($country) {
- $info['country'] = $country;
- }
- }
- if (!empty($addressParts[5])) {
- include 'Horde/NLS/countries.php';
- $country = array_search($addressParts[5], $countries);
- if ($country) {
- $info['country'] = String::lower($country);
- } elseif (!isset($info['street'])) {
- $info['street'] = trim($addressParts[5]);
- } else {
- $info['street'] .= "\n" . $addressParts[5];
- }
- }
- if (!empty($addressParts[3])) {
- $info['zip'] = $addressParts[3];
- }
- if (!empty($addressParts[4])) {
- $info['city'] = trim($addressParts[4]);
- }
- }
- return $info;
- }
- /**
- * Return info about field type.
- */
- function about()
- {
- return array(
- 'name' => _("Address"),
- 'params' => array(
- 'rows' => array('label' => _("Number of rows"),
- 'type' => 'int'),
- 'cols' => array('label' => _("Number of columns"),
- 'type' => 'int')));
- }
- }
- class Horde_Form_Type_addresslink extends Horde_Form_Type_address {
- function isValid(&$var, &$vars, $value, &$message)
- {
- return true;
- }
- /**
- * Return info about field type.
- */
- function about()
- {
- return array('name' => _("Address Link"));
- }
- }
- /**
- * @since Horde 3.3
- */
- class Horde_Form_Type_pgp extends Horde_Form_Type_longtext {
- /**
- * Path to the GnuPG binary.
- *
- * @var string
- */
- var $_gpg;
- /**
- * A temporary directory.
- *
- * @var string
- */
- var $_temp;
- function init($gpg, $temp_dir = null, $rows = null, $cols = null)
- {
- $this->_gpg = $gpg;
- $this->_temp = $temp_dir;
- parent::init($rows, $cols);
- }
- /**
- * Returns a parameter hash for the Horde_Crypt_pgp constructor.
- *
- * @return array A parameter hash.
- */
- function getPGPParams()
- {
- return array('program' => $this->_gpg, 'temp' => $this->_temp);
- }
- /**
- * Return info about field type.
- */
- function about()
- {
- return array(
- 'name' => _("PGP Key"),
- 'params' => array(
- 'gpg' => array('label' => _("Path to the GnuPG binary"),
- 'type' => 'string'),
- 'temp_dir' => array('label' => _("A temporary directory"),
- 'type' => 'string'),
- 'rows' => array('label' => _("Number of rows"),
- 'type' => 'int'),
- 'cols' => array('label' => _("Number of columns"),
- 'type' => 'int')));
- }
- }
- /**
- * @since Horde 3.3
- */
- class Horde_Form_Type_smime extends Horde_Form_Type_longtext {
- /**
- * A temporary directory.
- *
- * @var string
- */
- var $_temp;
- function init($temp_dir = null, $rows = null, $cols = null)
- {
- $this->_temp = $temp_dir;
- parent::init($rows, $cols);
- }
- /**
- * Returns a parameter hash for the Horde_Crypt_smime constructor.
- *
- * @return array A parameter hash.
- */
- function getSMIMEParams()
- {
- return array('temp' => $this->_temp);
- }
- /**
- * Return info about field type.
- */
- function about()
- {
- return array(
- 'name' => _("S/MIME Key"),
- 'params' => array(
- 'temp_dir' => array('label' => _("A temporary directory"),
- 'type' => 'string'),
- 'rows' => array('label' => _("Number of rows"),
- …
Large files files are truncated, but you can click here to view the full file