Symbi0nt's Model Validation | |
| Type: Full Script |
Category: Other |
| License: GNU General Public License |
Language: PHP |
| Description: My app_model.php with my approch of makeing validation more handy and step-by-step like. See my other example models and example views for "how-to-use" it. | |
|
Download a raw-text version of this code by clicking on "Download Version"
<?php
/* SVN FILE: $Id: app_model.php 2951 2006-05-25 22:12:33Z phpnut $ */
/**
* Application model for Cake.
*
* This file is application-wide model file. You can put all
* application-wide model-related methods here.
*
* PHP versions 4 and 5
*
* CakePHP : Rapid Development Framework <http://www.cakephp.org/>
* Copyright (c) 2006, Cake Software Foundation, Inc.
* 1785 E. Sahara Avenue, Suite 490-204
* Las Vegas, Nevada 89104
*
* Licensed under The MIT License
* Redistributions of files must retain the above copyright notice.
*
* @filesource
* @copyright Copyright (c) 2006, Cake Software Foundation, Inc.
* @link http://www.cakefoundation.org/projects/info/cakephp CakePHP Project
* @package cake
* @subpackage cake.cake
* @since CakePHP v 0.2.9
* @version $Revision: 2951 $
* @modifiedby $LastChangedBy: phpnut $
* @lastmodified $Date: 2006-05-25 17:12:33 -0500 (Thu, 25 May 2006) $
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
*/
/**
* Application model for Cake.
*
* This is a placeholder class.
* Create the same file in app/app_model.php
* Add your application-wide methods to the class, your models will inherit them.
*
* @package cake
* @subpackage cake.cake
*/
// vendor('validator.class');
define('VALID_IF_NOT_EMPTY', '_chkIfNotEmpty');
define('VALID_IF_NUMBER', '_chkIfNumber');
define('VALID_IF_EMAIL', '_chkIfEmail');
define('VALID_IF_URI', '_chkIfUri');
define('VALID_IF_YEAR', '_chkIfYear');
define('VALID_IF_MONTH', '_chkIfMonth');
define('VALID_IF_MONTH_DAY', '_chkIfMonthDay');
define('VALID_IF_EXISTING_DATE', '_chkIfExistingDate');
define('VALID_IF_MINIMUM_LENGTH_OF', '_chkIfMinimumLength');
define('VALID_IF_MAXIMUM_LENGTH_OF', '_chkIfMaximumLength');
define('VALID_IF_MINUMUM_AGE_OF', '_chkIfMinimumAge');
define('VALID_IF_CREDITCARD_NUMBER', '_chkIfCreditCardNumber');
define('VALID_IF_CONTAINS_PARTS_OF', '_chkIfContainsPartsOf');
define('VALID_IF_LENGTH_OF', '_chkIfHasLength');
define('VALID_IF_MATCHES_FIELD_VALUE_OF', '_chkIfMatchesAnotherFieldValue');
define('VALID_IF_IP', '_chkIfIP');
define('VALID_IF_ONLY_NAME_CHARS', '_chkIfOnlyNameChars');
define('VALID_IF_IS_ONE_OF', '_chkIfIsOneOf');
define('VALID_IF_MD5', '_chkIfMd5');
define('VALID_IF_ADDITIONAL_FIELDS_ARE_NOT_EMPTY', '_chkIfAdditionalFieldsAreNotEmpty');
define('VALID_NAME_CHARS_SYMBOLS', 'ŠŒŽšœžŸ¥µÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝßàáâãäåæçèéêëìíîïðñòóôõöøùúûüýÿ');
define('VALID_NAME_CHARS_CONVERT', 'SOZsozYYuAAAAAAACEEEEIIIIDNOOOOOOUUUUYsaaaaaaaceeeeiiiionoooooouuuuyy');
define('VALID_NAME_CHARS', '/[-A-Za-z. ]/i');
define('VALID_MD5', '/[A-Fa-f0-9]{32}/i');
define('VALID_IP', '\b(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.'.
'(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.'.
'(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.'.
'(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b'); // I am not sure about this
define('VALID_LETTERS', '/[A-Za-z]+/i');
define('VALID_SYMBOLS', '/[!"§$%&/()=?}{,.-;:_#\']/i');
define('INVALIDATE_SIMPLE', 1);
define('INVALIDATE_VERBOSE_ALL', 2);
define('INVALIDATE_VERBOSE_STEP', 3);
define('VALIDATOR_DEBUG', 0);
class AppModel extends Model {
var $validationErrorMessages = INVALIDATE_VERBOSE_STEP;
var $validationErrorMessage;
function invalidFields($data = array()) {
if (VALIDATOR_DEBUG) {
echo "Start Validation<br />\n";
echo "Incomming \$data is:<br />\n";
print_r($data);
}
if (!$this->beforeValidate()) {
return false;
}
if (!isset($this->validate)) {
return true;
}
if (!empty($data)){
if (VALIDATOR_DEBUG) {
echo "Using incomming \$data Array<br />\n";
print_r($data);
}
$data = $data;
}
elseif (isset($this->data)){
if (VALIDATOR_DEBUG) {
echo "Using \$this->data Array<br />\n";
print_r($this->data);
}
$data = $this->data;
}
if (isset($data[$this->name])) {
if (VALIDATOR_DEBUG) {
echo "Using \$data[\$this->name] Array<br />\n";
print_r($data[$this->name]);
}
$data = $data[$this->name];
}
if (VALIDATOR_DEBUG) {
echo "Data is:<br />\n";
print_r($data);
}
foreach($this->validate as $field_name => $validators) {
if (VALIDATOR_DEBUG) {
// print_r($this->validate);
}
if (!isset($data[$field_name])) {
if (VALIDATOR_DEBUG) {
echo "Field not found=".$field_name."<br />\n";
}
continue;
}
foreach($validators as $validator) {
$checker = $validator;
if (VALIDATOR_DEBUG) {
echo "Validator-Array is:<br />\n";
print_r($validator);
}
if (!is_array($validator)) {
$checker = array($validator);
}
$checkerName = array_shift($checker);
$errorMessage = array_pop($checker);
if (VALIDATOR_DEBUG) {
echo "FieldName=".$field_name."/Value=".$data[$field_name]."<br />\n";
echo "CheckerName=".$checkerName."<br />\n";
echo "ErrorMessage=".$errorMessage."<br />\n";
}
if (!method_exists($this, $checkerName)) {
if (VALIDATOR_DEBUG) {
echo "Validator Methode not found=".$checkerName."<br />\n";
}
continue;
}
if (!$this->_check($data[$field_name], $checkerName, $checker, $data)) {
switch ($this->validationErrorMessages) {
default:
case INVALIDATE_SIMPLE: // One Name for all Errors
$field_to_invalidate = $field_name;
break;
case INVALIDATE_VERBOSE_ALL : // Fieldname plus Function Name are for Custom Errors
case INVALIDATE_VERBOSE_STEP : // Fieldname plus Function Name are for Custom Errors
$field_to_invalidate = $field_name.$checkerName;
break;
}
if (VALIDATOR_DEBUG) {
echo "Invalidated! with=".$field_to_invalidate."<br />\n";
}
$this->invalidate($field_to_invalidate, $errorMessage);
switch($this->validationErrorMessages) {
case INVALIDATE_SIMPLE: continue 3; // First broken Rule breaks the loop
case INVALIDATE_VERBOSE_ALL: continue 2; // All Validation Rules are parsed
case INVALIDATE_VERBOSE_STEP: continue 3; // First broken Rule breaks the loop
default: continue 3;
}
}
if (VALIDATOR_DEBUG) {
echo "FieldValue was OK<br />\n";
}
}
}
return $this->validationErrors;
}
// As following additional Validation Methods
function _check($field, $validator) {
$params = func_get_args();
if(method_exists($this, $validator)) {
return call_user_func(array(&$this, $validator), $field, $params);
}
}
function _chkIfNotEmpty() {
$args = func_get_args();
return !empty($args[0]);
}
function _chkIfMinimumLength() {
$args = func_get_args();
return strlen($args[0]) >= $args[1][2][0];
}
function _chkIfMaximumLength() {
$args = func_get_args();
return strlen($args[0]) <= $args[1][2][0];
}
function _chkIfHasLength() {
$args = func_get_args();
return strlen($args[0]) == $args[1][2][0];
}
function _chkIfIsOneOf() {
$args = func_get_args();
foreach($args[1][2] as $param) {
if ($param == $args[0]) {
return true;
}
}
return false;
}
function _chkIfOnlyNameChars() {
$args = func_get_args();
$value = strtr($args[0], VALID_NAME_CHARS_SYMBOLS, VALID_NAME_CHARS_CONVERT);
return $this->_chkByRegEx($value, VALID_NAME_CHARS);
}
function _chkIfNumber() {
$args = func_get_args();
return $this->_chkByRegEx($args[0], VALID_NUMBER);
}
function _chkIfEmail() {
$args = func_get_args();
return $this->_chkByRegEx($args[0], VALID_EMAIL);
}
function _chkIfYear() {
$args = func_get_args();
return $this->_chkByRegEx($args[0], VALID_YEAR);
}
function _chkIfMonth() {
$args = func_get_args();
return intval($args[0]) >= 1 && intval($args[0]) <= 12;
}
function _chkIfExistingDate() {
$args = func_get_args();
return $this->_parseDate($args[0], $args[1][2][0]) !== false;
}
function _chkIfMonthDay() {
$args = func_get_args();
return intval($args[0]) >= 1 && intval($args[0]) <= 31;
}
function _chkIfMatchesAnotherFieldValue() {
$args = func_get_args();
if (!isset($args[1][3][$args[1][2][0]])) {
return false;
}
return $args[0] == $args[1][3][$args[1][2][0]];
}
function _chkIfMd5() {
$args = func_get_args();
return $this->_chkByRegEx($args[0], VALID_MD5);
}
function _chkIfAdditionalFieldsAreNotEmpty() {
$args = func_get_args();
foreach($args[1][2] as $elem) {
if(empty($args[1][3][$elem])) {
return false;
}
}
return true;
}
/**
* Copy and Paste this into your Model if you need CreditCard Number
* Validation. Uncommenting works too, but this will load it into every model.
function _chkIfCreditCardNumber()
{
$args = func_get_args();
$value = $args[0];
$param = $args[1][2][1];
return $this->CCValidationSolution($value, $this->data[$this->name][$param]);
}
// CreditCard Check Code //////////////////////////////////////////////////////////////////////////////
function CCValidationSolution($number, $card = null)
{
$name = $this->CCNameSolution($number);
if(!$name) {
return false;
} else {
$CardName = $name['CardName'];
$ShouldLength = $name['ShouldLength'];
}
if($card != null) {
if($card != $CardName) {
return false;
}
}
$numberLength = strlen($number);
# 3) Is the number the right length?
if ($numberLength != $ShouldLength)
return false;
# 4) Does the number pass the Mod 10 Algorithm Checksum?
if ($this->Mod10Solution($number) == true)
return true;
else
return false;
}
function CCNameSolution($number)
{
$numberLeft = substr($number, 0, 4);
if ($numberLeft >= 3000 and $numberLeft <= 3059)
{
$CardName = 'Diners Club';
$ShouldLength = 14;
}
elseif ($numberLeft >= 3600 and $numberLeft <= 3699)
{
$CardName = 'Diners Club';
$ShouldLength = 14;
}
elseif ($numberLeft >= 3800 and $numberLeft <= 3889)
{
$CardName = 'Diners Club';
$ShouldLength = 14;
}
elseif ($numberLeft >= 3400 and $numberLeft <= 3499)
{
$CardName = 'American Express';
$ShouldLength = 15;
}
elseif ($numberLeft >= 3700 and $numberLeft <= 3799)
{
$CardName = 'American Express';
$ShouldLength = 15;
}
elseif ($numberLeft >= 3528 and $numberLeft <= 3589)
{
$CardName = 'JCB';
$ShouldLength = 16;
}
elseif ($numberLeft >= 3890 and $numberLeft <= 3899)
{
$CardName = 'Carte Blache';
$ShouldLength = 14;
}
elseif ($numberLeft >= 4000 and $numberLeft <= 4999)
{
$CardName = 'Visa';
$ShouldLength = 16;
}
elseif ($numberLeft >= 5100 and $numberLeft <= 5599)
{
$CardName = 'MasterCard';
$ShouldLength = 16;
}
elseif ($numberLeft == 5610)
{
$CardName = 'Australian BankCard';
$ShouldLength = 16;
}
elseif ($numberLeft == 6011)
{
$CardName = 'Discover/Novus';
$ShouldLength = 16;
}
if(isset($CardName) && isset($ShouldLength))
{
$return_array['CardName'] = $CardName;
$return_array['ShouldLength'] = $ShouldLength;
return $return_array;
}
else
return false;
}
function Mod10Solution($number)
{
$numberLength = strlen($number);
$Checksum = 0;
# Add even digits in even length strings
# or odd digits in odd length strings.
for ($Location = 1 - ($numberLength % 2); $Location < $numberLength; $Location += 2)
{
$Checksum += substr($number, $Location, 1);
}
# Analyze odd digits in even length strings
# or even digits in odd length strings.
for ($Location = ($numberLength % 2); $Location < $numberLength; $Location += 2)
{
$Digit = substr($number, $Location, 1) * 2;
if ($Digit < 10)
$Checksum += $Digit;
else
$Checksum += $Digit - 9;
}
# Is the checksum divisible by ten?
return ($Checksum % 10 == 0);
}
*/
function _chkByRegEx($value, $regEx) {
return preg_match($regEx, $value);
}
/**
* Returns a formatted date from a string based on a given format
*
* Supported formats
*
* %Y - year as a decimal number including the century
* %m - month as a decimal number (range 1 to 12)
* %d - day of the month as a decimal number (range 1 to 31)
*
* %H - hour as decimal number using a 24-hour clock (range 0 to 23)
* %M - minute as decimal number
* %s - second as decimal number
* %u - microsec as decimal number
* @param string date string to convert to date
* @param string format expected format of the original date
* @return string rfc3339 w/o timezone YYYY-MM-DD YYYY-MM-DDThh:mm:ss YYYY-MM-DDThh:mm:ss.s
*/
function _parseDate($date, $format) {
// Builds up date pattern from the given $format, keeping delimiters in place.
if (!preg_match_all("/%([YmdHMsu])([^%])*/", $format, $formatTokens, PREG_SET_ORDER)) {
return false;
}
$datePattern = '';
foreach ($formatTokens as $formatToken) {
if (!isset($formatToken[2])) {
$formatToken[2] = '';
}
$delimiter = preg_quote($formatToken[2], '/');
if ($formatToken[1] == 'Y') {
$datePattern .= '(.{1,4})'.$delimiter;
} elseif ($formatToken[1] == 'u') {
$datePattern .= '(.{1,5})'.$delimiter;
} else {
$datePattern .= '(.{1,2})'.$delimiter;
}
}
// Splits up the given $date
if (!preg_match('/'.$datePattern.'/', $date, $dateTokens)) {
return false;
}
$dateSegments = array();
for ($i = 0; $i < count($formatTokens); $i++) {
$dateSegments[$formatTokens[$i][1]] = $dateTokens[$i+1];
}
// Reformats the given $date into rfc3339
if (isset($dateSegments['Y']) && isset($dateSegments['m']) && isset($dateSegments['d'])) {
if (!checkdate($dateSegments['m'], $dateSegments['d'], $dateSegments['Y'])) {
return false;
}
$dateReformated = str_pad($dateSegments['Y'], 4, '0', STR_PAD_LEFT).'-'.
str_pad($dateSegments['m'], 2, '0', STR_PAD_LEFT).'-'.
str_pad($dateSegments['d'], 2, '0', STR_PAD_LEFT);
} else {
return false;
}
if (isset($dateSegments['H']) && isset($dateSegments['M'])) {
if (intval($dateSegments['H']) < 0 || intval($dateSegments['H']) > 23) {
return false;
}
if (intval($dateSegments['M']) < 0 || intval($dateSegments['M']) > 59) {
return false;
}
if (intval($dateSegments['s']) < 0 || intval($dateSegments['s']) > 59) {
return false;
}
$dateReformated .= 'T'.str_pad($dateSegments['H'], 2, '0', STR_PAD_LEFT).':'.
str_pad($dateSegments['M'], 2, '0', STR_PAD_LEFT);
if (isset($dateSegments['s'])) {
$dateReformated .= ':'.str_pad($dateSegments['s'], 2, '0', STR_PAD_LEFT);
if (isset($dateSegments['u'])) {
$dateReformated .= '.'.str_pad($dateSegments['u'], 5, '0', STR_PAD_RIGHT);
}
}
}
return $dateReformated;
}
function invalidate($field, $message) {
if (!is_array($this->validationErrors)) {
$this->validationErrors = array();
}
if (!is_array($this->validationErrorMessage)) {
$this->validationErrorMessage = array();
}
$this->validationErrors[$field] = 1;
$this->validationErrorMessage[] = $message;
}
}
?>
You can submit a new version of this snippet if you have modified it and you feel it is appropriate to share with others..