/** * Retrieve the max length of the country calling codes. * * @return int */ public static function getMaxPrefixLength() { static $result; if (!isset($result)) { $maxLen = 0; $data = Data::getGeneric('telephoneCodeData'); foreach ($data as $territoryCode => $prefixes) { foreach ($prefixes as $prefix) { $len = strlen($prefix); if ($maxLen < $len) { $maxLen = $len; } } } $result = $maxLen; } return $result; }
protected static function getStructure() { static $cache = null; if (is_null($cache)) { $data = Data::getGeneric('territoryContainment'); $result = static::fillStructure($data, '001', 0); $cache = $result; } else { $result = $cache; } return $result; }
/** * Return the plural rule ('zero', 'one', 'two', 'few', 'many' or 'other') for a number and a locale. * * @param string|int|float $number The number to check the plural rule for for * @param string $locale The locale to use. If empty we'll use the default locale set in \Punic\Data * * @return string Returns one of the following values: 'zero', 'one', 'two', 'few', 'many', 'other' * * @throws \Punic\Exception\BadArgumentType Throws a \Punic\Exception\BadArgumentType if $number is not a valid number * @throws \Exception Throws a \Exception if there were problems calculating the plural rule */ public static function getRule($number, $locale = '') { if (is_int($number)) { $intPartAbs = strval(abs($number)); $floatPart = ''; } elseif (is_float($number)) { $s = strval($number); if (strpos($s, '.') === false) { $intPart = $s; $floatPart = ''; } else { list($intPart, $floatPart) = explode('.', $s); } $intPartAbs = strval(abs(intval($intPart))); } elseif (is_string($number) && isset($number[0])) { if (preg_match('/^[+|\\-]?\\d+\\.?$/', $number)) { $v = intval($number); $intPartAbs = strval(abs($v)); $floatPart = ''; } elseif (preg_match('/^(\\d*)\\.(\\d+)$/', $number, $m)) { list($intPart, $floatPart) = explode('.', $number); $v = @intval($intPart); $intPartAbs = strval(abs($v)); } else { throw new Exception\BadArgumentType($number, 'number'); } } else { throw new Exception\BadArgumentType($number, 'number'); } // 'n' => '%1$s', // absolute value of the source number (integer and decimals). $v1 = $intPartAbs . (strlen($floatPart) ? ".{$floatPart}" : ''); // 'i' => '%2$s', // integer digits of n $v2 = $intPartAbs; // 'v' => '%3$s', // number of visible fraction digits in n, with trailing zeros. $v3 = strlen($floatPart); // 'w' => '%4$s', // number of visible fraction digits in n, without trailing zeros. $v4 = strlen(rtrim($floatPart, '0')); // 'f' => '%5$s', // visible fractional digits in n, with trailing zeros. $v5 = strlen($floatPart) ? strval(intval($floatPart)) : '0'; // 't' => '%6$s', // visible fractional digits in n, without trailing zeros. $v6 = trim($floatPart, '0'); if (!isset($v6[0])) { $v6 = '0'; } $result = 'other'; $node = Data::getLanguageNode(Data::getGeneric('plurals'), $locale); foreach ($node as $rule => $formulaPattern) { $formula = sprintf($formulaPattern, $v1, $v2, $v3, $v4, $v5, $v6); $check = str_replace(array('static::inRange(', ' and ', ' or ', ', false, ', ', true, ', ', array('), ' , ', $formula); if (preg_match('/[a-z]/', $check)) { throw new \Exception('Bad formula!'); } // fix for difference in modulo (%) in the definition and the one implemented in PHP for decimal numbers while (preg_match('/(\\d+\\.\\d+) % (\\d+(\\.\\d+)?)/', $formula, $m)) { list(, $decimalPart) = explode('.', $m[1], 2); $decimals = strlen(rtrim($decimalPart, '0')); if ($decimals > 0) { $pow = intval(pow(10, $decimals)); $repl = '(' . strval(intval(floatval($m[1]) * $pow)) . ' % ' . strval(intval(floatval($m[2] * $pow))) . ') / ' . $pow; } else { $repl = strval(intval($m[1])) . ' % ' . $m[2]; } $formula = str_replace($m[0], $repl, $formula); } $formulaResult = @eval("return ({$formula}) ? 'yes' : 'no';"); if ($formulaResult === 'yes') { $result = $rule; break; } elseif ($formulaResult !== 'no') { throw new \Exception('There was a problem in the formula ' . $formulaPattern); } } return $result; }
/** * Retrieve the first weekday for a specific locale (from 0-Sunday to 6-Saturnday). * * @param string $locale The locale to use. If empty we'll use the default locale set in \Punic\Data * * @return int Returns a number from 0 (Sunday) to 7 (Saturnday) */ public static function getFirstWeekday($locale = '') { static $cache = array(); $locale = empty($locale) ? Data::getDefaultLocale() : $locale; if (!isset($cache[$locale])) { $result = 0; $data = Data::getGeneric('weekData'); $i = Data::getTerritoryNode($data['firstDay'], $locale); if (is_int($i)) { $result = $i; } $cache[$locale] = $result; } return $cache[$locale]; }
/** * Return the history for the currencies used in a territory. * * @param string $territoryCode The territoy code * * @return array Return a list of items with these keys: * <ul> * <li>string `currency`: the currency code (always present)</li> * <li>string `from`: start date of the currency validity in the territory (not present if no start date) - Format is YYYY-MM-DD</li> * <li>string `to`: end date of the currency validity in the territory (not present if no end date) - Format is YYYY-MM-DD</li> * <li>bool `tender`: true if the currency was or is legal tender, false otherwise (always present)</li> * </ul> */ public static function getCurrencyHistoryForTerritory($territoryCode) { $result = array(); if (preg_match('/^[A-Z]{2}|[0-9]{3}$/', $territoryCode)) { $data = Data::getGeneric('currencyData'); if (isset($data['regions'][$territoryCode])) { foreach ($data['regions'][$territoryCode] as $c) { if (isset($c['notTender'])) { $c['tender'] = !$c['notTender']; unset($c['notTender']); } else { $c['tender'] = true; } $result[] = $c; } } } return $result; }
/** * Returns the list of countries that use a specific paper size by default. * * @param string $paperSize The paper size identifier ('A4' or 'US-Letter') * * @return array The list of country IDs that use the specified paper size (if $paperSize is invalid you'll get an empty array) */ public static function getCountriesWithPaperSize($paperSize) { $result = array(); if (is_string($paperSize) && isset($paperSize[0])) { $someGroup = false; $data = Data::getGeneric('measurementData'); foreach ($data['paperSize'] as $territory => $ms) { if (strcasecmp($paperSize, $ms) === 0) { $children = Territory::getChildTerritoryCodes($territory, true); if (empty($children)) { $result[] = $territory; } else { $someGroup = true; $result = array_merge($result, $children); } } } if ($someGroup) { $otherCountries = array(); foreach ($data['paperSize'] as $territory => $ms) { if ($territory !== '001' && strcasecmp($paperSize, $ms) !== 0) { $children = Territory::getChildTerritoryCodes($territory, true); if (empty($children)) { $otherCountries[] = $territory; } else { $otherCountries = array_merge($otherCountries, $children); } } } $result = array_values(array_diff($result, $otherCountries)); } } return $result; }