Created
November 20, 2013 17:10
-
-
Save damonjones/7566978 to your computer and use it in GitHub Desktop.
UPC/EAN Validator
This file contains hidden or 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 | |
namespace Insig\UtilBundle\Validator\Constraints; | |
use Symfony\Component\Validator\Constraint; | |
/** | |
* Metadata for the UpcEanValidator. | |
* | |
* @Annotation | |
*/ | |
class UpcEan extends Constraint | |
{ | |
public $message = '{{ value }} is not a valid UPC/EAN.'; | |
} | |
This file contains hidden or 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 | |
namespace Insig\UtilBundle\Validator\Constraints; | |
use Symfony\Component\Validator\Constraint; | |
use Symfony\Component\Validator\ConstraintValidator; | |
use Symfony\Component\Validator\Exception\UnexpectedTypeException; | |
/** | |
* Validates a UPC/EAN using a variation of the Luhn Algorithm | |
*/ | |
class UpcEanValidator extends ConstraintValidator | |
{ | |
/** | |
* Validates a UPC/EAN number with a variation of the Luhn algorithm. | |
* | |
* @param mixed $value | |
* @param Constraint $constraint | |
*/ | |
public function validate($value, Constraint $constraint) | |
{ | |
// Must be a string | |
if (!is_string($value)) { | |
throw new UnexpectedTypeException($value, 'string'); | |
} | |
// Must consist of 12 (UPC) or 13 (EAN) digits | |
if (!preg_match('/^\d{12,13}$/', $value)) { | |
$this->context->addViolation($constraint->message, array('{{ value }}' => $value)); | |
} | |
$lastDigitIndex = strlen($value) - 1; | |
$accumulator = 0; | |
$checkDigit = (int) $value[$lastDigitIndex]; | |
// reverse the actual digits (excluding the check digit) | |
$str = strrev(substr($value, 0, $lastDigitIndex)); | |
/** | |
* Moving from right to left | |
* Even digits are just added | |
* Odd digits are multiplied by three | |
*/ | |
$accumulator = 0; | |
for ($i = 0; $i < $lastDigitIndex; $i++) { | |
$accumulator += $i % 2 ? (int) $value[$i] : (int) $value[$i] * 3; | |
} | |
$checksum = (10 - ($accumulator % 10)) % 10; | |
if ($checksum !== $checkDigit) { | |
$this->context->addViolation($constraint->message, array('{{ value }}' => $value)); | |
} | |
} | |
} |
need also a "return;" after the line 29, without you get 2 error messages
if (!preg_match('/^\d{12,13}$/', $value)) {
$this->context->addViolation($constraint->message, array('{{ value }}' => $value));
return;
}
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
There is an error in this code, for example the EAN 3263852666610 will not be validated. The correct code should use $str (reversed EAN without check digit) to calculate the accumulator:
Replace lines 45 to 47 inf file UpcEanValidator.php with above code.