diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..6537ca4 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,15 @@ +root = true + +[*] +charset = utf-8 +end_of_line = lf +insert_final_newline = true +indent_style = space +indent_size = 4 +trim_trailing_whitespace = true + +[*.md] +trim_trailing_whitespace = false + +[*.{yml,yaml}] +indent_size = 2 diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..15eb96f --- /dev/null +++ b/.gitattributes @@ -0,0 +1,14 @@ +* text=auto + +*.md diff=markdown +*.php diff=php + +/.github export-ignore +/tests export-ignore +.editorconfig export-ignore +.gitattributes export-ignore +.gitignore export-ignore +.styleci.yml export-ignore +CHANGELOG.md export-ignore +LICENSE.md export-ignore +phpunit.xml.dist export-ignore diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml new file mode 100644 index 0000000..eab4d08 --- /dev/null +++ b/.github/workflows/run-tests.yml @@ -0,0 +1,41 @@ +name: run-tests + +on: [push, pull_request] + +jobs: + test: + runs-on: ubuntu-20.04 + strategy: + fail-fast: true + matrix: + php: [ 7.1, 7.4 ] + laravel: [ 5.* ] + include: + - laravel: 5.* + + name: PHP ${{ matrix.php }} - Laravel ${{ matrix.laravel }} + + steps: + - name: Checkout code + uses: actions/checkout@v2 + + - name: Cache dependencies + uses: actions/cache@v2 + with: + path: ~/.composer/cache/files + key: dependencies-laravel-${{ matrix.laravel }}-php-${{ matrix.php }}-composer-${{ hashFiles('composer.json') }} + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php }} + extensions: dom, curl, libxml, mbstring, zip + coverage: none + + - name: Install dependencies + run: | + composer require "laravel/framework:${{ matrix.laravel }}" --no-interaction --no-update + composer update --prefer-dist --no-interaction --no-progress + + - name: Execute tests + run: vendor/bin/phpunit diff --git a/.gitignore b/.gitignore index 30babff..660fc15 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ -/vendor/ -.idea +/vendor composer.lock +/phpunit.xml +.phpunit.result.cache diff --git a/.styleci.yml b/.styleci.yml new file mode 100644 index 0000000..b06f883 --- /dev/null +++ b/.styleci.yml @@ -0,0 +1,5 @@ +preset: laravel +enabled: + - concat_with_spaces +disabled: + - concat_without_spaces diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 775b2b7..0000000 --- a/.travis.yml +++ /dev/null @@ -1,19 +0,0 @@ -sudo: false - -language: php - -php: - - '7.1' - -cache: - directories: - - $HOME/.composer/cache - -before_script: - - composer install --prefer-source --no-interaction - -script: - - vendor/bin/phpunit --coverage-clover build/logs/clover.xml - -after_success: - - bash <(curl -s build/logs/ https://codecov.io/bash) diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..20d8779 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,161 @@ +# Changelog + +All notable changes to `pod-point/countries` will be documented in this file. + +## 3.2.2 - 2024-05-23 + +* Adds Spain and France as locales for present and future expansion (target 3.2 base for API3) + +## 3.2.0 - 2022-04-29 + +* Adds precision to the `NumberHelper` and implements `NumberHelper` Facade ([#57](https://github.com/Pod-Point/countries/pull/57)). + + +## 3.1.4 - 2022-04-13 + +* Fix the memoization and the `getSymbol` method in the CurrencyHelper ([#51](https://github.com/Pod-Point/countries/pull/51)). + +## 3.1.3 - 2021-05-19 + +* [SWP-2788](https://podpoint.atlassian.net/browse/SWP-2788) Introduce memoization for efficiency during use on mass + * Introduced a history for finds in the `CountryHelper` so that we don't perform the same lookup many times + * Introduced a caching layer for `NumberFormatters` used in the `CurrencyHelper` to avoid creating many unnecessary instances when used on mass + +## 3.1.2 - 2021-05-18 + +* Minor modernisations +* Moved from Travis CI to Github Actions + +## 3.1.1 - 2020-11-05 + +* `getSystemLocale` in `LocalizedHelper` now returns the fallback locale if the given one is not found. This created issues with some tests because NumberFormatter becomes system dependent if null is given. + +## 3.1.0 - 2020-11-03 + +* Add `CountryHelper` facade with `getCountryCodeFromLocale` and `findByLocale` functions. +* Improve `CurrencyHelper` facade with a new function `toStandardFormat`. It returns the typical currency format and can also show a specified number of decimals. + +## 3.0.9 - 2020-10-12 + +* Add `formatToMinorUnitWhenApplicable` method: formats currency with pence when the rate is less than 1.00. + +## 3.0.8 - 2020-07-01 + +* [SWP-1718](https://podpoint.atlassian.net/browse/SWP-1718) - Revert “Republic of Ireland” to have its locale set to ie instead of en + +## 3.0.7 - 2020-06-09 + +### [SWP-1648] DT breaking change on i18n v 3.0.6 + +* Fix locale for supported countries (should only be `en` or `no` for now) +* Renaming wrongly named test files. +* Improve test coverage. +* Improve ViewComposer tests. + +### [SWP-1609] [ALT] Extract VAT logic into i18n package + +* Leverage `mpociot/vat-calculator` in order to bring VAT resolution support +* Exposing it through a Facade too +* Improve service provider +* Better type hinting +* Update readme + +## 3.0.6 - 2020-04-21 + +* Update Ireland details +* Add EUR as currency code +* IE as country code + +## 3.0.5 - 2019-07-08 + +* Reverting the order when merging countries so that the name in our config is the one that is going to be used. + +## 3.0.4 - 2019-07-04 + +### CurrencyHelper: up to 6 decimals of a monetary unit supported + +* PHP NumberFormatter will round up with 2 decimals only by default. +* Sometimes we can display up to 6 decimals of the monetary unit (ex: `£0.106544`) especially for energy prices like `£0.106544 per kWh`. +* If a regular float like `19.99` with only 2 decimals is given, it will still be formatted as usual `£19.99`. + +## 3.0.3 - 2019-06-26 + +* [SWP-36](https://podpoint.atlassian.net/browse/SWP-36) Adding to format from cents helper method with the new `toFormatFromInt` and `moneyFormatFromInt` helpers method. + +## 3.0.2 - 2019-05-22 + +* Adding new abstract `LocalizedHelper` that will have the logic to retrieve a locale in a `NumberFormatter` format +* Changing the currency helper so that it extends the localized helper +* Adding new number helper that allows us to format a number in the right locale +* renaming `format` to `toFormat` for consistency in the `NumberHelper` +* Changing the style from `DECIMAL` to `DEFAULT_STYLE` + +## 3.0.0 - 2019-03-14 + +### Added + +* Support of currency conversion service +* Helpers to format money given the currency and locale +* Helper to get the currency symbol given the currency code and locale + +### Updated + +* Namespace was update to `PodPoint\I18n` + +## 2.4.4 - 2018-09-12 + +* Add GB system locale + +## 2.4.3 - 2018-09-04 + +* Add Norway and UK timezones + +## 2.4.2 - 2018-02-21 + +* Add system locale to NO + +## 2.4.1 - 2018-02-15 + +* Added country helper + +## 2.4.0 - 2018-02-01 + +* Add ISO country information to existing country config + +## 2.3.2 - 2018-01-26 + +* Adding the extension linked to the countries in `countries-partial` config files +* Renaming the index 'extension' to 'tld' + +## 2.3.1/2.3.0 - 2018-01-23 + +* Adding locale informations in config file `contries-partials.php`, and a new view composer that prepares values for language switchers +* Adding language field into configuration files for the languages switchers + +## 2.2.0 - 2018-01-19 + +* Add country code constants + +## 2.1.0 - 2017-10-23 + +* Add country code view composer + +## 2.0.1 - 2017-09-01 + +* Fix to country with no dialling code: `null` value where no dialling code + +## 2.0 - 2017-08-31 + +* Added dialling codes + +#### Breaking changes: + +* This is a breaking change from v1.0.* as config arrays have been restructured to include dialling codes. + +## 1.0.1 - 2015-12-07 + +* Support Laravel 5.1 and 5.2 + +## 1.0.0 - 2015-09-07 + +* Initial release diff --git a/LICENCE.md b/LICENCE.md index f21c21d..43a3657 100644 --- a/LICENCE.md +++ b/LICENCE.md @@ -1,21 +1,21 @@ -MIT License +# The MIT License (MIT) -Copyright (c) 2019 POD Point Ltd +Copyright (c) Pod Point -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +> Permission is hereby granted, free of charge, to any person obtaining a copy +> of this software and associated documentation files (the "Software"), to deal +> in the Software without restriction, including without limitation the rights +> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +> copies of the Software, and to permit persons to whom the Software is +> furnished to do so, subject to the following conditions: +> +> The above copyright notice and this permission notice shall be included in +> all copies or substantial portions of the Software. +> +> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +> THE SOFTWARE. diff --git a/README.md b/README.md index b023624..b3e2061 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Internationalisation Package -[![Build Status](https://travis-ci.org/Pod-Point/countries.svg?branch=master)](https://travis-ci.org/Pod-Point/countries) [![codecov](https://codecov.io/gh/Pod-Point/countries/branch/master/graph/badge.svg?token=kG5ptGaEFs)](https://codecov.io/gh/Pod-Point/countries) [![Packagist](https://img.shields.io/packagist/v/Pod-Point/countries.svg)](https://packagist.org/packages/pod-point/countries) +[![run-tests](https://github.com/Pod-Point/countries/actions/workflows/run-tests.yml/badge.svg)](https://github.com/Pod-Point/countries/actions/workflows/run-tests.yml) This package provides Laravel and Lumen applications internationalisation features: @@ -14,15 +14,24 @@ The countries are indexed using their uppercase ISO codes (alpha2/cca2). ## Installation -Require the package in composer: +You can install the package via composer: -```javascript -"require": { - "pod-point/countries": "^3.0" -}, +For Laravel 5.x and PHP <= 7.1 +```bash +composer require pod-point/countries:^3.0 ``` -Then finally, if you're using Laravel, add the service provider to your `config/app.php` providers array: +For Laravel 6.x and PHP >= 7.2 +```bash +composer require pod-point/countries:^4.0 +``` + +For Laravel 7.x or 8.x and PHP >= 7.3 +```bash +composer require pod-point/countries:^5.0 +``` + +Then, finally, if you're using a Laravel version which doesn't support Auto Discovery, add the service provider to your `config/app.php` providers array: ```php 'providers' => [ @@ -35,3 +44,19 @@ If you're using Lumen, add the following line to your `bootstrap/app.php` file: ```php $app->register(PodPoint\I18n\Providers\CountriesServiceProvider::class); ``` + +## Changelog + +Please see [CHANGELOG](CHANGELOG.md) for more information on what has changed recently. + +## Licence + +The MIT Licence (MIT). Please see [Licence File](LICENCE.md) for more information. + +--- + + + +Travel shouldn't damage the earth 🌍 + +Made with ❤️  at [Pod Point](https://pod-point.com) diff --git a/composer.json b/composer.json index 34cfda6..8ddf6ad 100644 --- a/composer.json +++ b/composer.json @@ -1,7 +1,15 @@ { "name": "pod-point/i18n", "description": "A package of useful components for internationalisation in Laravel applications.", - "type": "library", + "keywords": ["laravel", "i18n", "internationalisation", "tax", "currencies", "markets", "languages", "countries"], + "homepage": "https://github.com/pod-point/countries", + "license": "MIT", + "authors": [ + { + "name": "Pod Point Software Team", + "email": "software@pod-point.com" + } + ], "require": { "php": ">=7.1", "ext-intl": "*", @@ -16,13 +24,6 @@ "satooshi/php-coveralls": "^1.0", "phpunit/phpunit": "^7.5" }, - "license": "MIT", - "authors": [ - { - "name": "Pod Point Software Team", - "email": "software@pod-point.com" - } - ], "autoload": { "psr-4": { "PodPoint\\I18n\\": "src/" @@ -38,9 +39,21 @@ }, "extra": { "laravel": { + "providers": [ + "PodPoint\\I18n\\CountriesServiceProvider" + ], "dont-discover": [ "mpociot/vat-calculator" ] } + }, + "scripts": { + "test": "vendor/bin/phpunit --colors=always", + "test-coverage": "vendor/bin/phpunit --coverage-html coverage" + }, + "minimum-stability": "dev", + "prefer-stable": true, + "config": { + "sort-packages": true } } diff --git a/phpunit.xml b/phpunit.xml deleted file mode 100644 index 9ee800d..0000000 --- a/phpunit.xml +++ /dev/null @@ -1,28 +0,0 @@ - - - - - src - - src/config - tests - vendor - src/helpers.php - src/Facades/CurrencyHelper.php - - - - - - tests - - - diff --git a/phpunit.xml.dist b/phpunit.xml.dist new file mode 100644 index 0000000..1275da2 --- /dev/null +++ b/phpunit.xml.dist @@ -0,0 +1,18 @@ + + + + + tests + + + diff --git a/src/CountryCode.php b/src/CountryCode.php index 9e008aa..cc09434 100644 --- a/src/CountryCode.php +++ b/src/CountryCode.php @@ -10,6 +10,8 @@ class CountryCode const UNITED_KINGDOM = 'GB'; const IRELAND = 'IE'; const NORWAY = 'NO'; + const SPAIN = 'ES'; + const FRANCE = 'FR'; /** * Retrieves all supported country codes. @@ -22,6 +24,8 @@ public static function all(): array self::UNITED_KINGDOM, self::IRELAND, self::NORWAY, + self::SPAIN, + self::FRANCE, ]; } } diff --git a/src/CountryHelper.php b/src/CountryHelper.php index c24d859..f93bf17 100644 --- a/src/CountryHelper.php +++ b/src/CountryHelper.php @@ -5,16 +5,28 @@ class CountryHelper extends Helper { /** - * Returns the first country matching the given property/value pair. + * Recent lookup results by `property-value`. * - * @param string $property - * @param mixed $value + * @var array + */ + protected $results = []; + + /** + * Returns the first country matching the given property/value pair. * + * @param string $property + * @param mixed $value * @return array|null */ public function findBy(string $property, $value): ?array { - return collect($this->config->get('countries')) + $key = $this->generateResultsKey($property, $value); + + if ($this->results[$key] ?? false) { + return $this->results[$key]; + } + + return $this->results[$key] = collect($this->config->get('countries')) ->where($property, $value) ->first(); } @@ -22,7 +34,7 @@ public function findBy(string $property, $value): ?array /** * Returns the first country matching the given locale. * - * @param string $locale + * @param string $locale * @return array|null */ public function findByLocale(string $locale): ?array @@ -33,7 +45,7 @@ public function findByLocale(string $locale): ?array /** * Returns the country code matching the given locale. * - * @param string $locale + * @param string $locale * @return string|null */ public function getCountryCodeFromLocale(string $locale): ?string @@ -42,6 +54,19 @@ public function getCountryCodeFromLocale(string $locale): ?string ->search(function ($item) use ($locale) { return isset($item['locale']) && $item['locale'] === $locale; }); + return $code ? $code : null; } + + /** + * Generate a string formed of the property and value for the results cache. + * + * @param string $property + * @param string $value + * @return string + */ + protected function generateResultsKey(string $property, string $value): string + { + return "${property}-{$value}"; + } } diff --git a/src/Currency/Cache/Service.php b/src/Currency/Cache/Service.php index 4806565..b43daaf 100644 --- a/src/Currency/Cache/Service.php +++ b/src/Currency/Cache/Service.php @@ -3,12 +3,12 @@ namespace PodPoint\I18n\Currency\Cache; use Carbon\Carbon; -use PodPoint\I18n\CurrencyCode; +use Illuminate\Contracts\Cache\Repository as Cache; use Illuminate\Support\Collection; use PodPoint\I18n\Currency\ExchangeRate; -use Illuminate\Contracts\Cache\Repository as Cache; use PodPoint\I18n\Currency\Service as CurrencyService; use PodPoint\I18n\Currency\Service as ServiceInterface; +use PodPoint\I18n\CurrencyCode; class Service implements CurrencyService { @@ -23,8 +23,8 @@ class Service implements CurrencyService private $service; /** - * @param Cache $cache - * @param ServiceInterface $service + * @param Cache $cache + * @param ServiceInterface $service */ public function __construct(Cache $cache, ServiceInterface $service) { @@ -35,11 +35,11 @@ public function __construct(Cache $cache, ServiceInterface $service) /** * Fetches the exchange rates from another service if they don't already exist in cache. * - * @param string $base - * @param string[] $currencies - * @param Carbon|null $timestamp - * + * @param string $base + * @param string[] $currencies + * @param Carbon|null $timestamp * @return Collection|ExchangeRate[] + * * @throws \Psr\SimpleCache\InvalidArgumentException */ public function getExchangeRates(string $base = CurrencyCode::POUND_STERLING, array $currencies = [], ?Carbon $timestamp = null): Collection @@ -80,11 +80,11 @@ public function getExchangeRates(string $base = CurrencyCode::POUND_STERLING, ar /** * Builds the key used to access/store this rate in cache. * - * @param string $base - * @param string $currency - * @param Carbon $timestamp - * + * @param string $base + * @param string $currency + * @param Carbon $timestamp * @return string + * * @throws \Psr\SimpleCache\InvalidArgumentException */ private function getCacheKey(string $base, string $currency, Carbon $timestamp): string diff --git a/src/Currency/ExchangeRate.php b/src/Currency/ExchangeRate.php index 453c2d6..edf999e 100644 --- a/src/Currency/ExchangeRate.php +++ b/src/Currency/ExchangeRate.php @@ -37,7 +37,7 @@ class ExchangeRate public $timestamp; /** - * @param array $attributes + * @param array $attributes */ public function __construct(array $attributes = []) { diff --git a/src/Currency/OpenExchangeRates/Client.php b/src/Currency/OpenExchangeRates/Client.php index cfa7885..d440390 100644 --- a/src/Currency/OpenExchangeRates/Client.php +++ b/src/Currency/OpenExchangeRates/Client.php @@ -2,14 +2,14 @@ namespace PodPoint\I18n\Currency\OpenExchangeRates; -use Illuminate\Support\Str; use Illuminate\Contracts\Config\Repository; +use Illuminate\Support\Str; class Client extends \GuzzleHttp\Client { /** - * @param Repository $configRepository - * @param array $config + * @param Repository $configRepository + * @param array $config */ public function __construct(Repository $configRepository, array $config = []) { diff --git a/src/Currency/OpenExchangeRates/Service.php b/src/Currency/OpenExchangeRates/Service.php index 31f4fec..e55eb17 100644 --- a/src/Currency/OpenExchangeRates/Service.php +++ b/src/Currency/OpenExchangeRates/Service.php @@ -3,11 +3,11 @@ namespace PodPoint\I18n\Currency\OpenExchangeRates; use Carbon\Carbon; -use PodPoint\I18n\CurrencyCode; +use Illuminate\Contracts\Config\Repository as Config; use Illuminate\Support\Collection; use PodPoint\I18n\Currency\ExchangeRate; -use Illuminate\Contracts\Config\Repository as Config; use PodPoint\I18n\Currency\Service as CurrencyService; +use PodPoint\I18n\CurrencyCode; class Service implements CurrencyService { @@ -22,8 +22,8 @@ class Service implements CurrencyService private $client; /** - * @param Config $config - * @param Client $client + * @param Config $config + * @param Client $client */ public function __construct(Config $config, Client $client) { @@ -34,10 +34,9 @@ public function __construct(Config $config, Client $client) /** * Fetches the exchange rates from the OpenExchangeRates API. * - * @param string $base - * @param string[] $currencies - * @param Carbon|null $timestamp - * + * @param string $base + * @param string[] $currencies + * @param Carbon|null $timestamp * @return Collection|ExchangeRate[] */ public function getExchangeRates(string $base = CurrencyCode::POUND_STERLING, array $currencies = [], ?Carbon $timestamp = null): Collection diff --git a/src/Currency/Service.php b/src/Currency/Service.php index 8c340dc..4892ad3 100644 --- a/src/Currency/Service.php +++ b/src/Currency/Service.php @@ -3,8 +3,8 @@ namespace PodPoint\I18n\Currency; use Carbon\Carbon; -use PodPoint\I18n\CurrencyCode; use Illuminate\Support\Collection; +use PodPoint\I18n\CurrencyCode; interface Service { @@ -13,10 +13,9 @@ interface Service * Passing an array of currencies will restrict the set of results to only the given currencies. * Passing a timestamp will retrieve the rates from that given date (& time if possible). * - * @param string $base - * @param string[] $currencies - * @param Carbon|null $timestamp - * + * @param string $base + * @param string[] $currencies + * @param Carbon|null $timestamp * @return Collection|ExchangeRate[] */ public function getExchangeRates(string $base = CurrencyCode::POUND_STERLING, array $currencies = [], ?Carbon $timestamp = null): Collection; diff --git a/src/CurrencyHelper.php b/src/CurrencyHelper.php index 274fdcd..fa9a361 100644 --- a/src/CurrencyHelper.php +++ b/src/CurrencyHelper.php @@ -9,40 +9,33 @@ class CurrencyHelper extends LocalizedHelper /** * Return a value in the given currency formatted for the given locale. * - * @param float|int $value - * @param string $currencyCode - * @param string $locale + * @param float|int $value + * @param string $currencyCode + * @param string $locale + * @return string * * @deprecated toStandardFormat should be used. - * @return string */ public function toFormat( $value, string $currencyCode = CurrencyCode::POUND_STERLING, string $locale = 'en' ): string { - $formatter = new NumberFormatter( - $this->getSystemLocale($locale), - NumberFormatter::CURRENCY - ); - /* - * NumberFormatter will round up with 2 decimals only by default. * Sometimes we can display up to 6 decimals of the monetary unit (ex: £0.106544) for energy prices. */ - $formatter->setAttribute(NumberFormatter::MAX_FRACTION_DIGITS, 6); - - return $formatter->formatCurrency($value, $currencyCode); + return $this + ->getDefaultFormatter($locale, 6) + ->formatCurrency($value, $currencyCode); } /** * Transform an integer representing a decimal currency value (penny, cents...) into a monetary formatted string * with the right currency symbol and the right localised format for the parameters respectively given. * - * @param int $value - * @param string $currencyCode - * @param string $locale - * + * @param int $value + * @param string $currencyCode + * @param string $locale * @return string */ public function toFormatFromInt( @@ -57,10 +50,9 @@ public function toFormatFromInt( * Transform an integer representing a decimal currency value (penny, cents...) into a monetary formatted string * with the right currency symbol and the right localised format for the parameters respectively given. * - * @param int $value - * @param string $currencyCode - * @param string $locale - * + * @param int $value + * @param string $currencyCode + * @param string $locale * @return string */ public function formatToMinorUnitWhenApplicable( @@ -71,14 +63,9 @@ public function formatToMinorUnitWhenApplicable( $pattern = $this->getMinorUnitPattern($locale); if ($value <= $this->getMinorUnitEnd($locale) && $pattern) { - $formatter = new NumberFormatter( - $this->getSystemLocale($locale), - NumberFormatter::CURRENCY - ); - - $formatter->setPattern($pattern); - - return $formatter->formatCurrency($value, $currencyCode); + return $this + ->getPatternedFormatter($locale, $pattern) + ->formatCurrency($value, $currencyCode); } return $this->toFormatFromInt($value, $currencyCode, $locale); @@ -87,45 +74,68 @@ public function formatToMinorUnitWhenApplicable( /** * Return a currency symbol formatted in the right locale. * - * @param string $locale - * @param string $currencyCode - * + * @param string $locale + * @param string $currencyCode * @return string */ public function getSymbol(string $currencyCode = CurrencyCode::POUND_STERLING, string $locale = 'en'): string { - $formatter = new NumberFormatter( - "{$this->getSystemLocale($locale)}@currency={$currencyCode}", - NumberFormatter::CURRENCY - ); - - return $formatter->getSymbol(NumberFormatter::CURRENCY_SYMBOL); + return $this + ->getSymbolFormatter($locale, $currencyCode) + ->getSymbol(NumberFormatter::CURRENCY_SYMBOL); } /** * Return a value in the given currency format for the given currency code and locale. * - * @param float $value - * @param string $currencyCode - * @param string $locale - * @param int|null $precision Number of decimals to show. If null is given, it will take the default currency - * precision - * + * @param float $value + * @param string $currencyCode + * @param string $locale + * @param int|null $precision Number of decimals to show. If null is given, it will take the default currency + * precision * @return string */ public function toStandardFormat( float $value, - $currencyCode = CurrencyCode::POUND_STERLING, + string $currencyCode = CurrencyCode::POUND_STERLING, string $locale = 'en', - $precision = null + int $precision = null ): string { - $formatter = new NumberFormatter($this->getSystemLocale($locale), NumberFormatter::CURRENCY); - - if (is_int($precision)) { - $formatter->setAttribute(NumberFormatter::MAX_FRACTION_DIGITS, $precision); - $formatter->setAttribute(NumberFormatter::MIN_FRACTION_DIGITS, $precision); + if (is_null($precision)) { + return $this->getDefaultFormatter($locale)->formatCurrency($value, $currencyCode); } - return $formatter->formatCurrency($value, $currencyCode); + return $this + ->getFixedPrecisionFormatter($locale, $precision) + ->formatCurrency($value, $currencyCode); + } + + /** + * Create a number formatter for retrieving symbols. + * + * @param string $locale + * @param string $currencyCode + * @return NumberFormatter + */ + protected function getSymbolFormatter(string $locale, string $currencyCode): NumberFormatter + { + return $this->getFormatter( + $this->getFormatterCacheKey(__FUNCTION__, func_get_args()), + function () use ($locale, $currencyCode) { + return $this->getBaseFormatter( + $this->getSystemLocale($locale) . "@currency=$currencyCode" + ); + } + ); + } + + /** + * Return the formatter style used by the number formatter. + * + * @return int + */ + protected function getFormatterStyle(): int + { + return NumberFormatter::CURRENCY; } } diff --git a/src/Facades/CurrencyHelper.php b/src/Facades/CurrencyHelper.php index cb123cb..04bf086 100755 --- a/src/Facades/CurrencyHelper.php +++ b/src/Facades/CurrencyHelper.php @@ -2,17 +2,15 @@ namespace PodPoint\I18n\Facades; -use PodPoint\I18n\CurrencyCode; use Illuminate\Support\Facades\Facade; +use PodPoint\I18n\CurrencyCode; /** - * // phpcs:disable * @method static string toFormat($value, string $currencyCode = CurrencyCode::POUND_STERLING, string $locale = 'en') * @method static string toFormatFromInt(int $value, string $currencyCode = CurrencyCode::POUND_STERLING, string $locale = 'en') * @method static string toStandardFormat(float $value, string $currencyCode = CurrencyCode::POUND_STERLING, string $locale = 'en') * @method static string getFormatToMinorUnitWhenApplicable(int $value, string $currencyCode = CurrencyCode::POUND_STERLING, string $locale = 'en') * @method static string getSymbol(string $currencyCode = CurrencyCode::POUND_STERLING, string $locale = 'en') - * // phpcs:enable */ class CurrencyHelper extends Facade { diff --git a/src/Facades/NumberHelper.php b/src/Facades/NumberHelper.php new file mode 100755 index 0000000..889f361 --- /dev/null +++ b/src/Facades/NumberHelper.php @@ -0,0 +1,21 @@ + en_GB.UTF-8) - * - * @param string $locale - * @param bool $fallback + * Return system locale from locale. (en => en_GB.UTF-8). * + * @param string $locale + * @param bool $fallback * @return string|null */ - protected function getSystemLocale(string $locale, $fallback = true): ?string + protected function getSystemLocale(string $locale, bool $fallback = true): ?string { $country = $this->countryHelper->findByLocale($locale); @@ -39,10 +53,9 @@ protected function getSystemLocale(string $locale, $fallback = true): ?string } /** - * Return minor unit pattern from locale. (en => #.##p) - * - * @param string $locale + * Return minor unit pattern from locale. (en => #.##p). * + * @param string $locale * @return string|null */ protected function getMinorUnitPattern(string $locale): ?string @@ -53,10 +66,9 @@ protected function getMinorUnitPattern(string $locale): ?string } /** - * Return the last minor unit from locale. (en => 99) - * - * @param string $locale + * Return the last minor unit from locale. (en => 99). * + * @param string $locale * @return int|null */ protected function getMinorUnitEnd(string $locale): ?int @@ -77,4 +89,110 @@ protected function getFallbackSystemLocale(): ?string return $country['systemLocale'] ?? null; } + + /** + * Gets a formatter or creates and returns it if not already. + * + * @param string $key + * @param callable $createHandler + * @return NumberFormatter + */ + protected function getFormatter(string $key, callable $createHandler): NumberFormatter + { + if (array_key_exists($key, $this->cachedFormatters)) { + return $this->cachedFormatters[$key]; + } + + $this->cachedFormatters[$key] = $createHandler(); + + return $this->cachedFormatters[$key] = $createHandler(); + } + + /** + * Get the formatter cache key. + * + * @param string $method + * @param array $params + * @return string + */ + protected function getFormatterCacheKey(string $method, array $params): string + { + return hash('sha256', $method . serialize($params)); + } + + /** + * Create a basic number formatter for the given locale in the given style. + * + * @param string $locale + * @return NumberFormatter + */ + protected function getBaseFormatter(string $locale): NumberFormatter + { + return new NumberFormatter($locale, $this->getFormatterStyle()); + } + + /** + * Create a number formatter with a fixed given precision. + * + * @param string $locale + * @param int $precision + * @return NumberFormatter + */ + protected function getFixedPrecisionFormatter(string $locale, int $precision): NumberFormatter + { + return $this->getDefaultFormatter($locale, $precision, $precision); + } + + /** + * Create the default formatter for the given locale. The precision can be variable based on the max and min values. + * If no precision is specified, the default one for the locale and NumberFormatter style will be used. + * + * @param string $locale + * @param int|null $maxPrecision + * @param int|null $minPrecision + * @return NumberFormatter + */ + protected function getDefaultFormatter( + string $locale, + int $maxPrecision = null, + int $minPrecision = null + ): NumberFormatter { + return $this->getFormatter( + $this->getFormatterCacheKey(__FUNCTION__, func_get_args()), + function () use ($locale, $maxPrecision, $minPrecision) { + $formatter = $this->getBaseFormatter($this->getSystemLocale($locale)); + + if (! is_null($maxPrecision)) { + $formatter->setAttribute(NumberFormatter::MAX_FRACTION_DIGITS, $maxPrecision); + } + + if (! is_null($minPrecision)) { + $formatter->setAttribute(NumberFormatter::MIN_FRACTION_DIGITS, $minPrecision); + } + + return $formatter; + } + ); + } + + /** + * Create a number formatter using a pattern. + * + * @param string $locale + * @param string $pattern + * @return NumberFormatter + */ + protected function getPatternedFormatter(string $locale, string $pattern): NumberFormatter + { + return $this->getFormatter( + $this->getFormatterCacheKey(__FUNCTION__, func_get_args()), + function () use ($locale, $pattern) { + $formatter = $this->getBaseFormatter($this->getSystemLocale($locale)); + + $formatter->setPattern($pattern); + + return $formatter; + } + ); + } } diff --git a/src/NumberHelper.php b/src/NumberHelper.php index 2d36772..edeba90 100644 --- a/src/NumberHelper.php +++ b/src/NumberHelper.php @@ -7,20 +7,29 @@ class NumberHelper extends LocalizedHelper { /** - * Return a number formatted for the given locale. - * - * @param float|int $value - * @param string $locale + * Return a number formatted for the given locale. Specify precision to define the exact number of decimal digits. * + * @param float|int $value + * @param string $locale + * @param int|null $precision * @return string */ - public function toFormat($value, string $locale = 'en'): string + public function toFormat($value, string $locale = 'en', int $precision = null): string { - $formatter = new NumberFormatter( - $this->getSystemLocale($locale), - NumberFormatter::DEFAULT_STYLE - ); + if (is_null($precision)) { + return $this->getDefaultFormatter($locale)->format($value); + } + + return $this->getFixedPrecisionFormatter($locale, $precision)->format($value); + } - return $formatter->format($value); + /** + * Return the formatter style used by the number formatter. + * + * @return int + */ + protected function getFormatterStyle(): int + { + return NumberFormatter::DEFAULT_STYLE; } } diff --git a/src/Providers/CountriesServiceProvider.php b/src/Providers/CountriesServiceProvider.php index 4b03f07..c34aff8 100644 --- a/src/Providers/CountriesServiceProvider.php +++ b/src/Providers/CountriesServiceProvider.php @@ -2,13 +2,14 @@ namespace PodPoint\I18n\Providers; -use PodPoint\I18n\CountryHelper; -use PodPoint\I18n\TaxRate; -use League\ISO3166\ISO3166; -use PodPoint\I18n\CurrencyHelper; use Illuminate\Support\Collection; use Illuminate\Support\ServiceProvider; +use League\ISO3166\ISO3166; use Mpociot\VatCalculator\VatCalculator; +use PodPoint\I18n\CountryHelper; +use PodPoint\I18n\CurrencyHelper; +use PodPoint\I18n\NumberHelper; +use PodPoint\I18n\TaxRate; class CountriesServiceProvider extends ServiceProvider { @@ -69,18 +70,21 @@ protected function enhanceConfig() $onlySupportedCountries = $enhancedCountries->whereIn('alpha2', $partialCountries->keys()); $this->app->config->set('countries', $enhancedCountries - ->sortBy(function ($country, $key) { return $key; }) + ->sortBy(function ($country, $key) { + return $key; + }) ->toArray()); $this->app->config->set('countries-partial', $onlySupportedCountries - ->sortBy(function ($country, $key) { return $key; }) + ->sortBy(function ($country, $key) { + return $key; + }) ->toArray()); } /** * Adds ISO country information to our existing country configuration. * - * @param Collection $countries - * + * @param Collection $countries * @return Collection */ protected function addIsoInfoToCountryConfig(Collection $countries): Collection @@ -94,9 +98,8 @@ protected function addIsoInfoToCountryConfig(Collection $countries): Collection * Adds miscellaneous country information, like the Laravel locale for each country for example, * to our existing country configuration. * - * @param Collection $countries - * @param Collection $partialCountries - * + * @param Collection $countries + * @param Collection $partialCountries * @return Collection */ protected function addPartialInfoToCountryConfig(Collection $countries, Collection $partialCountries): Collection @@ -124,6 +127,10 @@ protected function registerBindings() $this->app->singleton('country.helper', function ($app) { return new CountryHelper($app->config); }); + + $this->app->singleton('number.helper', function ($app) { + return new NumberHelper($app->config); + }); } /** @@ -137,6 +144,7 @@ protected function registerFacades() $this->app->alias('currency.helper', CurrencyHelper::class); $this->app->alias('i18n.taxrate', TaxRate::class); $this->app->alias('country.helper', CountryHelper::class); + $this->app->alias('number.helper', NumberHelper::class); }); } } diff --git a/src/TaxRate.php b/src/TaxRate.php index b3aff7d..04e80f4 100644 --- a/src/TaxRate.php +++ b/src/TaxRate.php @@ -19,8 +19,7 @@ public function __construct(VatCalculator $vatCalculator) /** * Returns the tax rate for the given country code. * - * @param string $countryCode - * + * @param string $countryCode * @return float */ public function get(string $countryCode): float @@ -32,12 +31,11 @@ public function get(string $countryCode): float * Calculate the VAT based on the net price, country code and indication if the * customer is a company or not. * - * @param int|float $netPrice The net price to use for the calculation - * @param string $countryCode The country code to use for the rate lookup - * @param string|null $postalCode The postal code to use for the rate exception lookup - * @param bool|null $company Whether or not the customer is a company - * @param string|null $type The type can be low or high - * + * @param int|float $netPrice The net price to use for the calculation + * @param string $countryCode The country code to use for the rate lookup + * @param string|null $postalCode The postal code to use for the rate exception lookup + * @param bool|null $company Whether or not the customer is a company + * @param string|null $type The type can be low or high * @return float */ public function calculate($netPrice, string $countryCode, ?string $postalCode = null, ?bool $company = null, ?string $type = null): float @@ -49,12 +47,11 @@ public function calculate($netPrice, string $countryCode, ?string $postalCode = * Calculate the net price on the gross price, country code and indication if the * customer is a company or not. * - * @param int|float $grossPrice The gross price to use for the calculation - * @param string $countryCode The country code to use for the rate lookup - * @param string|null $postalCode The postal code to use for the rate exception lookup - * @param bool|null $company Whether or not the customer is a company - * @param string|null $type The type can be low or high - * + * @param int|float $grossPrice The gross price to use for the calculation + * @param string $countryCode The country code to use for the rate lookup + * @param string|null $postalCode The postal code to use for the rate exception lookup + * @param bool|null $company Whether or not the customer is a company + * @param string|null $type The type can be low or high * @return float */ public function exclude($grossPrice, string $countryCode, ?string $postalCode = null, ?bool $company = null, ?string $type = null): float diff --git a/src/ViewComposers/CountryCodeViewComposer.php b/src/ViewComposers/CountryCodeViewComposer.php index 4eefad9..8fd1262 100644 --- a/src/ViewComposers/CountryCodeViewComposer.php +++ b/src/ViewComposers/CountryCodeViewComposer.php @@ -2,8 +2,8 @@ namespace PodPoint\I18n\ViewComposers; -use Illuminate\View\View; use Illuminate\Config\Repository; +use Illuminate\View\View; use PodPoint\I18n\CountryCode; class CountryCodeViewComposer @@ -14,7 +14,7 @@ class CountryCodeViewComposer private $config; /** - * @param Repository $config + * @param Repository $config */ public function __construct(Repository $config) { @@ -24,7 +24,7 @@ public function __construct(Repository $config) /** * Binds the data to the view. * - * @param View $view + * @param View $view */ public function compose(View $view) { @@ -36,10 +36,9 @@ public function compose(View $view) /** * Get a country choice. * - * @param string $countryCode - * @param array $country - * @param bool $defaultChoice - * + * @param string $countryCode + * @param array $country + * @param bool $defaultChoice * @return array */ public function countryChoice(string $countryCode, array $country, bool $defaultChoice = false): array @@ -56,9 +55,9 @@ public function countryChoice(string $countryCode, array $country, bool $default /** * Get the country-code options by looping the countries in the config, while also adding the flag emojis. * - * @throws \InvalidArgumentException - * * @return string + * + * @throws \InvalidArgumentException */ private function countryCodeOptions(): string { @@ -97,11 +96,10 @@ private function countryCodeOptions(): string /** * Get a country label. * - * @param string $countryCode - * @param string $countryName - * @param int|null $diallingCode - * @param bool $defaultChoice - * + * @param string $countryCode + * @param string $countryName + * @param int|null $diallingCode + * @param bool $defaultChoice * @return string */ private function countryLabel(string $countryCode, string $countryName, $diallingCode, bool $defaultChoice = false): string @@ -116,9 +114,8 @@ private function countryLabel(string $countryCode, string $countryName, $diallin /** * Get a country name markup. * - * @param string $name - * @param bool $defaultChoice - * + * @param string $name + * @param bool $defaultChoice * @return string */ private function countryNameMarkup(string $name, bool $defaultChoice = false): string @@ -129,9 +126,8 @@ private function countryNameMarkup(string $name, bool $defaultChoice = false): s /** * Get a dialling code markup. * - * @param int|null $diallingCode - * @param bool $defaultChoice - * + * @param int|null $diallingCode + * @param bool $defaultChoice * @return string */ private function dialingCodeMarkup(?int $diallingCode = null, bool $defaultChoice = false): string @@ -146,8 +142,7 @@ private function dialingCodeMarkup(?int $diallingCode = null, bool $defaultChoic /** * Get the emoji flag for a given country code. * - * @param string $countryCode - * + * @param string $countryCode * @return string */ private function emojiFlag(string $countryCode): string @@ -164,8 +159,7 @@ private function emojiFlag(string $countryCode): string /** * Get the unicode character for a given letter. * - * @param string $letter - * + * @param string $letter * @return string */ private function unicodeCharacter(string $letter): string diff --git a/src/ViewComposers/CountryLocaleViewComposer.php b/src/ViewComposers/CountryLocaleViewComposer.php index 1fc7d96..47ad56b 100644 --- a/src/ViewComposers/CountryLocaleViewComposer.php +++ b/src/ViewComposers/CountryLocaleViewComposer.php @@ -2,8 +2,8 @@ namespace PodPoint\I18n\ViewComposers; -use Illuminate\View\View; use Illuminate\Config\Repository; +use Illuminate\View\View; class CountryLocaleViewComposer { @@ -17,7 +17,7 @@ class CountryLocaleViewComposer /** * CountryLocaleViewComposer constructor. * - * @param Repository $config + * @param Repository $config */ public function __construct(Repository $config) { @@ -28,7 +28,7 @@ public function __construct(Repository $config) * Fetches the supported application locales for Laravel and their "Display names" from the * enhanced configuration array and binds the data to the view. * - * @param View $view + * @param View $view * * @see \PodPoint\I18n\Providers\CountriesServiceProvider::addIsoInfoToCountryConfig() */ diff --git a/src/config/countries-partial.php b/src/config/countries-partial.php index 6a3cb4f..5cb90fb 100644 --- a/src/config/countries-partial.php +++ b/src/config/countries-partial.php @@ -24,7 +24,7 @@ 'tld' => 'com', 'timezone' => 'Europe/London', 'minorUnitEnd' => 99, - 'minorUnitPattern' => '#.##p' + 'minorUnitPattern' => '#.##p', ], CountryCode::IRELAND => [ 'systemLocale' => 'en_IE.UTF-8', @@ -40,4 +40,18 @@ 'tld' => 'no', 'timezone' => 'Europe/Oslo', ], + CountryCode::SPAIN => [ + 'locale' => 'es', + 'systemLocale' => 'es_ES.UTF-8', + 'language' => 'SPA', + 'tld' => 'es', + 'timezone' => 'Europe/Madrid', + ], + CountryCode::FRANCE => [ + 'locale' => 'fr', + 'systemLocale' => 'fr_FR.UTF-8', + 'language' => 'FRA', + 'tld' => 'fr', + 'timezone' => 'Europe/Paris', + ], ]; diff --git a/src/helpers.php b/src/helpers.php index 26f9aba..203e260 100644 --- a/src/helpers.php +++ b/src/helpers.php @@ -1,17 +1,16 @@ assertEquals($currentVatRate, $this->taxRate->get($countryCode)); - } + } /** * Make sure that if a Country couldn't be found, the tax rate returned is zero. @@ -70,7 +70,7 @@ public function testTaxRateWillBeZeroIfCountryIsNotFound() } /** - * Data Provider for testWeCanCalculatePriceWithVat() + * Data Provider for testWeCanCalculatePriceWithVat(). * * @return array */ @@ -99,9 +99,9 @@ public function supportedCountriesCalculationDataProvider() * Make sure we can calculate the price after tax (with VAT) based on a net price, before tax, * for a specific country. We only test the supported countries through a Data Provider. * - * @param string $countryCode - * @param float $netPrice - * @param float $vatPrice + * @param string $countryCode + * @param float $netPrice + * @param float $vatPrice * * @dataProvider supportedCountriesCalculationDataProvider */ @@ -111,7 +111,7 @@ public function testWeCanCalculatePriceWithVat(string $countryCode, float $netPr } /** - * Data Provider for testWeCanCalculatePriceExcludingVat() + * Data Provider for testWeCanCalculatePriceExcludingVat(). * * @return array */ @@ -140,9 +140,9 @@ public function supportedCountriesExclusionDataProvider() * Make sure we can calculate the price before tax (excluding VAT) based on a gross price, after tax, * for a specific country. We only test the supported countries through a Data Provider. * - * @param string $countryCode - * @param float $grossPrice - * @param float $exVatPrice + * @param string $countryCode + * @param float $grossPrice + * @param float $exVatPrice * * @dataProvider supportedCountriesExclusionDataProvider */ diff --git a/tests/TestCase.php b/tests/TestCase.php index eda459b..4bd32f6 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -3,11 +3,11 @@ namespace PodPoint\I18n\Tests; use Illuminate\Config\Repository; +use Illuminate\Contracts\Filesystem\FileNotFoundException; +use Illuminate\Contracts\Foundation\Application; use Illuminate\Filesystem\Filesystem; use PHPUnit\Framework\MockObject\MockObject; -use Illuminate\Contracts\Foundation\Application; use PodPoint\I18n\Providers\CountriesServiceProvider; -use Illuminate\Contracts\Filesystem\FileNotFoundException; abstract class TestCase extends \PHPUnit\Framework\TestCase { @@ -42,7 +42,7 @@ public function loadConfiguration() 'countries-partial' => $filesystem->getRequire(__DIR__ . '/../src/config/countries-partial.php'), ]); } catch (FileNotFoundException $e) { - die("Package configuration files not found: {$e->getMessage()}"); + exit("Package configuration files not found: {$e->getMessage()}"); } return $this; diff --git a/tests/Unit/CurrencyHelperTest.php b/tests/Unit/CurrencyHelperTest.php index cb092da..ddda7bf 100644 --- a/tests/Unit/CurrencyHelperTest.php +++ b/tests/Unit/CurrencyHelperTest.php @@ -13,7 +13,7 @@ class CurrencyHelperTest extends TestCase * * @return array */ - public function providerTestToFormat() + public function providerTestToFormat(): array { $value = 1500.5; @@ -38,10 +38,10 @@ public function providerTestToFormat() * * @dataProvider providerTestToFormat * - * @param float $value - * @param string $currencyCode - * @param string $locale - * @param string $expected + * @param float $value + * @param string $currencyCode + * @param string $locale + * @param string $expected */ public function testToFormat(float $value, string $currencyCode, string $locale, string $expected) { @@ -61,9 +61,14 @@ public function testToFormat(float $value, string $currencyCode, string $locale, * * @return array */ - public function providerTestGetSymbol() + public function providerTestGetSymbol(): array { return [ + 'Euro' => [ + CurrencyCode::EURO, + 'en', + '€', + ], 'Pound Sterling' => [ CurrencyCode::POUND_STERLING, 'en', @@ -82,7 +87,7 @@ public function providerTestGetSymbol() * * @return array */ - public function providerTestFormatToMinorUnitWhenApplicable() + public function providerTestFormatToMinorUnitWhenApplicable(): array { return [ 'Pound Sterling happy path' => [ @@ -124,15 +129,14 @@ public function providerTestFormatToMinorUnitWhenApplicable() ]; } - /** * Tests that it returns a currency symbol. * * @dataProvider providerTestGetSymbol * - * @param string $currencyCode - * @param string $locale - * @param string $expected + * @param string $currencyCode + * @param string $locale + * @param string $expected */ public function testGetSymbol(string $currencyCode, string $locale, string $expected) { @@ -233,13 +237,14 @@ public function testToStandardFormatWithCustomPrecision() /** * Tests that it returns formatted value with minor unit symbol from fractional monetary values. * - * @dataProvider providerTestFormatToMinorUnitWhenApplicable - * @param int $value - * @param string $currencyCode - * @param string $locale - * @param string $expected + * @dataProvider providerTestFormatToMinorUnitWhenApplicable + * + * @param int $value + * @param string $currencyCode + * @param string $locale + * @param string $expected */ - public function testFormatToMinorUnitWhenApplicablel(int $value, string $currencyCode, string $locale, string $expected) + public function testFormatToMinorUnitWhenApplicable(int $value, string $currencyCode, string $locale, string $expected) { $this->loadConfiguration()->loadServiceProvider(); diff --git a/tests/Unit/CurrencyServiceTest.php b/tests/Unit/CurrencyServiceTest.php index 39919ac..e3ae988 100644 --- a/tests/Unit/CurrencyServiceTest.php +++ b/tests/Unit/CurrencyServiceTest.php @@ -4,14 +4,14 @@ use Carbon\Carbon; use GuzzleHttp\Psr7\Response; -use PodPoint\I18n\Tests\TestCase; -use PodPoint\I18n\Currency\ExchangeRate; -use PHPUnit\Framework\MockObject\MockObject; use Illuminate\Contracts\Cache\Repository as Cache; -use PodPoint\I18n\Currency\OpenExchangeRates\Client; use Illuminate\Contracts\Config\Repository as Config; -use PodPoint\I18n\Currency\OpenExchangeRates\Service; +use PHPUnit\Framework\MockObject\MockObject; use PodPoint\I18n\Currency\Cache\Service as CacheService; +use PodPoint\I18n\Currency\ExchangeRate; +use PodPoint\I18n\Currency\OpenExchangeRates\Client; +use PodPoint\I18n\Currency\OpenExchangeRates\Service; +use PodPoint\I18n\Tests\TestCase; class CurrencyServiceTest extends TestCase { diff --git a/tests/Unit/NumberHelperTest.php b/tests/Unit/NumberHelperTest.php index 3aad8c5..ac11643 100644 --- a/tests/Unit/NumberHelperTest.php +++ b/tests/Unit/NumberHelperTest.php @@ -12,20 +12,46 @@ class NumberHelperTest extends TestCase * * @return array */ - public function providerTestToFormat() + public function providerTestToFormat(): array { - $value = 1500.51254567890; + $nonBreakingSpace = "\xC2\xA0"; return [ - 'number in english format' => [ - $value, + 'number in english format with default precision' => [ + 2456.3487283384, 'en', - '1,500.513', + null, + '2,456.349', ], - 'number in norwegian format' => [ - $value, + 'number in english format with fixed precision' => [ + 2456.3487283384, + 'en', + 5, + '2,456.34873', + ], + 'number in english (IE) format with default precision' => [ + 1569.7834745, + 'ie', + null, + '1,569.783', + ], + 'number in english (IE) format with fixed precision' => [ + 1569.7834745, + 'ie', + 0, + '1,570', + ], + 'number in norwegian format with default precision' => [ + 1500.51254567890, + 'no', + null, + "1{$nonBreakingSpace}500,513", + ], + 'number in norwegian format with fixed precision' => [ + 1500.51254567890, 'no', - '1 500,513', + 7, + "1{$nonBreakingSpace}500,5125457", ], ]; } @@ -35,18 +61,19 @@ public function providerTestToFormat() * * @dataProvider providerTestToFormat * - * @param float $value - * @param string $locale - * @param string $expected + * @param float $value + * @param string $locale + * @param int|null $precision + * @param string $expected */ - public function testToFormat(float $value, string $locale, string $expected) + public function testToFormat(float $value, string $locale, ?int $precision, string $expected) { $this->loadConfiguration()->loadServiceProvider(); - $currencyHelper = new NumberHelper($this->app->config); + $numberHelper = new NumberHelper($this->app->config); - $actual = $currencyHelper->toFormat($value, $locale); + $actual = $numberHelper->toFormat($value, $locale, $precision); - $this->assertEquals($expected, $actual); + $this->assertSame($expected, $actual); } } diff --git a/tests/Unit/Providers/CountriesServiceProviderTest.php b/tests/Unit/Providers/CountriesServiceProviderTest.php index d4cea29..b54a949 100644 --- a/tests/Unit/Providers/CountriesServiceProviderTest.php +++ b/tests/Unit/Providers/CountriesServiceProviderTest.php @@ -3,10 +3,8 @@ namespace PodPoint\I18n\Tests\Unit\Providers; use PodPoint\I18n\CountryCode; -use Illuminate\Config\Repository; -use PodPoint\I18n\Tests\TestCase; use PodPoint\I18n\Providers\CountriesServiceProvider; -use PodPoint\I18n\CurrencyHelper; +use PodPoint\I18n\Tests\TestCase; class CountriesServiceProviderTest extends TestCase { @@ -76,10 +74,13 @@ public function testPartialCountriesConfigHasOnlySupportedCountriesAndLocales() $countryCodes = array_keys($this->app->config->get('countries-partial')); - $this->assertEquals(CountryCode::all(), $countryCodes); + $countryCodeAll = CountryCode::all(); + sort($countryCodeAll); + sort($countryCodes); + $this->assertEquals($countryCodeAll, $countryCodes); collect($this->app->config->get('countries-partial'))->each(function ($country) { - $supportedLocales = ['en', 'no', 'ie']; + $supportedLocales = ['es', 'fr', 'en', 'ie', 'no']; if (isset($country['locale'])) { $this->assertTrue(in_array($country['locale'], $supportedLocales)); diff --git a/tests/Unit/ViewComposers/CountryCodeViewComposerTest.php b/tests/Unit/ViewComposers/CountryCodeViewComposerTest.php index 8c4218e..3321cf4 100644 --- a/tests/Unit/ViewComposers/CountryCodeViewComposerTest.php +++ b/tests/Unit/ViewComposers/CountryCodeViewComposerTest.php @@ -51,10 +51,10 @@ public function testCountryChoiceReturnsAnArrayProperlyFormattedWhenNotDefaultCh ]); $expected = [ - "value" => "GB", - "label" => '🇬🇧 United Kingdom (+44)', - "customProperties" => [ - "description" => "United Kingdom", + 'value' => 'GB', + 'label' => '🇬🇧 United Kingdom (+44)', + 'customProperties' => [ + 'description' => 'United Kingdom', ], ]; @@ -76,10 +76,10 @@ public function testCountryChoiceReturnsAnArrayProperlyFormattedWhenDefaultChoic ], true); $expected = [ - "value" => "GB", - "label" => '🇬🇧 United Kingdom (+44)', - "customProperties" => [ - "description" => "United Kingdom", + 'value' => 'GB', + 'label' => '🇬🇧 United Kingdom (+44)', + 'customProperties' => [ + 'description' => 'United Kingdom', ], ]; diff --git a/tests/Unit/ViewComposers/CountryLocaleViewComposerTest.php b/tests/Unit/ViewComposers/CountryLocaleViewComposerTest.php index 102a70d..a5b8ee8 100644 --- a/tests/Unit/ViewComposers/CountryLocaleViewComposerTest.php +++ b/tests/Unit/ViewComposers/CountryLocaleViewComposerTest.php @@ -30,7 +30,9 @@ public function testCompose() 'countryLocalesOptions' => [ 'en' => 'ENG', 'no' => 'NOR', - 'ie' => 'ENG' + 'ie' => 'ENG', + 'es' => 'SPA', + 'fr' => 'FRA', ], ]);