diff --git a/docs/SubdivisionCode.md b/docs/SubdivisionCode.md new file mode 100644 index 00000000..3a4c167e --- /dev/null +++ b/docs/SubdivisionCode.md @@ -0,0 +1,284 @@ +# SubdivisionCode + +- `v::subdivisionCode(string $countryCode)` + +Validates subdivision country codes according to [ISO 3166-2][]. + +The `$countryCode` must be a country in [ISO 3166-1 alpha-2][] format. + +```php +v::subdivisionCode('BR')->validate('SP'); //true +v::subdivisionCode('US')->validate('CA'); //true +``` + +This rule is case sensitive. + +## Available country codes + +- `AD`: Andorra +- `AE`: United Arab Emirates +- `AF`: Afghanistan +- `AG`: Antigua and Barbuda +- `AI`: Anguilla +- `AL`: Albania +- `AM`: Armenia +- `AN`: AN.html +- `AO`: Angola +- `AQ`: Antarctica +- `AR`: Argentina +- `AS`: American Samoa +- `AT`: Austria +- `AU`: Australia +- `AW`: Aruba +- `AX`: Åland +- `AZ`: Azerbaijan +- `BA`: Bosnia and Herzegovina +- `BB`: Barbados +- `BD`: Bangladesh +- `BE`: Belgium +- `BF`: Burkina Faso +- `BG`: Bulgaria +- `BH`: Bahrain +- `BI`: Burundi +- `BJ`: Benin +- `BL`: Saint Barthélemy +- `BM`: Bermuda +- `BN`: Brunei +- `BO`: Bolivia +- `BQ`: Bonaire +- `BR`: Brazil +- `BS`: Bahamas +- `BT`: Bhutan +- `BV`: Bouvet Island +- `BW`: Botswana +- `BY`: Belarus +- `BZ`: Belize +- `CA`: Canada +- `CC`: Cocos [Keeling] Islands +- `CD`: Democratic Republic of the Congo +- `CF`: Central African Republic +- `CG`: Republic of the Congo +- `CH`: Switzerland +- `CI`: Ivory Coast +- `CK`: Cook Islands +- `CL`: Chile +- `CM`: Cameroon +- `CN`: China +- `CO`: Colombia +- `CR`: Costa Rica +- `CS`: CS.html +- `CU`: Cuba +- `CV`: Cape Verde +- `CW`: Curacao +- `CX`: Christmas Island +- `CY`: Cyprus +- `CZ`: Czech Republic +- `DE`: Germany +- `DJ`: Djibouti +- `DK`: Denmark +- `DM`: Dominica +- `DO`: Dominican Republic +- `DZ`: Algeria +- `EC`: Ecuador +- `EE`: Estonia +- `EG`: Egypt +- `EH`: Western Sahara +- `ER`: Eritrea +- `ES`: Spain +- `ET`: Ethiopia +- `FI`: Finland +- `FJ`: Fiji +- `FK`: Falkland Islands +- `FM`: Micronesia +- `FO`: Faroe Islands +- `FR`: France +- `GA`: Gabon +- `GB`: United Kingdom +- `GD`: Grenada +- `GE`: Georgia +- `GF`: French Guiana +- `GG`: Guernsey +- `GH`: Ghana +- `GI`: Gibraltar +- `GL`: Greenland +- `GM`: Gambia +- `GN`: Guinea +- `GP`: Guadeloupe +- `GQ`: Equatorial Guinea +- `GR`: Greece +- `GS`: South Georgia and the South Sandwich Islands +- `GT`: Guatemala +- `GU`: Guam +- `GW`: Guinea-Bissau +- `GY`: Guyana +- `HK`: Hong Kong +- `HM`: Heard Island and McDonald Islands +- `HN`: Honduras +- `HR`: Croatia +- `HT`: Haiti +- `HU`: Hungary +- `ID`: Indonesia +- `IE`: Ireland +- `IL`: Israel +- `IM`: Isle of Man +- `IN`: India +- `IO`: British Indian Ocean Territory +- `IQ`: Iraq +- `IR`: Iran +- `IS`: Iceland +- `IT`: Italy +- `JE`: Jersey +- `JM`: Jamaica +- `JO`: Jordan +- `JP`: Japan +- `KE`: Kenya +- `KG`: Kyrgyzstan +- `KH`: Cambodia +- `KI`: Kiribati +- `KM`: Comoros +- `KN`: Saint Kitts and Nevis +- `KP`: North Korea +- `KR`: South Korea +- `KW`: Kuwait +- `KY`: Cayman Islands +- `KZ`: Kazakhstan +- `LA`: Laos +- `LB`: Lebanon +- `LC`: Saint Lucia +- `LI`: Liechtenstein +- `LK`: Sri Lanka +- `LR`: Liberia +- `LS`: Lesotho +- `LT`: Lithuania +- `LU`: Luxembourg +- `LV`: Latvia +- `LY`: Libya +- `MA`: Morocco +- `MC`: Monaco +- `MD`: Moldova +- `ME`: Montenegro +- `MF`: Saint Martin +- `MG`: Madagascar +- `MH`: Marshall Islands +- `MK`: Macedonia +- `ML`: Mali +- `MM`: Myanmar [Burma] +- `MN`: Mongolia +- `MO`: Macao +- `MP`: Northern Mariana Islands +- `MQ`: Martinique +- `MR`: Mauritania +- `MS`: Montserrat +- `MT`: Malta +- `MU`: Mauritius +- `MV`: Maldives +- `MW`: Malawi +- `MX`: Mexico +- `MY`: Malaysia +- `MZ`: Mozambique +- `NA`: Namibia +- `NC`: New Caledonia +- `NE`: Niger +- `NF`: Norfolk Island +- `NG`: Nigeria +- `NI`: Nicaragua +- `NL`: Netherlands +- `NO`: Norway +- `NP`: Nepal +- `NR`: Nauru +- `NU`: Niue +- `NZ`: New Zealand +- `OM`: Oman +- `PA`: Panama +- `PE`: Peru +- `PF`: French Polynesia +- `PG`: Papua New Guinea +- `PH`: Philippines +- `PK`: Pakistan +- `PL`: Poland +- `PM`: Saint Pierre and Miquelon +- `PN`: Pitcairn Islands +- `PR`: Puerto Rico +- `PS`: Palestine +- `PT`: Portugal +- `PW`: Palau +- `PY`: Paraguay +- `QA`: Qatar +- `RE`: Réunion +- `RO`: Romania +- `RS`: Serbia +- `RU`: Russia +- `RW`: Rwanda +- `SA`: Saudi Arabia +- `SB`: Solomon Islands +- `SC`: Seychelles +- `SD`: Sudan +- `SE`: Sweden +- `SG`: Singapore +- `SH`: Saint Helena +- `SI`: Slovenia +- `SJ`: Svalbard and Jan Mayen +- `SK`: Slovakia +- `SL`: Sierra Leone +- `SM`: San Marino +- `SN`: Senegal +- `SO`: Somalia +- `SR`: Suriname +- `SS`: South Sudan +- `ST`: São Tomé and Príncipe +- `SV`: El Salvador +- `SX`: Sint Maarten +- `SY`: Syria +- `SZ`: Swaziland +- `TC`: Turks and Caicos Islands +- `TD`: Chad +- `TF`: French Southern Territories +- `TG`: Togo +- `TH`: Thailand +- `TJ`: Tajikistan +- `TK`: Tokelau +- `TL`: East Timor +- `TM`: Turkmenistan +- `TN`: Tunisia +- `TO`: Tonga +- `TR`: Turkey +- `TT`: Trinidad and Tobago +- `TV`: Tuvalu +- `TW`: Taiwan +- `TZ`: Tanzania +- `UA`: Ukraine +- `UG`: Uganda +- `UM`: U.S. Minor Outlying Islands +- `US`: United States +- `UY`: Uruguay +- `UZ`: Uzbekistan +- `VA`: Vatican City +- `VC`: Saint Vincent and the Grenadines +- `VE`: Venezuela +- `VG`: British Virgin Islands +- `VI`: U.S. Virgin Islands +- `VN`: Vietnam +- `VU`: Vanuatu +- `WF`: Wallis and Futuna +- `WS`: Samoa +- `XK`: Kosovo +- `YE`: Yemen +- `YT`: Mayotte +- `ZA`: South Africa +- `ZM`: Zambia +- `ZW`: Zimbabwe + +All data was extrated from [GeoNames][] which is licensed under a +[Creative Commons Attribution 3.0 License][]. + +*** +See also: + + * [CountryCode](CountryCode.md) + * [Tld](Tld.md) + + +[Creative Commons Attribution 3.0 License]: http://creativecommons.org/licenses/by/3.0 "Creative Commons Attribution 3.0 License" +[GeoNames]: http://www.geonames.org "GetNames" +[ISO 3166-1 alpha-2]: http://en.wikipedia.org/wiki/ISO_3166-1_alpha-2 "ISO 3166-1 alpha-2" +[ISO 3166-2]: http://en.wikipedia.org/wiki/ISO_3166-2 "ISO 3166-2" diff --git a/docs/VALIDATORS.md b/docs/VALIDATORS.md index 40c7ddb9..e9752e72 100644 --- a/docs/VALIDATORS.md +++ b/docs/VALIDATORS.md @@ -126,6 +126,7 @@ * [CountryCode](CountryCode.md) * [PostalCode](PostalCode.md) + * [SubdivisionCode](SubdivisionCode.md) * [Tld](Tld.md) ## Files @@ -263,6 +264,7 @@ * [Space](Space.md) * [StartsWith](StartsWith.md) * [String](String.md) + * [SubdivisionCode](SubdivisionCode.md) * [SymbolicLink](SymbolicLink.md) * [Tld](Tld.md) * [True](True.md) diff --git a/library/Exceptions/SubdivisionCodeException.php b/library/Exceptions/SubdivisionCodeException.php new file mode 100644 index 00000000..ee4c9306 --- /dev/null +++ b/library/Exceptions/SubdivisionCodeException.php @@ -0,0 +1,24 @@ + + * + * For the full copyright and license information, please view the "LICENSE.md" + * file that was distributed with this source code. + */ + +namespace Respect\Validation\Exceptions; + +class SubdivisionCodeException extends ValidationException +{ + public static $defaultTemplates = array( + self::MODE_DEFAULT => array( + self::STANDARD => '{{name}} must be a valid subdivision code for {{countryCode}}', + ), + self::MODE_NEGATIVE => array( + self::STANDARD => '{{name}} must not be a valid subdivision code for {{countryCode}}', + ), + ); +} diff --git a/library/Rules/SubdivisionCode.php b/library/Rules/SubdivisionCode.php new file mode 100644 index 00000000..4be77a99 --- /dev/null +++ b/library/Rules/SubdivisionCode.php @@ -0,0 +1,37 @@ + + * + * For the full copyright and license information, please view the "LICENSE.md" + * file that was distributed with this source code. + */ + +namespace Respect\Validation\Rules; + +use Respect\Validation\Exceptions\ComponentException; + +/** + * Validates country subdivision codes according to ISO 3166-2. + * + * @link http://en.wikipedia.org/wiki/ISO_3166-2 + * @link http://www.geonames.org/countries/ + */ +class SubdivisionCode extends AbstractWrapper +{ + public $countryCode; + + public function __construct($countryCode) + { + $shortName = ucfirst(strtolower($countryCode)).'SubdivisionCode'; + $className = __NAMESPACE__.'\\Locale\\'.$shortName; + if (!class_exists($className)) { + throw new ComponentException(sprintf('"%s" is not a valid countryCode for ISO 3166-2', $countryCode)); + } + + $this->countryCode = $countryCode; + $this->validatable = new $className(); + } +} diff --git a/library/Validator.php b/library/Validator.php index bd178957..611e85c9 100644 --- a/library/Validator.php +++ b/library/Validator.php @@ -110,6 +110,7 @@ use Respect\Validation\Rules\Key; * @method static Validator space(string $additionalChars = null) * @method static Validator startsWith(mixed $startValue, bool $identical = false) * @method static Validator string() + * @method static Validator subdivisionCode(string $countryCode) * @method static Validator symbolicLink() * @method static Validator tld() * @method static Validator true() diff --git a/phpunit.xml.dist b/phpunit.xml.dist index cff0b719..35fa3175 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -20,6 +20,10 @@ library/ + + library/Exceptions/SubdivisionCode + library/Rules/SubdivisionCode + diff --git a/tests/Rules/SubdivisionCodeTest.php b/tests/Rules/SubdivisionCodeTest.php new file mode 100644 index 00000000..6265a2bc --- /dev/null +++ b/tests/Rules/SubdivisionCodeTest.php @@ -0,0 +1,96 @@ + + * + * For the full copyright and license information, please view the "LICENSE.md" + * file that was distributed with this source code. + */ + +namespace Respect\Validation\Rules; + +use PHPUnit_Framework_TestCase; + +/** + * @covers Respect\Validation\Rules\SubdivisionCode + * @covers Respect\Validation\Exceptions\SubdivisionCodeException + */ +class SubdivisionCodeTest extends PHPUnit_Framework_TestCase +{ + /** + * @expectedException Respect\Validation\Exceptions\ComponentException + * @expectedExceptionMessage "whatever" is not a valid entry for ISO 3166-2 + */ + public function testShouldThrowsExceptionWhenInvalidFormat() + { + new SubdivisionCode('whatever'); + } + + /** + * @expectedException Respect\Validation\Exceptions\ComponentException + * @expectedExceptionMessage "JK" is not a valid entry for ISO 3166-2 + */ + public function testShouldNotAcceptWrongNamesOnConstructor() + { + new SubdivisionCode('JK'); + } + + public function testShouldDefineASubdivisionCodeFormatOnConstructor() + { + $countrySubdivision = new SubdivisionCode('US'); + + $this->assertEquals('US', $countrySubdivision->entry); + } + + public function providerForValidSubdivisionCodeInformation() + { + return array( + array('AQ', null), + array('BR', 'SP'), + array('MV', '00'), + array('US', 'CA'), + array('YT', ''), + ); + } + + /** + * @dataProvider providerForValidSubdivisionCodeInformation + */ + public function testShouldValidateValidSubdivisionCodeInformation($entry, $input) + { + $countrySubdivision = new SubdivisionCode($entry); + + $this->assertTrue($countrySubdivision->validate($input)); + } + + public function providerForInvalidSubdivisionCodeInformation() + { + return array( + array('BR', 'CA'), + array('MV', 0), + array('US', 'CE'), + ); + } + + /** + * @dataProvider providerForInvalidSubdivisionCodeInformation + */ + public function testShouldNotValidateInvalidSubdivisionCodeInformation($entry, $input) + { + $countrySubdivision = new SubdivisionCode($entry); + + $this->assertFalse($countrySubdivision->validate($input)); + } + + /** + * @expectedException Respect\Validation\Exceptions\SubdivisionCode\BrSubdivisionCodeException + * @expectedExceptionMessage "CA" must be a country subdivision of Brazil + */ + public function testShouldThrowsSubdivisionCodeException() + { + $countrySubdivision = new SubdivisionCode('BR'); + $countrySubdivision->assert('CA'); + } +}