File: D:/HostingSpaces/SBogers10/rentman2019.komma.pro/app/Komma/Globalization/CultureInfo.php
<?php
namespace App\Komma\Globalization;
/**
* Class CultureInfo
*
* Provides information about a specific culture (called a locale for unmanaged code development)
* Based of the C# variant.
*
* @see https://docs.microsoft.com/en-us/dotnet/api/system.globalization.cultureinfo?view=netframework-4.7.2
*/
class CultureInfo extends AbstractCultureParser
{
/** @var CultureInfo[] cached objects */
private static $cache = [];
/** @var string */
private $displayName = '';
/** @var string */
private $englishName = '';
/** @var bool */
private $isNeutralCulture;
/** @var CultureInfo */
private $parent;
/** @var string */
private $nativeName = '';
/** @var string */
private $threeLetterIsoLanguageName = '';
/** @var string */
private $twoLetterIsoLanguageName = '';
/** @var string */
private $name = '';
/** @var array Cultures that are associated with a language but are not specific to a country/region. Example 'NL' */
private static $neutralCultures = [];
/** @var array Cultures that are specific to a country/region. Example nl-BE */
private static $specificCultures = [];
/**
* Provides information about a specific culture (called a locale for unmanaged code development)
*
* The format for the culture name based on RFC 4646 is languagecode2>-country/regioncode2, where languagecode2 is the two-letter
* language code and country/regioncode2 is the two-letter subculture code. Examples include ja-JP for Japanese (Japan)
* and en-US for English (United States). In cases where a two-letter language code is not available,
* a three-letter code derived from ISO 639-2 is used.
*
* Notice that some culture names also specify an ISO 15924 script. For example, Cyrl specifies the Cyrillic script
* and Latn specifies the Latin script. A culture name that includes a script uses the pattern languagecode2-scripttag-country/regioncode2.
* An example of this type of culture name is uz-Cyrl-UZ for Uzbek (Cyrillic, Uzbekistan).
*
* A neutral culture is specified by only the two-letter lowercase language code. For example, fr specifies the neutral culture for French, and de specifies the neutral culture for German.
*
* CultureInfo constructor.
* @param string $name
*/
public function __construct(string $name)
{
if (in_array('name', array_keys(self::$cache), true)) {
return self::$cache['name'];
} //Return the culture if it was initiated before
parent::__construct($name);
$this->englishName = Culture::DATA[$this->cultureId]['EnglishName'] ?? '';
$this->name = $this->currentName;
$this->twoLetterIsoLanguageName = Culture::DATA[$this->cultureId]['ISO-639-1'] ?? '';
$this->threeLetterIsoLanguageName = Culture::DATA[$this->cultureId]['ISO-639-2'] ?? Culture::DATA[$this->cultureId]['ISO-639-3'] ?? '';
$this->determineIfNeutralCulture();
$this->determineParentCulture();
$this->determineDisplayName();
$this->determineNativeName();
}
/**
* Parses a culture name into an array that contains the language code, scripttag if needed, and country or region code 2.
*
* @param string $name
*/
protected function parseName(string $name)
{
if ($name !== '') {
$explodedCultureName = explode('-', $name);
$count = count($explodedCultureName);
if ($count == 3) {
$this->languageCode2 = strtolower($explodedCultureName[0]);
$this->scriptTagCountry = strtolower($explodedCultureName[1]);
$this->countryOrRegionCode2 = strtolower($explodedCultureName[2]);
} elseif ($count == 2) {
$this->languageCode2 = strtolower($explodedCultureName[0]);
$this->countryOrRegionCode2 = strtolower($explodedCultureName[1]);
} elseif ($count == 1) { //Neutral culture ()
$this->languageCode2 = strtolower($explodedCultureName[0]);
}
} else {
//Invariant culture that should default to english. Processed in the setId method
}
}
/**
* Determines the display name
*/
private function determineDisplayName()
{
$displayName = Culture::DATA[$this->cultureId]['DisplayName'];
if ($this->countryOrRegionCode2 && $this->countryOrRegionCode2 !== '') {
$regionInfo = new RegionInfo($this->countryOrRegionCode2);
$displayName .= ' ('.$regionInfo->getDisplayName().')';
}
$this->displayName = $displayName;
}
/**
* Determines the display name
*/
private function determineNativeName()
{
$nativeName = Culture::DATA[$this->cultureId]['NativeName'];
if ($this->countryOrRegionCode2 && $this->countryOrRegionCode2 !== '') {
$regionInfo = new RegionInfo($this->countryOrRegionCode2);
$nativeName .= ' ('.$regionInfo->getNativeName().')';
}
$this->nativeName = $nativeName;
}
/**
* Looks up any combination of languageCode2, scriptTagCountry and countryOrRegionCode2 in the data in
* AbstractCultureData and stores the ID
*/
protected function setId()
{
foreach (Culture::DATA as $cultureId => $cultureData) {
if (isset($cultureData['ISO-639-1'])) {
if ($this->languageCode2 == '' && $this->scriptTagCountry == '' && $this->countryOrRegionCode2) {
//Invariant culture. An invariant culture is culture-insensitive.
//Your application specifies the invariant culture by name using an empty string ("") or by its identifier.
//It is associated with the English language but not with any country/region. To make improve this function we should return an instance of a
//yet still non existing culture instance called InvariantCulture.
if ($cultureData['ISO-639-1'] == 'en') {
$this->cultureId = $cultureId;
}
} elseif (strtoupper($cultureData['ISO-639-1']) == strtoupper($this->languageCode2)) {
$this->cultureId = $cultureId;
}
}
}
}
/**
* Parses the neutral cultures. e.g. Cultures not associated to a country, but with a language. For example with name 'nl';
*/
private static function parseNeutralCultures()
{
if (empty(self::$neutralCultures)) {
foreach (Culture::DATA as $cultureId => $cultureData) {
self::$neutralCultures[] = new self(strtolower($cultureData['ISO-639-1']));
}
}
}
/**
* Parses specific cultures. e.g. Cultures both associated with to a country and language. For example with name 'nl-BE'
*/
private static function parseSpecificCultures()
{
if (empty(self::$specificCultures)) {
foreach (Culture::DATA as $cultureId => $cultureData) {
$languageCode = $cultureData['ISO-639-1'];
foreach ($cultureData['country/regions'] as $countryRegionId => $countryRegion) {
$countryRegionCode = strtolower($countryRegion['TwoLetterISORegionName']);
self::$specificCultures[] = new self($languageCode.'-'.strtoupper($countryRegionCode));
}
}
}
}
/**
* A neutral culture is a culture that is associated with a language but not with a country/region.
* A specific culture is a culture that is associated with a language and a country/region. For example,
* fr is the neutral name for the French culture, and fr-FR is the name of the specific French (France) culture.
*/
private function determineIfNeutralCulture()
{
$this->isNeutralCulture = ($this->languageCode2 !== '' && $this->countryOrRegionCode2 == '' && $this->scriptTagCountry == '');
}
/**
* Set the CultureInfo that represents the parent culture of the current CultureInfo.
*/
private function determineParentCulture()
{
if (strtolower($this->currentName) != strtolower($this->languageCode2)) {
$this->parent = new self($this->languageCode2);
}
}
/**
* @return string
*/
public function getDisplayName(): string
{
return $this->displayName;
}
/**
* @return string
*/
public function getEnglishName(): string
{
return $this->englishName;
}
/**
* A neutral culture is a culture that is associated with a language but not with a country/region.
* A specific culture is a culture that is associated with a language and a country/region. For example,
* fr is the neutral name for the French culture, and fr-FR is the name of the specific French (France) culture.
*
* @return bool
*/
public function isNeutralCulture(): bool
{
return $this->isNeutralCulture;
}
/**
* @return CultureInfo
*/
public function getParent(): ? self
{
return $this->parent;
}
/**
* @return string
*/
public function getNativeName(): string
{
return $this->nativeName;
}
/**
* @return string
*/
public function getThreeLetterIsoLanguageName(): string
{
return $this->threeLetterIsoLanguageName;
}
/**
* @return string
*/
public function getTwoLetterIsoLanguageName(): string
{
return $this->twoLetterIsoLanguageName;
}
/**
* @return string
*/
public function getName(): string
{
return $this->name;
}
/**
* @param int $type a CultureType value
* @return CultureInfo[]
*/
public static function getCultures(int $type): array
{
self::parseNeutralCultures();
self::parseSpecificCultures();
//Determine what to return
switch ($type) {
case CultureTypes::ALL_CULTURES:
return array_merge(self::$neutralCultures, self::$specificCultures);
case CultureTypes::NEUTRAL_CULTURES:
return self::$neutralCultures;
case CultureTypes::SPECIFIC_CULTURES:
return self::$specificCultures;
}
}
}