Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixed errors and modified code so it is consistent through out the file #13

Merged
merged 1 commit into from Nov 6, 2012
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
235 changes: 137 additions & 98 deletions validators/EIBANValidator/EIBANValidator.php
Expand Up @@ -33,25 +33,30 @@
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/ */
class EIBANValidator extends CValidator{ class EIBANValidator extends CValidator
{
const NOTSUPPORTED = 'IBAN_Not_Supported'; const NOTSUPPORTED = 'IBAN_Not_Supported';
const WRONGFORMAT = 'Wrong_IBAN_Format'; const WRONGFORMAT = 'Wrong_IBAN_Format';
const WRONGLENGTH = 'Wrong_IBAN_Length'; const WRONGLENGTH = 'Wrong_IBAN_Length';
const CHECKFAILED = 'IBAN_Check_Failed'; const CHECKFAILED = 'IBAN_Check_Failed';


/** /**
* Validation failure message template definitions * Validation failure message template definitions
* *
* @var array * @var array
*/ */
protected $_messages = array( protected $_messages = array(
self::NOTSUPPORTED => "Unknown country within the IBAN '{value}'", self::NOTSUPPORTED => "Unknown country within the IBAN '{value}'",
self::WRONGFORMAT => "'{value}' has a false IBAN format", self::WRONGFORMAT => "'{value}' has a false IBAN format",
self::WRONGLENGTH => "'{value}' has wrong IBAN length for specified country", self::WRONGLENGTH => "'{value}' has wrong IBAN length for specified country",
self::CHECKFAILED => "'{value}' has failed the IBAN check", self::CHECKFAILED => "'{value}' has failed the IBAN check",
); );


/**
* IBAN lengths for each country
*
* @var array
*/
protected $_lengths = array( protected $_lengths = array(
'AD'=>24,'AT'=>20,'BA'=>20,'BE'=>16,'BG'=>22, 'AD'=>24,'AT'=>20,'BA'=>20,'BE'=>16,'BG'=>22,
'CH'=>21,'CS'=>22,'CY'=>28,'CZ'=>24,'DE'=>22, 'CH'=>21,'CS'=>22,'CY'=>28,'CZ'=>24,'DE'=>22,
Expand All @@ -65,140 +70,174 @@ class EIBANValidator extends CValidator{
'SM'=>27,'TF'=>27,'TN'=>24,'TR'=>26,'YT'=>27, 'SM'=>27,'TF'=>27,'TN'=>24,'TR'=>26,'YT'=>27,
'WF'=>27 'WF'=>27
); );

/**
* IBAN patterns for each country
*
* @var array
*/
protected $_patterns = array( protected $_patterns = array(
'AD' => '/^AD[0-9]{2}[0-9]{8}[A-Z0-9]{12}$/', // Andorra 'AD' => '/^AD[0-9]{2}[0-9]{8}[A-Z0-9]{12}$/', // Andorra
'AT' => '/^AT[0-9]{2}[0-9]{5}[0-9]{11}$/', // Austria 'AT' => '/^AT[0-9]{2}[0-9]{5}[0-9]{11}$/', // Austria
'BA' => '/^BA[0-9]{2}[0-9]{6}[0-9]{10}$/', // Bosnia and Herzegovina 'BA' => '/^BA[0-9]{2}[0-9]{6}[0-9]{10}$/', // Bosnia and Herzegovina
'BE' => '/^BE[0-9]{2}[0-9]{3}[0-9]{9}$/', // Belgium 'BE' => '/^BE[0-9]{2}[0-9]{3}[0-9]{9}$/', // Belgium
'BG' => '/^BG[0-9]{2}[A-Z]{4}[0-9]{4}[0-9]{2}[A-Z0-9]{8}$/', // Bulgaria 'BG' => '/^BG[0-9]{2}[A-Z]{4}[0-9]{4}[0-9]{2}[A-Z0-9]{8}$/', // Bulgaria
'CH' => '/^CH[0-9]{2}[0-9]{5}[A-Z0-9]{12}$/', // Switzerland 'CH' => '/^CH[0-9]{2}[0-9]{5}[A-Z0-9]{12}$/', // Switzerland
// CS to Serbia and Montenegro until the split into rs (Serbia) and me (Montenegro) // CS to Serbia and Montenegro until the split into rs (Serbia) and me (Montenegro)
'CS' => '/^CS[0-9]{2}[0-9]{3}[0-9]{15}$/', // Serbia and Montenegro 'CS' => '/^CS[0-9]{2}[0-9]{3}[0-9]{15}$/', // Serbia and Montenegro
'CY' => '/^CY[0-9]{2}[0-9]{8}[A-Z0-9]{16}$/', // Cyrus 'CY' => '/^CY[0-9]{2}[0-9]{8}[A-Z0-9]{16}$/', // Cyrus
'CZ' => '/^CZ[0-9]{2}[0-9]{4}[0-9]{16}$/', // Czech Republic 'CZ' => '/^CZ[0-9]{2}[0-9]{4}[0-9]{16}$/', // Czech Republic
'DE' => '/^DE[0-9]{2}[0-9]{8}[0-9]{10}$/', // Germany 'DE' => '/^DE[0-9]{2}[0-9]{8}[0-9]{10}$/', // Germany
'DK' => '/^DK[0-9]{2}[0-9]{4}[0-9]{10}$/', // Denmark 'DK' => '/^DK[0-9]{2}[0-9]{4}[0-9]{10}$/', // Denmark
'EE' => '/^EE[0-9]{2}[0-9]{4}[0-9]{12}$/', // Estonia 'EE' => '/^EE[0-9]{2}[0-9]{4}[0-9]{12}$/', // Estonia
'ES' => '/^ES[0-9]{2}[0-9]{8}[0-9]{12}$/', // Spain 'ES' => '/^ES[0-9]{2}[0-9]{8}[0-9]{12}$/', // Spain
'FR' => '/^FR[0-9]{2}[0-9]{10}[A-Z0-9]{13}$/', // France 'FR' => '/^FR[0-9]{2}[0-9]{10}[A-Z0-9]{13}$/', // France
'FI' => '/^FI[0-9]{2}[0-9]{6}[0-9]{8}$/', // Finland 'FI' => '/^FI[0-9]{2}[0-9]{6}[0-9]{8}$/', // Finland
'GB' => '/^GB[0-9]{2}[A-Z]{4}[0-9]{14}$/', // United Kingdom 'GB' => '/^GB[0-9]{2}[A-Z]{4}[0-9]{14}$/', // United Kingdom
'GI' => '/^GI[0-9]{2}[A-Z]{4}[A-Z0-9]{15}$/', // Gibraltar 'GI' => '/^GI[0-9]{2}[A-Z]{4}[A-Z0-9]{15}$/', // Gibraltar
'GR' => '/^GR[0-9]{2}[0-9]{7}[A-Z0-9]{16}$/', // Greece 'GR' => '/^GR[0-9]{2}[0-9]{7}[A-Z0-9]{16}$/', // Greece
'HR' => '/^HR[0-9]{2}[0-9]{7}[0-9]{10}$/', // Croatia 'HR' => '/^HR[0-9]{2}[0-9]{7}[0-9]{10}$/', // Croatia
'HU' => '/^HU[0-9]{2}[0-9]{7}[0-9]{1}[0-9]{15}[0-9]{1}$/', // Hungary 'HU' => '/^HU[0-9]{2}[0-9]{7}[0-9]{1}[0-9]{15}[0-9]{1}$/', // Hungary
'IE' => '/^IE[0-9]{2}[A-Z0-9]{4}[0-9]{6}[0-9]{8}$/', // Ireland 'IE' => '/^IE[0-9]{2}[A-Z0-9]{4}[0-9]{6}[0-9]{8}$/', // Ireland
'IS' => '/^IS[0-9]{2}[0-9]{4}[0-9]{18}$/', // Iceland 'IS' => '/^IS[0-9]{2}[0-9]{4}[0-9]{18}$/', // Iceland
'IT' => '/^IT[0-9]{2}[A-Z]{1}[0-9]{10}[A-Z0-9]{12}$/', // Italy 'IT' => '/^IT[0-9]{2}[A-Z]{1}[0-9]{10}[A-Z0-9]{12}$/', // Italy
'LI' => '/^LI[0-9]{2}[0-9]{5}[A-Z0-9]{12}$/', // Liechtenstein 'LI' => '/^LI[0-9]{2}[0-9]{5}[A-Z0-9]{12}$/', // Liechtenstein
'LU' => '/^LU[0-9]{2}[0-9]{3}[A-Z0-9]{13}$/', // Luxembourg 'LU' => '/^LU[0-9]{2}[0-9]{3}[A-Z0-9]{13}$/', // Luxembourg
'LT' => '/^LT[0-9]{2}[0-9]{5}[0-9]{11}$/', // Lithuania 'LT' => '/^LT[0-9]{2}[0-9]{5}[0-9]{11}$/', // Lithuania
'LV' => '/^LV[0-9]{2}[A-Z]{4}[A-Z0-9]{13}$/', // Latvia 'LV' => '/^LV[0-9]{2}[A-Z]{4}[A-Z0-9]{13}$/', // Latvia
'MC' => '/^MC(\d{2})(\d{5})(\d{5})([A-Za-z0-9]{11})(\d{2})$/', // Monaco 'MC' => '/^MC(\d{2})(\d{5})(\d{5})([A-Za-z0-9]{11})(\d{2})$/', // Monaco
'ME' => '/^ME(\d{2})(\d{3})(\d{13})(\d{2})$/', // Montenegro 'ME' => '/^ME(\d{2})(\d{3})(\d{13})(\d{2})$/', // Montenegro
'MU' => '/^MU(\d{2})([A-Z]{4})(\d{2})(\d{2})(\d{12})(\d{3})([A-Z]{3})$/',// Mauritius 'MU' => '/^MU(\d{2})([A-Z]{4})(\d{2})(\d{2})(\d{12})(\d{3})([A-Z]{3})$/',// Mauritius
'MK' => '/^MK(\d{2})(\d{3})([A-Za-z0-9]{10})(\d{2})$/', // Macedonia MK07 250 1200000589 84 3n,10c,2n 'MK' => '/^MK(\d{2})(\d{3})([A-Za-z0-9]{10})(\d{2})$/', // Macedonia MK07 250 1200000589 84 3n,10c,2n
'MT' => '/^MT[0-9]{2}[A-Z]{4}[0-9]{5}[A-Z0-9]{18}$/', // Malta 'MT' => '/^MT[0-9]{2}[A-Z]{4}[0-9]{5}[A-Z0-9]{18}$/', // Malta
'NC' => '/^NC(\d{2})(\d{5})(\d{5})([A-Za-z0-9]{11})(\d{2})$/', // New Caledonia 'NC' => '/^NC(\d{2})(\d{5})(\d{5})([A-Za-z0-9]{11})(\d{2})$/', // New Caledonia
'NL' => '/^NL[0-9]{2}[A-Z]{4}[0-9]{10}$/', // The Netherlands 'NL' => '/^NL[0-9]{2}[A-Z]{4}[0-9]{10}$/', // The Netherlands
'NO' => '/^NO[0-9]{2}[0-9]{4}[0-9]{7}$/', // Norway 'NO' => '/^NO[0-9]{2}[0-9]{4}[0-9]{7}$/', // Norway
'PF' => '/^PF(\d{2})(\d{5})(\d{5})([A-Za-z0-9]{11})(\d{2})$/', // French Polynesia 'PF' => '/^PF(\d{2})(\d{5})(\d{5})([A-Za-z0-9]{11})(\d{2})$/', // French Polynesia
'PL' => '/^PL[0-9]{2}[0-9]{8}[0-9]{16}$/', // Poland 'PL' => '/^PL[0-9]{2}[0-9]{8}[0-9]{16}$/', // Poland
'PM' => '/^PM(\d{2})(\d{5})(\d{5})([A-Za-z0-9]{11})(\d{2})$/', // Saint Pierre et Miquelon 'PM' => '/^PM(\d{2})(\d{5})(\d{5})([A-Za-z0-9]{11})(\d{2})$/', // Saint Pierre et Miquelon
'PT' => '/^PT[0-9]{2}[0-9]{8}[0-9]{13}$/', // Portugal 'PT' => '/^PT[0-9]{2}[0-9]{8}[0-9]{13}$/', // Portugal
'RO' => '/^RO[0-9]{2}[A-Z]{4}[A-Z0-9]{16}$/', // Romania 'RO' => '/^RO[0-9]{2}[A-Z]{4}[A-Z0-9]{16}$/', // Romania
'RS' => '/^RS(\d{2})(\d{3})(\d{13})(\d{2})$/', // Serbia 'RS' => '/^RS(\d{2})(\d{3})(\d{13})(\d{2})$/', // Serbia
'SA' => '/^SA(\d{2})(\d{2})([A-Za-z0-9]{18})$/', // Saudi Arabia 'SA' => '/^SA(\d{2})(\d{2})([A-Za-z0-9]{18})$/', // Saudi Arabia
'SE' => '/^SE[0-9]{2}[0-9]{3}[0-9]{17}$/', // Sweden 'SE' => '/^SE[0-9]{2}[0-9]{3}[0-9]{17}$/', // Sweden
'SI' => '/^SI[0-9]{2}[0-9]{5}[0-9]{8}[0-9]{2}$/', // Slovenia 'SI' => '/^SI[0-9]{2}[0-9]{5}[0-9]{8}[0-9]{2}$/', // Slovenia
'SK' => '/^SK[0-9]{2}[0-9]{4}[0-9]{16}$/', // Slovak Republic 'SK' => '/^SK[0-9]{2}[0-9]{4}[0-9]{16}$/', // Slovak Republic
'SM' => '/^SM(\d{2})([A-Z]{1})(\d{5})(\d{5})([A-Za-z0-9]{12})$/', // San Marino 'SM' => '/^SM(\d{2})([A-Z]{1})(\d{5})(\d{5})([A-Za-z0-9]{12})$/', // San Marino
'TF' => '/^TF(\d{2})(\d{5})(\d{5})([A-Za-z0-9]{11})(\d{2})$/', // French Southern Territories 'TF' => '/^TF(\d{2})(\d{5})(\d{5})([A-Za-z0-9]{11})(\d{2})$/', // French Southern Territories
'TN' => '/^TN[0-9]{2}[0-9]{5}[0-9]{15}$/', // Tunisia 'TN' => '/^TN[0-9]{2}[0-9]{5}[0-9]{15}$/', // Tunisia
'TR' => '/^TR[0-9]{2}[0-9]{5}[A-Z0-9]{17}$/', // Turkey 'TR' => '/^TR[0-9]{2}[0-9]{5}[A-Z0-9]{17}$/', // Turkey
'YT' => '/^YT(\d{2})(\d{5})(\d{5})([A-Za-z0-9]{11})(\d{2})$/', // Mayotte 'YT' => '/^YT(\d{2})(\d{5})(\d{5})([A-Za-z0-9]{11})(\d{2})$/', // Mayotte
'WF' => '/^WF(\d{2})(\d{5})(\d{5})([A-Za-z0-9]{11})(\d{2})$/' // Wallis and Futuna Islands 'WF' => '/^WF(\d{2})(\d{5})(\d{5})([A-Za-z0-9]{11})(\d{2})$/' // Wallis and Futuna Islands
); );



/** /**
* @var boolean whether the attribute value can be null or empty. Defaults to true, * @var boolean whether the attribute value can be null or empty. Defaults to true,
* meaning that if the attribute is empty, it is considered valid. * meaning that if the attribute is empty, it is considered valid.
*/ */
public $allowEmpty=true; public $allowEmpty = true;

/** /**
* (non-PHPdoc) * Validates a single attribute.
* @see CValidator::validateAttribute() *
* @param CModel $object the data object being validated
* @param string $attribute the name of the attribute to be validated.
*/ */
protected function validateAttribute($object,$attribute){ protected function validateAttribute($object, $attribute)
{
$value=$object->$attribute; $value=$object->$attribute;
if($this->allowEmpty && $this->isEmpty($value)) if ($this->isEmpty($value))
return;

$return = $this->validateIBAN($value);

if( true !== $return )
{ {
$message=$this->message!==null?$this->message:$this->getErrorMessage($return, $value); if ($this->allowEmpty)
$this->addError($object,$attribute,$message); {
return;
}
else
{
$arrValidators = $object->getValidators($attribute);
foreach ($arrValidators as $objValidator)
{ // do not duplicate error message if attribute is already required
if ($objValidator instanceof CRequiredValidator)
return;
}

$message=$this->message!==null?$this->message:Yii::t('yii','{attribute} cannot be blank.');
$this->addError($object,$attribute,$message);
}
}
else
{
$return = $this->validateIBAN($value);

if (true !== $return)
{
$message=$this->message!==null?$this->message:$this->getErrorMessage($return, $value);
$this->addError($object,$attribute,$message);
}
} }
} }

/** /**
*
* Validates IBAN Number * Validates IBAN Number
*
* @param string $ibanNumber * @param string $ibanNumber
* @return bool|string true if validated, else returns error message.
*/ */
public function validateIBAN( $ibanNumber ){ public function validateIBAN($ibanNumber)
{
// remove non-basic roman letter or digit characters // remove non-basic roman letter or digit characters
$ibanNumber = preg_replace('/[^A-Z0-9]/', '', ltrim(strtoupper($ibanNumber))); $ibanNumber = preg_replace('/[^A-Z0-9]/', '', ltrim(strtoupper($ibanNumber)));
// remove IBAN if any // remove IBAN if any
$ibanNumber = preg_replace('/^IBAN/','',$ibanNumber); $ibanNumber = preg_replace('/^IBAN/','',$ibanNumber);

// get country part // get country part
$country = substr($ibanNumber, 0, 2); $country = substr($ibanNumber, 0, 2);
echo $ibanNumber.'<br/>'; if (!array_key_exists($country, $this->_patterns))
if(!array_key_exists($country, $this->_patterns))
return self::NOTSUPPORTED; return self::NOTSUPPORTED;

// check pattern // check pattern
if(!preg_match($this->_patterns[$country], $ibanNumber)) if (!preg_match($this->_patterns[$country], $ibanNumber))
return self::WRONGFORMAT; return self::WRONGFORMAT;

// check length // check length
if(strlen($ibanNumber) != $this->_lengths[$country]){ if (strlen($ibanNumber) != $this->_lengths[$country])
echo strlen($ibanNumber).' '.$ibanNumber.'<br/>';
return self::WRONGLENGTH; return self::WRONGLENGTH;


}

// verify checksum // verify checksum
// move first four chars (country code and checksum) to the end of the string // move first four chars (country code and checksum) to the end of the string
$format = substr($ibanNumber, 4) . substr($ibanNumber, 0, 4); $format = substr($ibanNumber, 4) . substr($ibanNumber, 0, 4);


$format = str_replace( $format = str_replace(
range('A','Z'), range('A','Z'),
array('10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', array('10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22',
'23', '24', '25', '26', '27', '28', '29', '30', '31', '32', '33', '34', '35'), '23', '24', '25', '26', '27', '28', '29', '30', '31', '32', '33', '34', '35'),
$format); $format
// perform MOD97-10 checksum calculation );
$temp = intval(substr($format,0,1)); // perform MOD97-10 checksum calculation
$len = strlen($format); $temp = intval(substr($format,0,1));
for ($pos = 1; $pos < $len; ++$pos){ $len = strlen($format);
$temp *= 10; for ($pos = 1; $pos < $len; ++$pos){
$temp += intval(substr($format,$pos,1)); $temp *= 10;
$temp %=97; $temp += intval(substr($format,$pos,1));
} $temp %=97;

}
if($temp != 1){
return self::CHECKFAILED; if ($temp != 1)
} return self::CHECKFAILED;
return true;
return true;
} }

/** /**
* *
* Returns a formatted error message * Returns a formatted error message
*
* @param string $error * @param string $error
* @param string $ibanNumber * @param string $ibanNumber
* @return string translated error message
*/ */
public function getErrorMessage( $error, $ibanNumber ){ public function getErrorMessage($error, $ibanNumber)
{
return Yii::t('EIBANValidator',$this->_messages[$error], array('{value}'=>$ibanNumber)); return Yii::t('EIBANValidator',$this->_messages[$error], array('{value}'=>$ibanNumber));
} }
} }