Created
September 6, 2013 23:01
-
-
Save NaszvadiG/6471144 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); | |
/** | |
* CodeIgniter Better Form Validation | |
* | |
* @package CodeIgniter | |
* @author Sepehr Lajevardi <me@sepehr.ws> | |
* @copyright Copyright (c) 2012 Sepehr Lajevardi. | |
* @license http://codeigniter.com/user_guide/license.html | |
* @link https://github.com/sepehr/ci-form-validation | |
* @version Version 1.0 | |
* @filesource | |
*/ | |
// ------------------------------------------------------------------------ | |
/** | |
* CI Form Validation Extension. | |
* | |
* @package CodeIgniter | |
* @subpackage Libraries | |
* @category Forms | |
* @author Sepehr Lajevardi <me@sepehr.ws> | |
* @link https://github.com/sepehr/ci-form-validation | |
* @todo - Document. | |
*/ | |
class MY_Form_validation extends CI_Form_validation { | |
/** | |
* Stores CI superglobal. | |
*/ | |
public $CI; | |
// ------------------------------------------------------------------------ | |
/** | |
* Class constructor | |
*/ | |
function __construct($params = array()) | |
{ | |
// Merge $_FILES and $_POST arrays and let lazies cheer! | |
if (isset($_FILES) AND is_array($_FILES) AND ! empty($_FILES)) | |
{ | |
$_POST = array_merge($_POST, $_FILES); | |
} | |
parent::__construct($params); | |
} | |
// ------------------------------------------------------------------------ | |
/** | |
* Provides easy-lazy access to CI's superobject. | |
*/ | |
function __get($var) | |
{ | |
return $this->CI->$var; | |
} | |
// -------------------------------------------------------------------- | |
// Parent Extensions | |
// -------------------------------------------------------------------- | |
/** | |
* Executes form validation. | |
* | |
* Extends default run() regarding HMVC compatibility. | |
*/ | |
public function run($module = '', $group = '') | |
{ | |
is_object($module) AND $this->CI =& $module; | |
return parent::run($group); | |
} | |
// ------------------------------------------------------------------------ | |
// Authentication Validation Callbacks (Requires IonAuth) | |
// ------------------------------------------------------------------------ | |
/** | |
* Custom validation callback to validate password length. | |
* | |
* Note: It's only usable for "password" fields. | |
*/ | |
public function check_pass($pass) | |
{ | |
if ( ! empty($pass)) | |
{ | |
$pass = strlen($pass); | |
// Get password length configs | |
$min = $this->config->item('min_password_length', 'ion_auth'); | |
$max = $this->config->item('max_password_length', 'ion_auth'); | |
// Set callback's custom error message | |
$this->set_message('check_pass', "Incorrect password length. Minimum: $min, maximum: $max"); | |
return $pass >= $min AND $pass <= $max; | |
} | |
return TRUE; | |
} | |
// ------------------------------------------------------------------------ | |
/** | |
* Custom validation callback to verify user credentials. | |
* | |
* Note: It's only usable for "password" fields. | |
*/ | |
public function check_login($pass, $email) | |
{ | |
// Set callback's custom error message | |
$this->set_message('check_login', 'Invalid username/password combination.'); | |
return $this->auth->login($this->input->post($email), $pass, TRUE); | |
} | |
// ------------------------------------------------------------------------ | |
/** | |
* Custom validation callback to verify user group. | |
* | |
* NOTE: The user should be already logged in and its only usable for "password" fields. | |
*/ | |
public function check_group($pass, $group) | |
{ | |
if ( ! $this->auth->in_group($group)) | |
{ | |
// Set callback's custom error message | |
$this->set_message('check_group', "Your account is not registered as a $group."); | |
// Make sure that user is already logged out | |
$this->auth->logout(); | |
$this->user = array(); | |
return FALSE; | |
} | |
return TRUE; | |
} | |
// ------------------------------------------------------------------------ | |
/** | |
* Custom validation callback to check existing email. | |
* | |
* Note: It's only usable for "email" fields. | |
*/ | |
public function check_email_existing($email) | |
{ | |
// Set callback's custom error message | |
$this->set_message('check_email_existing', 'E-mail address not found.'); | |
return $this->auth->email_check($email); | |
} | |
// ------------------------------------------------------------------------ | |
/** | |
* Custom validation callback to check if an email is free. | |
* | |
* Note: It's only usable for "email" fields. | |
*/ | |
public function check_email_free($email) | |
{ | |
// Set callback's custom error message | |
$this->set_message('check_email_free', 'E-mail address already exists.'); | |
return ! $this->auth->email_check($email); | |
} | |
// ------------------------------------------------------------------------ | |
/** | |
* Custom validation callback to check existing username. | |
* | |
* Note: It's only usable for "username" fields. | |
*/ | |
public function check_username($username) | |
{ | |
// Set callback's custom error message | |
$this->set_message('check_username', 'Username is not available to register.'); | |
return $this->auth->username_check($username); | |
} | |
// ------------------------------------------------------------------------ | |
// UK Address Validators (Application Specific) | |
// ------------------------------------------------------------------------ | |
/** | |
* Custom validation callback to validate Country field. | |
* | |
* It's identical to "required" rule but with just one exception, | |
* if the "county" field is set to "Channel Islands" which has | |
* no "country" associated with. | |
* | |
* Note: It's only usable for "country" fields. | |
*/ | |
public function check_country($country, $county) | |
{ | |
// Set callback's custom error message | |
$this->set_message('check_country', 'The Country field is required.'); | |
// Get county value from $_POST array | |
$county = $this->input->post($county); | |
return $county === 'Channel Islands' ? TRUE : (bool) $country; | |
} | |
// ------------------------------------------------------------------------ | |
/** | |
* Custom validation callback to validate County field. | |
* | |
* Checks if the conty is located in the specified country. | |
*/ | |
public function check_county($county, $country) | |
{ | |
// This kid got no parent, skip | |
if ($county === 'Channel Islands') | |
{ | |
return TRUE; | |
} | |
// Set callback's custom error message | |
$this->set_message('check_county', 'Please provide a valid county/country combination.'); | |
// Get country value | |
$country = $this->input->post($country); | |
if (! $country) | |
{ | |
return FALSE; | |
} | |
// Load town model, if not yet loaded | |
class_exists('Town_model') OR $this->load->model('system/town_model'); | |
// Prepare country value. Weired widget, you know! | |
$criteria = in_array($country, array( | |
// List of non-england countries: | |
'N. Ireland', 'Scotland', 'Wales', | |
)) ? 'country' : 'region'; | |
// Count documents matching both county and country/region | |
return (bool) $this->town_model->count_by(array( | |
'county' => $county, | |
$criteria => $country, | |
)); | |
} | |
// ------------------------------------------------------------------------ | |
/** | |
* Custom validation callback to validate Town field. | |
* | |
* Checks if the town is located in the specified county. | |
*/ | |
public function check_town($town, $county = FALSE) | |
{ | |
if ( ! $town) | |
{ | |
return TRUE; | |
} | |
// Set callback's custom error message | |
$this->set_message('check_town', $county | |
? 'Please provide a valid town/county combination.' | |
: 'Please provide a valid town.'); | |
// Get county value if set | |
$county AND $county = $this->input->post($county); | |
// Load town model, if not yet loaded | |
class_exists('Town_model') OR $this->load->model('system/town_model'); | |
// Buildup conditions array | |
$wheres = array('town' => $town); | |
$county AND $wheres['county'] = $county; | |
// Count documents matching town, and county if set | |
return (bool) $this->town_model->count_by($wheres); | |
} | |
// ------------------------------------------------------------------------ | |
/** | |
* Custom validation callback to validate UK postcodes. | |
* | |
* It also tries to format provided postcode in correct format. | |
* | |
* Note: It's only usable for "postcode" fields. | |
*/ | |
public function check_postcode_uk($original_postcode) | |
{ | |
// Set callback's custom error message | |
$this->set_message('check_postcode_uk', 'Invalid UK postcode format.'); | |
// Permitted letters depend upon their position in the postcode. | |
// Character 1 | |
$alpha1 = "[abcdefghijklmnoprstuwyz]"; | |
// Character 2 | |
$alpha2 = "[abcdefghklmnopqrstuvwxy]"; | |
// Character 3 | |
$alpha3 = "[abcdefghjkpmnrstuvwxy]"; | |
// Character 4 | |
$alpha4 = "[abehmnprvwxy]"; | |
// Character 5 | |
$alpha5 = "[abdefghjlnpqrstuwxyz]"; | |
// Expression for postcodes: AN NAA, ANN NAA, AAN NAA, and AANN NAA with a space | |
$pcexp[0] = '/^('.$alpha1.'{1}'.$alpha2.'{0,1}[0-9]{1,2})([[:space:]]{0,})([0-9]{1}'.$alpha5.'{2})$/'; | |
// Expression for postcodes: ANA NAA | |
$pcexp[1] = '/^('.$alpha1.'{1}[0-9]{1}'.$alpha3.'{1})([[:space:]]{0,})([0-9]{1}'.$alpha5.'{2})$/'; | |
// Expression for postcodes: AANA NAA | |
$pcexp[2] = '/^('.$alpha1.'{1}'.$alpha2.'{1}[0-9]{1}'.$alpha4.')([[:space:]]{0,})([0-9]{1}'.$alpha5.'{2})$/'; | |
// Exception for the special postcode GIR 0AA | |
$pcexp[3] = '/^(gir)([[:space:]]{0,})(0aa)$/'; | |
// Standard BFPO numbers | |
$pcexp[4] = '/^(bfpo)([[:space:]]{0,})([0-9]{1,4})$/'; | |
// c/o BFPO numbers | |
$pcexp[5] = '/^(bfpo)([[:space:]]{0,})(c\/o([[:space:]]{0,})[0-9]{1,3})$/'; | |
// Overseas Territories | |
$pcexp[6] = '/^([a-z]{4})([[:space:]]{0,})(1zz)$/'; | |
// Anquilla | |
$pcexp[7] = '/^ai-2640$/'; | |
// Load up the string to check, converting into lowercase | |
$postcode = strtolower($original_postcode); | |
// Assume we are not going to find a valid postcode | |
$valid = FALSE; | |
// Check the string against the six types of postcodes | |
foreach ($pcexp as $regexp) | |
{ | |
if (preg_match($regexp, $postcode, $matches)) | |
{ | |
// Load new postcode back into the form element | |
$postcode = strtoupper ($matches[1] . ' ' . $matches [3]); | |
// Take account of the special BFPO c/o format | |
$postcode = preg_replace ('/C\/O([[:space:]]{0,})/', 'c/o ', $postcode); | |
// Take acount of special Anquilla postcode format (a pain, but that's the way it is) | |
preg_match($pcexp[7], strtolower($original_postcode), $matches) AND $postcode = 'AI-2640'; | |
// Remember that we have found that the code is valid and break from loop | |
$valid = TRUE; | |
break; | |
} | |
} | |
// Return with the reformatted valid postcode in uppercase if the postcode was | |
return $valid ? $postcode : FALSE; | |
} | |
// ------------------------------------------------------------------------ | |
/** | |
* Custom validation callback to validate UK phone format. | |
* | |
* Note: It's only usable for "phone" fields. | |
*/ | |
public function check_phone_uk($phone) | |
{ | |
// Setting custom validation error | |
// There are more specific error messages commented out in the function | |
$this->set_message('check_phone_uk', 'Please provide a valid phone number, e.g. 07777 222222'); | |
// Copy the parameter and strip out the spaces | |
$phone_copy = str_replace(' ', '', $phone); | |
// Convert into a string and check that we were provided with something | |
if (empty($phone_copy)) | |
{ | |
// $this->set_message('check_phone_uk', 'Telephone number not provided.'); | |
return FALSE; | |
} | |
// Don't allow country codes to be included (assumes a leading "+") | |
if (preg_match('/^(\+)[\s]*(.*)$/',$phone_copy)) | |
{ | |
// $this->set_message('check_phone_uk', 'UK number without country code, please.'); | |
return FALSE; | |
} | |
// Remove hyphens - they are not part of a telephone number | |
$phone_copy = str_replace('-', '', $phone_copy); | |
// Now check that all the characters are digits | |
if ( ! preg_match('/^[0-9]{10,11}$/',$phone_copy)) | |
{ | |
// $this->set_message('check_phone_uk', 'UK numbers should contain 10 or 11 digits.'); | |
return FALSE; | |
} | |
// Now check that the first digit is 0 | |
if ( ! preg_match('/^0[0-9]{9,10}$/',$phone_copy)) | |
{ | |
// $this->set_message('check_phone_uk', 'The number should start with a 0.'); | |
return FALSE; | |
} | |
// Check the string against the numbers allocated for dramas | |
// Expression for numbers allocated to dramas | |
$tnexp[0] = '/^(0113|0114|0115|0116|0117|0118|0121|0131|0141|0151|0161)(4960)[0-9]{3}$/'; | |
$tnexp[1] = '/^02079460[0-9]{3}$/'; | |
$tnexp[2] = '/^01914980[0-9]{3}$/'; | |
$tnexp[3] = '/^02890180[0-9]{3}$/'; | |
$tnexp[4] = '/^02920180[0-9]{3}$/'; | |
$tnexp[5] = '/^01632960[0-9]{3}$/'; | |
$tnexp[6] = '/^07700900[0-9]{3}$/'; | |
$tnexp[7] = '/^08081570[0-9]{3}$/'; | |
$tnexp[8] = '/^09098790[0-9]{3}$/'; | |
$tnexp[9] = '/^03069990[0-9]{3}$/'; | |
foreach ($tnexp as $regexp) | |
{ | |
if (preg_match($regexp, $phone_copy, $matches)) | |
{ | |
// $this->set_message('check_phone_uk', 'The number is either invalid or inappropriate.'); | |
return FALSE; | |
} | |
} | |
// Finally, check that the telephone number is appropriate. | |
if ( ! preg_match('/^(01|02|03|05|070|071|072|073|074|075|07624|077|078|079)[0-9]+$/', $phone_copy)) | |
{ | |
// $this->set_message('check_phone_uk', 'The number is either invalid or inappropriate.'); | |
return FALSE; | |
} | |
// Seems to be valid, return the stripped telephone number | |
return $phone_copy; | |
} | |
// -------------------------------------------------------------------- | |
// Misc. Custom Validation Callbacks | |
// -------------------------------------------------------------------- | |
/** | |
* Improved version of CI matches rule. | |
*/ | |
public function matches($string, $args) | |
{ | |
// Extract args and get field name and label | |
list($field, $label) = array_map('trim', explode(',', $args)); | |
// Set label if not provided | |
$label OR $label = $field; | |
// Set callback's custom error message | |
$this->set_message('matches', "The %s field does not match the $label."); | |
if ( ! isset($_POST[$field])) | |
{ | |
return FALSE; | |
} | |
// Fetch password value | |
$field = $_POST[$field]; | |
return $string === $field; | |
} | |
// ------------------------------------------------------------------------ | |
/** | |
* Checks that a string only contains alphanum chars plus: | |
* - Spaces | |
* - Periods | |
* - Underscores | |
* - Dashes | |
*/ | |
function alpha_extra($string) | |
{ | |
// Set callback's custom error message | |
$this->set_message('alpha_extra', 'The %s field may only contain alpha-numeric characters, spaces, periods, underscores, and dashes.'); | |
return (bool) preg_match("/^([\.\s-a-z0-9_-])+$/i", $string); | |
} | |
// -------------------------------------------------------------------- | |
/** | |
* Checks that the string matches the passed regex pattern. | |
*/ | |
function regex($string, $pattern) | |
{ | |
// Set callback's custom error message | |
$this->set_message('regex', 'The %s field does not match the required pattern.'); | |
return (bool) preg_match('/^' . $pattern . '$/', $string); | |
} | |
// -------------------------------------------------------------------- | |
/** | |
* Checks that the passed string is one of the values entered as the second parameter. | |
* | |
* Usage: 'required|one_of[option1,option2,option3]' | |
*/ | |
public function one_of($string, $options = NULL) | |
{ | |
if ($options) | |
{ | |
// Set callback's custom error message | |
$this->set_message('one_of', "%s must contain one of the allowed options: $options"); | |
return in_array($string, explode(',', $options)); | |
} | |
return TRUE; | |
} | |
// -------------------------------------------------------------------- | |
// General File Validation Callbacks | |
// -------------------------------------------------------------------- | |
/** | |
* Checks file extension against passed allowed types. | |
* | |
* Usage: 'required|file_types[doc,pdf,rtf,odt]' | |
*/ | |
public function file_types($file, $types = NULL) | |
{ | |
if ($types) | |
{ | |
// Set callback's custom error message | |
$this->set_message('allowed_types', "%s has an invalid type. Allowed types are: $types"); | |
// Get types | |
$types = explode(',', $types); | |
$file_type = pathinfo($file['name'], PATHINFO_EXTENSION); | |
return in_array($file_type, $types); | |
} | |
return TRUE; | |
} | |
// -------------------------------------------------------------------- | |
/** | |
* Checks filesize against passed maximum size. | |
* | |
* Usage: 'required|file_max_size[1024]' | |
*/ | |
public function file_max_size($file, $size = 0) | |
{ | |
if ($size) | |
{ | |
// Set callback's custom error message | |
$this->set_message('one_of', "Invalid size for %s. Maximum size is: $size"); | |
return (bool) $file['size'] <= $size; | |
} | |
return TRUE; | |
} | |
// -------------------------------------------------------------------- | |
} | |
// End of MY_Form_validation class | |
/* End of file MY_Form_validation.php */ | |
/* Location: ./application/libraries/MY_Form_validation.php */ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment