aboutsummaryrefslogtreecommitdiffstats
path: root/vendor/commerceguys/intl/src
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/commerceguys/intl/src')
-rw-r--r--vendor/commerceguys/intl/src/Calculator.php247
-rw-r--r--vendor/commerceguys/intl/src/Country/Country.php168
-rw-r--r--vendor/commerceguys/intl/src/Country/CountryEntityInterface.php51
-rw-r--r--vendor/commerceguys/intl/src/Country/CountryInterface.php61
-rw-r--r--vendor/commerceguys/intl/src/Country/CountryRepository.php143
-rw-r--r--vendor/commerceguys/intl/src/Country/CountryRepositoryInterface.php41
-rw-r--r--vendor/commerceguys/intl/src/Currency/Currency.php168
-rw-r--r--vendor/commerceguys/intl/src/Currency/CurrencyEntityInterface.php51
-rw-r--r--vendor/commerceguys/intl/src/Currency/CurrencyInterface.php47
-rw-r--r--vendor/commerceguys/intl/src/Currency/CurrencyRepository.php144
-rw-r--r--vendor/commerceguys/intl/src/Currency/CurrencyRepositoryInterface.php41
-rw-r--r--vendor/commerceguys/intl/src/Exception/ExceptionInterface.php7
-rw-r--r--vendor/commerceguys/intl/src/Exception/InvalidArgumentException.php11
-rw-r--r--vendor/commerceguys/intl/src/Exception/UnknownCountryException.php11
-rw-r--r--vendor/commerceguys/intl/src/Exception/UnknownCurrencyException.php11
-rw-r--r--vendor/commerceguys/intl/src/Exception/UnknownLanguageException.php11
-rw-r--r--vendor/commerceguys/intl/src/Exception/UnknownLocaleException.php10
-rw-r--r--vendor/commerceguys/intl/src/Formatter/NumberFormatter.php421
-rw-r--r--vendor/commerceguys/intl/src/Formatter/NumberFormatterInterface.php151
-rw-r--r--vendor/commerceguys/intl/src/Language/Language.php91
-rw-r--r--vendor/commerceguys/intl/src/Language/LanguageEntityInterface.php24
-rw-r--r--vendor/commerceguys/intl/src/Language/LanguageInterface.php23
-rw-r--r--vendor/commerceguys/intl/src/Language/LanguageRepository.php115
-rw-r--r--vendor/commerceguys/intl/src/Language/LanguageRepositoryInterface.php41
-rw-r--r--vendor/commerceguys/intl/src/LocaleResolverTrait.php244
-rw-r--r--vendor/commerceguys/intl/src/NumberFormat/NumberFormat.php269
-rw-r--r--vendor/commerceguys/intl/src/NumberFormat/NumberFormatEntityInterface.php107
-rw-r--r--vendor/commerceguys/intl/src/NumberFormat/NumberFormatInterface.php106
-rw-r--r--vendor/commerceguys/intl/src/NumberFormat/NumberFormatRepository.php91
-rw-r--r--vendor/commerceguys/intl/src/NumberFormat/NumberFormatRepositoryInterface.php19
30 files changed, 2925 insertions, 0 deletions
diff --git a/vendor/commerceguys/intl/src/Calculator.php b/vendor/commerceguys/intl/src/Calculator.php
new file mode 100644
index 000000000..e00a564c1
--- /dev/null
+++ b/vendor/commerceguys/intl/src/Calculator.php
@@ -0,0 +1,247 @@
+<?php
+
+namespace CommerceGuys\Intl;
+
+/**
+ * Provides helpers for bcmath-based arithmetic.
+ *
+ * The bcmath extension provides support for arbitrary precision arithmetic,
+ * which does not suffer from the precision loses that make floating point
+ * arithmetic unsafe for eCommerce.
+ *
+ * Important: All numbers must be passed as strings.
+ */
+final class Calculator
+{
+ /**
+ * Adds the second number to the first number.
+ *
+ * @param string $first_number The first number.
+ * @param string $second_number The second number.
+ * @param int $scale The maximum number of digits after the
+ * decimal place. Any digit after $scale will
+ * be truncated.
+ *
+ * @return string The result.
+ */
+ public static function add($first_number, $second_number, $scale = 6)
+ {
+ self::assertNumberFormat($first_number);
+ self::assertNumberFormat($second_number);
+ $result = bcadd($first_number, $second_number, $scale);
+
+ return self::trim($result);
+ }
+
+ /**
+ * Subtracts the second number from the first number.
+ *
+ * @param string $first_number The first number.
+ * @param string $second_number The second number.
+ * @param int $scale The maximum number of digits after the
+ * decimal place. Any digit after $scale will
+ * be truncated.
+ *
+ * @return string The result.
+ */
+ public static function subtract($first_number, $second_number, $scale = 6)
+ {
+ self::assertNumberFormat($first_number);
+ self::assertNumberFormat($second_number);
+ $result = bcsub($first_number, $second_number, $scale);
+
+ return self::trim($result);
+ }
+
+ /**
+ * Multiplies the first number by the second number.
+ *
+ * @param string $first_number The first number.
+ * @param string $second_number The second number.
+ * @param int $scale The maximum number of digits after the
+ * decimal place. Any digit after $scale will
+ * be truncated.
+ *
+ * @return string The result.
+ */
+ public static function multiply($first_number, $second_number, $scale = 6)
+ {
+ self::assertNumberFormat($first_number);
+ self::assertNumberFormat($second_number);
+ $result = bcmul($first_number, $second_number, $scale);
+
+ return self::trim($result);
+ }
+
+ /**
+ * Divides the first number by the second number.
+ *
+ * @param string $first_number The first number.
+ * @param string $second_number The second number.
+ * @param int $scale The maximum number of digits after the
+ * decimal place. Any digit after $scale will
+ * be truncated.
+ *
+ * @return string The result.
+ */
+ public static function divide($first_number, $second_number, $scale = 6)
+ {
+ self::assertNumberFormat($first_number);
+ self::assertNumberFormat($second_number);
+ $result = bcdiv($first_number, $second_number, $scale);
+
+ return self::trim($result);
+ }
+
+ /**
+ * Calculates the next highest whole value of a number.
+ *
+ * @param string $number The number.
+ *
+ * @return string The result.
+ */
+ public static function ceil($number)
+ {
+ if (self::compare($number, 0) == 1) {
+ $result = bcadd($number, '1', 0);
+ } else {
+ $result = bcadd($number, '0', 0);
+ }
+
+ return $result;
+ }
+
+ /**
+ * Calculates the next lowest whole value of a number.
+ *
+ * @param string $number The number.
+ *
+ * @return string The result.
+ */
+ public static function floor($number)
+ {
+ if (self::compare($number, 0) == 1) {
+ $result = bcadd($number, '0', 0);
+ } else {
+ $result = bcadd($number, '-1', 0);
+ }
+
+ return $result;
+ }
+
+ /**
+ * Rounds the given number.
+ *
+ * Replicates PHP's support for rounding to the nearest even/odd number
+ * even if that number is decimal ($precision > 0).
+ *
+ * @param string $number The number.
+ * @param int $precision The number of decimals to round to.
+ * @param int $mode The rounding mode. One of the following constants:
+ * PHP_ROUND_HALF_UP, PHP_ROUND_HALF_DOWN,
+ * PHP_ROUND_HALF_EVEN, PHP_ROUND_HALF_ODD.
+ *
+ * @return string The rounded number.
+ *
+ * @throws \InvalidArgumentException
+ */
+ public static function round($number, $precision = 0, $mode = PHP_ROUND_HALF_UP)
+ {
+ self::assertNumberFormat($number);
+ if (!is_numeric($precision) || $precision < 0) {
+ throw new \InvalidArgumentException('The provided precision should be a positive number');
+ }
+
+ // Round the number in both directions (up/down) before choosing one.
+ $rounding_increment = bcdiv('1', pow(10, $precision), $precision);
+ if (self::compare($number, '0') == 1) {
+ $rounded_up = bcadd($number, $rounding_increment, $precision);
+ } else {
+ $rounded_up = bcsub($number, $rounding_increment, $precision);
+ }
+ $rounded_down = bcsub($number, 0, $precision);
+ // The rounding direction is based on the first decimal after $precision.
+ $number_parts = explode('.', $number);
+ $decimals = !empty($number_parts[1]) ? $number_parts[1] : '0';
+ $relevant_decimal = isset($decimals[$precision]) ? $decimals[$precision] : 0;
+ if ($relevant_decimal < 5) {
+ $number = $rounded_down;
+ } elseif ($relevant_decimal == 5) {
+ if ($mode == PHP_ROUND_HALF_UP) {
+ $number = $rounded_up;
+ } elseif ($mode == PHP_ROUND_HALF_DOWN) {
+ $number = $rounded_down;
+ } elseif ($mode == PHP_ROUND_HALF_EVEN) {
+ $integer = bcmul($rounded_up, pow(10, $precision), 0);
+ $number = bcmod($integer, '2') == 0 ? $rounded_up : $rounded_down;
+ } elseif ($mode == PHP_ROUND_HALF_ODD) {
+ $integer = bcmul($rounded_up, pow(10, $precision), 0);
+ $number = bcmod($integer, '2') != 0 ? $rounded_up : $rounded_down;
+ }
+ } elseif ($relevant_decimal > 5) {
+ $number = $rounded_up;
+ }
+
+ return $number;
+ }
+
+ /**
+ * Compares the first number to the second number.
+ *
+ * @param string $first_number The first number.
+ * @param string $second_number The second number.
+ * @param int $scale The maximum number of digits after the
+ * decimal place. Any digit after $scale will
+ * be truncated.
+ *
+ * @return int 0 if both numbers are equal, 1 if the first one is greater,
+ * -1 otherwise.
+ */
+ public static function compare($first_number, $second_number, $scale = 6)
+ {
+ self::assertNumberFormat($first_number);
+ self::assertNumberFormat($second_number);
+
+ return bccomp($first_number, $second_number, $scale);
+ }
+
+ /**
+ * Trims the given number.
+ *
+ * By default bcmath returns numbers with the number of digits according
+ * to $scale. This means that bcadd('2', '2', 6) will return '4.00000'.
+ * Trimming the number removes the excess zeroes.
+ *
+ * @param string $number The number to trim.
+ *
+ * @return string The trimmed number.
+ */
+ public static function trim($number)
+ {
+ if (strpos($number, '.') != false) {
+ // The number is decimal, strip trailing zeroes.
+ // If no digits remain after the decimal point, strip it as well.
+ $number = rtrim($number, '0');
+ $number = rtrim($number, '.');
+ }
+
+ return $number;
+ }
+
+ /**
+ * Assert that the given number is a numeric string value.
+ *
+ * @param string $number The number to check.
+ *
+ * @throws \InvalidArgumentException
+ */
+ public static function assertNumberFormat($number)
+ {
+ if (is_float($number)) {
+ throw new \InvalidArgumentException(sprintf('The provided value "%s" must be a string, not a float.', $number));
+ }
+ if (!is_numeric($number)) {
+ throw new \InvalidArgumentException(sprintf('The provided value "%s" is not a numeric value.', $number));
+ }
+ }
+}
diff --git a/vendor/commerceguys/intl/src/Country/Country.php b/vendor/commerceguys/intl/src/Country/Country.php
new file mode 100644
index 000000000..7063e7d58
--- /dev/null
+++ b/vendor/commerceguys/intl/src/Country/Country.php
@@ -0,0 +1,168 @@
+<?php
+
+namespace CommerceGuys\Intl\Country;
+
+class Country implements CountryEntityInterface
+{
+ /**
+ * The two-letter country code.
+ *
+ * @var string
+ */
+ protected $countryCode;
+
+ /**
+ * The country name.
+ *
+ * @var string
+ */
+ protected $name;
+
+ /**
+ * The three-letter country code.
+ *
+ * @var string
+ */
+ protected $threeLetterCode;
+
+ /**
+ * The numeric country code.
+ *
+ * @var string
+ */
+ protected $numericCode;
+
+ /**
+ * The country currency code.
+ *
+ * @var string
+ */
+ protected $currencyCode;
+
+ /**
+ * The country locale (i.e. "en_US").
+ *
+ * The country name is locale specific.
+ *
+ * @var string
+ */
+ protected $locale;
+
+ /**
+ * Returns the string representation of the Country.
+ *
+ * @return string
+ */
+ public function __toString()
+ {
+ return $this->getCountryCode();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getCountryCode()
+ {
+ return $this->countryCode;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setCountryCode($countryCode)
+ {
+ $this->countryCode = $countryCode;
+
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getName()
+ {
+ return $this->name;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setName($name)
+ {
+ $this->name = $name;
+
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getThreeLetterCode()
+ {
+ return $this->threeLetterCode;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setThreeLetterCode($threeLetterCode)
+ {
+ $this->threeLetterCode = $threeLetterCode;
+
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getNumericCode()
+ {
+ return $this->numericCode;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setNumericCode($numericCode)
+ {
+ $this->numericCode = $numericCode;
+
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getCurrencyCode()
+ {
+ return $this->currencyCode;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setCurrencyCode($currencyCode)
+ {
+ $this->currencyCode = $currencyCode;
+
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getLocale()
+ {
+ return $this->locale;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setLocale($locale)
+ {
+ $this->locale = $locale;
+
+ return $this;
+ }
+}
diff --git a/vendor/commerceguys/intl/src/Country/CountryEntityInterface.php b/vendor/commerceguys/intl/src/Country/CountryEntityInterface.php
new file mode 100644
index 000000000..b22bcd42f
--- /dev/null
+++ b/vendor/commerceguys/intl/src/Country/CountryEntityInterface.php
@@ -0,0 +1,51 @@
+<?php
+
+namespace CommerceGuys\Intl\Country;
+
+interface CountryEntityInterface extends CountryInterface
+{
+ /**
+ * Sets the two-letter country code.
+ *
+ * @param string $countryCode The two-letter country code.
+ *
+ * @return self
+ */
+ public function setCountryCode($countryCode);
+
+ /**
+ * Sets the country name.
+ *
+ * @param string $name The country name.
+ *
+ * @return self
+ */
+ public function setName($name);
+
+ /**
+ * Sets the three-letter country code.
+ *
+ * @param string $threeLetterCode The three-letter country code.
+ *
+ * @return self
+ */
+ public function setThreeLetterCode($threeLetterCode);
+
+ /**
+ * Sets the numeric country code.
+ *
+ * @param string $numericCode The numeric country code.
+ *
+ * @return self
+ */
+ public function setNumericCode($numericCode);
+
+ /**
+ * Sets the country currency code.
+ *
+ * @param string $currencyCode The currency code.
+ *
+ * @return self
+ */
+ public function setCurrencyCode($currencyCode);
+}
diff --git a/vendor/commerceguys/intl/src/Country/CountryInterface.php b/vendor/commerceguys/intl/src/Country/CountryInterface.php
new file mode 100644
index 000000000..f6aaf91b2
--- /dev/null
+++ b/vendor/commerceguys/intl/src/Country/CountryInterface.php
@@ -0,0 +1,61 @@
+<?php
+
+namespace CommerceGuys\Intl\Country;
+
+interface CountryInterface
+{
+ /**
+ * Gets the two-letter country code.
+ *
+ * @return string
+ */
+ public function getCountryCode();
+
+ /**
+ * Gets the country name.
+ *
+ * Note that certain locales have incomplete translations, in which
+ * case the english version of the country name is used instead.
+ *
+ * @return string
+ */
+ public function getName();
+
+ /**
+ * Gets the three-letter country code.
+ *
+ * Note that not every country has a three-letter code.
+ * CLDR lists "Canary Islands" (IC) and "Ceuta and Melilla" (EA)
+ * as separate countries, even though they are formally a part of Spain
+ * and have no three-letter or numeric ISO codes.
+ *
+ * @return string|null
+ */
+ public function getThreeLetterCode();
+
+ /**
+ * Gets the numeric country code.
+ *
+ * The numeric code has three digits, and the first one can be a zero,
+ * hence the need to pass it around as a string.
+ *
+ * Note that not every country has a numeric code.
+ * CLDR lists "Canary Islands" (IC) and "Ceuta and Melilla" (EA)
+ * as separate countries, even though they are formally a part of Spain
+ * and have no three-letter or numeric ISO codes.
+ * "Ascension Island" (AE) also has no numeric code, even though it has a
+ * three-letter code.
+ *
+ * @return string|null
+ */
+ public function getNumericCode();
+
+ /**
+ * Gets the country currency code.
+ *
+ * Represents the default currency used in the country, if known.
+ *
+ * @return string|null
+ */
+ public function getCurrencyCode();
+}
diff --git a/vendor/commerceguys/intl/src/Country/CountryRepository.php b/vendor/commerceguys/intl/src/Country/CountryRepository.php
new file mode 100644
index 000000000..fb027dc2f
--- /dev/null
+++ b/vendor/commerceguys/intl/src/Country/CountryRepository.php
@@ -0,0 +1,143 @@
+<?php
+
+namespace CommerceGuys\Intl\Country;
+
+use CommerceGuys\Intl\LocaleResolverTrait;
+use CommerceGuys\Intl\Exception\UnknownCountryException;
+
+/**
+ * Manages countries based on JSON definitions.
+ */
+class CountryRepository implements CountryRepositoryInterface
+{
+ use LocaleResolverTrait;
+
+ /**
+ * Base country definitions.
+ *
+ * Contains data common to all locales, such as the country numeric,
+ * three-letter, currency codes.
+ *
+ * @var array
+ */
+ protected $baseDefinitions = [];
+
+ /**
+ * Per-locale country definitions.
+ *
+ * @var array
+ */
+ protected $definitions = [];
+
+ /**
+ * Creates a CountryRepository instance.
+ *
+ * @param string $definitionPath The path to the country definitions.
+ * Defaults to 'resources/country'.
+ */
+ public function __construct($definitionPath = null)
+ {
+ $this->definitionPath = $definitionPath ? $definitionPath : __DIR__ . '/../../resources/country/';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function get($countryCode, $locale = null, $fallbackLocale = null)
+ {
+ $locale = $this->resolveLocale($locale, $fallbackLocale);
+ $definitions = $this->loadDefinitions($locale);
+ if (!isset($definitions[$countryCode])) {
+ throw new UnknownCountryException($countryCode);
+ }
+
+ return $this->createCountryFromDefinition($countryCode, $definitions[$countryCode], $locale);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getAll($locale = null, $fallbackLocale = null)
+ {
+ $locale = $this->resolveLocale($locale, $fallbackLocale);
+ $definitions = $this->loadDefinitions($locale);
+ $countries = [];
+ foreach ($definitions as $countryCode => $definition) {
+ $countries[$countryCode] = $this->createCountryFromDefinition($countryCode, $definition, $locale);
+ }
+
+ return $countries;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getList($locale = null, $fallbackLocale = null)
+ {
+ $locale = $this->resolveLocale($locale, $fallbackLocale);
+ $definitions = $this->loadDefinitions($locale);
+ $list = [];
+ foreach ($definitions as $countryCode => $definition) {
+ $list[$countryCode] = $definition['name'];
+ }
+
+ return $list;
+ }
+
+ /**
+ * Loads the country definitions for the provided locale.
+ *
+ * @param string $locale The desired locale.
+ *
+ * @return array
+ */
+ protected function loadDefinitions($locale)
+ {
+ if (!isset($this->definitions[$locale])) {
+ $filename = $this->definitionPath . $locale . '.json';
+ $this->definitions[$locale] = json_decode(file_get_contents($filename), true);
+
+ // Make sure the base definitions have been loaded.
+ if (empty($this->baseDefinitions)) {
+ $this->baseDefinitions = json_decode(file_get_contents($this->definitionPath . 'base.json'), true);
+ }
+ // Merge-in base definitions.
+ foreach ($this->definitions[$locale] as $countryCode => $definition) {
+ $this->definitions[$locale][$countryCode] += $this->baseDefinitions[$countryCode];
+ }
+ }
+
+ return $this->definitions[$locale];
+ }
+
+ /**
+ * Creates a country object from the provided definition.
+ *
+ * @param string $countryCode The country code.
+ * @param array $definition The country definition.
+ * @param string $locale The locale of the country definition.
+ *
+ * @return Country
+ */
+ protected function createCountryFromDefinition($countryCode, array $definition, $locale)
+ {
+ $country = new Country();
+ $setValues = \Closure::bind(function ($countryCode, $definition, $locale) {
+ $this->countryCode = $countryCode;
+ $this->name = $definition['name'];
+ $this->locale = $locale;
+ if (isset($definition['three_letter_code'])) {
+ $this->threeLetterCode = $definition['three_letter_code'];
+ }
+ if (isset($definition['numeric_code'])) {
+ $this->numericCode = $definition['numeric_code'];
+ }
+ if (isset($definition['currency_code'])) {
+ $this->currencyCode = $definition['currency_code'];
+ }
+ }, $country, '\CommerceGuys\Intl\Country\Country');
+ $setValues($countryCode, $definition, $locale);
+
+ return $country;
+ }
+}
diff --git a/vendor/commerceguys/intl/src/Country/CountryRepositoryInterface.php b/vendor/commerceguys/intl/src/Country/CountryRepositoryInterface.php
new file mode 100644
index 000000000..fbcd5551e
--- /dev/null
+++ b/vendor/commerceguys/intl/src/Country/CountryRepositoryInterface.php
@@ -0,0 +1,41 @@
+<?php
+
+namespace CommerceGuys\Intl\Country;
+
+/**
+ * Country repository interface.
+ */
+interface CountryRepositoryInterface
+{
+ /**
+ * Returns a country instance matching the provided country code.
+ *
+ * @param string $countryCode The country code.
+ * @param string $locale The locale (i.e. fr-FR).
+ * @param string $fallbackLocale A fallback locale (i.e "en").
+ *
+ * @return CountryInterface
+ */
+ public function get($countryCode, $locale = null, $fallbackLocale = null);
+
+ /**
+ * Returns all country instances.
+ *
+ * @param string $locale The locale (i.e. fr-FR).
+ * @param string $fallbackLocale A fallback locale (i.e "en").
+ *
+ * @return array An array of countries implementing the CountryInterface,
+ * keyed by country code.
+ */
+ public function getAll($locale = null, $fallbackLocale = null);
+
+ /**
+ * Returns a list of countries.
+ *
+ * @param string $locale The locale (i.e. fr-FR).
+ * @param string $fallbackLocale A fallback locale (i.e "en").
+ *
+ * @return array An array of country names, keyed by country code.
+ */
+ public function getList($locale = null, $fallbackLocale = null);
+}
diff --git a/vendor/commerceguys/intl/src/Currency/Currency.php b/vendor/commerceguys/intl/src/Currency/Currency.php
new file mode 100644
index 000000000..6f9256bf0
--- /dev/null
+++ b/vendor/commerceguys/intl/src/Currency/Currency.php
@@ -0,0 +1,168 @@
+<?php
+
+namespace CommerceGuys\Intl\Currency;
+
+class Currency implements CurrencyEntityInterface
+{
+ /**
+ * The alphanumeric currency code.
+ *
+ * @var string
+ */
+ protected $currencyCode;
+
+ /**
+ * The currency name.
+ *
+ * @var string
+ */
+ protected $name;
+
+ /**
+ * The numeric currency code.
+ *
+ * @var string
+ */
+ protected $numericCode;
+
+ /**
+ * The currency symbol.
+ *
+ * @var string
+ */
+ protected $symbol;
+
+ /**
+ * The number of fraction digits.
+ *
+ * @var int
+ */
+ protected $fractionDigits;
+
+ /**
+ * The currency locale (i.e. "en_US").
+ *
+ * The currency name and symbol are locale specific.
+ *
+ * @var string
+ */
+ protected $locale;
+
+ /**
+ * Returns the string representation of the currency.
+ *
+ * @return string
+ */
+ public function __toString()
+ {
+ return $this->getCurrencyCode();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getCurrencyCode()
+ {
+ return $this->currencyCode;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setCurrencyCode($currencyCode)
+ {
+ $this->currencyCode = $currencyCode;
+
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getName()
+ {
+ return $this->name;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setName($name)
+ {
+ $this->name = $name;
+
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getNumericCode()
+ {
+ return $this->numericCode;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setNumericCode($numericCode)
+ {
+ $this->numericCode = $numericCode;
+
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getSymbol()
+ {
+ return $this->symbol;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setSymbol($symbol)
+ {
+ $this->symbol = $symbol;
+
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getFractionDigits()
+ {
+ return $this->fractionDigits;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setFractionDigits($fractionDigits)
+ {
+ $this->fractionDigits = $fractionDigits;
+
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getLocale()
+ {
+ return $this->locale;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setLocale($locale)
+ {
+ $this->locale = $locale;
+
+ return $this;
+ }
+}
diff --git a/vendor/commerceguys/intl/src/Currency/CurrencyEntityInterface.php b/vendor/commerceguys/intl/src/Currency/CurrencyEntityInterface.php
new file mode 100644
index 000000000..85d4ab83d
--- /dev/null
+++ b/vendor/commerceguys/intl/src/Currency/CurrencyEntityInterface.php
@@ -0,0 +1,51 @@
+<?php
+
+namespace CommerceGuys\Intl\Currency;
+
+interface CurrencyEntityInterface extends CurrencyInterface
+{
+ /**
+ * Sets the alphabetic currency code.
+ *
+ * @param string $currencyCode The alphabetic currency code.
+ *
+ * @return self
+ */
+ public function setCurrencyCode($currencyCode);
+
+ /**
+ * Sets the currency name.
+ *
+ * @param string $name The currency name.
+ *
+ * @return self
+ */
+ public function setName($name);
+
+ /**
+ * Sets the numeric currency code.
+ *
+ * @param string $numericCode The numeric currency code.
+ *
+ * @return self
+ */
+ public function setNumericCode($numericCode);
+
+ /**
+ * Sets the currency symbol.
+ *
+ * @param string $symbol The currency symbol.
+ *
+ * @return self
+ */
+ public function setSymbol($symbol);
+
+ /**
+ * Sets the number of fraction digits.
+ *
+ * @param int $fractionDigits The number of fraction digits.
+ *
+ * @return self
+ */
+ public function setFractionDigits($fractionDigits);
+}
diff --git a/vendor/commerceguys/intl/src/Currency/CurrencyInterface.php b/vendor/commerceguys/intl/src/Currency/CurrencyInterface.php
new file mode 100644
index 000000000..8aa709ca0
--- /dev/null
+++ b/vendor/commerceguys/intl/src/Currency/CurrencyInterface.php
@@ -0,0 +1,47 @@
+<?php
+
+namespace CommerceGuys\Intl\Currency;
+
+interface CurrencyInterface
+{
+ /**
+ * Gets the alphabetic currency code.
+ *
+ * @return string
+ */
+ public function getCurrencyCode();
+
+ /**
+ * Gets the currency name.
+ *
+ * @return string
+ */
+ public function getName();
+
+ /**
+ * Gets the numeric currency code.
+ *
+ * The numeric code has three digits, and the first one can be a zero,
+ * hence the need to pass it around as a string.
+ *
+ * @return string
+ */
+ public function getNumericCode();
+
+ /**
+ * Gets the currency symbol.
+ *
+ * @return string
+ */
+ public function getSymbol();
+
+ /**
+ * Gets the number of fraction digits.
+ *
+ * Used when rounding or formatting an amount for display.
+ * Actual storage precision can be greater.
+ *
+ * @return int
+ */
+ public function getFractionDigits();
+}
diff --git a/vendor/commerceguys/intl/src/Currency/CurrencyRepository.php b/vendor/commerceguys/intl/src/Currency/CurrencyRepository.php
new file mode 100644
index 000000000..5fdfce216
--- /dev/null
+++ b/vendor/commerceguys/intl/src/Currency/CurrencyRepository.php
@@ -0,0 +1,144 @@
+<?php
+
+namespace CommerceGuys\Intl\Currency;
+
+use CommerceGuys\Intl\LocaleResolverTrait;
+use CommerceGuys\Intl\Exception\UnknownCurrencyException;
+
+/**
+ * Manages currencies based on JSON definitions.
+ */
+class CurrencyRepository implements CurrencyRepositoryInterface
+{
+ use LocaleResolverTrait;
+
+ /**
+ * Base currency definitions.
+ *
+ * Contains data common to all locales, such as the currency numeric
+ * code, number of fraction digits.
+ *
+ * @var array
+ */
+ protected $baseDefinitions = [];
+
+ /**
+ * Per-locale currency definitions.
+ *
+ * @var array
+ */
+ protected $definitions = [];
+
+ /**
+ * Creates a CurrencyRepository instance.
+ *
+ * @param string $definitionPath The path to the currency definitions.
+ * Defaults to 'resources/currency'.
+ */
+ public function __construct($definitionPath = null)
+ {
+ $this->definitionPath = $definitionPath ? $definitionPath : __DIR__ . '/../../resources/currency/';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function get($currencyCode, $locale = null, $fallbackLocale = null)
+ {
+ $locale = $this->resolveLocale($locale, $fallbackLocale);
+ $definitions = $this->loadDefinitions($locale);
+ if (!isset($definitions[$currencyCode])) {
+ throw new UnknownCurrencyException($currencyCode);
+ }
+
+ return $this->createCurrencyFromDefinition($currencyCode, $definitions[$currencyCode], $locale);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getAll($locale = null, $fallbackLocale = null)
+ {
+ $locale = $this->resolveLocale($locale, $fallbackLocale);
+ $definitions = $this->loadDefinitions($locale);
+ $currencies = [];
+ foreach ($definitions as $currencyCode => $definition) {
+ $currencies[$currencyCode] = $this->createCurrencyFromDefinition($currencyCode, $definition, $locale);
+ }
+
+ return $currencies;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getList($locale = null, $fallbackLocale = null)
+ {
+ $locale = $this->resolveLocale($locale, $fallbackLocale);
+ $definitions = $this->loadDefinitions($locale);
+ $list = [];
+ foreach ($definitions as $currencyCode => $definition) {
+ $list[$currencyCode] = $definition['name'];
+ }
+
+ return $list;
+ }
+
+ /**
+ * Loads the currency definitions for the provided locale.
+ *
+ * @param string $locale The desired locale.
+ *
+ * @return array
+ */
+ protected function loadDefinitions($locale)
+ {
+ if (!isset($this->definitions[$locale])) {
+ $filename = $this->definitionPath . $locale . '.json';
+ $this->definitions[$locale] = json_decode(file_get_contents($filename), true);
+
+ // Make sure the base definitions have been loaded.
+ if (empty($this->baseDefinitions)) {
+ $this->baseDefinitions = json_decode(file_get_contents($this->definitionPath . 'base.json'), true);
+ }
+ // Merge-in base definitions.
+ foreach ($this->definitions[$locale] as $currencyCode => $definition) {
+ $this->definitions[$locale][$currencyCode] += $this->baseDefinitions[$currencyCode];
+ }
+ }
+
+ return $this->definitions[$locale];
+ }
+
+ /**
+ * Creates a currency object from the provided definition.
+ *
+ * @param string $currencyCode The currency code.
+ * @param array $definition The currency definition.
+ * @param string $locale The locale of the currency definition.
+ *
+ * @return Currency
+ */
+ protected function createCurrencyFromDefinition($currencyCode, array $definition, $locale)
+ {
+ if (!isset($definition['symbol'])) {
+ $definition['symbol'] = $currencyCode;
+ }
+ if (!isset($definition['fraction_digits'])) {
+ $definition['fraction_digits'] = 2;
+ }
+
+ $currency = new Currency();
+ $setValues = \Closure::bind(function ($currencyCode, $definition, $locale) {
+ $this->currencyCode = $currencyCode;
+ $this->name = $definition['name'];
+ $this->numericCode = $definition['numeric_code'];
+ $this->symbol = $definition['symbol'];
+ $this->fractionDigits = $definition['fraction_digits'];
+ $this->locale = $locale;
+ }, $currency, '\CommerceGuys\Intl\Currency\Currency');
+ $setValues($currencyCode, $definition, $locale);
+
+ return $currency;
+ }
+}
diff --git a/vendor/commerceguys/intl/src/Currency/CurrencyRepositoryInterface.php b/vendor/commerceguys/intl/src/Currency/CurrencyRepositoryInterface.php
new file mode 100644
index 000000000..f0a091969
--- /dev/null
+++ b/vendor/commerceguys/intl/src/Currency/CurrencyRepositoryInterface.php
@@ -0,0 +1,41 @@
+<?php
+
+namespace CommerceGuys\Intl\Currency;
+
+/**
+ * Currency repository interface.
+ */
+interface CurrencyRepositoryInterface
+{
+ /**
+ * Returns a currency instance matching the provided currency code.
+ *
+ * @param string $currencyCode The currency code.
+ * @param string $locale The locale (i.e. fr-FR).
+ * @param string $fallbackLocale A fallback locale (i.e "en").
+ *
+ * @return CurrencyInterface
+ */
+ public function get($currencyCode, $locale = null, $fallbackLocale = null);
+
+ /**
+ * Returns all currency instances.
+ *
+ * @param string $locale The locale (i.e. fr-FR).
+ * @param string $fallbackLocale A fallback locale (i.e "en").
+ *
+ * @return array An array of currencies implementing the CurrencyInterface,
+ * keyed by currency code.
+ */
+ public function getAll($locale = null, $fallbackLocale = null);
+
+ /**
+ * Returns a list of currencies.
+ *
+ * @param string $locale The locale (i.e. fr-FR).
+ * @param string $fallbackLocale A fallback locale (i.e "en").
+ *
+ * @return array An array of currency names, keyed by currency code.
+ */
+ public function getList($locale = null, $fallbackLocale = null);
+}
diff --git a/vendor/commerceguys/intl/src/Exception/ExceptionInterface.php b/vendor/commerceguys/intl/src/Exception/ExceptionInterface.php
new file mode 100644
index 000000000..a7d17f9ab
--- /dev/null
+++ b/vendor/commerceguys/intl/src/Exception/ExceptionInterface.php
@@ -0,0 +1,7 @@
+<?php
+
+namespace CommerceGuys\Intl\Exception;
+
+interface ExceptionInterface
+{
+}
diff --git a/vendor/commerceguys/intl/src/Exception/InvalidArgumentException.php b/vendor/commerceguys/intl/src/Exception/InvalidArgumentException.php
new file mode 100644
index 000000000..afbe114a4
--- /dev/null
+++ b/vendor/commerceguys/intl/src/Exception/InvalidArgumentException.php
@@ -0,0 +1,11 @@
+<?php
+
+namespace CommerceGuys\Intl\Exception;
+
+/**
+ * This exception is thrown when an invalid argument is passed to a method.
+ * For example, a float amount instead of the expected string amount.
+ */
+class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface
+{
+}
diff --git a/vendor/commerceguys/intl/src/Exception/UnknownCountryException.php b/vendor/commerceguys/intl/src/Exception/UnknownCountryException.php
new file mode 100644
index 000000000..c89845b23
--- /dev/null
+++ b/vendor/commerceguys/intl/src/Exception/UnknownCountryException.php
@@ -0,0 +1,11 @@
+<?php
+
+namespace CommerceGuys\Intl\Exception;
+
+/**
+ * This exception is thrown when an unknown country code is passed to the
+ * CountryRepository.
+ */
+class UnknownCountryException extends InvalidArgumentException implements ExceptionInterface
+{
+}
diff --git a/vendor/commerceguys/intl/src/Exception/UnknownCurrencyException.php b/vendor/commerceguys/intl/src/Exception/UnknownCurrencyException.php
new file mode 100644
index 000000000..f94c93d8a
--- /dev/null
+++ b/vendor/commerceguys/intl/src/Exception/UnknownCurrencyException.php
@@ -0,0 +1,11 @@
+<?php
+
+namespace CommerceGuys\Intl\Exception;
+
+/**
+ * This exception is thrown when an unknown currency code is passed to the
+ * CurrencyRepository.
+ */
+class UnknownCurrencyException extends InvalidArgumentException implements ExceptionInterface
+{
+}
diff --git a/vendor/commerceguys/intl/src/Exception/UnknownLanguageException.php b/vendor/commerceguys/intl/src/Exception/UnknownLanguageException.php
new file mode 100644
index 000000000..922b42185
--- /dev/null
+++ b/vendor/commerceguys/intl/src/Exception/UnknownLanguageException.php
@@ -0,0 +1,11 @@
+<?php
+
+namespace CommerceGuys\Intl\Exception;
+
+/**
+ * This exception is thrown when an unknown language code is passed to the
+ * LanguageRepository.
+ */
+class UnknownLanguageException extends InvalidArgumentException implements ExceptionInterface
+{
+}
diff --git a/vendor/commerceguys/intl/src/Exception/UnknownLocaleException.php b/vendor/commerceguys/intl/src/Exception/UnknownLocaleException.php
new file mode 100644
index 000000000..0deca13e8
--- /dev/null
+++ b/vendor/commerceguys/intl/src/Exception/UnknownLocaleException.php
@@ -0,0 +1,10 @@
+<?php
+
+namespace CommerceGuys\Intl\Exception;
+
+/**
+ * This exception is thrown when an unknown locale is passed to a repository.
+ */
+class UnknownLocaleException extends InvalidArgumentException implements ExceptionInterface
+{
+}
diff --git a/vendor/commerceguys/intl/src/Formatter/NumberFormatter.php b/vendor/commerceguys/intl/src/Formatter/NumberFormatter.php
new file mode 100644
index 000000000..5d36fc89b
--- /dev/null
+++ b/vendor/commerceguys/intl/src/Formatter/NumberFormatter.php
@@ -0,0 +1,421 @@
+<?php
+
+namespace CommerceGuys\Intl\Formatter;
+
+use CommerceGuys\Intl\Currency\CurrencyInterface;
+use CommerceGuys\Intl\Exception\InvalidArgumentException;
+use CommerceGuys\Intl\NumberFormat\NumberFormatInterface;
+
+/**
+ * Formats numbers using locale-specific patterns.
+ */
+class NumberFormatter implements NumberFormatterInterface
+{
+ /**
+ * The number format.
+ *
+ * @var NumberFormatInterface
+ */
+ protected $numberFormat;
+
+ /**
+ * The number pattern used to format positive numbers.
+ *
+ * @var string
+ */
+ protected $positivePattern;
+
+ /**
+ * The number pattern used to format negative numbers.
+ *
+ * @var string
+ */
+ protected $negativePattern;
+
+ /**
+ * Whether grouping is used.
+ *
+ * @var bool
+ */
+ protected $groupingUsed;
+
+ /**
+ * The size of the group of digits closest to the decimal point.
+ *
+ * @var int
+ */
+ protected $primaryGroupSize;
+
+ /**
+ * The size of every group of digits after the primary group.
+ *
+ * @var int
+ */
+ protected $secondaryGroupSize;
+
+ /**
+ * The minimum number of fraction digits to show.
+ *
+ * @var int
+ */
+ protected $minimumFractionDigits;
+
+ /**
+ * The maximum number of fraction digits to show.
+ *
+ * @var int
+ */
+ protected $maximumFractionDigits;
+
+ /**
+ * The currency display style.
+ *
+ * @var int
+ */
+ protected $currencyDisplay;
+
+ /**
+ * Localized digits.
+ *
+ * @var array
+ */
+ protected $digits = [
+ NumberFormatInterface::NUMBERING_SYSTEM_ARABIC => [
+ 0 => 'Ù ', 1 => 'Ù¡', 2 => 'Ù¢', 3 => 'Ù£', 4 => 'Ù¤',
+ 5 => 'Ù¥', 6 => 'Ù¦', 7 => 'Ù§', 8 => 'Ù¨', 9 => 'Ù©',
+ ],
+ NumberFormatInterface::NUMBERING_SYSTEM_ARABIC_EXTENDED => [
+ 0 => 'Û°', 1 => 'Û±', 2 => 'Û²', 3 => 'Û³', 4 => 'Û´',
+ 5 => 'Ûµ', 6 => 'Û¶', 7 => 'Û·', 8 => 'Û¸', 9 => 'Û¹',
+ ],
+ NumberFormatInterface::NUMBERING_SYSTEM_BENGALI => [
+ 0 => '০', 1 => '১', 2 => '২', 3 => '৩', 4 => '৪',
+ 5 => '৫', 6 => '৬', 7 => '৭', 8 => '৮', 9 => '৯',
+ ],
+ NumberFormatInterface::NUMBERING_SYSTEM_DEVANAGARI => [
+ 0 => '०', 1 => '१', 2 => '२', 3 => '३', 4 => '४',
+ 5 => '५', 6 => '६', 7 => '७', 8 => '८', 9 => '९',
+ ],
+ ];
+
+ /**
+ * Creaes a NumberFormatter instance.
+ *
+ * @param NumberFormatInterface $numberFormat The number format.
+ * @param int $style The formatting style.
+ *
+ * @throws \InvalidArgumentException
+ * @throws \RuntimeException
+ */
+ public function __construct(NumberFormatInterface $numberFormat, $style = self::DECIMAL)
+ {
+ if (!extension_loaded('bcmath')) {
+ throw new \RuntimeException('The bcmath extension is required by NumberFormatter.');
+ }
+ $availablePatterns = [
+ self::DECIMAL => $numberFormat->getDecimalPattern(),
+ self::PERCENT => $numberFormat->getPercentPattern(),
+ self::CURRENCY => $numberFormat->getCurrencyPattern(),
+ self::CURRENCY_ACCOUNTING => $numberFormat->getAccountingCurrencyPattern(),
+ ];
+ if (!array_key_exists($style, $availablePatterns)) {
+ // Unknown type.
+ throw new InvalidArgumentException('Unknown format style provided to NumberFormatter::__construct().');
+ }
+
+ // Split the selected pattern into positive and negative patterns.
+ $patterns = explode(';', $availablePatterns[$style]);
+ if (!isset($patterns[1])) {
+ // No explicit negative pattern was provided, construct it.
+ $patterns[1] = '-' . $patterns[0];
+ }
+
+ $this->numberFormat = $numberFormat;
+ $this->positivePattern = $patterns[0];
+ $this->negativePattern = $patterns[1];
+ $this->groupingUsed = (strpos($this->positivePattern, ',') !== false);
+ // This pattern has number groups, parse them.
+ if ($this->groupingUsed) {
+ preg_match('/#+0/', $this->positivePattern, $primaryGroupMatches);
+ $this->primaryGroupSize = $this->secondaryGroupSize = strlen($primaryGroupMatches[0]);
+ $numberGroups = explode(',', $this->positivePattern);
+ if (count($numberGroups) > 2) {
+ // This pattern has a distinct secondary group size.
+ $this->secondaryGroupSize = strlen($numberGroups[1]);
+ }
+ }
+
+ // Initialize the fraction digit settings for decimal and percent
+ // styles only. The currency ones will default to the currency values.
+ if (in_array($style, [self::DECIMAL, self::PERCENT])) {
+ $this->minimumFractionDigits = 0;
+ $this->maximumFractionDigits = 3;
+ }
+ $this->currencyDisplay = self::CURRENCY_DISPLAY_SYMBOL;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function format($value)
+ {
+ if (!is_numeric($value)) {
+ $message = sprintf('The provided value "%s" must be a valid number or numeric string.', $value);
+ throw new InvalidArgumentException($message);
+ }
+
+ // Ensure that the value is positive and has the right number of digits.
+ $negative = (bccomp('0', $value, 12) == 1);
+ $signMultiplier = $negative ? '-1' : '1';
+ $value = bcdiv($value, $signMultiplier, $this->maximumFractionDigits);
+ // Split the number into major and minor digits.
+ $valueParts = explode('.', $value);
+ $majorDigits = $valueParts[0];
+ // Account for maximumFractionDigits = 0, where the number won't
+ // have a decimal point, and $valueParts[1] won't be set.
+ $minorDigits = isset($valueParts[1]) ? $valueParts[1] : '';
+
+ if ($this->groupingUsed) {
+ // Reverse the major digits, since they are grouped from the right.
+ $majorDigits = array_reverse(str_split($majorDigits));
+ // Group the major digits.
+ $groups = [];
+ $groups[] = array_splice($majorDigits, 0, $this->primaryGroupSize);
+ while (!empty($majorDigits)) {
+ $groups[] = array_splice($majorDigits, 0, $this->secondaryGroupSize);
+ }
+ // Reverse the groups and the digits inside of them.
+ $groups = array_reverse($groups);
+ foreach ($groups as &$group) {
+ $group = implode(array_reverse($group));
+ }
+ // Reconstruct the major digits.
+ $majorDigits = implode(',', $groups);
+ }
+
+ if ($this->minimumFractionDigits < $this->maximumFractionDigits) {
+ // Strip any trailing zeroes.
+ $minorDigits = rtrim($minorDigits, '0');
+ if (strlen($minorDigits) < $this->minimumFractionDigits) {
+ // Now there are too few digits, re-add trailing zeroes
+ // until the desired length is reached.
+ $neededZeroes = $this->minimumFractionDigits - strlen($minorDigits);
+ $minorDigits .= str_repeat('0', $neededZeroes);
+ }
+ }
+
+ // Assemble the final number and insert it into the pattern.
+ $value = strlen($minorDigits) ? $majorDigits . '.' . $minorDigits : $majorDigits;
+ $pattern = $negative ? $this->negativePattern : $this->positivePattern;
+ $value = preg_replace('/#(?:[\.,]#+)*0(?:[,\.][0#]+)*/', $value, $pattern);
+
+ // Localize the number.
+ $value = $this->replaceDigits($value);
+ $value = $this->replaceSymbols($value);
+
+ return $value;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function formatCurrency($value, CurrencyInterface $currency)
+ {
+ // Use the currency defaults if the values weren't set by the caller.
+ $resetMinimumFractionDigits = $resetMaximumFractionDigits = false;
+ if (!isset($this->minimumFractionDigits)) {
+ $this->minimumFractionDigits = $currency->getFractionDigits();
+ $resetMinimumFractionDigits = true;
+ }
+ if (!isset($this->maximumFractionDigits)) {
+ $this->maximumFractionDigits = $currency->getFractionDigits();
+ $resetMaximumFractionDigits = true;
+ }
+
+ // Format the decimal part of the value first.
+ $value = $this->format($value);
+
+ // Reset the fraction digit settings, so that they don't affect
+ // future formattings with different currencies.
+ if ($resetMinimumFractionDigits) {
+ $this->minimumFractionDigits = null;
+ }
+ if ($resetMaximumFractionDigits) {
+ $this->maximumFractionDigits = null;
+ }
+
+ // Determine whether to show the currency symbol or the currency code.
+ if ($this->currencyDisplay == self::CURRENCY_DISPLAY_SYMBOL) {
+ $symbol = $currency->getSymbol();
+ } else {
+ $symbol = $currency->getCurrencyCode();
+ }
+
+ return str_replace('¤', $symbol, $value);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function parse($value)
+ {
+ $replacements = [
+ $this->numberFormat->getGroupingSeparator() => '',
+ // Convert the localized symbols back to their original form.
+ $this->numberFormat->getDecimalSeparator() => '.',
+ $this->numberFormat->getPlusSign() => '+',
+ $this->numberFormat->getMinusSign() => '-',
+
+ // Strip whitespace (spaces and non-breaking spaces).
+ ' ' => '',
+ chr(0xC2) . chr(0xA0) => '',
+ ];
+ $numberingSystem = $this->numberFormat->getNumberingSystem();
+ if (isset($this->digits[$numberingSystem])) {
+ // Convert the localized digits back to latin.
+ $replacements += array_flip($this->digits[$numberingSystem]);
+ }
+
+ $value = strtr($value, $replacements);
+ if (substr($value, 0, 1) == '(' && substr($value, -1, 1) == ')') {
+ // This is an accounting formatted negative number.
+ $value = '-' . str_replace(['(', ')'], '', $value);
+ }
+
+ return is_numeric($value) ? $value : false;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function parseCurrency($value, CurrencyInterface $currency)
+ {
+ $replacements = [
+ // Strip the currency code or symbol.
+ $currency->getCurrencyCode() => '',
+ $currency->getSymbol() => '',
+ ];
+ $value = strtr($value, $replacements);
+
+ return $this->parse($value);
+ }
+
+ /**
+ * Replaces digits with their localized equivalents.
+ *
+ * @param string $value The value being formatted.
+ *
+ * @return string
+ */
+ protected function replaceDigits($value)
+ {
+ $numberingSystem = $this->numberFormat->getNumberingSystem();
+ if (isset($this->digits[$numberingSystem])) {
+ $value = strtr($value, $this->digits[$numberingSystem]);
+ }
+
+ return $value;
+ }
+
+ /**
+ * Replaces number symbols with their localized equivalents.
+ *
+ * @param string $value The value being formatted.
+ *
+ * @return string
+ *
+ * @see http://cldr.unicode.org/translation/number-symbols
+ */
+ protected function replaceSymbols($value)
+ {
+ $replacements = [
+ '.' => $this->numberFormat->getDecimalSeparator(),
+ ',' => $this->numberFormat->getGroupingSeparator(),
+ '+' => $this->numberFormat->getPlusSign(),
+ '-' => $this->numberFormat->getMinusSign(),
+ '%' => $this->numberFormat->getPercentSign(),
+ ];
+
+ return strtr($value, $replacements);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getNumberFormat()
+ {
+ return $this->numberFormat;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getMinimumFractionDigits()
+ {
+ return $this->minimumFractionDigits;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setMinimumFractionDigits($minimumFractionDigits)
+ {
+ $this->minimumFractionDigits = $minimumFractionDigits;
+
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getMaximumFractionDigits()
+ {
+ return $this->maximumFractionDigits;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setMaximumFractionDigits($maximumFractionDigits)
+ {
+ $this->maximumFractionDigits = $maximumFractionDigits;
+
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function isGroupingUsed()
+ {
+ return $this->groupingUsed;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setGroupingUsed($groupingUsed)
+ {
+ $this->groupingUsed = $groupingUsed;
+
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getCurrencyDisplay()
+ {
+ return $this->currencyDisplay;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setCurrencyDisplay($currencyDisplay)
+ {
+ $this->currencyDisplay = $currencyDisplay;
+
+ return $this;
+ }
+}
diff --git a/vendor/commerceguys/intl/src/Formatter/NumberFormatterInterface.php b/vendor/commerceguys/intl/src/Formatter/NumberFormatterInterface.php
new file mode 100644
index 000000000..3a510be2a
--- /dev/null
+++ b/vendor/commerceguys/intl/src/Formatter/NumberFormatterInterface.php
@@ -0,0 +1,151 @@
+<?php
+
+namespace CommerceGuys\Intl\Formatter;
+
+use CommerceGuys\Intl\Currency\CurrencyInterface;
+use CommerceGuys\Intl\NumberFormat\NumberFormatInterface;
+
+interface NumberFormatterInterface
+{
+ /* Format style constants */
+ const DECIMAL = 1;
+ const PERCENT = 2;
+ const CURRENCY = 3;
+ const CURRENCY_ACCOUNTING = 4;
+
+ /* Currency display style constants */
+ const CURRENCY_DISPLAY_SYMBOL = 1;
+ const CURRENCY_DISPLAY_CODE = 2;
+
+ /**
+ * Formats a number.
+ *
+ * Please note that the provided value should already be rounded.
+ * This formatter doesn't do any rounding of its own, and will simply
+ * truncate extra digits.
+ *
+ * @param string $value The value to format.
+ *
+ * @return string
+ */
+ public function format($value);
+
+ /**
+ * Formats a currency value.
+ *
+ * Please note that the provided value should already be rounded.
+ * This formatter doesn't do any rounding of its own, and will simply
+ * truncate extra digits.
+ *
+ * @param string $value The value to format.
+ * @param CurrencyInterface $currency The currency.
+ *
+ * @return string
+ */
+ public function formatCurrency($value, CurrencyInterface $currency);
+
+ /**
+ * Parses a number.
+ *
+ * Commonly used in input widgets where the end-user might input
+ * a value using digits and symbols common to their locale.
+ *
+ * @param string $value The value to parse.
+ *
+ * @return string|false The parsed numeric value or FALSE on error.
+ */
+ public function parse($value);
+
+ /**
+ * Parses a formatted currency value.
+ *
+ * @param string $value The value to parse.
+ * @param CurrencyInterface $currency The currency.
+ *
+ * @return string|false The parsed numeric value or FALSE on error.
+ */
+ public function parseCurrency($value, CurrencyInterface $currency);
+
+ /**
+ * Gets the number format.
+ *
+ * @return NumberFormatInterface
+ */
+ public function getNumberFormat();
+
+ /**
+ * Gets the minimum number of fraction digits.
+ *
+ * Defaults to 0 for decimal and percentage styles.
+ * Defaults to null for currency styles, since the currency number of
+ * fraction digits is used as the default in that case.
+ *
+ * @return int
+ */
+ public function getMinimumFractionDigits();
+
+ /**
+ * Sets the minimum number of fraction digits.
+ *
+ * @param int $minimumFractionDigits
+ *
+ * @return self
+ */
+ public function setMinimumFractionDigits($minimumFractionDigits);
+
+ /**
+ * Gets the maximum number of fraction digits.
+ *
+ * Defaults to 3 for decimal and percentage styles.
+ * Defaults to null for currency styles, since the currency number of
+ * fraction digits is used as the default in that case.
+ *
+ * @return int
+ */
+ public function getMaximumFractionDigits();
+
+ /**
+ * Sets the maximum number of fraction digits.
+ *
+ * @param int $maximumFractionDigits
+ *
+ * @return self
+ */
+ public function setMaximumFractionDigits($maximumFractionDigits);
+
+ /**
+ * Returns whether the major digits will be grouped.
+ *
+ * @return bool
+ */
+ public function isGroupingUsed();
+
+ /**
+ * Sets whether or not major digits should be grouped.
+ *
+ * @param bool $groupingUsed
+ *
+ * @return self
+ */
+ public function setGroupingUsed($groupingUsed);
+
+ /**
+ * Gets the currency display style.
+ *
+ * Controls whether a currency amount will be shown with the
+ * currency symbol (CURRENCY_DISPLAY_SYMBOL) or the
+ * currency code (CURRENCY_DISPLAY_CODE).
+ *
+ * @return int
+ */
+ public function getCurrencyDisplay();
+
+ /**
+ * Sets the currency display style.
+ *
+ * @param int $currencyDisplay One of the CURRENCY_DISPLAY_ constants.
+ *
+ * @return self
+ */
+ public function setCurrencyDisplay($currencyDisplay);
+}
diff --git a/vendor/commerceguys/intl/src/Language/Language.php b/vendor/commerceguys/intl/src/Language/Language.php
new file mode 100644
index 000000000..9958d5481
--- /dev/null
+++ b/vendor/commerceguys/intl/src/Language/Language.php
@@ -0,0 +1,91 @@
+<?php
+
+namespace CommerceGuys\Intl\Language;
+
+class Language implements LanguageEntityInterface
+{
+ /**
+ * The two-letter language code.
+ *
+ * @var string
+ */
+ protected $languageCode;
+
+ /**
+ * The language name.
+ *
+ * @var string
+ */
+ protected $name;
+
+ /**
+ * The language locale (i.e. "en-US").
+ *
+ * @var string
+ */
+ protected $locale;
+
+ /**
+ * Returns the string representation of the Language.
+ *
+ * @return string
+ */
+ public function __toString()
+ {
+ return $this->getLanguageCode();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getLanguageCode()
+ {
+ return $this->languageCode;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setLanguageCode($languageCode)
+ {
+ $this->languageCode = $languageCode;
+
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getName()
+ {
+ return $this->name;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setName($name)
+ {
+ $this->name = $name;
+
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getLocale()
+ {
+ return $this->locale;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setLocale($locale)
+ {
+ $this->locale = $locale;
+
+ return $this;
+ }
+}
diff --git a/vendor/commerceguys/intl/src/Language/LanguageEntityInterface.php b/vendor/commerceguys/intl/src/Language/LanguageEntityInterface.php
new file mode 100644
index 000000000..e36e0bf77
--- /dev/null
+++ b/vendor/commerceguys/intl/src/Language/LanguageEntityInterface.php
@@ -0,0 +1,24 @@
+<?php
+
+namespace CommerceGuys\Intl\Language;
+
+interface LanguageEntityInterface extends LanguageInterface
+{
+ /**
+ * Sets the two-letter language code.
+ *
+ * @param string $languageCode The two-letter language code.
+ *
+ * @return self
+ */
+ public function setLanguageCode($languageCode);
+
+ /**
+ * Sets the language name.
+ *
+ * @param string $name The language name.
+ *
+ * @return self
+ */
+ public function setName($name);
+}
diff --git a/vendor/commerceguys/intl/src/Language/LanguageInterface.php b/vendor/commerceguys/intl/src/Language/LanguageInterface.php
new file mode 100644
index 000000000..14c603dfd
--- /dev/null
+++ b/vendor/commerceguys/intl/src/Language/LanguageInterface.php
@@ -0,0 +1,23 @@
+<?php
+
+namespace CommerceGuys\Intl\Language;
+
+interface LanguageInterface
+{
+ /**
+ * Gets the two-letter language code.
+ *
+ * @return string
+ */
+ public function getLanguageCode();
+
+ /**
+ * Gets the language name.
+ *
+ * Note that certain locales have incomplete translations, in which
+ * case the english version of the language name is used instead.
+ *
+ * @return string
+ */
+ public function getName();
+}
diff --git a/vendor/commerceguys/intl/src/Language/LanguageRepository.php b/vendor/commerceguys/intl/src/Language/LanguageRepository.php
new file mode 100644
index 000000000..4fc02f2ff
--- /dev/null
+++ b/vendor/commerceguys/intl/src/Language/LanguageRepository.php
@@ -0,0 +1,115 @@
+<?php
+
+namespace CommerceGuys\Intl\Language;
+
+use CommerceGuys\Intl\LocaleResolverTrait;
+use CommerceGuys\Intl\Exception\UnknownLanguageException;
+
+/**
+ * Manages languages based on JSON definitions.
+ */
+class LanguageRepository implements LanguageRepositoryInterface
+{
+ use LocaleResolverTrait;
+
+ /**
+ * Per-locale language definitions.
+ *
+ * @var array
+ */
+ protected $definitions = [];
+
+ /**
+ * Creates a LanguageRepository instance.
+ *
+ * @param string $definitionPath The path to the currency definitions.
+ * Defaults to 'resources/language'.
+ */
+ public function __construct($definitionPath = null)
+ {
+ $this->definitionPath = $definitionPath ? $definitionPath : __DIR__ . '/../../resources/language/';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function get($languageCode, $locale = null, $fallbackLocale = null)
+ {
+ $locale = $this->resolveLocale($locale, $fallbackLocale);
+ $definitions = $this->loadDefinitions($locale);
+ if (!isset($definitions[$languageCode])) {
+ throw new UnknownLanguageException($languageCode);
+ }
+
+ return $this->createLanguageFromDefinition($languageCode, $definitions[$languageCode], $locale);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getAll($locale = null, $fallbackLocale = null)
+ {
+ $locale = $this->resolveLocale($locale, $fallbackLocale);
+ $definitions = $this->loadDefinitions($locale);
+ $languages = [];
+ foreach ($definitions as $languageCode => $definition) {
+ $languages[$languageCode] = $this->createLanguageFromDefinition($languageCode, $definition, $locale);
+ }
+
+ return $languages;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getList($locale = null, $fallbackLocale = null)
+ {
+ $locale = $this->resolveLocale($locale, $fallbackLocale);
+ $definitions = $this->loadDefinitions($locale);
+ $list = [];
+ foreach ($definitions as $languageCode => $definition) {
+ $list[$languageCode] = $definition['name'];
+ }
+
+ return $list;
+ }
+
+ /**
+ * Loads the language definitions for the provided locale.
+ *
+ * @param string $locale The desired locale.
+ *
+ * @return array
+ */
+ protected function loadDefinitions($locale)
+ {
+ if (!isset($this->definitions[$locale])) {
+ $filename = $this->definitionPath . $locale . '.json';
+ $this->definitions[$locale] = json_decode(file_get_contents($filename), true);
+ }
+
+ return $this->definitions[$locale];
+ }
+
+ /**
+ * Creates a language object from the provided definition.
+ *
+ * @param string $languageCode The language code.
+ * @param array $definition The language definition.
+ * @param string $locale The locale of the language definition.
+ *
+ * @return Language
+ */
+ protected function createLanguageFromDefinition($languageCode, array $definition, $locale)
+ {
+ $language = new Language();
+ $setValues = \Closure::bind(function ($languageCode, $definition, $locale) {
+ $this->languageCode = $languageCode;
+ $this->name = $definition['name'];
+ $this->locale = $locale;
+ }, $language, '\CommerceGuys\Intl\Language\Language');
+ $setValues($languageCode, $definition, $locale);
+
+ return $language;
+ }
+}
diff --git a/vendor/commerceguys/intl/src/Language/LanguageRepositoryInterface.php b/vendor/commerceguys/intl/src/Language/LanguageRepositoryInterface.php
new file mode 100644
index 000000000..dd14250e0
--- /dev/null
+++ b/vendor/commerceguys/intl/src/Language/LanguageRepositoryInterface.php
@@ -0,0 +1,41 @@
+<?php
+
+namespace CommerceGuys\Intl\Language;
+
+/**
+ * Language repository interface.
+ */
+interface LanguageRepositoryInterface
+{
+ /**
+ * Returns a language instance matching the provided language code.
+ *
+ * @param string $languageCode The language code.
+ * @param string $locale The locale (i.e. fr-FR).
+ * @param string $fallbackLocale A fallback locale (i.e "en").
+ *
+ * @return LanguageInterface
+ */
+ public function get($languageCode, $locale = null, $fallbackLocale = null);
+
+ /**
+ * Returns all language instances.
+ *
+ * @param string $locale The locale (i.e. fr-FR).
+ * @param string $fallbackLocale A fallback locale (i.e "en").
+ *
+ * @return array An array of languages implementing the LanguageInterface,
+ * keyed by language code.
+ */
+ public function getAll($locale = null, $fallbackLocale = null);
+
+ /**
+ * Returns a list of languages.
+ *
+ * @param string $locale The locale (i.e. fr-FR).
+ * @param string $fallbackLocale A fallback locale (i.e "en").
+ *
+ * @return array An array of language names, keyed by language code.
+ */
+ public function getList($locale = null, $fallbackLocale = null);
+}
diff --git a/vendor/commerceguys/intl/src/LocaleResolverTrait.php b/vendor/commerceguys/intl/src/LocaleResolverTrait.php
new file mode 100644
index 000000000..797e5abaf
--- /dev/null
+++ b/vendor/commerceguys/intl/src/LocaleResolverTrait.php
@@ -0,0 +1,244 @@
+<?php
+
+namespace CommerceGuys\Intl;
+
+use CommerceGuys\Intl\Exception\UnknownLocaleException;
+
+trait LocaleResolverTrait
+{
+ /**
+ * The path where per-locale definitions are stored.
+ *
+ * @var string
+ */
+ protected $definitionPath;
+
+ /**
+ * The default locale.
+ *
+ * @var string
+ */
+ protected $defaultLocale = 'en';
+
+ /**
+ * The fallback locale.
+ *
+ * @var string
+ */
+ protected $fallbackLocale = null;
+
+ /**
+ * Common locale aliases.
+ *
+ * @var array
+ */
+ protected $localeAliases = [
+ 'az-AZ' => 'az-Latn-AZ',
+ 'bs-BA' => 'bs-Latn-BA',
+ 'ha-GH' => 'ha-Latn-GH',
+ 'ha-NE' => 'ha-Latn-NE',
+ 'ha-NG' => 'ha-Latn-NG',
+ 'in' => 'id',
+ 'in-ID' => 'id-ID',
+ 'iw' => 'he',
+ 'iw-IL' => 'he-IL',
+ 'kk-KZ' => 'kk-Cyrl-KZ',
+ 'ks-IN' => 'ks-Arab-IN',
+ 'ky-KG' => 'ky-Cyrl-KG',
+ 'mn-MN' => 'mn-Cyrl-MN',
+ 'mo' => 'ro-MD',
+ 'ms-BN' => 'ms-Latn-BN',
+ 'ms-MY' => 'ms-Latn-MY',
+ 'ms-SG' => 'ms-Latn-SG',
+ 'no' => 'nb',
+ 'no-NO' => 'nb-NO',
+ 'no-NO-NY' => 'nn-NO',
+ 'pa-IN' => 'pa-Guru-IN',
+ 'pa-PK' => 'pa-Arab-PK',
+ 'sh' => 'sr-Latn',
+ 'sh-BA' => 'sr-Latn-BA',
+ 'sh-CS' => 'sr-Latn-RS',
+ 'sh-YU' => 'sr-Latn-RS',
+ 'shi-MA' => 'shi-Tfng-MA',
+ 'sr-BA' => 'sr-Cyrl-BA',
+ 'sr-ME' => 'sr-Latn-ME',
+ 'sr-RS' => 'sr-Cyrl-RS',
+ 'sr-XK' => 'sr-Cyrl-XK',
+ 'tl' => 'fil',
+ 'tl-PH' => 'fil-PH',
+ 'tzm-MA' => 'tzm-Latn-MA',
+ 'ug-CN' => 'ug-Arab-CN',
+ 'uz-AF' => 'uz-Arab-AF',
+ 'uz-UZ' => 'uz-Latn-UZ',
+ 'vai-LR' => 'vai-Vaii-LR',
+ 'zh-CN' => 'zh-Hans-CN',
+ 'zh-HK' => 'zh-Hant-HK',
+ 'zh-MO' => 'zh-Hant-MO',
+ 'zh-SG' => 'zh-Hans-SG',
+ 'zh-TW' => 'zh-Hant-TW',
+ ];
+
+ /**
+ * Determines which locale should be used for loading definitions.
+ *
+ * If the "bs-Cyrl-BA" locale is requested, with an "en" fallback,
+ * the system will try to find the definitions for:
+ * 1) bs-Cyrl-BA
+ * 2) bs-Cyrl
+ * 3) bs
+ * 4) en
+ * The first locale for which a definition file is found, wins.
+ * Otherwise, an exception is thrown.
+ *
+ * @param string $locale The desired locale (i.e. fr-FR).
+ * @param string $fallbackLocale A fallback locale (i.e "en").
+ *
+ * @return string
+ *
+ * @throws UnknownLocaleException
+ */
+ protected function resolveLocale($locale = null, $fallbackLocale = null)
+ {
+ $locale = $locale ?: $this->getDefaultLocale();
+ $locale = $this->canonicalizeLocale($locale);
+ $locale = $this->resolveLocaleAlias($locale);
+ // List all possible variants (i.e. en-US gives "en-US" and "en").
+ $localeVariants = $this->getLocaleVariants($locale);
+ // A fallback locale was provided, add it to the end of the chain.
+ $fallbackLocale = $fallbackLocale ?: $this->getFallbackLocale();
+ if (isset($fallbackLocale)) {
+ $localeVariants[] = $fallbackLocale;
+ }
+
+ // Try to resolve a locale by finding a matching definition file.
+ $resolvedLocale = null;
+ foreach ($localeVariants as $localeVariant) {
+ $path = $this->definitionPath . $localeVariant . '.json';
+ if (file_exists($path)) {
+ $resolvedLocale = $localeVariant;
+ break;
+ }
+ }
+ // No locale could be resolved, stop here.
+ if (!$resolvedLocale) {
+ throw new UnknownLocaleException($locale);
+ }
+
+ return $resolvedLocale;
+ }
+
+ /**
+ * Resolves known locale aliases.
+ *
+ * For example, "zh-CN" is resolved to "zh-Hans-CN".
+ *
+ * @param string $locale The locale.
+ *
+ * @return string The locale.
+ */
+ protected function resolveLocaleAlias($locale = null)
+ {
+ if ($locale && isset($this->localeAliases[$locale])) {
+ $locale = $this->localeAliases[$locale];
+ }
+
+ return $locale;
+ }
+
+ /**
+ * Canonicalize the given locale.
+ *
+ * @param string $locale The locale.
+ *
+ * @return string The canonicalized locale.
+ */
+ protected function canonicalizeLocale($locale = null)
+ {
+ if (is_null($locale)) {
+ return $locale;
+ }
+
+ $locale = str_replace('-', '_', strtolower($locale));
+ $localeParts = explode('_', $locale);
+ foreach ($localeParts as $index => $part) {
+ if ($index === 0) {
+ // The language code should stay lowercase.
+ continue;
+ }
+
+ if (strlen($part) == 4) {
+ // Script code.
+ $localeParts[$index] = ucfirst($part);
+ } else {
+ // Country or variant code.
+ $localeParts[$index] = strtoupper($part);
+ }
+ }
+
+ return implode('-', $localeParts);
+ }
+
+ /**
+ * Gets the default locale.
+ *
+ * @return string The default locale.
+ */
+ public function getDefaultLocale()
+ {
+ return $this->defaultLocale;
+ }
+
+ /**
+ * Sets the default locale.
+ *
+ * @return void
+ */
+ public function setDefaultLocale($locale)
+ {
+ $this->defaultLocale = $locale;
+ }
+
+ /**
+ * Gets the fallback locale.
+ *
+ * @return string The fallback locale.
+ */
+ public function getFallbackLocale()
+ {
+ return $this->fallbackLocale;
+ }
+
+ /**
+ * Sets the fallback locale.
+ *
+ * @return void
+ */
+ public function setFallbackLocale($locale)
+ {
+ $this->fallbackLocale = $locale;
+ }
+
+ /**
+ * Gets all variants of a locale.
+ *
+ * For example, "bs-Cyrl-BA" has the following variants:
+ * 1) bs-Cyrl-BA
+ * 2) bs-Cyrl
+ * 3) bs
+ *
+ * @param string $locale The locale (i.e. fr-FR).
+ *
+ * @return array An array of all variants of a locale.
+ */
+ protected function getLocaleVariants($locale)
+ {
+ $localeVariants = [];
+ $localeParts = explode('-', $locale);
+ while (!empty($localeParts)) {
+ $localeVariants[] = implode('-', $localeParts);
+ array_pop($localeParts);
+ }
+
+ return $localeVariants;
+ }
+}
diff --git a/vendor/commerceguys/intl/src/NumberFormat/NumberFormat.php b/vendor/commerceguys/intl/src/NumberFormat/NumberFormat.php
new file mode 100644
index 000000000..077f6721f
--- /dev/null
+++ b/vendor/commerceguys/intl/src/NumberFormat/NumberFormat.php
@@ -0,0 +1,269 @@
+<?php
+
+namespace CommerceGuys\Intl\NumberFormat;
+
+class NumberFormat implements NumberFormatEntityInterface
+{
+ /**
+ * The locale (i.e. "en_US").
+ *
+ * @var string
+ */
+ protected $locale;
+
+ /**
+ * The numbering system.
+ *
+ * @var string
+ */
+ protected $numberingSystem = [];
+
+ /**
+ * The decimal separator.
+ *
+ * @var string
+ */
+ protected $decimalSeparator = [];
+
+ /**
+ * The grouping separator.
+ *
+ * @var string
+ */
+ protected $groupingSeparator = [];
+
+ /**
+ * The plus sign.
+ *
+ * @var string
+ */
+ protected $plusSign = [];
+
+ /**
+ * The number symbols.
+ *
+ * @var string
+ */
+ protected $minusSign = [];
+
+ /**
+ * The percent sign.
+ *
+ * @var string
+ */
+ protected $percentSign = [];
+
+ /**
+ * The number pattern used to format decimal numbers.
+ *
+ * @var string
+ */
+ protected $decimalPattern;
+
+ /**
+ * The number pattern used to format percentages.
+ *
+ * @var string
+ */
+ protected $percentPattern;
+
+ /**
+ * The number pattern used to format currency amounts.
+ *
+ * @var string
+ */
+ protected $currencyPattern;
+
+ /**
+ * The number pattern used to format accounting currency amounts.
+ *
+ * @var string
+ */
+ protected $accountingCurrencyPattern;
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getLocale()
+ {
+ return $this->locale;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setLocale($locale)
+ {
+ $this->locale = $locale;
+
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getNumberingSystem()
+ {
+ return $this->numberingSystem;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setNumberingSystem($numberingSystem)
+ {
+ $this->numberingSystem = $numberingSystem;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getDecimalSeparator()
+ {
+ return $this->decimalSeparator;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setDecimalSeparator($decimalSeparator)
+ {
+ $this->decimalSeparator = $decimalSeparator;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getGroupingSeparator()
+ {
+ return $this->groupingSeparator;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setGroupingSeparator($groupingSeparator)
+ {
+ $this->groupingSeparator = $groupingSeparator;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getPlusSign()
+ {
+ return $this->plusSign;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setPlusSign($plusSign)
+ {
+ $this->plusSign = $plusSign;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getMinusSign()
+ {
+ return $this->minusSign;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setMinusSign($minusSign)
+ {
+ $this->minusSign = $minusSign;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getPercentSign()
+ {
+ return $this->percentSign;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setPercentSign($percentSign)
+ {
+ $this->percentSign = $percentSign;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getDecimalPattern()
+ {
+ return $this->decimalPattern;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setDecimalPattern($decimalPattern)
+ {
+ $this->decimalPattern = $decimalPattern;
+
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getPercentPattern()
+ {
+ return $this->percentPattern;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setPercentPattern($percentPattern)
+ {
+ $this->percentPattern = $percentPattern;
+
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getCurrencyPattern()
+ {
+ return $this->currencyPattern;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setCurrencyPattern($currencyPattern)
+ {
+ $this->currencyPattern = $currencyPattern;
+
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getAccountingCurrencyPattern()
+ {
+ return $this->accountingCurrencyPattern;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setAccountingCurrencyPattern($accountingCurrencyPattern)
+ {
+ $this->accountingCurrencyPattern = $accountingCurrencyPattern;
+
+ return $this;
+ }
+}
diff --git a/vendor/commerceguys/intl/src/NumberFormat/NumberFormatEntityInterface.php b/vendor/commerceguys/intl/src/NumberFormat/NumberFormatEntityInterface.php
new file mode 100644
index 000000000..debafd6ba
--- /dev/null
+++ b/vendor/commerceguys/intl/src/NumberFormat/NumberFormatEntityInterface.php
@@ -0,0 +1,107 @@
+<?php
+
+namespace CommerceGuys\Intl\NumberFormat;
+
+interface NumberFormatEntityInterface extends NumberFormatInterface
+{
+ /**
+ * Sets the locale.
+ *
+ * @param string $locale The locale (i.e. "en_US").
+ *
+ * @return self
+ */
+ public function setLocale($locale);
+
+ /**
+ * Sets the numbering system.
+ *
+ * @param string $numberingSystem One of the NUMBERING_SYSTEM_ constants.
+ *
+ * @return self
+ */
+ public function setNumberingSystem($numberingSystem);
+
+ /**
+ * Sets the decimal separator.
+ *
+ * @param string $decimalSeparator
+ *
+ * @return self
+ */
+ public function setDecimalSeparator($decimalSeparator);
+
+ /**
+ * Sets the grouping separator.
+ *
+ * @param string $groupingSeparator
+ *
+ * @return self
+ */
+ public function setGroupingSeparator($groupingSeparator);
+
+ /**
+ * Sets the plus sign.
+ *
+ * @param string $plusSign
+ *
+ * @return self
+ */
+ public function setPlusSign($plusSign);
+
+ /**
+ * Sets the minus sign.
+ *
+ * @param string $minusSign
+ *
+ * @return self
+ */
+ public function setMinusSign($minusSign);
+
+ /**
+ * Sets the percent sign.
+ *
+ * @param string $percentSign
+ *
+ * @return self
+ */
+ public function setPercentSign($percentSign);
+
+ /**
+ * Sets the number pattern used to format decimal numbers.
+ *
+ * @param string $decimalPattern The decimal pattern.
+ *
+ * @return self
+ */
+ public function setDecimalPattern($decimalPattern);
+
+ /**
+ * Sets the number pattern used to format percentages.
+ *
+ * @param string $percentPattern The percent pattern.
+ *
+ * @return self
+ */
+ public function setPercentPattern($percentPattern);
+
+ /**
+ * Sets the number pattern used to format currency amounts.
+ *
+ * @param string $currencyPattern The currency pattern.
+ *
+ * @return self
+ */
+ public function setCurrencyPattern($currencyPattern);
+
+ /**
+ * Sets the number pattern used to format accounting currency amounts.
+ *
+ * Most commonly used when formatting amounts on invoices.
+ *
+ * @param string $accountingCurrencyPattern The accounting currency pattern.
+ *
+ * @return self
+ */
+ public function setAccountingCurrencyPattern($accountingCurrencyPattern);
+}
diff --git a/vendor/commerceguys/intl/src/NumberFormat/NumberFormatInterface.php b/vendor/commerceguys/intl/src/NumberFormat/NumberFormatInterface.php
new file mode 100644
index 000000000..bb343f366
--- /dev/null
+++ b/vendor/commerceguys/intl/src/NumberFormat/NumberFormatInterface.php
@@ -0,0 +1,106 @@
+<?php
+
+namespace CommerceGuys\Intl\NumberFormat;
+
+interface NumberFormatInterface
+{
+ // Arabic-Indic digits.
+ const NUMBERING_SYSTEM_ARABIC = 'arab';
+ // Extended Arabic-Indic digits.
+ const NUMBERING_SYSTEM_ARABIC_EXTENDED = 'arabext';
+ // Bengali digits.
+ const NUMBERING_SYSTEM_BENGALI = 'beng';
+ // Devanagari digits.
+ const NUMBERING_SYSTEM_DEVANAGARI = 'deva';
+ // Latin digits
+ const NUMBERING_SYSTEM_LATIN = 'latn';
+
+ /**
+ * Gets the locale.
+ *
+ * @return string
+ */
+ public function getLocale();
+
+ /**
+ * Gets the numbering system.
+ *
+ * The value is one of the NUMBERING_SYSTEM_ constants.
+ *
+ * @return string
+ */
+ public function getNumberingSystem();
+
+ /**
+ * Gets the decimal separator.
+ *
+ * @return string
+ */
+ public function getDecimalSeparator();
+
+ /**
+ * Gets the grouping separator.
+ *
+ * @return string
+ */
+ public function getGroupingSeparator();
+
+ /**
+ * Gets the plus sign.
+ *
+ * @return string
+ */
+ public function getPlusSign();
+
+ /**
+ * Gets the minus sign.
+ *
+ * @return string
+ */
+ public function getMinusSign();
+
+ /**
+ * Gets the percent sign.
+ *
+ * @return string
+ */
+ public function getPercentSign();
+
+ /**
+ * Gets the number pattern used to format decimal numbers.
+ *
+ * @return string
+ *
+ * @see http://cldr.unicode.org/translation/number-patterns
+ */
+ public function getDecimalPattern();
+
+ /**
+ * Gets the number pattern used to format percentages.
+ *
+ * @return string
+ *
+ * @see http://cldr.unicode.org/translation/number-patterns
+ */
+ public function getPercentPattern();
+
+ /**
+ * Gets the number pattern used to format currency amounts.
+ *
+ * @return string
+ *
+ * @see http://cldr.unicode.org/translation/number-patterns
+ */
+ public function getCurrencyPattern();
+
+ /**
+ * Gets the number pattern used to format accounting currency amounts.
+ *
+ * Most commonly used when formatting amounts on invoices.
+ *
+ * @return string
+ *
+ * @see http://cldr.unicode.org/translation/number-patterns
+ */
+ public function getAccountingCurrencyPattern();
+}
diff --git a/vendor/commerceguys/intl/src/NumberFormat/NumberFormatRepository.php b/vendor/commerceguys/intl/src/NumberFormat/NumberFormatRepository.php
new file mode 100644
index 000000000..368eb7e2b
--- /dev/null
+++ b/vendor/commerceguys/intl/src/NumberFormat/NumberFormatRepository.php
@@ -0,0 +1,91 @@
+<?php
+
+namespace CommerceGuys\Intl\NumberFormat;
+
+use CommerceGuys\Intl\LocaleResolverTrait;
+
+/**
+ * Repository for number formats based on JSON definitions.
+ */
+class NumberFormatRepository implements NumberFormatRepositoryInterface
+{
+ use LocaleResolverTrait;
+
+ /**
+ * Number formats.
+ *
+ * @var array
+ */
+ protected $numberFormats = [];
+
+ /**
+ * Creates a NumberFormatRepository instance.
+ *
+ * @param string $definitionPath The path to the number format definitions.
+ * Defaults to 'resources/number_format'.
+ */
+ public function __construct($definitionPath = null)
+ {
+ $this->definitionPath = $definitionPath ? $definitionPath : __DIR__ . '/../../resources/number_format/';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function get($locale, $fallbackLocale = null)
+ {
+ $locale = $this->resolveLocale($locale, $fallbackLocale);
+ if (!isset($this->numberFormats[$locale])) {
+ $filename = $this->definitionPath . $locale . '.json';
+ $definition = json_decode(file_get_contents($filename), true);
+ $this->numberFormats[$locale] = $this->createNumberFormatFromDefinition($definition, $locale);
+ }
+
+ return $this->numberFormats[$locale];
+ }
+
+ /**
+ * Creates a number format object from the provided definition.
+ *
+ * @param array $definition The number format definition.
+ * @param string $locale The locale of the number format definition.
+ *
+ * @return NumberFormat
+ */
+ protected function createNumberFormatFromDefinition(array $definition, $locale)
+ {
+ if (!isset($definition['decimal_separator'])) {
+ $definition['decimal_separator'] = '.';
+ }
+ if (!isset($definition['grouping_separator'])) {
+ $definition['grouping_separator'] = ',';
+ }
+ if (!isset($definition['plus_sign'])) {
+ $definition['plus_sign'] = '+';
+ }
+ if (!isset($definition['minus_sign'])) {
+ $definition['minus_sign'] = '-';
+ }
+ if (!isset($definition['percent_sign'])) {
+ $definition['percent_sign'] = '%';
+ }
+
+ $numberFormat = new NumberFormat();
+ $setValues = \Closure::bind(function ($definition, $locale) {
+ $this->locale = $locale;
+ $this->numberingSystem = $definition['numbering_system'];
+ $this->decimalSeparator = $definition['decimal_separator'];
+ $this->groupingSeparator = $definition['grouping_separator'];
+ $this->plusSign = $definition['plus_sign'];
+ $this->minusSign = $definition['minus_sign'];
+ $this->percentSign = $definition['percent_sign'];
+ $this->decimalPattern = $definition['decimal_pattern'];
+ $this->percentPattern = $definition['percent_pattern'];
+ $this->currencyPattern = $definition['currency_pattern'];
+ $this->accountingCurrencyPattern = $definition['accounting_currency_pattern'];
+ }, $numberFormat, '\CommerceGuys\Intl\NumberFormat\NumberFormat');
+ $setValues($definition, $locale);
+
+ return $numberFormat;
+ }
+}
diff --git a/vendor/commerceguys/intl/src/NumberFormat/NumberFormatRepositoryInterface.php b/vendor/commerceguys/intl/src/NumberFormat/NumberFormatRepositoryInterface.php
new file mode 100644
index 000000000..ff162b522
--- /dev/null
+++ b/vendor/commerceguys/intl/src/NumberFormat/NumberFormatRepositoryInterface.php
@@ -0,0 +1,19 @@
+<?php
+
+namespace CommerceGuys\Intl\NumberFormat;
+
+/**
+ * Number format repository interface.
+ */
+interface NumberFormatRepositoryInterface
+{
+ /**
+ * Returns a number format instance for the provided locale.
+ *
+ * @param string $locale The locale (i.e. fr-FR).
+ * @param string $fallbackLocale A fallback locale (i.e "en").
+ *
+ * @return NumberFormatInterface
+ */
+ public function get($locale, $fallbackLocale = null);
+}