diff --git a/readme.md b/readme.md index 1584abbd86..e2f050289c 100644 --- a/readme.md +++ b/readme.md @@ -1023,6 +1023,15 @@ echo $faker->vat; // "A35864370" echo $faker->dni; // '83367512' ``` +### `Faker\Provider\fa_IR\Person` + +```php +nationalCode; // "0078475759" +``` + ### `Faker\Provider\fa_IR\Address` ```php diff --git a/src/Faker/Provider/fa_IR/Person.php b/src/Faker/Provider/fa_IR/Person.php index 055b863ef1..e332968d8d 100644 --- a/src/Faker/Provider/fa_IR/Person.php +++ b/src/Faker/Provider/fa_IR/Person.php @@ -134,4 +134,68 @@ class Person extends \Faker\Provider\Person protected static $titleMale = array('آقای', 'استاد', 'دکتر', 'مهندس'); protected static $titleFemale = array('خانم', 'استاد', 'دکتر', 'مهندس'); + + /** + * This method returns a valid Iranian nationalCode + * @example '8075859741' + * @link https://fa.wikipedia.org/wiki/%DA%A9%D8%A7%D8%B1%D8%AA_%D8%B4%D9%86%D8%A7%D8%B3%D8%A7%DB%8C%DB%8C_%D9%85%D9%84%DB%8C#%D8%AD%D8%B3%D8%A7%D8%A8_%DA%A9%D8%B1%D8%AF%D9%86_%DA%A9%D8%AF_%DA%A9%D9%86%D8%AA%D8%B1%D9%84 + * @return string + */ + public static function nationalCode() + { + $area = self::createAreaCode(); + $core = self::createCoreCode(); + $control = self::createControlCode($area, $core); + + return sprintf("%03d%06d%01d", $area, $core, $control); + } + + /** + * This method generates a 3-digit valid area code to be used in nationalCode + * @return int|string + */ + private static function createAreaCode() + { + $area = "000"; + + while ($area == "000") { + $area = static::numerify("###"); + } + + return $area; + } + + /** + * This method randomly generates a 6-digit core code for nationalCode + * @return string + */ + private static function createCoreCode() + { + return static::numerify("######"); + } + + /** + * This method uses the Iranian nationalCode validation algorithm to generate a valid 10-digit code + * @param $area + * @param $core + * @link https://fa.wikipedia.org/wiki/%DA%A9%D8%A7%D8%B1%D8%AA_%D8%B4%D9%86%D8%A7%D8%B3%D8%A7%DB%8C%DB%8C_%D9%85%D9%84%DB%8C#%D8%AD%D8%B3%D8%A7%D8%A8_%DA%A9%D8%B1%D8%AF%D9%86_%DA%A9%D8%AF_%DA%A9%D9%86%D8%AA%D8%B1%D9%84 + * @return int + */ + private static function createControlCode($area, $core) + { + $subNationalCodeString = $area . $core; + + $sum = 0; + $count = 0; + + for ($i = 10; $i > 1; $i--) { + $sum += $subNationalCodeString[$count] * ($i); + $count++; + } + + if (($sum % 11) < 2) { + return $sum % 11; + } + return 11 - ($sum % 11); + } } diff --git a/test/Faker/Provider/fa_IR/PersonTest.php b/test/Faker/Provider/fa_IR/PersonTest.php new file mode 100644 index 0000000000..28dbda29e3 --- /dev/null +++ b/test/Faker/Provider/fa_IR/PersonTest.php @@ -0,0 +1,54 @@ +addProvider(new Person($faker)); + $this->faker = $faker; + } + + public function testNationalCode() + { + for ($i = 0; $i < 100; $i++) { + $nationalCode = $this->faker->nationalCode; + + // nationalCode should be in the format ########## + $this->assertRegExp('/^[0-9]{10}$/', $nationalCode); + + $areaCode = substr($nationalCode, 0, 3); + $controlCode = substr($nationalCode, 9, 1); + + // the areaCode must in the format ###, excluding '000' + $this->assertNotEquals('000', $areaCode); + + // the controlCode should comply with the Iranian National Code validation algorithm + $sum = 0; + $count = 0; + + for ($j = 10; $j > 1; $j--) { + $sum += $nationalCode[$count] * ($j); + $count++; + } + + if (($sum % 11) < 2) { + $this->assertEquals($sum % 11, (int)$controlCode); + } else { + $this->assertEquals(11 - ($sum % 11), (int)$controlCode); + } + } + } +}