Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ jobs:
uses: shivammathur/setup-php@v2
with:
php-version: ${{ env.PHP_VERSION }}
extensions: bcmath
tools: composer:2

- name: Validate composer.json
Expand Down Expand Up @@ -52,7 +51,6 @@ jobs:
uses: shivammathur/setup-php@v2
with:
php-version: ${{ env.PHP_VERSION }}
extensions: bcmath
tools: composer:2

- name: Download vendor artifact from build
Expand All @@ -77,7 +75,6 @@ jobs:
uses: shivammathur/setup-php@v2
with:
php-version: ${{ env.PHP_VERSION }}
extensions: bcmath
tools: composer:2

- name: Download vendor artifact from build
Expand Down
98 changes: 87 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,20 @@
* [Overview](#overview)
* [Installation](#installation)
* [How to use](#how-to-use)
* [Alpha2Code](#alpha2code)
* [Alpha3Code](#alpha3code)
* [Country](#country-1)
* [Timezones](#timezones)
* [Timezone](#timezone)
* [License](#license)
* [Contributing](#contributing)

<div id='overview'></div>
<div id='overview'></div>

## Overview

Value Object representing a country using [ISO-3166 specifications](https://www.iso.org/iso-3166-country-codes.html).
Value Object representing a country using [ISO-3166 specifications](https://www.iso.org/iso-3166-country-codes.html),
with built-in support for [IANA timezones](https://www.iana.org).

<div id='installation'></div>

Expand All @@ -26,9 +32,8 @@ composer require tiny-blocks/country

## How to use

The library exposes country codes according
to [ISO-3166 specifications](https://www.iso.org/iso-3166-country-codes.html). Also, it is possible to create a
representation of a country that groups the codes and its name.
The library exposes country codes according to ISO-3166 specifications. It is possible to create a representation
of a country that groups the codes, its name, and all its IANA timezones.

### Alpha2Code

Expand All @@ -44,8 +49,7 @@ $alpha2Code->toAlpha3()->value; # USA

### Alpha3Code

A three-letter code that represents a country name, which is usually more closely related to the
country name.
A three-letter code that represents a country name, which is usually more closely related to the country name.

```php
$alpha3Code = Alpha3Code::UNITED_STATES_OF_AMERICA;
Expand All @@ -61,6 +65,8 @@ A `Country` instance can be created using either an `Alpha-2` or `Alpha-3` code,
There are two main methods to create a `Country` object: `from` (which accepts objects) and `fromString` (which accepts
strings).

Each `Country` automatically carries all its IANA timezones.

#### Creating from objects

You can create a `Country` instance using the `from` method by providing an `Alpha2Code` or `Alpha3Code` object.
Expand All @@ -75,8 +81,6 @@ $country->alpha2->value; # US
$country->alpha3->value; # USA
```

or

```php
$country = Country::from(alphaCode: Alpha3Code::UNITED_STATES_OF_AMERICA);

Expand All @@ -98,7 +102,7 @@ $country->alpha3->value; # USA
#### Creating from string

Alternatively, you can create a `Country` instance using the `fromString` method, which accepts an `Alpha-2` or
`Alpha-3` code as a string. This method is useful when the alpha code is provided as a string.
`Alpha-3` code as a string.

```php
$country = Country::fromString(alphaCode: 'US');
Expand All @@ -108,7 +112,7 @@ $country->alpha2->value; # US
$country->alpha3->value; # USA
```

You can also pass a custom country name when using the `fromString` method:
You can also pass a custom country name:

```php
$country = Country::fromString(alphaCode: 'USA', name: 'United States');
Expand All @@ -118,6 +122,78 @@ $country->alpha2->value; # US
$country->alpha3->value; # USA
```

### Timezones

Every `Country` includes an immutable `Timezones` collection, built from the IANA timezone database (via PHP's ICU
integration).

```php
$country = Country::from(alphaCode: Alpha2Code::BRAZIL);

$country->timezones->count(); # 4
$country->timezones->default(); # Timezone("America/Noronha")
$country->timezones->toStrings(); # ["America/Noronha", "America/Belem", "America/Sao_Paulo", ...]
```

#### Getting all timezones

Returns all `Timezone` objects for the country:

```php
$country->timezones->all(); # [Timezone("America/Noronha"), Timezone("America/Belem"), ...]
```

#### Getting the default timezone

Returns the primary timezone (first in the IANA list). Falls back to `UTC` for territories without an assigned timezone:

```php
$country = Country::from(alphaCode: Alpha2Code::JAPAN);
$country->timezones->default(); # Timezone("Asia/Tokyo")

$country = Country::from(alphaCode: Alpha2Code::BOUVET_ISLAND);
$country->timezones->default(); # Timezone("UTC")
```

#### Finding a timezone by identifier

Searches for a specific IANA identifier within the country's timezones:

```php
$country = Country::from(alphaCode: Alpha2Code::UNITED_STATES_OF_AMERICA);

$country->timezones->findByIdentifier(iana: 'America/New_York'); # Timezone("America/New_York")
$country->timezones->findByIdentifier(iana: 'Asia/Tokyo'); # null
```

#### Checking if a timezone belongs to the country

```php
$country = Country::from(alphaCode: Alpha2Code::JAPAN);

$country->timezones->contains(iana: 'Asia/Tokyo'); # true
$country->timezones->contains(iana: 'America/New_York'); # false
```

### Timezone

A `Timezone` is a Value Object representing a single valid IANA timezone identifier.

```php
$timezone = Timezone::from(identifier: 'America/Sao_Paulo');

$timezone->value; # America/Sao_Paulo
$timezone->toString(); # America/Sao_Paulo
```

Creating a UTC timezone:

```php
$timezone = Timezone::utc();

$timezone->value; # UTC
```

<div id='license'></div>

## License
Expand Down
7 changes: 5 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,11 @@
"vo",
"psr",
"country",
"iso-3166",
"timezones",
"tiny-blocks",
"value-object"
"value-object",
"iana-timezone"
],
"authors": [
{
Expand All @@ -36,7 +39,7 @@
},
"autoload-dev": {
"psr-4": {
"TinyBlocks\\Country\\": "tests/"
"Test\\TinyBlocks\\Country\\": "tests/"
}
},
"require": {
Expand Down
3 changes: 2 additions & 1 deletion infection.json.dist
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@
"customPath": "./vendor/bin/phpunit"
},
"mutators": {
"@default": true
"@default": true,
"AssignCoalesce": false
},
"minCoveredMsi": 100,
"testFramework": "phpunit"
Expand Down
3 changes: 2 additions & 1 deletion phpstan.neon.dist
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@ parameters:
level: 9
tmpDir: report/phpstan
ignoreErrors:
- '#value type specified in iterable type array#'
- '#Cannot access property#'
- '#Unsafe usage of new static#'
reportUnmatchedIgnoredErrors: false
22 changes: 13 additions & 9 deletions src/Alpha2Code.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,15 @@

namespace TinyBlocks\Country;

use TinyBlocks\Country\Internal\AlphaCodeMapper;

/**
* Alpha-2 code – a two-letter code that represents a country name, recommended as the general purpose code.
* Alpha-2 code – a two-letter code that represents a country name,
* recommended as the general purpose code.
*
* @see https://www.iso.org/iso-3166-country-codes.html
* @see https://www.iso.org/glossary-for-iso-3166.html
*/
enum Alpha2Code: string implements AlphaCode
{
Comment thread
gustavofreze marked this conversation as resolved.
use AlphaCodeMapper;

public const int CODE_LENGTH = 2;

case AFGHANISTAN = 'AF';
case ALAND_ISLANDS = 'AX';
case ALBANIA = 'AL';
Expand Down Expand Up @@ -265,9 +260,18 @@ public function getName(): string
return $this->name;
}

/**
* Converts this Alpha-2 code to its corresponding Alpha-3 code.
*
* @return Alpha3Code The corresponding Alpha-3 code.
*/
public function toAlpha3(): Alpha3Code
{
$value = $this->getBy(name: $this->name, alphaCodes: Alpha3Code::cases())->value;
return Alpha3Code::from(value: $value);
return Alpha3Code::from(
value: array_find(
Alpha3Code::cases(),
fn(Alpha3Code $alpha3): bool => $alpha3->name === $this->name
)->value
);
Comment thread
gustavofreze marked this conversation as resolved.
}
}
19 changes: 11 additions & 8 deletions src/Alpha3Code.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@

namespace TinyBlocks\Country;

use TinyBlocks\Country\Internal\AlphaCodeMapper;

/**
* Alpha-3 code – a three-letter code that represents a country name,
* which is usually more closely related to the country name.
Expand All @@ -15,10 +13,6 @@
*/
enum Alpha3Code: string implements AlphaCode
{
use AlphaCodeMapper;

public const int CODE_LENGTH = 3;

case AFGHANISTAN = 'AFG';
case ALAND_ISLANDS = 'ALA';
case ALBANIA = 'ALB';
Expand Down Expand Up @@ -266,9 +260,18 @@ public function getName(): string
return $this->name;
}

/**
* Converts this Alpha-3 code to its corresponding Alpha-2 code.
*
* @return Alpha2Code The corresponding Alpha-2 code.
*/
public function toAlpha2(): Alpha2Code
{
$value = $this->getBy(name: $this->name, alphaCodes: Alpha2Code::cases())->value;
return Alpha2Code::from(value: $value);
return Alpha2Code::from(
value: array_find(
Alpha2Code::cases(),
fn(Alpha2Code $alpha2): bool => $alpha2->name === $this->name
)->value
Comment thread
gustavofreze marked this conversation as resolved.
);
}
}
7 changes: 4 additions & 3 deletions src/AlphaCode.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,14 @@

/**
* Defines the contract for classes representing alpha codes of countries.
*
* @see https://www.iso.org/iso-3166-country-codes.html
*/
interface AlphaCode
{
/**
* Gets the name associated with the alpha code.
*
* @return string The name of the country or region corresponding to the code.
* Gets the enum case name associated with the alpha code (e.g. BRAZIL, UNITED_STATES_OF_AMERICA).
* @return string The name of the enum case representing the alpha code.
*/
public function getName(): string;
}
Loading