diff --git a/readme.md b/readme.md index daf53e7802..9e0b10f500 100644 --- a/readme.md +++ b/readme.md @@ -864,6 +864,44 @@ echo $faker->taxpayerIdentificationNumber; // '165249277' ``` +### `Faker\Provider\pt_BR\PhoneNumber` + +```php +areaCode; // 21 +echo $faker->cellphone; // 9432-5656 +echo $faker->landline; // 2654-3445 +echo $faker->phone; // random landline, 8-digit or 9-digit cellphone number + +// Using the phone functions with a false argument returns unformatted numbers +echo $faker->cellphone(false); // 74336667 + +// cellphone() has a special second argument to add the 9th digit. Ignored if generated a Radio number +echo $faker->cellphone(true, true); // 98983-3945 or 7343-1290 + +// Using the "Number" suffix adds area code to the phone +echo $faker->cellphoneNumber; // (11) 98309-2935 +echo $faker->landlineNumber(false); // 3522835934 +echo $faker->phoneNumber; // formatted, random landline or cellphone (obbeying the 9th digit rule) +echo $faker->phoneNumberCleared; // not formatted, random landline or cellphone (obbeying the 9th digit rule) +``` + +### `Faker\Provider\pt_BR\Person` + +```php +name; // 'Sr. Luis Adriano SepĂșlveda Filho' + +// Valid document generators have a boolean argument to remove formatting +echo $faker->cpf; // '145.343.345-76' +echo $faker->cpf(false); // '45623467866' +echo $faker->rg; // '84.405.736-3' +echo $faker->cnpj; // '23.663.478/0001-24' +``` + ### `Faker\Provider\ro_RO\Person` ```php diff --git a/src/Faker/Provider/pt_BR/Company.php b/src/Faker/Provider/pt_BR/Company.php index eaa34db1fa..79592aebc0 100644 --- a/src/Faker/Provider/pt_BR/Company.php +++ b/src/Faker/Provider/pt_BR/Company.php @@ -2,6 +2,8 @@ namespace Faker\Provider\pt_BR; +require_once "check_digit.php"; + class Company extends \Faker\Provider\Company { protected static $formats = array( @@ -13,4 +15,19 @@ class Company extends \Faker\Provider\Company ); protected static $companySuffix = array('e Filho', 'e Filha', 'e Filhos', 'e Associados', 'e Flia.', 'SRL', 'SA', 'S. de H.'); + + /** + * A random CNPJ number. + * @link http://en.wikipedia.org/wiki/CNPJ + * @param bool $formatted If the number should have dots/slashes/dashes or not. + * @return string + */ + public function cnpj($formatted = true) + { + $n = $this->generator->numerify('########0001'); + $n .= check_digit($n); + $n .= check_digit($n); + + return $formatted? vsprintf('%d%d.%d%d%d.%d%d%d/%d%d%d%d-%d%d', str_split($n)) : $n; + } } diff --git a/src/Faker/Provider/pt_BR/Person.php b/src/Faker/Provider/pt_BR/Person.php index a44f62adba..be39a2e709 100644 --- a/src/Faker/Provider/pt_BR/Person.php +++ b/src/Faker/Provider/pt_BR/Person.php @@ -2,6 +2,8 @@ namespace Faker\Provider\pt_BR; +require_once "check_digit.php"; + class Person extends \Faker\Provider\Person { protected static $maleNameFormats = array( @@ -90,7 +92,7 @@ class Person extends \Faker\Provider\Person protected static $titleFemale = array('Sra.', 'Srta.', 'Dr.',); - private static $suffix = array('Filho', 'Neto', 'Sobrinho', 'Jr.'); + protected static $suffix = array('Filho', 'Neto', 'Sobrinho', 'Jr.'); /** * @example 'Jr.' @@ -99,4 +101,33 @@ public static function suffix() { return static::randomElement(static::$suffix); } + + /** + * A random CPF number. + * @link http://en.wikipedia.org/wiki/Cadastro_de_Pessoas_F%C3%ADsicas + * @param bool $formatted If the number should have dots/dashes or not. + * @return string + */ + public function cpf($formatted = true) + { + $n = $this->generator->numerify('#########'); + $n .= check_digit($n); + $n .= check_digit($n); + + return $formatted? vsprintf('%d%d%d.%d%d%d.%d%d%d-%d%d', str_split($n)) : $n; + } + + /** + * A random RG number, following Sao Paulo state's rules. + * @link http://pt.wikipedia.org/wiki/C%C3%A9dula_de_identidade + * @param bool $formatted If the number should have dots/dashes or not. + * @return string + */ + public function rg($formatted = true) + { + $n = $this->generator->numerify('########'); + $n .= check_digit($n); + + return $formatted? vsprintf('%d%d.%d%d%d.%d%d%d-%s', str_split($n)) : $n; + } } diff --git a/src/Faker/Provider/pt_BR/PhoneNumber.php b/src/Faker/Provider/pt_BR/PhoneNumber.php index 30661d6b12..c66b0096a6 100644 --- a/src/Faker/Provider/pt_BR/PhoneNumber.php +++ b/src/Faker/Provider/pt_BR/PhoneNumber.php @@ -4,28 +4,139 @@ class PhoneNumber extends \Faker\Provider\PhoneNumber { - protected static $formats = array( - '+## (##) #### - ####', - '+## (##) 9#### - ####', - '(##) #### - ####', - '(##) ##### - ####', - '+##(##) ####-####', - '+##(##) 9####-####', - '(##) ####-####', - '(##) 9####-####', - '+##(##) #### - ####', - '+##(##) 9#### - ####', - '(##)#### - ####', - '(##)##### - ####', - '+##(##)####-####', - '+##(##)9####-####', - '(##)####-####', - '(##)9####-####', - '#### - ####', - '9#### - ####', - '####-####', - '9####-####', - '## #### ####', - '## 9#### ####', + + protected static $landlineFormats = array('2###-####', '3###-####'); + + protected static $cellphoneFormats = array('7###-####', '8###-####', '9###-####'); + + /** + * Extracted from http://portal.embratel.com.br/embratel/9-digito/ (point 11) + */ + protected static $ninthDigitAreaCodes = array( + 11, 12, 13, 14, 15, 16, 17, 18, 19, + 21, 22, 24, 27, 28, + 91, 92, 93, 94, 95, 96, 97, 98, 99, + //31, 32, 33, 34, 35, 37, 38, 71, 73, 74, 75, 77, 79, 81, 82, 83, 84, 85, 86, 87, 88, 89, //by dec/2015 + //41, 42, 43, 44, 45, 46, 47, 48, 49, 51, 53, 54, 55, 61,62, 63, 64, 65, 66, 67, 68, 69 //by dec/2016 ); + + /** + * Generates a 2-digit area code not composed by zeroes. + * @return string + */ + public static function areaCode() + { + return static::randomDigitNotNull().static::randomDigitNotNull(); + } + + /** + * Generates a 8/9-digit cellphone number without formatting characters. + * @param bool $formatted [def: true] If it should return a formatted number or not. + * @param bool $ninth [def: false] If the number should have a nine in the beginning or not. + * If the generated number begins with 7 this is ignored. + * @return string + */ + public static function cellphone($formatted = true, $ninth = false) + { + $number = static::numerify(static::randomElement(static::$cellphoneFormats)); + + if ($ninth && $number[0] != 7) { + $number = "9$number"; + } + + if (!$formatted) { + $number = strtr($number, array('-' => '')); + } + + return $number; + } + + /** + * Generates an 8-digit landline number without formatting characters. + * @param bool $formatted [def: true] If it should return a formatted number or not. + * @return string + */ + public static function landline($formatted = true) + { + $number = static::numerify(static::randomElement(static::$landlineFormats)); + + if (!$formatted) { + $number = strtr($number, array('-' => '')); + } + + return $number; + } + + /** + * Randomizes between cellphone and landline numbers. + * @param bool $formatted [def: true] If it should return a formatted number or not. + * @return mixed + */ + public static function phone($formatted = true) + { + $options = static::randomElement(array( + array('cellphone', false), + array('cellphone', true), + array('landline', null), + )); + + return call_user_func("static::{$options[0]}", $formatted, $options[1]); + } + + /** + * Generates a complete phone number. + * @param string $type [def: landline] One of "landline" or "cellphone". Defaults to "landline" on invalid values. + * @param bool $formatted [def: true] If the number should be formatted or not. + * @return string + */ + protected static function anyPhoneNumber($type, $formatted = true) + { + $area = static::areaCode(); + $number = ($type == 'cellphone')? + static::cellphone($formatted, in_array($area, static::$ninthDigitAreaCodes)) : + static::landline($formatted); + + return $formatted? "($area) $number" : $area.$number; + } + + /** + * Concatenates {@link areaCode} and {@link cellphone} into a national cellphone number. The ninth digit is + * derived from the area code. + * @param bool $formatted [def: true] If it should return a formatted number or not. + * @return string + */ + public static function cellphoneNumber($formatted = true) + { + return static::anyPhoneNumber('cellphone', $formatted); + } + + /** + * Concatenates {@link areaCode} and {@link landline} into a national landline number. + * @param bool $formatted [def: true] If it should return a formatted number or not. + * @return string + */ + public static function landlineNumber($formatted = true) + { + return static::anyPhoneNumber('landline', $formatted); + } + + /** + * Randomizes between complete cellphone and landline numbers. + * @return mixed + */ + public static function phoneNumber() + { + $method = static::randomElement(array('cellphoneNumber', 'landlineNumber')); + return call_user_func("static::$method", true); + } + + /** + * Randomizes between complete cellphone and landline numbers, cleared from formatting symbols. + * @return mixed + */ + public static function phoneNumberCleared() + { + $method = static::randomElement(array('cellphoneNumber', 'landlineNumber')); + return call_user_func("static::$method", false); + } } diff --git a/src/Faker/Provider/pt_BR/check_digit.php b/src/Faker/Provider/pt_BR/check_digit.php new file mode 100644 index 0000000000..ab67db9dfa --- /dev/null +++ b/src/Faker/Provider/pt_BR/check_digit.php @@ -0,0 +1,35 @@ += 12; + $verifier = 0; + + for ($i = 1; $i <= $length; $i++) { + if (!$second_algorithm) { + $multiplier = $i+1; + } else { + $multiplier = ($i >= 9)? $i-7 : $i+1; + } + $verifier += $numbers[$length-$i] * $multiplier; + } + + $verifier = 11 - ($verifier % 11); + if ($verifier >= 10) { + $verifier = 0; + } + + return $verifier; +} diff --git a/test/Faker/Provider/pt_BR/CompanyTest.php b/test/Faker/Provider/pt_BR/CompanyTest.php new file mode 100644 index 0000000000..f59142bd25 --- /dev/null +++ b/test/Faker/Provider/pt_BR/CompanyTest.php @@ -0,0 +1,25 @@ +addProvider(new Company($faker)); + $this->faker = $faker; + } + + public function testCnpjFormatIsValid() + { + $cnpj = $this->faker->cnpj(false); + $this->assertRegExp('/\d{8}\d{4}\d{2}/', $cnpj); + $cnpj = $this->faker->cnpj(true); + $this->assertRegExp('/\d{2}\.\d{3}\.\d{3}\/\d{4}-\d{2}/', $cnpj); + } +} diff --git a/test/Faker/Provider/pt_BR/PersonTest.php b/test/Faker/Provider/pt_BR/PersonTest.php new file mode 100644 index 0000000000..767c1887cd --- /dev/null +++ b/test/Faker/Provider/pt_BR/PersonTest.php @@ -0,0 +1,33 @@ +addProvider(new Person($faker)); + $this->faker = $faker; + } + + public function testCpfFormatIsValid() + { + $cpf = $this->faker->cpf(false); + $this->assertRegExp('/\d{9}\d{2}/', $cpf); + $cpf = $this->faker->cpf(true); + $this->assertRegExp('/\d{3}\.\d{3}\.\d{3}-\d{2}/', $cpf); + } + + public function testRgFormatIsValid() + { + $rg = $this->faker->rg(false); + $this->assertRegExp('/\d{8}\d/', $rg); + $rg = $this->faker->rg(true); + $this->assertRegExp('/\d{2}\.\d{3}\.\d{3}-[0-9X]/', $rg); + } +}