-
Notifications
You must be signed in to change notification settings - Fork 3.6k
Generate valid individual identification numbers kk_KZ #1161
Changes from 6 commits
93557c2
f24aa1a
b4a63ff
651cd6f
9dea2dd
96377e5
d939425
df2726c
3d6d208
63aecf8
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,9 +2,52 @@ | |
|
||
namespace Faker\Provider\kk_KZ; | ||
|
||
use \Faker\Provider\DateTime; | ||
|
||
class Person extends \Faker\Provider\Person | ||
{ | ||
|
||
const GENDER_MALE = 0; | ||
const GENDER_FEMALE = 1; | ||
|
||
const CENTURY_19TH = 0; | ||
const CENTURY_20TH = 1; | ||
const CENTURY_21ST = 2; | ||
|
||
const MALE_CENTURY_19TH = 1; | ||
const MALE_CENTURY_20TH = 3; | ||
const MALE_CENTURY_21ST = 5; | ||
|
||
const FEMALE_CENTURY_19TH = 2; | ||
const FEMALE_CENTURY_20TH = 4; | ||
const FEMALE_CENTURY_21ST = 6; | ||
|
||
/** | ||
* @var array | ||
*/ | ||
public static $firstSequenceBitWeights = array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11); | ||
|
||
/** | ||
* @var array | ||
*/ | ||
public static $secondSequenceBitWeights = array(3, 4, 5, 6, 7, 8, 9, 10, 11, 1, 2); | ||
|
||
/** | ||
* @var array | ||
*/ | ||
public static $genderCenturyMap = array( | ||
self::GENDER_MALE => array( | ||
self::CENTURY_19TH => self::MALE_CENTURY_19TH, | ||
self::CENTURY_20TH => self::MALE_CENTURY_20TH, | ||
self::CENTURY_21ST => self::MALE_CENTURY_21ST, | ||
), | ||
self::GENDER_FEMALE => array( | ||
self::CENTURY_19TH => self::FEMALE_CENTURY_19TH, | ||
self::CENTURY_20TH => self::FEMALE_CENTURY_20TH, | ||
self::CENTURY_21ST => self::FEMALE_CENTURY_21ST, | ||
), | ||
); | ||
|
||
/** | ||
* @see https://ru.wikipedia.org/wiki/%D0%9A%D0%B0%D0%B7%D0%B0%D1%85%D1%81%D0%BA%D0%B0%D1%8F_%D1%84%D0%B0%D0%BC%D0%B8%D0%BB%D0%B8%D1%8F | ||
* | ||
|
@@ -133,23 +176,69 @@ class Person extends \Faker\Provider\Person | |
'Ісмет', | ||
); | ||
|
||
/** | ||
* @param integer $year | ||
* | ||
* @return integer|null | ||
*/ | ||
private static function getCenturyByYear($year) | ||
{ | ||
if ($year >= 2000 && $year <= DateTime::year()) { | ||
return self::CENTURY_21ST; | ||
} elseif ($year >= 1900) { | ||
return self::CENTURY_20TH; | ||
} elseif ($year >= 1800) { | ||
return self::CENTURY_19TH; | ||
} | ||
} | ||
|
||
/** | ||
* National Individual Identification Numbers | ||
* | ||
* @link http://egov.kz/wps/portal/Content?contentPath=%2Fegovcontent%2Fcitizen_migration%2Fpassport_id_card%2Farticle%2Fiin_info&lang=en | ||
* @link https://ru.wikipedia.org/wiki/%D0%98%D0%BD%D0%B4%D0%B8%D0%B2%D0%B8%D0%B4%D1%83%D0%B0%D0%BB%D1%8C%D0%BD%D1%8B%D0%B9_%D0%B8%D0%B4%D0%B5%D0%BD%D1%82%D0%B8%D1%84%D0%B8%D0%BA%D0%B0%D1%86%D0%B8%D0%BE%D0%BD%D0%BD%D1%8B%D0%B9_%D0%BD%D0%BE%D0%BC%D0%B5%D1%80 | ||
* | ||
* @param \DateTime $birthDate | ||
* @param integer $gender | ||
* | ||
* @return string 12 digits, like 780322300455 | ||
*/ | ||
public static function individualIdentificationNumber(\DateTime $birthDate = null) | ||
public static function individualIdentificationNumber(\DateTime $birthDate = null, $gender = self::GENDER_MALE) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Haven't tested, but looks like your methods can be refactored like this: public static function individualIdentificationNumber(\DateTime $birthDate = null, $gender = self::GENDER_MALE)
{
if (!$birthDate) {
$birthDate = DateTime::dateTimeBetween();
}
$population = mt_rand(1000, 2000);
$century = self::getCenturyByYear((int) $birthDate->format('Y'));
$iin = $birthDate->format('ymd');
$iin .= (string) self::$genderCenturyMap[$gender][$century];
$iin .= (string) $population;
return $iin . (string) self::checkSum($iin);
}
/**
* @param string $iinValue
*
* @return integer
*/
public static function checkSum($iinValue)
{
$controlDigit = self::getControlDigit($iinValue, self::$firstSequenceBitWeights);
if ($controlDigit === 10) {
return self::getControlDigit($iinValue, self::$secondSequenceBitWeights);
}
return $controlDigit;
}
/**
* @param string $iinValue
* @param array $sequence
*
* @return integer
*/
protected static function getControlDigit($iinValue, $sequence)
{
$sum = 0;
for ($i = 0; $i <= 10; $i++) {
$sum += (int) $iinValue[$i] * $sequence[$i];
}
return $sum % 11;
} There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ok looks fine There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 |
||
{ | ||
if (!$birthDate) { | ||
$birthDate = \Faker\Provider\DateTime::dateTimeBetween(); | ||
$birthDate = DateTime::dateTimeBetween(); | ||
} | ||
|
||
$dateAsString = $birthDate->format('ymd'); | ||
$genderAndCenturyId = (string) static::numberBetween(1, 6); | ||
$randomDigits = (string) static::numerify('#####'); | ||
$dateAsString = $birthDate->format('ymd'); | ||
$totalPopulation = rand(1000, 2000); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. never, ever use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done |
||
$century = self::getCenturyByYear((int)$birthDate->format('Y')); | ||
$iin = $dateAsString; | ||
$sum = 0; | ||
$calculatedResult = array(); | ||
|
||
$iin .= (string)self::$genderCenturyMap[$gender][$century]; | ||
$iin .= (string)$totalPopulation; | ||
|
||
for ($i = 0; $i <= 10; $i++) { | ||
$calculatedResult[$i] = (int)substr($iin, $i, 1); | ||
$sum += $calculatedResult[$i] * self::$firstSequenceBitWeights[$i]; | ||
} | ||
|
||
$controlDigit = $sum % 11; | ||
$calculatedResult[11] = $controlDigit; | ||
|
||
if ($controlDigit === 10) { | ||
$sum = 0; | ||
|
||
for ($i = 0; $i <= 10; $i++) { | ||
$calculatedResult[$i] = (int)substr($iin, $i, 1); | ||
$sum += $calculatedResult[$i] * self::$secondSequenceBitWeights[$i]; | ||
} | ||
|
||
$controlDigit = $sum % 11; | ||
$calculatedResult[11] = $controlDigit; | ||
} | ||
|
||
return $dateAsString . $genderAndCenturyId . $randomDigits; | ||
return implode('', $calculatedResult); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,6 +2,7 @@ | |
namespace Faker\Test\Provider\kk_KZ; | ||
|
||
use Faker\Generator; | ||
use Faker\Provider\DateTime; | ||
use Faker\Provider\kk_KZ\Person; | ||
|
||
class PersonTest extends \PHPUnit_Framework_TestCase | ||
|
@@ -19,13 +20,28 @@ public function setUp() | |
|
||
public function testIndividualIdentificationNumberIsValid() | ||
{ | ||
$birthDate = new \DateTime('now'); | ||
$birthDate = DateTime::dateTimeBetween('-30 years', '-10 years'); | ||
$individualIdentificationNumber = $this->faker->individualIdentificationNumber($birthDate); | ||
$birthDateAsString = $birthDate->format('ymd'); | ||
$sum = 0; | ||
|
||
$this->assertRegExp( | ||
"/^(" . $birthDateAsString . ")([1-6]{1})(\\d{5})$/", | ||
$individualIdentificationNumber | ||
); | ||
for ($i = 0; $i <= 10; $i++) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. don't duplicate the checksum code here. Instead, refactor it into a utility function, and use it both in the generator and in the test. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done |
||
$calculatedResult[$i] = (int)substr($individualIdentificationNumber, $i, 1); | ||
$sum += $calculatedResult[$i] * Person::$firstSequenceBitWeights[$i]; | ||
} | ||
|
||
$controlDigit = $sum % 11; | ||
|
||
if ($controlDigit === 10) { | ||
$sum = 0; | ||
|
||
for ($i = 0; $i <= 10; $i++) { | ||
$calculatedResult[$i] = (int)substr($individualIdentificationNumber, $i, 1); | ||
$sum += $calculatedResult[$i] * Person::$secondSequenceBitWeights[$i]; | ||
} | ||
|
||
$controlDigit = $sum % 11; | ||
} | ||
|
||
$this->assertTrue($controlDigit === (int)substr($individualIdentificationNumber, 11, 1)); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can flip conditions and remove
&&