Open-Source PHP Framework - Designed for rapid development of performance-oriented scalable applications

/packages/validator

[return to app]
1
<?php
/**
 * This comes from the May 2007 php|architect article:
 * Unifying Server-Side and Client-Side Input Validation
 */
class ValidatedField {
    protected $_label, $_validation;

    public function __construct($label, $validation) {
        $this->_label = $label;
        $this->_validation = $validation;
    }

    public function __call($name, $val) {
        if (strpos($name, 'get') === 0) {
        $property = '_' . strtolower($name[3]) . substr($name, 4);
            if (isset($this->$property)) {
                return $this->$property;
            } else {
            $error_message = 'There is no property defined as ' . $property
                           . ' or method called ' . $name
                           . ' in the ' . __CLASS__ . ' class';
            }
        } else {
            $error_message = 'Call to undefined method ' . __CLASS__ . '::' . $name . '()';
        }

        if (isset($error_message)) {
            trigger_error($error_message, E_USER_ERROR);
        }
    }
}

class Validator {
    protected $_validatedFields = array();

    protected $_commonRegex = array(
        'match' => array(
            'HexColor' => '/^#?([\dA-F]{3}){1,2}$/i',
            'UsTelephone' =>
 
'/^\(?([2-9]\d{2})\)?[\.\s-]?([2-4|6-9]\d\d|5([0-4|6-9]\d|\d[0-4|6-9]))[\.\s-]?(\d{4})$/', 'Email' => '/(^[\w\.!#$%"*+\/=?`{}|~^-]+)@(([-\w]+\.)+[A-Za-z]{2,})$/', 'Url' => '/^(https?|ftp):\/\/([-\w]+\.)+[A-Za-z]{2,}(:\d+)?([\\\\\/]\S+)*?[\\\\\/]?(\?\S*)?$/i', 'Integer' => '/^-?\d+$/', 'Numeric' => '/^-?(\d*\.)?\d+$/', 'AlphaNumeric' => '/^[\w\s]+$/i'), 'get' => array( 'Integer' => '/\d+/', 'Numeric' => '/\d+(\.\d+)?/', 'Trim' => '/^\s*(.*?)\s*$/') ); protected $_validCssColors = array( 'aqua' => '00FFFF', 'black' => '000000', 'blue' => '0000FF', 'fuchsia' => 'FF00FF', 'gray' => '808080', 'green' => '008000', 'lime' => '00FF00', 'maroon' => '800000', 'navy' => '000080', 'olive' => '808000', 'purple' => '800080', 'red' => 'FF0000', 'silver' => 'C0C0C0', 'teal' => '008080', 'white' => 'FFFFFF', 'yellow' => 'FFFF00' ); public function getCommonData($dataType) { switch ($dataType) { case 'commonRegex': $x = -1; $return = '{'; foreach ($this->_commonRegex as $matchType => $regexArray) { $y = -1; if (++$x) { $return .= ', ' . PHP_EOL; } $return .= "'" . $matchType . "': {" . PHP_EOL; foreach ($regexArray as $key => $regexString) { if (++$y) { $return .= ', ' . PHP_EOL; } $return .= "'" . $key . "': " . $regexString; if ($matchType == 'get') { $return .= 'g'; } } $return .= "}"; } $return .= '}'; break; case 'validations': $return = array(); foreach ($this->_validatedFields as $formId => $validatedArray) { foreach ($validatedArray as $inputId => $obj) { $return[$formId][$inputId] = $obj->getValidation(); } } $return = json_encode($return); break; } return $return; } public function isValidNumeric($val) { return is_numeric($val); } public function isValidInteger($val) { return (is_numeric($val) && $val == intval($val)); } public function getNumbersOnly($val, $integerOnly = 0) { $regexType = ($integerOnly ? 'Integer' : 'Numeric'); preg_match_all($this->_commonRegex['get'][$regexType], $val, $matches); return implode($matches[0]); } public function isValidTelephone($val, $country = 'US') { if (strtoupper($country) == 'US') { $return = (preg_match($this->_commonRegex['match']['UsTelephone'], $val)); } else { $return = (strlen($this->getNumbersOnly($val)) > 6); } return $return; } public function isValidHexColor($val) { if (isset($this->_validCssColors[$val])) { $val = '#' . $this->_validCssColors[$val]; } return $this->__call('isValidHexColor', array($val)); } public function setValidatedField($formId, $inputId, $label, $validation) { $this->_validatedFields[$formId][$inputId] = new ValidatedField($label, $validation); } public function getClosingJs() { return 'var validations = ' . $this->getCommonData('validations') . '; var thisFormId; for (var formId in validations) { thisFormId = Validator.dom(formId); if (thisFormId) { thisFormId.onsubmit = function() { return Validator.validateForm(formId); } } }'; } public static $errors = array(); public function getErrorsFromPost($formId) { self::$errors[$formId] = array(); if (isset($_POST[key($this->_validatedFields[$formId])])) { foreach ($this->_validatedFields[$formId] as $inputId => $obj) { $_POST[$inputId] = trim($_POST[$inputId]); if (!$this->{$obj->getValidation()}($_POST[$inputId])) { self::$errors[$formId][$inputId] = $obj->getLabel() . ' is not valid'; } } } } public function __call($name, $val) { $triggerError = true; if (strpos($name, 'isValid') === 0) { $regexType = substr($name, 7); if (isset($this->_commonRegex['match'][$regexType])) { return preg_match($this->_commonRegex['match'][$regexType], current($val)); $triggerError = false; } } else if (strpos($name, 'set') === 0) { $this->{'_' . strtolower($name[3]) . substr($name, 4)} = current($val); $triggerError = false; } else if (strpos($name, 'get') === 0) { $property = '_' . strtolower($name[3]) . substr($name, 4); if (isset($this->$property)) { return $this->$property; $triggerError = false; } } if ($triggerError) { trigger_error('Call to undefined method ' . __CLASS__ . '::' . $name . '()', E_USER_ERROR); } } }