Skip to content

Instantly share code, notes, and snippets.

@ssaki
Created March 30, 2019 19:35
Show Gist options
  • Save ssaki/b255b9c5fbfe86ba578491fa288dd1d3 to your computer and use it in GitHub Desktop.
Save ssaki/b255b9c5fbfe86ba578491fa288dd1d3 to your computer and use it in GitHub Desktop.
Symfony validator for Bulgarian uniform civil number (EGN)
<?php
namespace App\Validator\Constraints;
use Symfony\Component\Validator\Constraint;
/**
* Constraint for Bulgarian uniform civil number (EGN).
*/
class UniformCivilNumber extends Constraint
{
public $messageSyntax = 'user.egn.syntax';
public $messageDate = 'user.egn.date';
public $messageChecksum = 'user.egn.checksum';
}
<?php
namespace App\Validator\Constraints;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
/**
* Validator for Bulgarian uniform civil number (EGN).
*/
class UniformCivilNumberValidator extends ConstraintValidator
{
/**
* {@inheritdoc}
*
* @param string $value the uniform civil number (EGN) as a string
* @param Constraint $constraint the validator constraint
*/
public function validate($value, $constraint)
{
if (!$constraint instanceof UniformCivilNumber) {
throw new \InvalidArgumentException('Invalid constraint provided.');
}
/*
* Validate syntax.
*/
if (strlen($value) !== 10 || !preg_match('~^\d+$~', $value)) {
$this->context->addViolation($constraint->messageSyntax);
return;
}
/**
* Validate the checksum.
*/
$multipliers = [2, 4, 8, 5, 10, 9, 7, 3, 6];
$digits = array_map('intval', str_split($value));
$controlSum = 0;
for ($i = 0; $i < 9; ++$i) {
$controlSum += $digits[$i] * $multipliers[$i];
}
$checkSum = $controlSum % 11;
if ($checkSum === 10) {
$checkSum = 0;
}
if ($checkSum !== $digits[9]) {
$this->context->addViolation($constraint->messageChecksum);
return;
}
/**
* Validate it contains a syntactically correct date.
*/
$year = (int) substr($value, 0, 2);
$month = (int) substr($value, 2, 2);
$day = (int) substr($value, 4, 2);
if ($month > 40) {
$year += 2000;
$month -= 40;
} elseif ($month > 20) {
$year += 1800;
$month -= 20;
} else {
$year += 1900;
}
if (!checkdate($month, $day, $year)) {
$this->context->addViolation($constraint->messageDate);
return;
}
/**
* Validate that the date is not in the future which should be impossible.
*/
$timestamp = mktime(23, 59, 59, $month, $day, $year);
if ($timestamp > time()) {
$this->context->addViolation($constraint->messageDate);
return;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment