Location: PHPKode > scripts > Form Checker > form-checker/package.formchecker.php
<?php
/**
 * FormChecker package
 * @author Johan Barbier <hide@address.com>
 * @version 20070104
 *
 */

/**
 * Messages classes
 * must be named this way : formCheckerMessagesXXX
 * where XXX is the alpha 3 country code
 */

/**
 * class formCheckerMessagesENG
 * English localization of the messages
 *
 */
class formCheckerMessagesENG {

	const EMAIL_INVALID = 'The email address is invalid';

	const URL_INVALID = 'The URL is invalid';

	const REGEXP_FOUND_NOT_MATCH = 'Input {__INPUT__} does not match given regexp pattern';

	const USER_FUNC_RETURNED_FALSE = 'User function {__FUNC__} returned false for {__INPUT__}';

	const INPUT_EMPTY = 'You must fill in your {__INPUT__}';
	const INPUT_NOT_IN_MIN_LENGTH = 'Your {__INPUT__} must et least have {__MIN_LENGTH__} characters';
	const INPUT_NOT_IN_MAX_LENGTH = 'Your {__INPUT__} must at most have {__MAX_LENGTH__} characters';
	const INPUT_NOT_IN_STRICT_LENGTH = 'Your {__INPUT__} must have {__STRICT_LENGTH__} characters';
	const INPUT_STARTS_WITH = 'Your {__INPUT__} must start with {__START__}';
	const INPUT_DONOT_START_WITH = 'Your {__INPUT__} must not start with {__START__}';
	const INPUT_FORBIDDEN = 'these input are forbidden : {__FORBIDDEN__}';

	const NUMERIC_NOT_NUMERIC = 'Your {__NUMERIC__} must be numeric';
	const NUMERIC_NOT_IN_MIN_RANGE = 'Your {__NUMERIC__} must be greater than {__MIN_RANGE__}';
	const NUMERIC_NOT_IN_MAX_RANGE = 'Your {__NUMERIC__} must be lesser than {__MAX_RANGE__}';
}

/**
 * class formCheckerMessagesFRA
 * French localization of the messages
 *
 */
class formCheckerMessagesFRA {

	const EMAIL_INVALID = 'L\'adresse email saisie est invalide';

	const URL_INVALID = 'L\'URL est invalide';

	const REGEXP_FOUND_NOT_MATCH = 'Le motif d\'expression régulière n\'a pas été trouvé dans {__INPUT__}';

	const USER_FUNC_RETURNED_FALSE = 'La fonction utilisateur {__FUNC__} a retourné false pour {__INPUT__}';

	const INPUT_EMPTY = 'Vous devez saisir votre {__INPUT__}';
	const INPUT_NOT_IN_MIN_LENGTH = 'Votre {__INPUT__} doit contenir au moins {__MIN_LENGTH__} caractères';
	const INPUT_NOT_IN_MAX_LENGTH = 'Votre {__INPUT__} doit contenir au plus {__MAX_LENGTH__} caractères';
	const INPUT_NOT_IN_STRICT_LENGTH = 'Votre {__INPUT__} doit être composé de {__STRICT_LENGTH__} caractères';
	const INPUT_STARTS_WITH = 'Votre {__INPUT__} doit commencer par {__START__}';
	const INPUT_DONOT_START_WITH = 'Votre {__INPUT__} ne doit pas commencer par {__START__}';
	const INPUT_FORBIDDEN = 'Ces entrées sont interdites : {__FORBIDDEN__}';

	const NUMERIC_NOT_NUMERIC = 'Votre {__NUMERIC__} doit être composé de chiffres';
	const NUMERIC_NOT_IN_MIN_RANGE = 'Votre {__NUMERIC__} doit être supérieur à {__MIN_RANGE__}';
	const NUMERIC_NOT_IN_MAX_RANGE = 'Votre {__NUMERIC__} doit être inférieur à {__MAX_RANGE__}';
}

/**
 * class formCheckerException extends Exception
 * Specialized exceptions class
 *
 */
class formCheckerException extends Exception {

	const CLASS_NOT_EXISTS = 'Invalid pattern';
	const CLASS_LOC_NOT_EXISTS = 'Invalid localization class';
	const FILTER_MUST_BE_INT = 'Filter must be an integer';
	const FILTER_NOT_ARRAY = 'Filter must be an array';
	const NO_REGEXP = 'Regexp filter needs a regexp option';
	const BAD_REGEXP = 'Bad regexp pattern';
	const NO_USER_FUNC = 'No user function filter given';
	const USER_FUNC_PARAMS_NO_ARRAY = 'User function parameters filter must be an array';
	const SANITIZE_NO_USER_FUNC = 'No user function given to the sanitizer';
	const SANITIZE_USER_FUNC_NOT_EXISTS = 'User function given to the sanitizer has not been found';
	const SANITIZE_USER_FUNC_PARAMS_NOT_ARRAY = 'User function parameters given to the sanitizer must be an array';
}

/**
 * class formCheckerMessages
 * The factory chosing correct messages localization class
 *
 */
class formCheckerMessages {

	/**
	 * public static function factory
	 * factory building the correct localized formCheckerMessages class through a ReflectionClass object
	 *
	 * @param string $loc : country alpha 3 code
	 * @return ReflectionClass object
	 */
	public static function factory ($loc) {
		if (false === class_exists ('formCheckerMessages'.$loc)) {
			throw new formCheckerException (formCheckerException::CLASS_LOC_NOT_EXISTS);
		}
		$sClass = 'formCheckerMessages'.$loc;
		return new ReflectionClass ($sClass);
	}
}

/**
 * abstract class validateGen
 * the parent of all validateZZZ classes
 * defines common methods and properties
 *
 */
abstract class validateGen {

	/**
	 * protected sName
	 * user defined name given to the input (used for the messages)
	 *
	 * @var string
	 */
	protected $sName = null;

	/**
	 * protected static sLocClass
	 * used to store a ReflectionClass object pointing on the messages localization class
	 *
	 * @var ReflectionClass
	 */
	protected static $sLocClass = null;

	/**
	 * private static sLoc
	 * used to store current localization code and check if there is any change
	 *
	 * @var string
	 */
	private static $sLoc = null;

	/**
	 * private function isEmpty
	 * test if a given input is empty or not
	 *
	 * @param string $mString : the input
	 * @param boolean $bMandatory : is the input mandatory or not (if not, it can be empty)
	 * @return boolean true if not empty, false if empty AND mandatory, -1 if empty AND NOT mandatory
	 */
	private function isEmpty ($mString, $bMandatory) {
		if (empty ($mString)) {
			if (true === $bMandatory) {
				throw new formCheckerException (str_replace ('{__INPUT__}', $this -> sName, self::$sLocClass -> getConstant('INPUT_EMPTY')));
			}
			return -1;
		}
		return true;
	}

	/**
	 * protected static function isInt
	 * checks if the given parameter is an integer
	 *
	 * @param int $iNum
	 * @return boolean tue if $iNum is an integer (throw an exception if not)
	 */
	protected static function isInt ($iNum) {
		if (!is_int ($iNum)) {
			throw new formCheckerException (formCheckerException::FILTER_MUST_BE_INT);
		}
		return true;
	}

	/**
	 * private function assign
	 * just assigns properties and instanciate the ReflectionClass via the formCheckerMessages::factory () method
	 *
	 * @param string $sName : name given to the input
	 * @param string $loc : country alpha 3 code
	 */
	private function assign ($sName, $loc) {
		$this -> sName = $sName;
		if ($loc !== self::$sLoc) {
			self::$sLoc = $loc;
			self::$sLocClass = formCheckerMessages::factory ($loc);
		}
	}

	/**
	 * protected static function validateMinLength
	 * checks if the input length matches the minimum required length
	 *
	 * @param string $mString : the input
	 * @param string $sName : user defined name for the data
	 * @param int $iMinLength : minimum length
	 * @return boolean true if the input length is greater or equal to the minimum length, false if not
	 */
	protected static function validateMinLength($mString, $sName, $iMinLength) {
		if (true === self::isInt ($iMinLength)) {
			if (strlen ($mString) < $iMinLength) {
				throw new formCheckerException (str_replace (array ('{__INPUT__}', '{__MIN_LENGTH__}'), array ($sName, $iMinLength), self::$sLocClass -> getConstant ('INPUT_NOT_IN_MIN_LENGTH')));
			}
			return true;
		}
		return false;
	}

	/**
	 * protected static function validateMaxLength
	 * checks if the input length matches the maximum required length
	 *
	 * @param string $mString : the input
	 * @param string $sName : user defined name for the data
	 * @param int $iMaxLength : maximum length
	 * @return boolean true if the input length is lesser or equal to the maximum length, false if not
	 */
	protected static function validateMaxLength($mString, $sName, $iMaxLength) {
		if (true === self::isInt ($iMaxLength)) {
			if (strlen ($mString) > $iMaxLength) {
				throw new formCheckerException (str_replace (array ('{__INPUT__}', '{__MAX_LENGTH__}'), array ($sName, $iMaxLength), self::$sLocClass -> getConstant ('INPUT_NOT_IN_MAX_LENGTH')));
			}
			return true;
		}
		return false;
	}

	/**
	 * protected static function validateStrictLength
	 * checks if the input has the mandatory strict length
	 *
	 * @param string $mString : the input
	 * @param string $sName : user defined name for the data
	 * @param int $iStrictLength : strict length
	 * @return boolean true if the input length is equal to the mandaotry strict length, false if not
	 */
	protected static function validateStrictLength($mString, $sName, $iStrictLength) {
		if (true === self::isInt ($iStrictLength)) {
			if (strlen ($mString) !== $iStrictLength) {
				throw new formCheckerException (str_replace (array ('{__INPUT__}', '{__STRICT_LENGTH__}'), array ($sName, $iStrictLength), self::$sLocClass -> getConstant ('INPUT_NOT_IN_STRICT_LENGTH')));
			}
			return true;
		}
		return false;
	}

	/**
	 * protected static function validateStartsWith
	 * checks if the input starts with each values in a given array
	 *
	 * @param string $mString : the input
	 * @param string $sName : user defined name for the data
	 * @param array $aStarts : array of values
	 * @return boolean true if the input starts with at least one of the values, false if not.
	 */
	protected static function validateStartsWith ($mString, $sName, $aStarts) {
		$bRes = false;
		if (!is_array ($aStarts)) {
			throw new formCheckerException (formCheckerException::FILTER_NOT_ARRAY);
		}
		foreach ($aStarts as $mVal) {
			if (substr ($mString, 0, strlen ($mVal)) === $mVal) {
				$bRes = true;
			}
		}
		if (false === $bRes) {
			throw new formCheckerException (str_replace (array ('{__INPUT__}', '{__START__}'), array ($sName, implode (',', $aStarts)), self::$sLocClass -> getConstant ('INPUT_STARTS_WITH')));
		}
		return $bRes;
	}

	/**
	 * protected static function validateStartsWith
	 * checks if the input does not start with each values in a given array
	 *
	 * @param string $mString : the input
	 * @param string $sName : user defined name for the data
	 * @param array $aStarts : array of values
	 * @return boolean false if the input starts with at least one of the values, true if not.
	 */
	protected static function validateStartsWithout ($mString, $sName, $aStarts) {
		$bRes = true;
		if (!is_array ($aStarts)) {
			throw new formCheckerException (formCheckerException::FILTER_NOT_ARRAY);
		}
		foreach ($aStarts as $mVal) {
			if (substr ($mString, 0, strlen ($mVal)) === $mVal) {
				$bRes = false;
				break;
			}
		}
		if (false === $bRes) {
			throw new formCheckerException (str_replace (array ('{__INPUT__}', '{__START__}'), array ($sName, implode (',', $aStarts)), self::$sLocClass -> getConstant ('INPUT_DONOT_START_WITH')));
		}
		return $bRes;
	}

	/**
	 * protected static function hasForbidden
	 * checks if the input is equal to one of the forbidden values
	 *
	 * @param string $mString : the input
	 * @param string or array $mForbidden : string or array of forbidden values
	 * @return boolean false if the input is equal to one of the forbidden values, true if not
	 */
	protected static function hasForbidden ($mString, $mForbidden) {
		if (is_array ($mForbidden)) {
			if (in_array ($mString, $mForbidden)) {
				throw new formCheckerException (str_replace ('{__FORBIDDEN__}', $mForbidden[array_search($mString, $mForbidden)], self::$sLocClass -> getConstant ('INPUT_FORBIDDEN')));
			}
		} else {
			if ($mForbidden === $mString) {
				throw new formCheckerException (str_replace ('{__FORBIDDEN__}',$mForbidden, self::$sLocClass -> getConstant ('INPUT_FORBIDDEN')));
			}
		}
		return true;
	}

	/**
	 * protected static function hasAllowed
	 * checks if the input is equal to one of the allowed (and mandatory) values
	 *
	 * @param string $mString : the input
	 * @param string or array $mForbidden : string or array of forbidden values
	 * @return boolean false if the input is equal to one of the forbidden values, true if not
	 */
	protected static function hasAllowed ($mString, $mAllowed) {
		if (is_array ($mAllowed)) {
			if (!in_array ($mString, $mAllowed)) {
				throw new formCheckerException (self::$sLocClass -> getConstant ('INPUT_ALLOWED'));
			}
		} else {
			if ($mAllowed !== $mString) {
				throw new formCheckerException (self::$sLocClass -> getConstant ('INPUT_ALLOWED'));
			}
		}
		return true;
	}

	/**
	 * protected function validate
	 * validation method, calls the required check methods
	 *
	 * @param string $mString : the input
	 * @param string $sName : user defined name given to the input
	 * @param string $loc : country alpha 3 code
	 * @param array $aOptions : null if no option, array of options
	 * @param boolean $bMandatory : true if the input is mandaotry, false if not
	 * @return boolean true if the input successfully meets all the requirements, false if not, -1 if input is empty
	 */
	protected function validate ($mString, $sName, $loc, $aOptions, $bMandatory) {
		$this -> assign ($sName, $loc);
		if (false === ($bRes = $this -> isEmpty ($mString, $bMandatory))) {
			return false;
		} elseif (true === $bRes) {
			if (isset ($aOptions['forbidden'])) {
				if (false === self::hasForbidden ($mString, $aOptions['forbidden'])) {
					return false;
				}
			}
			if (isset ($aOptions['allowed'])) {
				if (false === self::hasAllowed ($mString, $aOptions['allowed'])) {
					return false;
				}
			}
			if (isset ($aOptions['min_length']) && is_int ($aOptions['min_length'])) {
				if (false === self::validateMinLength ($mString, $this -> sName, $aOptions['min_length'])) {
					return false;
				}
			}
			if (isset ($aOptions['max_length']) && is_int ($aOptions['max_length'])) {
				if (false === self::validateMaxLength ($mString, $this -> sName, $aOptions['max_length'])) {
					return false;
				}
			}
			if (isset ($aOptions['strict_length']) && is_int ($aOptions['strict_length'])) {
				if (false === self::validateStrictLength ($mString, $this -> sName, $aOptions['strict_length'])) {
					return false;
				}
			}
			if (isset ($aOptions['starting_with'])) {
				if (false === self::validateStartsWith ($mString, $this -> sName, $aOptions['starting_with'])) {
					return false;
				}
			}
			if (isset ($aOptions['not_starting_with'])) {
				if (false === self::validateStartsWithout ($mString, $this -> sName, $aOptions['not_starting_with'])) {
					return false;
				}
			}
		} else {
			return -1;
		}
		return true;
	}
}

/**
 * class validateText extends validateGen
 * basic text checker class
 *
 */
class validateText extends validateGen {

	/**
	 * protected function validate
	 * validation method, calls the required check methods and prior to them, calls parent validate method
	 *
	 * @param string $mString : the input
	 * @param string $sName : user defined name given to the input
	 * @param string $loc : country alpha 3 code
	 * @param array $aOptions : null if no option, array of options
	 * @param boolean $bMandatory : true if the input is mandaotry, false if not
	 * @return boolean true if the input successfully meets all the requirements, false if not
	 */
	public function validate ($mString, $sName, $loc, $aOptions, $bMandatory) {
		if (false === parent::validate ($mString, $sName, $loc, $aOptions, $bMandatory)) {
			return false;
		}
		return true;
	}
}

/**
 * class validateEmail extends validateGen
 * emails checker class
 *
 */
class validateEmail extends validateGen {

	/**
	 * protected function validate
	 * validation method, checks if the input is an email and prior to it, calls parent validate method
	 *
	 * @param string $mString : the input
	 * @param string $sName : user defined name given to the input
	 * @param string $loc : country alpha 3 code
	 * @param array $aOptions : null if no option, array of options
	 * @param boolean $bMandatory : true if the input is mandaotry, false if not
	 * @return boolean true if the input successfully meets all the requirements, false if not
	 */
	public function validate ($mString, $sName, $loc, $aOptions, $bMandatory) {
		if (false === ($bRes = parent::validate ($mString, $sName, $loc, $aOptions, $bMandatory))) {
			return false;
		} elseif (true === $bRes){
			if (!preg_match ('`^[[:alnum:]]([-_.]?[[:alnum:]])*@[[:alnum:]]([-.]?[[:alnum:]])*\.([a-z]{2,4})$`', $mString)) {
				throw new formCheckerException (self::$sLocClass -> getConstant ('EMAIL_INVALID'));
			}
		}
		return true;
	}
}

/**
 * class validateUrl extends validateGen
 * url checker class
 *
 */
class validateUrl extends validateGen {

	/**
	 * protected function validate
	 * validation method, checks if the input is an url and prior to it, calls parent validate method
	 *
	 * @param string $mString : the input
	 * @param string $sName : user defined name given to the input
	 * @param string $loc : country alpha 3 code
	 * @param array $aOptions : null if no option, array of options
	 * @param boolean $bMandatory : true if the input is mandaotry, false if not
	 * @return boolean true if the input successfully meets all the requirements, false if not
	 */
	public function validate ($mString, $sName, $loc, $aOptions, $bMandatory) {
		if (false === ($bRes = parent::validate ($mString, $sName, $loc, $aOptions, $bMandatory))) {
			return false;
		} elseif (true === $bRes){
			if (!preg_match ('`((?:https?|ftp)://\S+[[:alnum:]]/?)`si', $mString) && !preg_match ('`((?<!//)(www\.\S+[[:alnum:]]/?))`si', $mString)) {
				throw new formCheckerException (self::$sLocClass -> getConstant ('URL_INVALID'));
			}
		}
		return true;
	}
}

/**
 * class validateRegExp extends validateGen
 * user defined regexp checker class
 *
 */
class validateRegExp extends validateGen {

	/**
	 * protected function validate
	 * validation method, checks if the input matches the user defined regexp and prior to it, calls parent validate method
	 * needs a mandaotory option at least : $aOptions['regexp'] = user defined regexp pattern
	 *
	 * @param string $mString : the input
	 * @param string $sName : user defined name given to the input
	 * @param string $loc : country alpha 3 code
	 * @param array $aOptions : null if no option, array of options
	 * @param boolean $bMandatory : true if the input is mandaotry, false if not
	 * @return boolean true if the input successfully meets all the requirements, false if not
	 */
	public function validate ($mString, $sName, $loc, $aOptions, $bMandatory) {
		if (false === ($bRes = parent::validate ($mString, $sName, $loc, $aOptions, $bMandatory))) {
			return false;
		} elseif (true === $bRes){
			if (!isset ($aOptions['regexp'])) {
				throw new formCheckerException (formCheckerException::NO_REGEXP);
			}
			$bReg = @preg_match ($aOptions['regexp'], $mString);
			if ((function_exists ('preg_last_error') && @preg_last_error() !== PREG_NO_ERROR) || false === $bReg) {
				throw new formCheckerException (formCheckerException::BAD_REGEXP);
			} elseif (0 === $bReg) {
				throw new formCheckerException (str_replace ('{__INPUT__}', $this -> sName, self::$sLocClass -> getConstant ('REGEXP_FOUND_NOT_MATCH')));
			}
		}
		return true;
	}
}

/**
 * class validateUserFunc extends validateGen
 * user defined function checker class
 *
 */
class validateUserFunc extends validateGen {

	/**
	 * protected function validate
	 * validation method, checks if the input matches the user defined function and prior to it, calls parent validate method
	 * needs a mandatory option at least : $aOptions['user_func'] = name of the user function
	 * you can add parameters via the optional option $aOptions['user_func_params']. This must be an array with all the parameters.
	 * Please note the method will add at the end of the array of options the input $mString.
	 * So, your user function MUST implements at least 1 parameter (the input), and if there are others, the input parameter MUST be the last parameter
	 *
	 * @param string $mString : the input
	 * @param string $sName : user defined name given to the input
	 * @param string $loc : country alpha 3 code
	 * @param array $aOptions : null if no option, array of options
	 * @param boolean $bMandatory : true if the input is mandaotry, false if not
	 * @return boolean true if the input successfully meets all the requirements, false if not
	 */
	public function validate ($mString, $sName, $loc, $aOptions, $bMandatory) {
		if (false === ($bRes = parent::validate ($mString, $sName, $loc, $aOptions, $bMandatory))) {
			return false;
		} elseif (true === $bRes){
			if (!isset ($aOptions['user_func'])) {
				throw new formCheckerException (formCheckerException::NO_USER_FUNC);
			}
			if (isset ($aOptions['user_func_params']) && !is_array ($aOptions['user_func_params'])) {
				throw new formCheckerException (formCheckerException::USER_FUNC_PARAMS_NO_ARRAY);
			}
			$aOptions['user_func_params'][] = $mString;
			$bFunc = call_user_func_array ($aOptions['user_func'], $aOptions['user_func_params']);
			if (false === $bFunc) {
				throw new formCheckerException (str_replace (array ('{__INPUT__}', '{__FUNC__}'), array ($this -> sName, $aOptions['user_func']), self::$sLocClass -> getConstant ('USER_FUNC_RETURNED_FALSE')));
			}
		}
		return true;
	}
}

/**
 * class validateInt extends validateGen
 * integer checker class
 *
 */
class validateInt extends validateGen {

	/**
	 * protected function validate
	 * validation method, checks some specific numeric requirements and prior to them, calls parent validate method
	 *
	 * @param string $mString : the input
	 * @param string $sName : user defined name given to the input
	 * @param string $loc : country alpha 3 code
	 * @param array $aOptions : null if no option, array of options
	 * @param boolean $bMandatory : true if the input is mandaotry, false if not
	 * @return boolean true if the input successfully meets all the requirements, false if not
	 */
	public function validate ($mString, $sName, $loc, $aOptions, $bMandatory) {
		if (false === ($bRes = parent::validate ($mString, $sName, $loc, $aOptions, $bMandatory))) {
			return false;
		} elseif (true === $bRes) {
			if (false === ctype_digit ($mString)) {
				throw new formCheckerException (str_replace ('{__NUMERIC__}', $this -> sName, self::$sLocClass -> getConstant ('NUMERIC_NOT_NUMERIC')));
			}
			if (isset ($aOptions['min_range'])) {
				if (false === $this -> validateMinRange ($mString, $aOptions['min_range'])) {
					return false;
				}
			}
			if (isset ($aOptions['max_range'])) {
				if (false === $this -> validateMaxRange ($mString, $aOptions['max_range'])) {
					return false;
				}
			}
		}
		return true;
	}

	/**
	 * private function validateMinRange
	 * checks if the numeric input is greater or equal than the minimum range
	 *
	 * @param string $mString : the input
	 * @param int $iMinRange : minimum range
	 * @return boolean if the input is greater or equal than the minimum range, false if not
	 */
	private function validateMinRange ($mString, $iMinRange) {
		if (true === parent::isInt ($iMinRange)) {
			if ($mString < $iMinRange) {
				throw new formCheckerException (str_replace (array ('{__NUMERIC__}', '{__MIN_RANGE__}'), array ($this -> sName, $iMinRange), self::$sLocClass -> getConstant ('NUMERIC_NOT_IN_MIN_RANGE')));
			}
			return true;
		}
		return false;
	}

	/**
	 * private function validateMaxRange
	 * checks if the numeric input is lesser or equal than the maximum range
	 *
	 * @param string $mString : the input
	 * @param int $iMaxRange : maximum range
	 * @return boolean if the input is lesser or equal than the maximum range, false if not
	 */
	private function validateMaxRange ($mString, $iMaxRange) {
		if (true === parent::isInt ($iMaxRange)) {
			if ($mString > $iMaxRange) {
				throw new formCheckerException (str_replace (array ('{__NUMERIC__}', '{__MAX_RANGE__}'), array ($this -> sName, $iMaxRange), self::$sLocClass -> getConstant ('NUMERIC_NOT_IN_MAX_RANGE')));
			}
			return true;
		}
		return false;
	}

}

/**
 * class formChecker
 * only class to be called
 * uses ReflectionClass to call the correct validateZZZ class
 *
 */
class formChecker {

	/**
	 * constants defining the allowed validation classes
	 *
	 */
	const VALIDATE_EMAIL = 'validateEmail';
	const VALIDATE_INT = 'validateInt';
	const VALIDATE_TEXT = 'validateText';
	const VALIDATE_URL = 'validateUrl';
	const VALIDATE_REGEXP = 'validateRegExp';
	const VALIDATE_USER_FUNC = 'validateUserFunc';

	/**
	 * public static aMsg
	 * static property storing the messages returned by the validateZZZ classes (error messages)
	 * key is the user defined name for the input, value being the error message
	 *
	 * @var array
	 */
	public static $aMsg = null;

	/**
	 * private bValid
	 * true if the form (all the input validated) is ok, false if there is at least one error among all the validation
	 *
	 * @var boolean
	 */
	private $bValid = true;

	/**
	 * private loc
	 * localization property, country alpha 3 code
	 *
	 * @var string
	 */
	private $loc = null;

	/**
	 * public function __construct
	 * constructor, sets some properties : localization, and reset aMsg array of error messages
	 *
	 * @param string $loc
	 */
	public function __construct ($loc = 'FRA') {
		self::$aMsg = null;
		$this -> loc = $loc;
	}

	/**
	 * public function validate
	 * call the validation type required, via ReflectionClass
	 * sets the formChecker::bValid property to false if any error is detected on an input
	 *
	 * @param string $mString : the input
	 * @param string $sName : user defined name for the input
	 * @param formChecker constant $cPattern : the validation type to be applied to this input
	 * @param array $aOptions : null if not options, array of options on the other hand. default to null
	 * @param boolean $bMandatory : true if the input must not be empty, false if not. default to true
	 * @return unknown
	 */
	public function validate ($mString, $sName, $cPattern, $aOptions = null, $bMandatory = true) {
		if (false === class_exists ($cPattern)) {
			throw new Exception (formCheckerException::CLASS_NOT_EXISTS);
		}
		$oReflect = new ReflectionClass($cPattern);
		$o = $oReflect -> newInstance ();
		try {
			$bRes = $o -> validate ($mString, $sName, $this -> loc, $aOptions, $bMandatory);
		} catch (Exception $e) {
			self::$aMsg[$sName] = $e -> getMessage ();
			$bRes = $this -> bValid = false;
		}
		return $bRes;
	}

	/**
	 * public function sanitizeStr
	 * sanitize a string, given an array of options :
	 * addslashes => adds slashes...(default)
	 * htmlentities => encode html entities (default)
	 * urlencode => encode as en url
	 * trim => apply a trim
	 * mssqlEscape => escape quotes for mssql
	 *
	 * @param string $mString : the input
	 * @param array $aOptions : array of options
	 * @return string
	 */
	public function sanitizeStr ($mString, $aOptions = array ('addslashes', 'htmlentities')) {
		if (in_array ('addslashes', $aOptions)) {
			$mString = addslashes ($mString);
		}
		if (in_array ('htmlentities', $aOptions)) {
			$mString = htmlentities ($mString);
		}
		if (in_array ('urlencode', $aOptions)) {
			$mString = urlencode ($mString);
		}
		if (in_array ('trim', $aOptions)) {
			$mString = trim ($mString);
		}
		if (in_array ('mssqlEscape', $aOptions)) {
			$mString = str_replace ("'", "''", $mString);
		}
		return $mString;
	}

	/**
	 * public function sanitizeInt
	 * sanitize a variable (input, so should be a string) as an integer, given an array of options :
	 * onlyInt => extract onnly the integer values in the variable
	 *
	 * @param string $mString : the input
	 * @param array $aOptions : array of options :
	 * onlyInt => retrieve only integer characters
	 * @return string
	 */
	public function sanitizeInt ($mString, $aOptions = array ('onlyInt')) {
		if (in_array ('onlyInt', $aOptions)) {
			preg_match_all ('@([\d]+)+@', $mString, $aRes);
			if (!empty ($aRes[0])) {
				$mString = implode ($aRes[0]);
			} else {
				$mString = '';
			}
		}
		return $mString;
	}

	/**
	 * public function sanitizeUserFunc
	 * sanitize a variable (input, so should be a string) as an integer, given a user function.
	 * Same rule as the formChecker::VALIDATE_USER_FUNC pattern : the user defined function MUST have at least one parameters which is the input.
	 * If there are more parameters, the input MUST be the last parameter.
	 *
	 * @param string $mString : the input
	 * @param array $aOptions : array of options
	 * @return string
	 */
	public function sanitizeUserFunc ($mString, $aOptions = array ('user_func' => '', 'user_func_params' => array ())) {
		if (!isset ($aOptions['user_func'])) {
			throw new formCheckerException (formCheckerException::SANITIZE_NO_USER_FUNC);
		}
		if (!function_exists ($aOptions['user_func'])) {
			throw new formCheckerException (formCheckerException::SANITIZE_USER_FUNC_NOT_EXISTS);
		}
		if (isset ($aOptions['user_func_params']) && !is_array ($aOptions['user_func_params'])) {
			throw new formCheckerException (formCheckerException::SANITIZE_USER_FUNC_PARAMS_NOT_ARRAY);
		}
		$aOptions['user_func_params'][] = $mString;
		$mString = call_user_func_array ($aOptions['user_func'], $aOptions['user_func_params']);
		return $mString;
	}

	/**
	 * public function isValid
	 * returns formChecker::bValid property
	 * it will be set to true if every input successfully passed the validation, false if one of them failed
	 *
	 * @return unknown
	 */
	public function isValid () {
		return $this -> bValid;
	}
}

/**
 * Example
 */

/**
 * declarations.
 * of course, should be user input values like POST or GET
 */
$sEmail = 'hide@address.com';
$sCp = '00345';
$sNom ='';
$sPrenom = '';
$sTel = '04-23-45-67-89';
$sUrl = 'http://monsite.com';
$sToBeSanitized = 'must be uppercase';

/**
* some user defined function to be used for the formchecker::VALIDATE_USER_FUNC pattern
*/
function myFunc ($sNeedle, $sHaystack) {
	if (false !== strpos ($sHaystack, $sNeedle)) {
		return true;
	}
	return false;
}

/**
* some user defined function to be used for the formchecker::sanitizeUserFunc method
*/
function mySanitizer ($mString) {
	return strtoupper ($mString);
}

/**
 * French test
 */
try {
	/**
	 * instanciation of the formChecker
	 */
	$iStart = microtime (true);
	$oChecker = new formChecker;

	/**
	 * just to show sanitization : we remove the '-' from the phone number
	 */
	$sSanitizedTel = $oChecker -> sanitizeInt ($sTel);

	/**
	 * just to show sanitization via user defined function : we just return the uppercase version of the string
	 */
	$sToBeSanitized = $oChecker -> sanitizeUserFunc ($sToBeSanitized, array ('user_func' => 'mySanitizer'));
	echo '<br />SANITIZED : ', $sToBeSanitized, '<br />';

	/**
	 * some validations
	 */

	/**
	 * using the email validation, and we forbid the use of the 'hide@address.com'
	 */
	if (false === $oChecker -> validate ($sEmail, 'email', formChecker::VALIDATE_EMAIL, array ('forbidden' => 'hide@address.com'))) {
		echo 'FALSE<br />';
	} else {
		echo 'OK<br />';
	}
	/**
	 * using the integer validation : the French zip code should broadly be only integers, strictly 5 in length, and cannot start with 00
	 */
	if (false === $oChecker -> validate ($sCp, 'code postal', formChecker::VALIDATE_INT, array ('strict_length' => 5, 'not_starting_with' => array ('00')))) {
		echo 'FALSE<br />';
	} else {
		echo 'OK<br />';
	}
	/**
	 * using the basic text validation, nothing special except that the input must not be empty (default valus is true for the mandatory parameter)
	 */
	if (false === $oChecker -> validate ($sNom, 'nom', formChecker::VALIDATE_TEXT)) {
		echo 'FALSE<br />';
	} else {
		echo 'OK<br />';
	}
	/**
	 * using again the basic text validation, but the first name is not mandatory (see the last parameter : false); note that mandatory being the last parameter, and
	 * as we do not need any option, wu must pass a null value instead of the array of options
	 */
	if (false === $oChecker -> validate ($sPrenom, 'prénom', formChecker::VALIDATE_TEXT, null, false)) {
		echo 'FALSE<br />';
	} else {
		echo 'OK<br />';
	}
	/**
	 * using the integer validation for the sanitized phone number. Broadly, the French phone number should be 10 cahracters long, only integers (that's why we sanitied it),
	 * and should start with 01, 02, 03, 04, 05, 06 or 08
	 */
	if (false === $oChecker -> validate ($sSanitizedTel, 'telephone', formChecker::VALIDATE_INT, array ('strict_length' => 10, 'starting_with' => array ('01', '02', '03', '04', '05', '06', '08')))) {
		echo 'FALSE<br />';
	} else {
		echo 'OK<br />';
	}
	/**
	 * using the URL validation
	 */
	if (false === $oChecker -> validate ($sUrl, 'url', formChecker::VALIDATE_URL)) {
		echo 'FALSE<br />';
	} else {
		echo 'OK<br />';
	}
	/**
	 * using the regexp validation (ok, my regexp is stupid...)
	 */
	if (false === $oChecker -> validate ($sUrl, 'url2', formChecker::VALIDATE_REGEXP, array ('regexp' => '@(doli)@'))) {
		echo 'FALSE<br />';
	} else {
		echo 'OK<br />';
	}
	/**
	 * using the user function validation (ok, my function is stupid...again!)
	 * here, my function will check if the string 'da' is in the email string ('hide@address.com'). It is not, obviously.
	 */
	if (false === $oChecker -> validate ($sEmail, 'url3', formChecker::VALIDATE_USER_FUNC, array ('user_func' => 'myFunc', 'user_func_params' => array ('da')))) {
		echo 'FALSE<br />';
	} else {
		echo 'OK<br />';
	}
	/**
	 * if there is any error, formchecker::isValid () returns false, else it returns true.
	 * If false, we check the error messages.
	 */
	if (false === $oChecker -> isValid ()) {
		echo '<pre>',print_r (formChecker::$aMsg), '</pre>';
	}
	$iStop = microtime (true);
	echo '<p>ELAPSED : ',$iStop - $iStart,'</p>';
} catch (Exception $e) {
	echo $e -> getMessage ();
}
/**
 * English test (same explanations as for the French one)
 */
try {
	$oChecker = new formChecker ('ENG');

	$sSanitizedTel = $oChecker -> sanitizeInt ($sTel);

	if (false === $oChecker -> validate ($sEmail, 'email', formChecker::VALIDATE_EMAIL, array ('forbidden' => 'hide@address.com'))) {
		echo 'FALSE<br />';
	} else {
		echo 'OK<br />';
	}
	if (false === $oChecker -> validate ($sCp, 'zip code', formChecker::VALIDATE_INT, array ('strict_length' => 5, 'not_starting_with' => array ('00')))) {
		echo 'FALSE<br />';
	} else {
		echo 'OK<br />';
	}
	if (false === $oChecker -> validate ($sNom, 'last name', formChecker::VALIDATE_TEXT)) {
		echo 'FALSE<br />';
	} else {
		echo 'OK<br />';
	}
	if (false === $oChecker -> validate ($sPrenom, 'first name', formChecker::VALIDATE_TEXT, null, false)) {
		echo 'FALSE<br />';
	} else {
		echo 'OK<br />';
	}
	if (false === $oChecker -> validate ($sSanitizedTel, 'phone number', formChecker::VALIDATE_INT, array ('strict_length' => 10, 'starting_with' => array ('01', '02', '03', '04', '05', '06', '08')))) {
		echo 'FALSE<br />';
	} else {
		echo 'OK<br />';
	}
	if (false === $oChecker -> validate ($sUrl, 'url', formChecker::VALIDATE_URL)) {
		echo 'FALSE<br />';
	} else {
		echo 'OK<br />';
	}
	if (false === $oChecker -> validate ($sUrl, 'url2', formChecker::VALIDATE_REGEXP, array ('regexp' => '@(doli)@'))) {
		echo 'FALSE<br />';
	} else {
		echo 'OK<br />';
	}
	if (false === $oChecker -> validate ($sEmail, 'url3', formChecker::VALIDATE_USER_FUNC, array ('user_func' => 'myFunc', 'user_func_params' => array ('da')))) {
		echo 'FALSE<br />';
	} else {
		echo 'OK<br />';
	}
	if (false === $oChecker -> isValid ()) {
		echo '<pre>',print_r (formChecker::$aMsg), '</pre>';
	}
} catch (Exception $e) {
	echo $e -> getMessage ();
}
?>
Return current item: Form Checker