diff --git a/.github/workflows/update-domains.yaml b/.github/workflows/update-domains.yaml deleted file mode 100644 index 6a926e9a..00000000 --- a/.github/workflows/update-domains.yaml +++ /dev/null @@ -1,34 +0,0 @@ -name: Update domains - -on: - workflow_dispatch: - schedule: - - cron: '0 0 * * *' - -jobs: - update-tld: - name: Update domains - - runs-on: ubuntu-latest - - steps: - - name: Checkout - uses: actions/checkout@v3 - with: - ref: ${{ secrets.LAST_MINOR_VERSION }} - - - name: Execute bin/update-domain-toplevel - run: bin/update-domain-toplevel - - - name: Execute bin/update-domain-suffixes - run: bin/update-domain-suffixes - - - name: Create pull request - uses: peter-evans/create-pull-request@v4 - with: - committer: The Respect Panda - author: The Respect Panda - commit-message: Update list of domains - title: Update list of domains - base: ${{ secrets.LAST_MINOR_VERSION }} - branch: "workflows/update-tld" diff --git a/.github/workflows/update-language-codes.yaml b/.github/workflows/update-language-codes.yaml deleted file mode 100644 index 049a5c0a..00000000 --- a/.github/workflows/update-language-codes.yaml +++ /dev/null @@ -1,31 +0,0 @@ -name: Update language codes - -on: - workflow_dispatch: - schedule: - - cron: '0 0 * * *' - -jobs: - update-language-codes: - name: Update language codes - - runs-on: ubuntu-latest - - steps: - - name: Checkout - uses: actions/checkout@v3 - with: - ref: ${{ secrets.LAST_MINOR_VERSION }} - - - name: Execute script - run: bin/update-language-codes - - - name: Create pull request - uses: peter-evans/create-pull-request@v4 - with: - committer: The Respect Panda - author: The Respect Panda - commit-message: Update list of language codes - title: Update list of language codes - base: ${{ secrets.LAST_MINOR_VERSION }} - branch: "workflows/update-language-codes" diff --git a/.github/workflows/update-currency-codes.yaml b/.github/workflows/update-regionals.yaml similarity index 53% rename from .github/workflows/update-currency-codes.yaml rename to .github/workflows/update-regionals.yaml index 348e8b88..97b300dd 100644 --- a/.github/workflows/update-currency-codes.yaml +++ b/.github/workflows/update-regionals.yaml @@ -1,4 +1,4 @@ -name: Update currency codes +name: Update Regional Information on: workflow_dispatch: @@ -6,8 +6,8 @@ on: - cron: '0 0 * * *' jobs: - update-currency-codes: - name: Update currency codes + update-regional-information: + name: Update Regional Information runs-on: ubuntu-latest @@ -20,15 +20,24 @@ jobs: with: ref: ${{ secrets.LAST_MINOR_VERSION }} - - name: Execute script + - name: Update currency codes run: bin/update-currency-codes + - name: Update language codes + run: bin/update-language-codes + + - name: Update top level domains + run: bin/update-domain-toplevel + + - name: Update public domain suffixes + run: bin/update-domain-suffixes + - name: Create pull request uses: peter-evans/create-pull-request@v4 with: committer: The Respect Panda author: The Respect Panda - commit-message: Update list of currency codes - title: Update list of currency codes + commit-message: Update Regional Information + title: Update Regional Information base: ${{ secrets.LAST_MINOR_VERSION }} - branch: "workflows/update-currency-codes" + branch: "workflows/update-regional-information" diff --git a/bin/update-postal-codes b/bin/update-postal-codes new file mode 100755 index 00000000..4f948313 --- /dev/null +++ b/bin/update-postal-codes @@ -0,0 +1,48 @@ +#!/usr/bin/env bash +# Usage: {script} +# Update the list of currency codes + +set -euo pipefail + +declare -r IFS=$'\n' + +declare -r LIST_URL="https://download.geonames.org/export/dump/countryInfo.txt" +declare -r LIST_FILENAME=$(mktemp) + +declare -r RULE_FILENAME=$(dirname "${BASH_SOURCE}")/../library/Rules/PostalCode.php +declare -r RULE_FILENAME_TEMPORARY=$(mktemp) + +echo "- Downloading list" +curl --silent --location "${LIST_URL}" --output "${LIST_FILENAME}" + +declare -r CURRENCY_CODES_COUNT=$(grep "" "${LIST_FILENAME}" | wc --lines) + +echo "- Creating temporary file" +{ + sed -n "/^ ['/^$country_format$/', '/$country_regex/']," + fi + done + echo ' // phpcs:disable Generic.Files.LineLength.TooLong' + sed --silent '/^ \];\/\/end/,/^}/p' "${RULE_FILENAME}" +} > "${RULE_FILENAME_TEMPORARY}" + +echo "- Updating content of '$(basename ${RULE_FILENAME})'" +mv "${RULE_FILENAME_TEMPORARY}" "${RULE_FILENAME}" + +echo "Finished!" diff --git a/docs/rules/PostalCode.md b/docs/rules/PostalCode.md index 1ccb8090..3658c693 100644 --- a/docs/rules/PostalCode.md +++ b/docs/rules/PostalCode.md @@ -1,6 +1,6 @@ # PostalCode -- `PostalCode(string $countryCode)` +- `PostalCode(string $countryCode, bool $formatted = false)` Validates whether the input is a valid postal code or not. @@ -12,6 +12,14 @@ v::postalCode('US')->validate('55372'); // true v::postalCode('PL')->validate('99-300'); // true ``` +By default, `PostalCode` won't validate the format (puncts, spaces), unless you pass `$formatted = true`: + + +```php +v::postalCode('BR', true)->validate('02179000'); // false +v::postalCode('BR', true)->validate('02179-000'); // true +``` + Message template for this validator includes `{{countryCode}}`. Extracted from [GeoNames](http://www.geonames.org/). @@ -25,6 +33,7 @@ Extracted from [GeoNames](http://www.geonames.org/). Version | Description --------|------------- + 2.3.0 | Add option to validate formatting 2.2.4 | Cambodian postal codes now support 5 and 6 digits 0.7.0 | Created diff --git a/library/Rules/PostalCode.php b/library/Rules/PostalCode.php index cb6e9747..d86c44a8 100644 --- a/library/Rules/PostalCode.php +++ b/library/Rules/PostalCode.php @@ -23,174 +23,189 @@ use function sprintf; final class PostalCode extends AbstractEnvelope { private const DEFAULT_PATTERN = '/^$/'; - private const POSTAL_CODES = [ + + private const POSTAL_CODES_EXTRA = [ // phpcs:disable Generic.Files.LineLength.TooLong - 'AD' => '/^(?:AD)*(\d{3})$/', - 'AL' => '/^(\d{4})$/', - 'AM' => '/^(\d{4})$/', - 'AR' => '/^[A-Z]?\d{4}[A-Z]{0,3}$/', - 'AS' => '/96799/', - 'AT' => '/^(\d{4})$/', - 'AU' => '/^(\d{4})$/', - 'AX' => '/^(?:FI)*(\d{5})$/', - 'AZ' => '/^(?:AZ)*(\d{4})$/', - 'BA' => '/^(\d{5})$/', - 'BB' => '/^(?:BB)*(\d{5})$/', - 'BD' => '/^(\d{4})$/', - 'BE' => '/^(\d{4})$/', - 'BG' => '/^(\d{4})$/', - 'BH' => '/^(\d{3}\d?)$/', - 'BL' => '/^(\d{5})$/', - 'BM' => '/^([A-Z]{2}\d{2})$/', - 'BN' => '/^([A-Z]{2}\d{4})$/', - 'BR' => '/^\d{5}-?\d{3}$/', - 'BY' => '/^(\d{6})$/', - 'CA' => '/^([ABCEGHJKLMNPRSTVXY]\d[ABCEGHJKLMNPRSTVWXYZ]) ?(\d[ABCEGHJKLMNPRSTVWXYZ]\d)$/', - 'CH' => '/^(\d{4})$/', - 'CL' => '/^(\d{7})$/', - 'CN' => '/^(\d{6})$/', - 'CO' => '/^(\d{6})$/', - 'CR' => '/^(\d{5})$/', - 'CS' => '/^(\d{5})$/', - 'CU' => '/^(?:CP)*(\d{5})$/', - 'CV' => '/^(\d{4})$/', - 'CX' => '/^(\d{4})$/', - 'CY' => '/^(\d{4})$/', - 'CZ' => '/^\d{3}\s?\d{2}$/', - 'DE' => '/^(\d{5})$/', - 'DK' => '/^(\d{4})$/', - 'DO' => '/^(\d{5})$/', - 'DZ' => '/^(\d{5})$/', - 'EC' => '/^(\d{6})$/', - 'EE' => '/^(\d{5})$/', - 'EG' => '/^(\d{5})$/', - 'ES' => '/^(\d{5})$/', - 'ET' => '/^(\d{4})$/', - 'FI' => '/^(?:FI)*(\d{5})$/', - 'FM' => '/^(\d{5})$/', - 'FO' => '/^(?:FO)*(\d{3})$/', - 'FR' => '/^(\d{5})$/', - 'GB' => '/^([Gg][Ii][Rr] 0[Aa]{2})|((([A-Za-z][0-9]{1,2})|(([A-Za-z][A-Ha-hJ-Yj-y][0-9]{1,2})|(([A-Za-z][0-9][A-Za-z])|([A-Za-z][A-Ha-hJ-Yj-y][0-9]?[A-Za-z])))) [0-9][A-Za-z]{2})$/', - 'GE' => '/^(\d{4})$/', - 'GF' => '/^((97|98)3\d{2})$/', - 'GG' => '/^((?:(?:[A-PR-UWYZ][A-HK-Y]\d[ABEHMNPRV-Y0-9]|[A-PR-UWYZ]\d[A-HJKPS-UW0-9])\s\d[ABD-HJLNP-UW-Z]{2})|GIR\s?0AA)$/', - 'GL' => '/^(\d{4})$/', - 'GP' => '/^((97|98)\d{3})$/', - 'GR' => '/^(\d{3}\s?\d{2})$/', - 'GT' => '/^(\d{5})$/', - 'GU' => '/^(969\d{2})$/', - 'GW' => '/^(\d{4})$/', - 'HN' => '/^([A-Z]{2}\d{4})$/', - 'HR' => '/^(?:HR)*(\d{5})$/', - 'HT' => '/^(?:HT)*(\d{4})$/', - 'HU' => '/^(\d{4})$/', - 'ID' => '/^(\d{5})$/', - 'IE' => '/^(D6W|[AC-FHKNPRTV-Y][0-9]{2})\s?([AC-FHKNPRTV-Y0-9]{4})/', - 'IL' => '/^(\d{7}|\d{5})$/', - 'IM' => '/^((?:(?:[A-PR-UWYZ][A-HK-Y]\d[ABEHMNPRV-Y0-9]|[A-PR-UWYZ]\d[A-HJKPS-UW0-9])\s\d[ABD-HJLNP-UW-Z]{2})|GIR\s?0AA)$/', - 'IN' => '/^(\d{6})$/', - 'IQ' => '/^(\d{5})$/', - 'IR' => '/^(\d{10})$/', - 'IS' => '/^(\d{3})$/', - 'IT' => '/^(\d{5})$/', - 'JE' => '/^((?:(?:[A-PR-UWYZ][A-HK-Y]\d[ABEHMNPRV-Y0-9]|[A-PR-UWYZ]\d[A-HJKPS-UW0-9])\s\d[ABD-HJLNP-UW-Z]{2})|GIR\s?0AA)$/', - 'JO' => '/^(\d{5})$/', - 'JP' => '/^\d{3}-\d{4}$/', - 'KE' => '/^(\d{5})$/', - 'KG' => '/^(\d{6})$/', - 'KH' => '/^(\d{5,6})$/', - 'KP' => '/^(\d{6})$/', - 'KR' => '/^(\d{5})$/', - 'KW' => '/^(\d{5})$/', - 'KY' => '/^KY[1-3]-\d{4}$/', - 'KZ' => '/^(\d{6})$/', - 'LA' => '/^(\d{5})$/', - 'LB' => '/^(\d{4}(\d{4})?)$/', - 'LI' => '/^(\d{4})$/', - 'LK' => '/^(\d{5})$/', - 'LR' => '/^(\d{4})$/', - 'LS' => '/^(\d{3})$/', - 'LT' => '/^(?:LT)*(\d{5})$/', - 'LU' => '/^(?:L-)?\d{4}$/', - 'LV' => '/^(?:LV)*(\d{4})$/', - 'MA' => '/^(\d{5})$/', - 'MC' => '/^(\d{5})$/', - 'MD' => '/^MD-\d{4}$/', - 'ME' => '/^(\d{5})$/', - 'MF' => '/^(\d{5})$/', - 'MG' => '/^(\d{3})$/', - 'MH' => '/^969\d{2}(-\d{4})$/', - 'MK' => '/^(\d{4})$/', - 'MM' => '/^(\d{5})$/', - 'MN' => '/^(\d{6})$/', - 'MP' => '/^9695\d{1}$/', - 'MQ' => '/^(\d{5})$/', - 'MT' => '/^[A-Z]{3}\s?\d{4}$/', - 'MV' => '/^(\d{5})$/', - 'MW' => '/^(\d{6})$/', - 'MX' => '/^(\d{5})$/', - 'MY' => '/^(\d{5})$/', - 'MZ' => '/^(\d{4})$/', - 'NC' => '/^(\d{5})$/', - 'NE' => '/^(\d{4})$/', - 'NF' => '/^(\d{4})$/', - 'NG' => '/^(\d{6})$/', - 'NI' => '/^(\d{7})$/', - 'NL' => '/^(\d{4} ?[A-Z]{2})$/', - 'NO' => '/^(\d{4})$/', - 'NP' => '/^(\d{5})$/', - 'NZ' => '/^(\d{4})$/', - 'OM' => '/^(\d{3})$/', - 'PF' => '/^((97|98)7\d{2})$/', - 'PG' => '/^(\d{3})$/', - 'PH' => '/^(\d{4})$/', - 'PK' => '/^(\d{5})$/', - 'PL' => '/^\d{2}-\d{3}$/', - 'PM' => '/^(97500)$/', - 'PR' => '/^00[679]\d{2}(?:-\d{4})?$/', - 'PT' => '/^\d{4}-?\d{3}$/', - 'PW' => '/^(96940)$/', - 'PY' => '/^(\d{4})$/', - 'RE' => '/^((97|98)(4|7|8)\d{2})$/', - 'RO' => '/^(\d{6})$/', - 'RS' => '/^(\d{5})$/', - 'RU' => '/^(\d{6})$/', - 'SA' => '/^(\d{5})$/', - 'SD' => '/^(\d{5})$/', - 'SE' => '/^(?:SE)?\d{3}\s\d{2}$/', - 'SG' => '/^(\d{6})$/', - 'SH' => '/^(STHL1ZZ)$/', - 'SI' => '/^(?:SI)*(\d{4})$/', - 'SJ' => '/^(\d{4})$/', - 'SK' => '/^\d{3}\s?\d{2}$/', - 'SM' => '/^(4789\d)$/', - 'SN' => '/^(\d{5})$/', - 'SO' => '/^([A-Z]{2}\d{5})$/', - 'SV' => '/^(?:CP)*(\d{4})$/', - 'SZ' => '/^([A-Z]\d{3})$/', - 'TC' => '/^(TKCA 1ZZ)$/', - 'TH' => '/^(\d{5})$/', - 'TJ' => '/^(\d{6})$/', - 'TM' => '/^(\d{6})$/', - 'TN' => '/^(\d{4})$/', - 'TR' => '/^(\d{5})$/', - 'TW' => '/^(\d{5})$/', - 'UA' => '/^(\d{5})$/', - 'US' => '/^\d{5}(-\d{4})?$/', - 'UY' => '/^(\d{5})$/', - 'UZ' => '/^(\d{6})$/', - 'VA' => '/^(\d{5})$/', - 'VE' => '/^(\d{4})$/', - 'VI' => '/^008\d{2}(?:-\d{4})?$/', - 'VN' => '/^(\d{6})$/', - 'WF' => '/^(986\d{2})$/', - 'YT' => '/^(\d{5})$/', - 'ZA' => '/^(\d{4})$/', - 'ZM' => '/^(\d{5})$/', + 'AM' => ['/^\d\d\d\d$/', '/^(\d{4})$/'], + 'BR' => ['/^\d\d\d\d\d-\d\d\d$/', '/^\d{5}-?\d{3}$/'], + 'EC' => ['/^\d\d\d\d\d\d$/', '/^(\d{6})$/'], + 'GR' => ['/^\d\d\d \d\d$/', '/^(\d{3}\s?\d{2})$/'], + 'GB' => ['/^\w\d \d\w\w|\w\d\d \d\w\w|\w\w\d \d\w\w|\w\w\d\d \d\w\w|\w\d\w \d\w\w|\w\w\d\w \d\w\w|GIR 0AA$/', '/^([Gg][Ii][Rr]\s?0[Aa]{2})|((([A-Za-z][0-9]{1,2})|(([A-Za-z][A-Ha-hJ-Yj-y][0-9]{1,2})|(([A-Za-z][0-9][A-Za-z])|([A-Za-z][A-Ha-hJ-Yj-y][0-9]?[A-Za-z]))))\s?[0-9][A-Za-z]{2})$/'], + 'KH' => ['/^\d\d\d\d\d\d?$/', '/^(\d{5,6})$/'], + 'KY' => ['/^KY[1-3]-\d{4}$/', '/^KY[1-3]-?\d{4}$/'], + 'PT' => ['/^\d\d\d\d-\d\d\d$/', '/^\d{4}-?\d{3}\s?[a-zA-Z]{0,25}$/'], + 'RS' => ['/^\d\d\d\d\d\d?$/', '/^(\d{5,6})$/'], // phpcs:enable Generic.Files.LineLength.TooLong ]; - public function __construct(string $countryCode) + private const POSTAL_CODES = [ + // phpcs:disable Generic.Files.LineLength.TooLong + 'AD' => ['/^AD\d\d\d$/', '/^(?:AD)*(\d{3})$/'], + 'AL' => ['/^\d\d\d\d$/', '/^(\d{4})$/'], + 'AM' => ['/^\d\d\d\d\d\d$/', '/^(\d{6})$/'], + 'AR' => ['/^\w\d\d\d\d\w\w\w$/', '/^[A-Z]?\d{4}[A-Z]{0,3}$/'], + 'AS' => ['/^\d\d\d\d\d-\d\d\d\d$/', '/96799/'], + 'AT' => ['/^\d\d\d\d$/', '/^(\d{4})$/'], + 'AU' => ['/^\d\d\d\d$/', '/^(\d{4})$/'], + 'AX' => ['/^\d\d\d\d\d$/', '/^(?:FI)*(\d{5})$/'], + 'AZ' => ['/^AZ \d\d\d\d$/', '/^(?:AZ)*(\d{4})$/'], + 'BA' => ['/^\d\d\d\d\d$/', '/^(\d{5})$/'], + 'BB' => ['/^BB\d\d\d\d\d$/', '/^(?:BB)*(\d{5})$/'], + 'BD' => ['/^\d\d\d\d$/', '/^(\d{4})$/'], + 'BE' => ['/^\d\d\d\d$/', '/^(\d{4})$/'], + 'BG' => ['/^\d\d\d\d$/', '/^(\d{4})$/'], + 'BH' => ['/^\d\d\d\d|\d\d\d$/', '/^(\d{3}\d?)$/'], + 'BL' => ['/^\d\d\d\d\d$/', '/^(\d{5})$/'], + 'BM' => ['/^\w\w \d\d$/', '/^([A-Z]{2}\d{2})$/'], + 'BN' => ['/^\w\w\d\d\d\d$/', '/^([A-Z]{2}\d{4})$/'], + 'BR' => ['/^\d\d\d\d\d-\d\d\d$/', '/^\d{5}-\d{3}$/'], + 'BY' => ['/^\d\d\d\d\d\d$/', '/^(\d{6})$/'], + 'CA' => ['/^\w\d\w \d\w\d$/', '/^([ABCEGHJKLMNPRSTVXY]\d[ABCEGHJKLMNPRSTVWXYZ]) ?(\d[ABCEGHJKLMNPRSTVWXYZ]\d)$/'], + 'CH' => ['/^\d\d\d\d$/', '/^(\d{4})$/'], + 'CL' => ['/^\d\d\d\d\d\d\d$/', '/^(\d{7})$/'], + 'CN' => ['/^\d\d\d\d\d\d$/', '/^(\d{6})$/'], + 'CO' => ['/^\d\d\d\d\d\d$/', '/^(\d{6})$/'], + 'CR' => ['/^\d\d\d\d\d$/', '/^(\d{5})$/'], + 'CS' => ['/^\d\d\d\d\d$/', '/^(\d{5})$/'], + 'CU' => ['/^CP \d\d\d\d\d$/', '/^(?:CP)*(\d{5})$/'], + 'CV' => ['/^\d\d\d\d$/', '/^(\d{4})$/'], + 'CX' => ['/^\d\d\d\d$/', '/^(\d{4})$/'], + 'CY' => ['/^\d\d\d\d$/', '/^(\d{4})$/'], + 'CZ' => ['/^\d\d\d \d\d$/', '/^\d{3}\s?\d{2}$/'], + 'DE' => ['/^\d\d\d\d\d$/', '/^(\d{5})$/'], + 'DK' => ['/^\d\d\d\d$/', '/^(\d{4})$/'], + 'DO' => ['/^\d\d\d\d\d$/', '/^(\d{5})$/'], + 'DZ' => ['/^\d\d\d\d\d$/', '/^(\d{5})$/'], + 'EC' => ['/^\w\d\d\d\d\w$/', '/^([a-zA-Z]\d{4}[a-zA-Z])$/'], + 'EE' => ['/^\d\d\d\d\d$/', '/^(\d{5})$/'], + 'EG' => ['/^\d\d\d\d\d$/', '/^(\d{5})$/'], + 'ES' => ['/^\d\d\d\d\d$/', '/^(\d{5})$/'], + 'ET' => ['/^\d\d\d\d$/', '/^(\d{4})$/'], + 'FI' => ['/^\d\d\d\d\d$/', '/^(?:FI)*(\d{5})$/'], + 'FM' => ['/^\d\d\d\d\d$/', '/^(\d{5})$/'], + 'FO' => ['/^\d\d\d$/', '/^(?:FO)*(\d{3})$/'], + 'FR' => ['/^\d\d\d\d\d$/', '/^(\d{5})$/'], + 'GB' => ['/^\w\d \d\w\w|\w\d\d \d\w\w|\w\w\d \d\w\w|\w\w\d\d \d\w\w|\w\d\w \d\w\w|\w\w\d\w \d\w\w|GIR0AA$/', '/^([Gg][Ii][Rr]\s?0[Aa]{2})|((([A-Za-z][0-9]{1,2})|(([A-Za-z][A-Ha-hJ-Yj-y][0-9]{1,2})|(([A-Za-z][0-9][A-Za-z])|([A-Za-z][A-Ha-hJ-Yj-y][0-9]?[A-Za-z]))))\s?[0-9][A-Za-z]{2})$/'], + 'GE' => ['/^\d\d\d\d$/', '/^(\d{4})$/'], + 'GF' => ['/^\d\d\d\d\d$/', '/^((97|98)3\d{2})$/'], + 'GG' => ['/^\w\d \d\w\w|\w\d\d \d\w\w|\w\w\d \d\w\w|\w\w\d\d \d\w\w|\w\d\w \d\w\w|\w\w\d\w \d\w\w|GIR0AA$/', '/^((?:(?:[A-PR-UWYZ][A-HK-Y]\d[ABEHMNPRV-Y0-9]|[A-PR-UWYZ]\d[A-HJKPS-UW0-9])\s\d[ABD-HJLNP-UW-Z]{2})|GIR\s?0AA)$/'], + 'GL' => ['/^\d\d\d\d$/', '/^(\d{4})$/'], + 'GP' => ['/^\d\d\d\d\d$/', '/^((97|98)\d{3})$/'], + 'GR' => ['/^\d\d\d \d\d$/', '/^(\d{5})$/'], + 'GT' => ['/^\d\d\d\d\d$/', '/^(\d{5})$/'], + 'GU' => ['/^969\d\d$/', '/^(969\d{2})$/'], + 'GW' => ['/^\d\d\d\d$/', '/^(\d{4})$/'], + 'HN' => ['/^\w\w\d\d\d\d$/', '/^([A-Z]{2}\d{4})$/'], + 'HR' => ['/^\d\d\d\d\d$/', '/^(?:HR)*(\d{5})$/'], + 'HT' => ['/^HT\d\d\d\d$/', '/^(?:HT)*(\d{4})$/'], + 'HU' => ['/^\d\d\d\d$/', '/^(\d{4})$/'], + 'ID' => ['/^\d\d\d\d\d$/', '/^(\d{5})$/'], + 'IE' => ['/^\w\w\w \w\w\w\w$/', '/^(D6W|[AC-FHKNPRTV-Y][0-9]{2})\s?([AC-FHKNPRTV-Y0-9]{4})/'], + 'IL' => ['/^\d\d\d\d\d\d\d$/', '/^(\d{7}|\d{5})$/'], + 'IM' => ['/^\w\d \d\w\w|\w\d\d \d\w\w|\w\w\d \d\w\w|\w\w\d\d \d\w\w|\w\d\w \d\w\w|\w\w\d\w \d\w\w|GIR0AA$/', '/^((?:(?:[A-PR-UWYZ][A-HK-Y]\d[ABEHMNPRV-Y0-9]|[A-PR-UWYZ]\d[A-HJKPS-UW0-9])\s\d[ABD-HJLNP-UW-Z]{2})|GIR\s?0AA)$/'], + 'IN' => ['/^\d\d\d\d\d\d$/', '/^(\d{6})$/'], + 'IQ' => ['/^\d\d\d\d\d$/', '/^(\d{5})$/'], + 'IR' => ['/^\d\d\d\d\d\d\d\d\d\d$/', '/^(\d{10})$/'], + 'IS' => ['/^\d\d\d$/', '/^(\d{3})$/'], + 'IT' => ['/^\d\d\d\d\d$/', '/^(\d{5})$/'], + 'JE' => ['/^\w\d \d\w\w|\w\d\d \d\w\w|\w\w\d \d\w\w|\w\w\d\d \d\w\w|\w\d\w \d\w\w|\w\w\d\w \d\w\w|GIR0AA$/', '/^((?:(?:[A-PR-UWYZ][A-HK-Y]\d[ABEHMNPRV-Y0-9]|[A-PR-UWYZ]\d[A-HJKPS-UW0-9])\s\d[ABD-HJLNP-UW-Z]{2})|GIR\s?0AA)$/'], + 'JO' => ['/^\d\d\d\d\d$/', '/^(\d{5})$/'], + 'JP' => ['/^\d\d\d-\d\d\d\d$/', '/^\d{3}-\d{4}$/'], + 'KE' => ['/^\d\d\d\d\d$/', '/^(\d{5})$/'], + 'KG' => ['/^\d\d\d\d\d\d$/', '/^(\d{6})$/'], + 'KH' => ['/^\d\d\d\d\d$/', '/^(\d{5})$/'], + 'KP' => ['/^\d\d\d-\d\d\d$/', '/^(\d{6})$/'], + 'KR' => ['/^\d\d\d\d\d$/', '/^(\d{5})$/'], + 'KW' => ['/^\d\d\d\d\d$/', '/^(\d{5})$/'], + 'KZ' => ['/^\d\d\d\d\d\d$/', '/^(\d{6})$/'], + 'LA' => ['/^\d\d\d\d\d$/', '/^(\d{5})$/'], + 'LB' => ['/^\d\d\d\d \d\d\d\d|\d\d\d\d$/', '/^(\d{4}(\d{4})?)$/'], + 'LI' => ['/^\d\d\d\d$/', '/^(\d{4})$/'], + 'LK' => ['/^\d\d\d\d\d$/', '/^(\d{5})$/'], + 'LR' => ['/^\d\d\d\d$/', '/^(\d{4})$/'], + 'LS' => ['/^\d\d\d$/', '/^(\d{3})$/'], + 'LT' => ['/^LT-\d\d\d\d\d$/', '/^(?:LT)*(\d{5})$/'], + 'LU' => ['/^L-\d\d\d\d$/', '/^(?:L-)?\d{4}$/'], + 'LV' => ['/^LV-\d\d\d\d$/', '/^(?:LV)*(\d{4})$/'], + 'MA' => ['/^\d\d\d\d\d$/', '/^(\d{5})$/'], + 'MC' => ['/^\d\d\d\d\d$/', '/^(\d{5})$/'], + 'MD' => ['/^MD-\d\d\d\d$/', '/^MD-\d{4}$/'], + 'ME' => ['/^\d\d\d\d\d$/', '/^(\d{5})$/'], + 'MF' => ['/^\d\d\d\d\d$/', '/^(\d{5})$/'], + 'MG' => ['/^\d\d\d$/', '/^(\d{3})$/'], + 'MH' => ['/^\d\d\d\d\d-\d\d\d\d$/', '/^969\d{2}(-\d{4})$/'], + 'MK' => ['/^\d\d\d\d$/', '/^(\d{4})$/'], + 'MM' => ['/^\d\d\d\d\d$/', '/^(\d{5})$/'], + 'MN' => ['/^\d\d\d\d\d\d$/', '/^(\d{6})$/'], + 'MP' => ['/^\d\d\d\d\d$/', '/^9695\d{1}$/'], + 'MQ' => ['/^\d\d\d\d\d$/', '/^(\d{5})$/'], + 'MT' => ['/^\w\w\w \d\d\d\d$/', '/^[A-Z]{3}\s?\d{4}$/'], + 'MV' => ['/^\d\d\d\d\d$/', '/^(\d{5})$/'], + 'MW' => ['/^\d\d\d\d\d\d$/', '/^(\d{6})$/'], + 'MX' => ['/^\d\d\d\d\d$/', '/^(\d{5})$/'], + 'MY' => ['/^\d\d\d\d\d$/', '/^(\d{5})$/'], + 'MZ' => ['/^\d\d\d\d$/', '/^(\d{4})$/'], + 'NC' => ['/^\d\d\d\d\d$/', '/^(\d{5})$/'], + 'NE' => ['/^\d\d\d\d$/', '/^(\d{4})$/'], + 'NF' => ['/^\d\d\d\d$/', '/^(\d{4})$/'], + 'NG' => ['/^\d\d\d\d\d\d$/', '/^(\d{6})$/'], + 'NI' => ['/^\d\d\d-\d\d\d-\d$/', '/^(\d{7})$/'], + 'NL' => ['/^\d\d\d\d \w\w$/', '/^(\d{4}\s?[a-zA-Z]{2})$/'], + 'NO' => ['/^\d\d\d\d$/', '/^(\d{4})$/'], + 'NP' => ['/^\d\d\d\d\d$/', '/^(\d{5})$/'], + 'NZ' => ['/^\d\d\d\d$/', '/^(\d{4})$/'], + 'OM' => ['/^\d\d\d$/', '/^(\d{3})$/'], + 'PE' => ['/^\d\d\d\d\d$/', '/^(\d{5})$/'], + 'PF' => ['/^\d\d\d\d\d$/', '/^((97|98)7\d{2})$/'], + 'PG' => ['/^\d\d\d$/', '/^(\d{3})$/'], + 'PH' => ['/^\d\d\d\d$/', '/^(\d{4})$/'], + 'PK' => ['/^\d\d\d\d\d$/', '/^(\d{5})$/'], + 'PL' => ['/^\d\d-\d\d\d$/', '/^\d{2}-\d{3}$/'], + 'PM' => ['/^\d\d\d\d\d$/', '/^(97500)$/'], + 'PR' => ['/^\d\d\d\d\d-\d\d\d\d$/', '/^00[679]\d{2}(?:-\d{4})?$/'], + 'PT' => ['/^\d\d\d\d-\d\d\d$/', '/^\d{4}-\d{3}\s?[a-zA-Z]{0,25}$/'], + 'PW' => ['/^96940$/', '/^(96940)$/'], + 'PY' => ['/^\d\d\d\d$/', '/^(\d{4})$/'], + 'RE' => ['/^\d\d\d\d\d$/', '/^((97|98)(4|7|8)\d{2})$/'], + 'RO' => ['/^\d\d\d\d\d\d$/', '/^(\d{6})$/'], + 'RS' => ['/^\d\d\d\d\d\d$/', '/^(\d{6})$/'], + 'RU' => ['/^\d\d\d\d\d\d$/', '/^(\d{6})$/'], + 'SA' => ['/^\d\d\d\d\d$/', '/^(\d{5})$/'], + 'SD' => ['/^\d\d\d\d\d$/', '/^(\d{5})$/'], + 'SE' => ['/^\d\d\d \d\d$/', '/^(?:SE)?\d{3}\s\d{2}$/'], + 'SG' => ['/^\d\d\d\d\d\d$/', '/^(\d{6})$/'], + 'SH' => ['/^STHL 1ZZ$/', '/^(STHL1ZZ)$/'], + 'SI' => ['/^\d\d\d\d$/', '/^(?:SI)*(\d{4})$/'], + 'SJ' => ['/^\d\d\d\d$/', '/^(\d{4})$/'], + 'SK' => ['/^\d\d\d \d\d$/', '/^\d{3}\s?\d{2}$/'], + 'SM' => ['/^4789\d$/', '/^(4789\d)$/'], + 'SN' => ['/^\d\d\d\d\d$/', '/^(\d{5})$/'], + 'SO' => ['/^\w\w \d\d\d\d\d$/', '/^([A-Z]{2}\d{5})$/'], + 'SV' => ['/^CP \d\d\d\d$/', '/^(?:CP)*(\d{4})$/'], + 'SZ' => ['/^\w\d\d\d$/', '/^([A-Z]\d{3})$/'], + 'TC' => ['/^TKCA 1ZZ$/', '/^(TKCA 1ZZ)$/'], + 'TH' => ['/^\d\d\d\d\d$/', '/^(\d{5})$/'], + 'TJ' => ['/^\d\d\d\d\d\d$/', '/^(\d{6})$/'], + 'TM' => ['/^\d\d\d\d\d\d$/', '/^(\d{6})$/'], + 'TN' => ['/^\d\d\d\d$/', '/^(\d{4})$/'], + 'TR' => ['/^\d\d\d\d\d$/', '/^(\d{5})$/'], + 'TW' => ['/^\d\d\d\d\d$/', '/^(\d{5})$/'], + 'UA' => ['/^\d\d\d\d\d$/', '/^(\d{5})$/'], + 'US' => ['/^\d\d\d\d\d-\d\d\d\d$/', '/^\d{5}(-\d{4})?$/'], + 'UY' => ['/^\d\d\d\d\d$/', '/^(\d{5})$/'], + 'UZ' => ['/^\d\d\d\d\d\d$/', '/^(\d{6})$/'], + 'VA' => ['/^\d\d\d\d\d$/', '/^(\d{5})$/'], + 'VE' => ['/^\d\d\d\d$/', '/^(\d{4})$/'], + 'VI' => ['/^\d\d\d\d\d-\d\d\d\d$/', '/^008\d{2}(?:-\d{4})?$/'], + 'VN' => ['/^\d\d\d\d\d\d$/', '/^(\d{6})$/'], + 'WF' => ['/^\d\d\d\d\d$/', '/^(986\d{2})$/'], + 'YT' => ['/^\d\d\d\d\d$/', '/^(\d{5})$/'], + 'ZA' => ['/^\d\d\d\d$/', '/^(\d{4})$/'], + 'ZM' => ['/^\d\d\d\d\d$/', '/^(\d{5})$/'], + // phpcs:disable Generic.Files.LineLength.TooLong + ];//end + + public function __construct(string $countryCode, bool $formatted = false) { $countryCodeRule = new CountryCode(); if (!$countryCodeRule->validate($countryCode)) { @@ -198,7 +213,9 @@ final class PostalCode extends AbstractEnvelope } parent::__construct( - new Regex(self::POSTAL_CODES[$countryCode] ?? self::DEFAULT_PATTERN), + new Regex( + self::POSTAL_CODES_EXTRA[$countryCode][$formatted ? 0 : 1] ?? self::POSTAL_CODES[$countryCode][$formatted ? 0 : 1] ?? self::DEFAULT_PATTERN + ), ['countryCode' => $countryCode] ); } diff --git a/tests/unit/Rules/PostalCodeTest.php b/tests/unit/Rules/PostalCodeTest.php index 2a85dfd0..94244fd4 100644 --- a/tests/unit/Rules/PostalCodeTest.php +++ b/tests/unit/Rules/PostalCodeTest.php @@ -86,10 +86,12 @@ final class PostalCodeTest extends RuleTestCase [new PostalCode('KY'), 'KY3-2500'], [new PostalCode('AM'), '0010'], [new PostalCode('RS'), '24430'], + [new PostalCode('RS'), '244300'], [new PostalCode('GR'), '24430'], [new PostalCode('GR'), '244 30'], [new PostalCode('KH'), '12080'], [new PostalCode('KH'), '120802'], + [new PostalCode('CZ', true), '120 80'], ]; } @@ -103,8 +105,8 @@ final class PostalCodeTest extends RuleTestCase [new PostalCode('BR'), '02179.000'], [new PostalCode('CA'), '1A1B2B'], [new PostalCode('GB'), 'GIR 00A'], - [new PostalCode('GB'), 'GIR0AA'], - [new PostalCode('GB'), 'PR19LY'], + [new PostalCode('GB', true), 'GIR0AA'], + [new PostalCode('GB', true), 'PR19LY'], [new PostalCode('US'), '021 79'], [new PostalCode('YE'), '02179'], [new PostalCode('PL'), '99300'], @@ -113,8 +115,8 @@ final class PostalCodeTest extends RuleTestCase [new PostalCode('EC'), 'A1234B'], [new PostalCode('KY'), 'KY4-2500'], [new PostalCode('AM'), '375010'], - [new PostalCode('RS'), '244300'], [new PostalCode('KH'), '1208'], + [new PostalCode('CZ', true), '12080'], ]; } }