Файл: concrete5.7.5.6/concrete/vendor/punic/punic/code/Territory.php
Строк: 503
<?php
namespace Punic;
/**
* Territory-related stuff.
*/
class Territory
{
/**
* Retrieve the name of a territory (country, continent, ...).
*
* @param string $territoryCode The territory code
* @param string $locale The locale to use. If empty we'll use the default locale set in PunicData
*
* @return string Returns the localized territory name (returns $territoryCode if not found)
*/
public static function getName($territoryCode, $locale = '')
{
$result = $territoryCode;
if (preg_match('/^[a-z0-9]{2,3}$/i', $territoryCode)) {
$territoryCode = strtoupper($territoryCode);
$data = Data::get('territories', $locale);
if (isset($data[$territoryCode])) {
$result = $data[$territoryCode];
}
}
return $result;
}
/**
* Return the list of continents in the form of an array with key=ID, value=name.
*
* @param string $locale The locale to use. If empty we'll use the default locale set in PunicData
*
* @return array
*/
public static function getContinents($locale = '')
{
return static::getList('C', $locale);
}
/**
* Return the list of countries in the form of an array with key=ID, value=name.
*
* @param string $locale The locale to use. If empty we'll use the default locale set in PunicData
*
* @return array
*/
public static function getCountries($locale = '')
{
return static::getList('c', $locale);
}
/**
* Return a list of continents and relative countries. The resulting array is in the following form (JSON representation):
* ```json
* {
* "002": {
* "name": "Africa",
* "children": {
* "DZ": {"name": "Algeria"},
* "AO": {"name": "Angola"},
* ...
* }
* },
* "150": {
* "name": "Europe",
* "children": {
* "AL": {"name": "Albania"},
* "AD": {"name": "Andorra"},
* ...
* }
* }
* ...
* }
* ```
* The arrays are sorted by territory name.
*
* @param string $locale The locale to use. If empty we'll use the default locale set in PunicData
*
* @return array
*/
public static function getContinentsAndCountries($locale = '')
{
return static::getList('Cc', $locale);
}
/**
* Return a list of some specified territory, structured or not.
* $levels control which data you want to retrieve. It can be one or more of the following values:
* <ul>
* <li>'W': world</li>
* <li>'C': continents</li>
* <li>'S': sub-continents</li>
* <li>'c': countries</li>
* </ul>
* If only one level is specified you'll get a flat list (like the one returned by {@link getContinents}).
* If one or more levels are specified, you'll get a structured list (like the one returned by {@link getContinentsAndCountries}).
*
* @param string $levels A string with one or more of the characters: 'W' (for world), 'C' (for continents), 'S' (for sub-continents), 'c' (for countries)
* @param string $locale The locale to use. If empty we'll use the default locale set in PunicData
*
* @return array
*
* @link http://www.unicode.org/cldr/charts/latest/supplemental/territory_containment_un_m_49.html
*
* @throws ExceptionBadArgumentType
*/
public static function getList($levels = 'W', $locale = '')
{
static $levelMap = array('W' => 0, 'C' => 1, 'S' => 2, 'c' => 3);
$decodedLevels = array();
$n = is_string($levels) ? strlen($levels) : 0;
if ($n > 0) {
for ($i = 0; $i < $n; ++$i) {
$l = substr($levels, $i, 1);
if (!isset($levelMap[$l])) {
$decodedLevels = array();
break;
}
if (!in_array($levelMap[$l], $decodedLevels, true)) {
$decodedLevels[] = $levelMap[$l];
}
}
}
if (count($decodedLevels) === 0) {
throw new PunicExceptionBadArgumentType($levels, "list of territory kinds: it should be a list of one or more of the codes '".implode("', '", array_keys($levelMap))."'");
}
$struct = self::filterStructure(self::getStructure(), $decodedLevels, 0);
$flatList = (count($decodedLevels) > 1) ? false : true;
$finalized = self::finalizeWithNames(Data::get('territories', $locale), $struct, $flatList);
if ($flatList) {
$sorter = new PunicComparer();
$sorter->sort($finalized, true);
} else {
$finalized = static::sort($finalized);
}
return $finalized;
}
/**
* Return a list of territory identifiers for which we have some info (languages, population, literacy level, Gross Domestic Product).
*
* @return array The list of territory IDs for which we have some info
*/
public static function getTerritoriesWithInfo()
{
return array_keys(Data::getGeneric('territoryInfo'));
}
/**
* Return the list of languages spoken in a territory.
*
* @param string $territoryCode The territory code
* @param string $filterStatuses Filter language status.
* <ul>
* <li>If empty no filter will be applied</li>
* <li>'o' to include official languages</li>
* <li>'r' to include official regional languages</li>
* <li>'f' to include de facto official languages</li>
* <li>'m' to include official minority languages</li>
* <li>'u' to include unofficial or unknown languages</li>
* </ul>
* @param string $onlyCodes Set to true to retrieve only the language codes. If set to false (default) you'll receive a list of arrays with these keys:
* <ul>
* <li>string id: the language identifier</li>
* <li>string status: 'o' for official; 'r' for official regional; 'f' for de facto official; 'm' for official minority; 'u' for unofficial or unknown</li>
* <li>number population: the amount of people speaking the language (%)</li>
* <li>number|null writing: the amount of people able to write (%). May be null if no data is available</li>
* </ul>
*
* @return array|null Return the languages spoken in the specified territory, as described by the $onlyCodes parameter (or null if $territoryCode is not valid or no data is available)
*/
public static function getLanguages($territoryCode, $filterStatuses = '', $onlyCodes = false)
{
$result = null;
$info = self::getTerritoryInfo($territoryCode);
if (is_array($info)) {
$result = array();
foreach ($info['languages'] as $languageID => $languageInfo) {
if (!isset($languageInfo['status'])) {
$languageInfo['status'] = 'u';
}
if ((strlen($filterStatuses) === 0) || (stripos($filterStatuses, $languageInfo['status']) !== false)) {
if (!isset($languageInfo['writing'])) {
$languageInfo['writing'] = null;
}
if ($onlyCodes) {
$result[] = $languageID;
} else {
$result[] = array_merge(array('id' => $languageID), $languageInfo);
}
}
}
}
return $result;
}
/**
* Return the population of a specific territory.
*
* @param string $territoryCode The territory code
*
* @return number|null Return the size of the population of the specified territory (or null if $territoryCode is not valid or no data is available)
*/
public static function getPopulation($territoryCode)
{
$result = null;
$info = self::getTerritoryInfo($territoryCode);
if (is_array($info)) {
$result = $info['population'];
}
return $result;
}
/**
* Return the literacy level for a specific territory, in %.
*
* @param string $territoryCode The territory code
*
* @return number|null Return the % of literacy lever of the specified territory (or null if $territoryCode is not valid or no data is available)
*/
public static function getLiteracyLevel($territoryCode)
{
$result = null;
$info = self::getTerritoryInfo($territoryCode);
if (is_array($info)) {
$result = $info['literacy'];
}
return $result;
}
/**
* Return the GDP (Gross Domestic Product) for a specific territory, in US$.
*
* @param string $territoryCode The territory code
*
* @return number|null Return the GDP of the specified territory (or null if $territoryCode is not valid or no data is available)
*/
public static function getGrossDomesticProduct($territoryCode)
{
$result = null;
$info = self::getTerritoryInfo($territoryCode);
if (is_array($info)) {
$result = $info['gdp'];
}
return $result;
}
/**
* Return a list of territory IDs where a specific language is spoken, sorted by the total number of people speaking that language.
*
* @param string $languageID The language identifier
*
* @return array
*/
public static function getTerritoriesForLanguage($languageID)
{
$langPeople = array();
foreach (Data::getGeneric('territoryInfo') as $territoryID => $territoryInfo) {
foreach ($territoryInfo['languages'] as $langID => $langInfo) {
if ((strcasecmp($languageID, $langID) === 0) || (stripos($langID, $languageID.'_') === 0)) {
$langPeople[] = array('territoryID' => $territoryID, 'people' => $territoryInfo['population'] * $langInfo['population']);
}
}
}
usort($langPeople, function ($a, $b) {
$delta = $a['people'] - $b['people'];
if ($delta != 0) {
$result = ($delta > 0) ? -1 : 1;
} else {
$result = strcmp($a['territoryID'], $b['territoryID']);
}
return $result;
});
$territoryIDs = array();
foreach ($langPeople as $lp) {
$territoryIDs[] = $lp['territoryID'];
}
return $territoryIDs;
}
/**
* Return the code of the territory that contains a territory.
*
* @param string $childTerritoryCode
*
* @return string Return the parent territory code, or an empty string if $childTerritoryCode is the World (001) or if it's invalid.
*/
public static function getParentTerritoryCode($childTerritoryCode)
{
$result = '';
if (is_string($childTerritoryCode) && preg_match('/^[a-z0-9]{2,3}$/i', $childTerritoryCode)) {
$childTerritoryCode = strtoupper($childTerritoryCode);
foreach (Data::getGeneric('territoryContainment') as $parentTerritoryCode => $parentTerritoryInfo) {
if (in_array($childTerritoryCode, $parentTerritoryInfo['contains'], true)) {
$result = is_int($parentTerritoryCode) ? substr('00'.$parentTerritoryCode, -3) : $parentTerritoryCode;
if (($result === '001') || (strlen(static::getParentTerritoryCode($result)) > 0)) {
break;
}
}
}
}
return $result;
}
/**
* Retrieve the child territories of a parent territory.
*
* @param string $parentTerritoryCode
* @param bool $expandSubGroups Set to true to expand the sub-groups, false to retrieve them.
*
* @return array Return the list of territory codes that are children of $parentTerritoryCode (if $parentTerritoryCode is invalid you'll get an empty list)
*/
public static function getChildTerritoryCodes($parentTerritoryCode, $expandSubGroups = false)
{
$result = array();
if (is_string($parentTerritoryCode) && preg_match('/^[a-z0-9]{2,3}$/i', $parentTerritoryCode)) {
$parentTerritoryCode = strtoupper($parentTerritoryCode);
$data = Data::getGeneric('territoryContainment');
if (isset($data[$parentTerritoryCode])) {
$children = $data[$parentTerritoryCode]['contains'];
if ($expandSubGroups) {
foreach ($children as $child) {
$grandChildren = static::getChildTerritoryCodes($child, true);
if (empty($grandChildren)) {
$result[] = $child;
} else {
$result = array_merge($result, $grandChildren);
}
}
} else {
$result = $children;
}
}
}
return $result;
}
protected static function getTerritoryInfo($territoryCode)
{
$result = null;
if (preg_match('/^[a-z0-9]{2,3}$/i', $territoryCode)) {
$territoryCode = strtoupper($territoryCode);
$data = Data::getGeneric('territoryInfo');
if (isset($data[$territoryCode])) {
$result = $data[$territoryCode];
}
}
return $result;
}
protected static function getStructure()
{
static $cache = null;
if ($cache === null) {
$data = Data::getGeneric('territoryContainment');
$result = static::fillStructure($data, '001', 0);
$cache = $result;
} else {
$result = $cache;
}
return $result;
}
protected static function fillStructure($data, $id, $level)
{
$item = array('id' => $id, 'level' => $level, 'children' => array());
if (isset($data[$id])) {
foreach ($data[$id]['contains'] as $childID) {
$item['children'][] = static::fillStructure($data, $childID, $level + 1);
}
}
return $item;
}
protected static function finalizeWithNames($data, $list, $flatList)
{
$result = array();
foreach ($list as $item) {
$name = $data[$item['id']];
if ($flatList) {
$result[$item['id']] = $name;
} else {
$result[$item['id']] = array('name' => $name);
if (count($item['children']) > 0) {
$result[$item['id']]['children'] = static::finalizeWithNames($data, $item['children'], $flatList);
}
}
}
return $result;
}
protected static function filterStructure($parent, $levels)
{
$thisResult = array();
if (in_array($parent['level'], $levels, true)) {
$thisResult[0] = $parent;
$thisResult[0]['children'] = array();
$addToSub = true;
} else {
$addToSub = false;
}
$subList = array();
foreach ($parent['children'] as $child) {
$subList = array_merge($subList, static::filterStructure($child, $levels));
}
if ($addToSub) {
$thisResult[0]['children'] = $subList;
} else {
$thisResult = $subList;
}
return $thisResult;
}
protected static function sort($list)
{
foreach (array_keys($list) as $i) {
if (isset($list[$i]['children'])) {
$list[$i]['children'] = static::sort($list[$i]['children']);
}
}
$sorter = new PunicComparer();
uasort($list, function ($a, $b) use ($sorter) {
return $sorter->compare($a['name'], $b['name']);
});
return $list;
}
}