Invision Power Services, Inc. * @copyright (c) 2001 - SVN_YYYY Invision Power Services, Inc. * @license http://www.invisionpower.com/legal/standards/ * @package IPS Social Suite * @since 18 Feb 2013 * @version SVN_VERSION_NUMBER */ namespace IPS\Helpers\Form; /* To prevent PHP errors (extending class does not exist) revealing path */ if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) ) { header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' ); exit; } /** * Text input class for Form Builder */ class _Number extends FormAbstract { /** * @brief Default Options * @code $defaultOptions = array( 'min' => 0, // Minimum number. NULL is no minimum. Default is 0. 'max' => 100, // Maximum number. NULL is no maximum. Default is NULL. 'unlimited' => -1, // If any value other than NULL is provided, an "Unlimited" checkbox will be displayed. If checked, the value specified will be sent. 'unlimitedLang' => 'unlimited', // Language string to use for unlimited checkbox label 'unlimitedToggles' => array(...), // Names of other input fields that should show/hide when the "Unlimited" checkbox is toggled. 'unlimitedToggleOn' => TRUE, // Whether the toggles should show on unlimited checked (TRUE) or unchecked(FALSE). Default is TRUE 'valueToggles' => array(...), // Names of other input fields that should show/hide if the value is/isn't 0. 'decimals' => 2, // Number of decimal places (or TRUE to allow any number) 'step' => NULL, // Increase step for supported browsers. NULL will cause the value to be based off "decimals". Default is NULL. 'range' => TRUE, // Use a range selection for supported browsers? Default is FALSE. 'disabled' => FALSE, // Disables input. Default is FALSE. 'suffixAfterNumber' => TRUE, // A suffix to go after the unlimited checkbox ); * @endcode */ protected $defaultOptions = array( 'min' => 0, 'max' => NULL, 'unlimited' => NULL, 'unlimitedLang' => 'unlimited', 'unlimitedToggles' => array(), 'unlimitedToggleOn' => TRUE, 'valueToggles' => array(), 'decimals' => 0, 'step' => NULL, 'range' => FALSE, 'disabled' => FALSE, 'endSuffix' => NULL, ); /** * Constructor * Formats the value appropriately * * @see \IPS\Helpers\Form\Abstract::__construct * @param string $name Name * @param mixed $defaultValue Default value * @param bool $required Required? * @param array $options Type-specific options * @return void */ public function __construct( $name, $defaultValue=NULL, $required=FALSE, $options=array() ) { /* Specify there's a value if the unlimited element contains a value */ $unlimitedName = "{$name}_unlimited"; if( isset( $options['unlimited'] ) and $options['unlimited'] !== NULL and isset( \IPS\Request::i()->$unlimitedName ) ) { \IPS\Request::i()->$name = $options['unlimited']; } /* Work out the step */ $args = func_get_args(); if ( !isset( $options['base'] ) and isset( $options['decimals'] ) ) { if ( $options['decimals'] === TRUE ) { $args[3]['step'] = 'any'; } else { $args[3]['step'] = 1 / ( pow( 10, $options['decimals'] ) ); } } /* Call parent constructor */ call_user_func_array( 'parent::__construct', $args ); } /** * Get HTML * * @return string */ public function html() { /* Display */ return \IPS\Theme::i()->getTemplate( 'forms', 'core', 'global' )->number( $this->name, $this->value, $this->required, $this->options['unlimited'], $this->options['range'], $this->options['min'], $this->options['max'], $this->options['step'], $this->options['decimals'], $this->options['unlimitedLang'], $this->options['disabled'], $this->suffix, $this->options['unlimitedToggles'], $this->options['unlimitedToggleOn'], $this->options['valueToggles'] ); } /** * Get Value * * @return mixed */ public function getValue() { $name = $this->name; if ( $pos = mb_strpos( $name, '[' ) ) { $_name = mb_substr( preg_replace( '/\[(.+?)\]/', '[$1_unlimited]', $name, 1 ), 0, $pos ); $val = \IPS\Request::i()->$_name; preg_match_all( '/\[(.+?)\]/', $name, $matches ); foreach ( $matches[1] as $_name ) { if ( isset( $val[ $_name ] ) ) { $val = $val[ $_name ]; } else { $val = FALSE; break; } } return $val; } else { $unlimitedName = "{$name}_unlimited"; $unlimitedChecked = isset( \IPS\Request::i()->$unlimitedName ); } /* Unlimited? */ if ( $this->options['unlimited'] !== NULL and isset( \IPS\Request::i()->$unlimitedName ) ) { return $this->options['unlimited']; } /* Get value */ return \IPS\Request::i()->$name; } /** * Format Value * * @return mixed */ public function formatValue() { /* Get value */ $value = $this->value; /* If this is the "unlimited" value, we don't need to format it */ if ( $this->options['unlimited'] !== NULL and $value === $this->options['unlimited'] ) { return $value; } /* Convert decimal point and thousand separators to a way PHP understand */ $value = str_replace( trim( \IPS\Member::loggedIn()->language()->locale['thousands_sep'] ), '', $value ); $value = str_replace( trim( \IPS\Member::loggedIn()->language()->locale['decimal_point'] ), '.', $value ); /* If it's not numeric, throw an exception */ if ( ( !is_numeric( $value ) and $value !== '' and $this->required === FALSE ) or ( !is_numeric( $value ) and $this->required === TRUE ) ) { throw new \InvalidArgumentException( 'form_number_bad' ); } /* Convert to int/float */ if ( $this->options['decimals'] ) { $value = floatval( $value ); if ( is_int( $this->options['decimals'] ) ) { $value = round( $value, $this->options['decimals'] ); } } else { $value = intval( $value ); } /* Return */ return $value; } /** * Validate * * @throws \LengthException * @return TRUE */ public function validate() { parent::validate(); if ( $this->options['unlimited'] === NULL or $this->value !== $this->options['unlimited'] ) { if ( $this->options['min'] !== NULL and $this->value < $this->options['min'] ) { throw new \LengthException( \IPS\Member::loggedIn()->language()->addToStack('form_number_min', FALSE, array( 'sprintf' => array( $this->options['min'] ) ) ) ); } if ( $this->options['max'] !== NULL and $this->value > $this->options['max'] ) { throw new \LengthException( \IPS\Member::loggedIn()->language()->addToStack('form_number_max', FALSE, array( 'sprintf' => array( $this->options['max'] ) ) ) ); } } } }