siimliimand
11/30/2017 - 7:59 AM

PersonCodeValidator.php

<?php
namespace ;

use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;

class PersonCodeValidator extends ConstraintValidator
{
    static $nrsList1 = "1234567891";
    static $nrsList2 = "3456789123";
    
    public function validate($value, Constraint $constraint)
    {
        $list = str_split($value);
        
        try {
            if(count($list) != 11) {
                throw new \Exception("Invalid length");
            }
            
            $this->validateFirstNr($list);
            $this->validateMonth($list);
            $this->validateDay($list);
            $this->validateLastNr($list);
            
        } catch (\Exception $ex) {
            $this->context->buildViolation($constraint->message)
                ->setParameter('{{ person_code }}', $value)
                ->addViolation();
        }
    }
    
    protected function validateFirstNr(array $list)
    {
        $firstNr = $list[0];
        if($firstNr == 0 || $firstNr == 9) {
            throw new \Exception("Invalid first nr.");
        }
    }
    
    protected function validateMonth(array $list)
    {
        $month = (int) "{$list[3]}{$list[4]}";
        if($month == 0 || $month > 12) {
            throw new \Exception("Invalid month");
        }
    }
    
    protected function validateDay(array $list)
    {
        $day = (int) "{$list[5]}{$list[6]}";
        if($day == 0 || $day > 31) {
            throw new \Exception("Invalid day");
        }
    }
    
    protected function validateLastNr(array $list)
    {
        $lastNr = $this->calculateLastNr($list);
        if($lastNr != $list[10]) {
            throw new \Exception("Invalid last nr");
        }
    }
    
    protected function calculateLastNr(array $list, $nrsType = 1)
    {
        $sum = 0;
        $nrs = $nrsType == 1 ? static::$nrsList1 : static::$nrsList2;
        $nrsList = str_split($nrs);
        $index = 0;
        foreach($nrsList as $nr) {
            $sum += ($nr * $list[$index]);
            $index ++;
        }
        
        $floor = floor($sum / 11);
        $floor11 = $floor * 11;
        $lastNr = (int) ($sum - $floor11);
        
        if($lastNr == 10 && $nrsType == 1) {
            $lastNr = $this->calculateLastNr($list, 2);
        } else if($lastNr == 10 && $nrsType == 2) {
            $lastNr = 0;
        }
        
        return $lastNr;
    }
}