public function validate(Validation $validation, $attribute)
{
$value = preg_replace('/[^\\d]/', '', $validation->getValue($attribute));
$message = $this->hasOption('message') ? $this->getOption('message') : 'Credit card number is invalid';
if ($this->hasOption('type')) {
$type = $this->getOption('type');
switch ($type) {
case CardNumber::AMERICAN_EXPRESS:
$issuer = substr($value, 0, 2);
$result = true === in_array($issuer, [34, 37]);
break;
case CardNumber::MASTERCARD:
$issuer = substr($value, 0, 2);
$result = true === in_array($issuer, [51, 52, 53, 54, 55]);
break;
case CardNumber::VISA:
$issuer = $value[0];
$result = $issuer == 4;
break;
default:
throw new Exception('Incorrect type specifier');
}
if (false === $result) {
$validation->appendMessage(new Message($message, $attribute, 'CardNumber'));
return false;
}
}
$value = strrev($value);
$checkSum = 0;
for ($i = 0; $i < strlen($value); $i++) {
if ($i % 2 == 0) {
$temp = $value[$i];
} else {
$temp = $value[$i] * 2;
if ($temp > 9) {
$temp -= 9;
}
}
$checkSum += $temp;
}
if ($checkSum % 10 != 0) {
$validation->appendMessage(new Message($message, $attribute, 'CardNumber'));
return false;
}
return true;
}