JEMBOT MAWOT Bypass Shell

Current Path : /home/cinepatreb/billetterie/src/Core/Localization/CLDR/
Upload File :
Current File : /home/cinepatreb/billetterie/src/Core/Localization/CLDR/Reader.php

<?php

/**
 * Copyright since 2007 PrestaShop SA and Contributors
 * PrestaShop is an International Registered Trademark & Property of PrestaShop SA
 *
 * NOTICE OF LICENSE
 *
 * This source file is subject to the Open Software License (OSL 3.0)
 * that is bundled with this package in the file LICENSE.md.
 * It is also available through the world-wide-web at this URL:
 * https://opensource.org/licenses/OSL-3.0
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@prestashop.com so we can send you a copy immediately.
 *
 * DISCLAIMER
 *
 * Do not edit or add to this file if you wish to upgrade PrestaShop to newer
 * versions in the future. If you wish to customize PrestaShop for your
 * needs please refer to https://devdocs.prestashop.com/ for more information.
 *
 * @author    PrestaShop SA and Contributors <contact@prestashop.com>
 * @copyright Since 2007 PrestaShop SA and Contributors
 * @license   https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
 */

namespace PrestaShop\PrestaShop\Core\Localization\CLDR;

use PrestaShop\PrestaShop\Core\Localization\Exception\LocalizationException;
use PrestaShop\PrestaShop\Core\Localization\Exception\LocalizationFileNotFoundException;
use SimpleXMLElement;

/**
 * CLDR files reader class.
 *
 * This class provides CLDR LocaleData objects built with data coming from official CLDR xml data files.
 */
class Reader implements ReaderInterface
{
    public const CLDR_ROOT = 'localization/CLDR/';
    public const CLDR_MAIN = 'localization/CLDR/core/common/main/';
    public const CLDR_SUPPLEMENTAL = 'localization/CLDR/core/common/supplemental/';

    public const CLDR_ROOT_LOCALE = 'root';

    public const SUPPL_DATA_CURRENCY = 'currencyData';
    public const SUPPL_DATA_LANGUAGE = 'languageData';
    public const SUPPL_DATA_NUMBERING = 'numberingSystems';
    public const SUPPL_DATA_PARENT_LOCALES = 'parentLocales'; // For specific locales hierarchy

    public const DEFAULT_CURRENCY_DIGITS = 2;

    public const CURRENCY_CODE_TEST = 'XTS';

    /**
     * delay after currency deactivation to prevent currency add by list
     */
    public const CURRENCY_ACTIVE_DELAY = 365;

    protected $mainXml = [];

    /**
     * Supplemental data for all locales.
     * Contains data about parent locales, currencies, languages...
     *
     * @var SimpleXMLElement|null
     */
    protected $supplementalXml;

    /**
     * Additional data about numbering systems
     * Mainly used for digits (they depend on numbering system).
     *
     * @var SimpleXMLElement|null
     */
    protected $numberingSystemsXml;

    /**
     * Read locale data by locale code.
     *
     * @param string $localeCode The locale code (simplified IETF tag syntax)
     *                           Combination of ISO 639-1 (2-letters language code) and ISO 3166-2 (2-letters region code)
     *                           eg: fr-FR, en-US
     *                           The underscore notation is also accepted (fr_FR, en_US...)
     *
     * @return LocaleData A LocaleData object
     *
     * @throws LocalizationException When the locale code is unknown or invalid
     */
    public function readLocaleData($localeCode)
    {
        // CLDR filenames use a different notation from IETF.
        $localeCode = str_replace('-', '_', $localeCode);

        $this->validateLocaleCodeForFilenames($localeCode);
        $this->initSupplementalData();

        $finalData = new LocaleData();
        $lookup = $this->getLookup($localeCode);
        foreach ($lookup as $thisLocaleCode) {
            try {
                $partialData = $this->getLocaleData($thisLocaleCode);
                $finalData = $finalData->overrideWith($partialData);
            } catch (LocalizationFileNotFoundException $e) {
                // Sometimes a file can be missing.
                // Example for Chinese : zh_CN.xml doesn't exist. There is only a zh.xml file.
                // That's why we can't let this exception bubble up.
                continue;
            }
        }

        return $finalData;
    }

    /**
     * Validate a locale code.
     *
     * If the passed code doesn't respect the CLDR files naming style, an exception will be raised
     * e.g.: "fr_FR" and "en_001" are valid
     *
     * @param string $localeCode Locale code to be validated
     *
     * @throws LocalizationException When locale code is invalid
     */
    protected function validateLocaleCodeForFilenames($localeCode)
    {
        if (!preg_match('#^[a-zA-Z0-9]+(_[a-zA-Z0-9]+)*$#', $localeCode)) {
            throw new LocalizationException(sprintf('Invalid locale code: "%s"', $localeCode));
        }
    }

    /**
     * Initialize supplemental CLDR data.
     */
    protected function initSupplementalData()
    {
        // Supplemental data about currencies, languages and parent locales
        if (!isset($this->supplementalXml)) {
            $supplementalPath = realpath(
                _PS_ROOT_DIR_ . '/'
                . self::CLDR_SUPPLEMENTAL
                . 'supplementalData.xml'
            );
            $this->supplementalXml = simplexml_load_file($supplementalPath);
        }

        // This file contains special digits for non-occidental numbering systems
        if (!isset($this->numberingSystemsXml)) {
            $numberingSystemsPath = realpath(
                _PS_ROOT_DIR_ . '/'
                . self::CLDR_SUPPLEMENTAL
                . 'numberingSystems.xml'
            );
            $this->numberingSystemsXml = simplexml_load_file($numberingSystemsPath);
        }
    }

    /**
     * Build lookup files stack for a given locale code.
     *
     * @param string $localeCode The given locale code (simplified IETF notation)
     *
     * @return array The lookup ['root', <intermediate codes>, $localeCode]
     *
     * @throws LocalizationException When locale code is invalid or unknown
     *
     * @see http://www.unicode.org/reports/tr35/tr35.html#Lookup
     */
    protected function getLookup($localeCode)
    {
        $lookup = [$localeCode];

        while ($localeCode = $this->getParentLocale($localeCode)) {
            array_unshift($lookup, $localeCode);
        }

        return $lookup;
    }

    /**
     * Get the parent locale for a given locale code.
     *
     * @param string $localeCode CLDR filenames' style locale code (with underscores) eg.: en, fr, en_GB, fr_FR...
     *
     * @return string|null The parent locale code (CLDR filenames' style). Null if no parent.
     *
     * @throws LocalizationException
     */
    protected function getParentLocale($localeCode)
    {
        // root is the... root of all CLDR locales' data. Then no parent.
        if (self::CLDR_ROOT_LOCALE == $localeCode) {
            return null;
        }

        // The special case from supplemental data
        foreach ($this->supplementalXml->parentLocales->parentLocale as $data) {
            $locales = explode(' ', $data['locales']);
            if (in_array($localeCode, $locales)) {
                return $data['parent'];
            }
        }

        // The common case with truncation
        $pos = strrpos($localeCode, '_');
        if (false !== $pos) {
            return substr($localeCode, 0, $pos);
        }

        // The "top level" case. When only language code is left in $localeCode: 'en', 'fr'... then parent is "root".
        return self::CLDR_ROOT_LOCALE;
    }

    /**
     * Get CLDR official xml data for a given locale tag.
     *
     * The locale tag can be either an IETF tag (en-GB) or a simple language code (en)
     *
     * @param string $localeCode The locale code
     *
     * @return SimpleXMLElement The locale data
     *
     * @throws LocalizationFileNotFoundException If this locale code has no corresponding xml file
     */
    protected function getMainXmlData($localeCode)
    {
        return simplexml_load_file($this->mainPath($localeCode . '.xml'));
    }

    /**
     * Get the real path for CLDR main data folder
     * If a filename is provided, it will be added at the end of the path.
     *
     * @param string $filename (Optional) The filename to be added to the path
     *
     * @return string The realpath of CLDR main data folder
     *
     * @throws LocalizationFileNotFoundException
     */
    protected function mainPath($filename = '')
    {
        $path = realpath(_PS_ROOT_DIR_ . '/' . self::CLDR_MAIN . ($filename ? $filename : ''));
        if (false === $path) {
            throw new LocalizationFileNotFoundException("The file $filename does not exist");
        }

        return $path;
    }

    /**
     * Extracts locale data from CLDR xml data.
     * XML data will be mapped in a LocaleData object.
     *
     * @param string $localeTag The wanted locale. Can be either a language code (e.g.: fr) of an IETF tag (e.g.: en-US)
     *
     * @return LocaleData
     */
    protected function getLocaleData($localeTag)
    {
        $xmlData = $this->getMainXmlData($localeTag);

        $supplementalData = ['digits' => $this->getDigitsData()];

        return $this->mapLocaleData($xmlData, $supplementalData);
    }

    /**
     * Maps locale data from SimplexmlElement to a LocaleData object.
     *
     * @param SimplexmlElement $xmlLocaleData
     *                                        XML locale data
     * @param array $supplementalData
     *                                Supplemental locale data
     *
     * @return LocaleData
     *                    The mapped locale data
     *
     * @todo use $supplementalData for non-occidental digits
     *
     * @see  http://cldr.unicode.org/development/development-process/design-proposals/resolution-of-cldr-files
     */
    protected function mapLocaleData(SimpleXMLElement $xmlLocaleData, $supplementalData)
    {
        $localeData = new LocaleData();

        // Geo
        if (isset($xmlLocaleData->identity->language)) {
            $localeData->setLocaleCode((string) $xmlLocaleData->identity->language['type']);
        }
        if (isset($xmlLocaleData->identity->territory)) {
            $localeData->setLocaleCode(
                $localeData->getLocaleCode() . '-' . $xmlLocaleData->identity->territory['type']
            );
        }

        // Numbers
        $numbersData = $xmlLocaleData->numbers;
        // Default numbering system.
        if (isset($numbersData->defaultNumberingSystem)) {
            $localeData->setDefaultNumberingSystem((string) $numbersData->defaultNumberingSystem);
        }
        // Minimum grouping digits value defines when we should start grouping digits.
        // 1 => we start grouping at 4 figures numbers (1,000+) (most frequent)
        // 2 => we start grouping at 5 figures numbers (10,000+)
        if (isset($numbersData->minimumGroupingDigits)) {
            $localeData->setMinimumGroupingDigits((int) $numbersData->minimumGroupingDigits);
        }
        // Complete numbering systems list with the "others" available for this locale.
        // Possible other systems are "native", "traditional" and "finance".
        // @see http://www.unicode.org/reports/tr35/tr35-numbers.html#otherNumberingSystems
        if (isset($numbersData->otherNumberingSystems)) {
            $numberingSystems = [];
            foreach ($numbersData->otherNumberingSystems->children() as $system) {
                /* @var $system SimplexmlElement */
                $numberingSystems[$system->getName()] = (string) $system;
            }
            $localeData->setNumberingSystems($numberingSystems);
        }
        // Symbols (by numbering system)
        if (isset($numbersData->symbols)) {
            $numberSymbols = $localeData->getNumberSymbols();
            /** @var SimpleXMLElement $symbolsNode */
            foreach ($numbersData->symbols as $symbolsNode) {
                if (!isset($symbolsNode['numberSystem'])) {
                    continue;
                }
                $thisNumberingSystem = (string) $symbolsNode['numberSystem'];

                // Copying data from another node when relevant (alias)
                if (isset($symbolsNode->alias)) {
                    // @see <project root>/localization/CLDR/core/common/main/root.xml
                    $results = $symbolsNode->xpath($symbolsNode->alias['path']);
                    if (empty($results)) {
                        continue;
                    }
                    $symbolsNode = $results[0];
                }

                $symbolsList = new NumberSymbolsData();
                if (isset($symbolsNode->decimal)) {
                    $symbolsList->setDecimal((string) $symbolsNode->decimal);
                }
                if (isset($symbolsNode->group)) {
                    $symbolsList->setGroup((string) $symbolsNode->group);
                }
                if (isset($symbolsNode->list)) {
                    $symbolsList->setList((string) $symbolsNode->list);
                }
                if (isset($symbolsNode->percentSign)) {
                    $symbolsList->setPercentSign((string) $symbolsNode->percentSign);
                }
                if (isset($symbolsNode->minusSign)) {
                    $symbolsList->setMinusSign((string) $symbolsNode->minusSign);
                }
                if (isset($symbolsNode->plusSign)) {
                    $symbolsList->setPlusSign((string) $symbolsNode->plusSign);
                }
                if (isset($symbolsNode->exponential)) {
                    $symbolsList->setExponential((string) $symbolsNode->exponential);
                }
                if (isset($symbolsNode->superscriptingExponent)) {
                    $symbolsList->setSuperscriptingExponent((string) $symbolsNode->superscriptingExponent);
                }
                if (isset($symbolsNode->perMille)) {
                    $symbolsList->setPerMille((string) $symbolsNode->perMille);
                }
                if (isset($symbolsNode->infinity)) {
                    $symbolsList->setInfinity((string) $symbolsNode->infinity);
                }
                if (isset($symbolsNode->nan)) {
                    $symbolsList->setNan((string) $symbolsNode->nan);
                }
                if (isset($symbolsNode->timeSeparator)) {
                    $symbolsList->setTimeSeparator((string) $symbolsNode->timeSeparator);
                }
                if (isset($symbolsNode->currencyDecimal)) {
                    $symbolsList->setCurrencyDecimal((string) $symbolsNode->currencyDecimal);
                }
                if (isset($symbolsNode->currencyGroup)) {
                    $symbolsList->setCurrencyGroup((string) $symbolsNode->currencyGroup);
                }

                $numberSymbols[$thisNumberingSystem] = $symbolsList;
            }
            $localeData->setNumberSymbols($numberSymbols);
        }
        // Decimal patterns (by numbering system)
        if (isset($numbersData->decimalFormats)) {
            $decimalPatterns = $localeData->getDecimalPatterns();
            /** @var SimplexmlElement $format */
            foreach ($numbersData->decimalFormats as $format) {
                /** @var SimplexmlElement $format */
                $numberSystem = (string) $format['numberSystem'];
                $patternResult = $format->xpath('decimalFormatLength[not(@type)]/decimalFormat/pattern');
                if (isset($patternResult[0])) {
                    $decimalPatterns[$numberSystem] = (string) $patternResult[0];
                }
            }
            // Aliases nodes are in root.xml only. They avoid duplicated data.
            // We browse aliases after all regular patterns have been defined, and duplicate data for target number
            // systems.
            foreach ($numbersData->decimalFormats as $format) {
                /** @var SimplexmlElement $format */
                $numberSystem = (string) $format['numberSystem'];
                // If alias is set, we just copy data from another numbering system:
                $alias = $format->alias;
                if (isset($alias['path']) && preg_match(
                        "#^\.\.\/decimalFormats\[@numberSystem='([^)]+)'\]$#",
                        (string) $alias['path'],
                        $matches
                    )
                ) {
                    $aliasNumSys = $matches[1];
                    $decimalPatterns[$numberSystem] = $decimalPatterns[$aliasNumSys];

                    continue;
                }
            }
            $localeData->setDecimalPatterns($decimalPatterns);
        }
        // Percent patterns (by numbering system)
        if (isset($numbersData->percentFormats)) {
            $percentPatterns = $localeData->getPercentPatterns();
            foreach ($numbersData->percentFormats as $format) {
                $numberSystem = (string) $format['numberSystem'];
                $patternResult = $format->xpath('percentFormatLength/percentFormat/pattern');
                if (isset($patternResult[0])) {
                    $percentPatterns[$numberSystem] = (string) $patternResult[0];
                }
            }
            // Aliases nodes are in root.xml only. They avoid duplicated data.
            // We browse aliases after all regular patterns have been defined, and duplicate data for target number
            // systems.
            foreach ($numbersData->percentFormats as $format) {
                /** @var SimplexmlElement $format */
                $numberSystem = (string) $format['numberSystem'];
                // If alias is set, we just copy data from another numbering system:
                $alias = $format->alias;
                if (isset($alias['path']) && preg_match(
                        "#^\.\.\/percentFormats\[@numberSystem='([^)]+)'\]$#",
                        (string) $alias['path'],
                        $matches
                    )
                ) {
                    $aliasNumSys = $matches[1];
                    $percentPatterns[$numberSystem] = $percentPatterns[$aliasNumSys];

                    continue;
                }
            }
            $localeData->setPercentPatterns($percentPatterns);
        }
        // Currency patterns (by numbering system)
        if (isset($numbersData->currencyFormats)) {
            $currencyPatterns = $localeData->getCurrencyPatterns();
            foreach ($numbersData->currencyFormats as $format) {
                /** @var SimplexmlElement $format */
                $numberSystem = (string) $format['numberSystem'];
                $patternResult = $format->xpath(
                    'currencyFormatLength[not(@*)]/currencyFormat[@type="standard"]/pattern'
                );
                if (isset($patternResult[0])) {
                    $currencyPatterns[$numberSystem] = (string) $patternResult[0];
                }
            }
            // Aliases nodes are in root.xml only. They avoid duplicated data.
            // We browse aliases after all regular patterns have been defined, and duplicate data for target number
            // systems.
            foreach ($numbersData->currencyFormats as $format) {
                /** @var SimplexmlElement $format */
                $numberSystem = (string) $format['numberSystem'];
                // If alias is set, we just copy data from another numbering system:
                $alias = $format->alias;
                if (isset($alias['path']) && preg_match(
                        "#^\.\.\/currencyFormats\[@numberSystem='([^)]+)'\]$#",
                        (string) $alias['path'],
                        $matches
                    )
                ) {
                    $aliasNumSys = $matches[1];
                    $currencyPatterns[$numberSystem] = $currencyPatterns[$aliasNumSys];

                    continue;
                }
            }
            $localeData->setCurrencyPatterns($currencyPatterns);
        }

        // Currencies
        $currenciesData = $numbersData->currencies;
        $currencyActiveDateThreshold = time() - self::CURRENCY_ACTIVE_DELAY * 86400;
        if (isset($currenciesData->currency)) {
            $currencies = $localeData->getCurrencies();
            foreach ($currenciesData->currency as $currencyNode) {
                $currencyCode = (string) $currencyNode['type'];
                if ($currencyCode == self::CURRENCY_CODE_TEST) {
                    // dont store test currency
                    continue;
                }

                $currencyData = new CurrencyData();
                $currencyData->setIsoCode($currencyCode);

                // check if currency is still active in one territory
                $currencyDates = $this->supplementalXml->currencyData->xpath('//region/currency[@iso4217="' . $currencyCode . '"]');
                if (!empty($currencyDates) && $this->isCurrencyActiveSomewhere($currencyDates, $currencyActiveDateThreshold)) {
                    $currencyData->setActive(true);
                } else {
                    // no territory with dates means currency was never used
                    $currencyData->setActive(false);
                }

                // Symbols
                $symbols = $currencyData->getSymbols();
                foreach ($currencyNode->symbol as $symbolNode) {
                    $type = (string) $symbolNode['alt'];
                    if (empty($type)) {
                        $type = 'default';
                    }
                    $symbols[$type] = (string) $symbolNode;
                }
                $currencyData->setSymbols($symbols);

                // Names
                $displayNames = $currencyData->getDisplayNames();
                foreach ($currencyNode->displayName as $nameNode) {
                    $countContext = 'default';
                    if (!empty($nameNode['count'])) {
                        $countContext = (string) $nameNode['count'];
                    }
                    $displayNames[$countContext] = (string) $nameNode;
                }
                $currencyData->setDisplayNames($displayNames);

                // Supplemental (fraction digits and numeric iso code)
                $codesMapping = $this->supplementalXml->xpath(
                    '//codeMappings/currencyCodes[@type="' . $currencyCode . '"]'
                );

                if (!empty($codesMapping)) {
                    /** @var SimplexmlElement $codesMapping */
                    $codesMapping = $codesMapping[0];
                    $numericIsoCode = (string) $codesMapping->attributes()->numeric;
                    if (strlen($numericIsoCode) < 3) {
                        $numericIsoCode = str_pad($numericIsoCode, 3, '0', STR_PAD_LEFT);
                    }
                    $currencyData->setNumericIsoCode($numericIsoCode);
                }

                $fractionsData = $this->supplementalXml->xpath(
                    '//currencyData/fractions/info[@iso4217="' . $currencyCode . '"]'
                );

                if (empty($fractionsData)) {
                    $fractionsData = $this->supplementalXml->xpath(
                        '//currencyData/fractions/info[@iso4217="DEFAULT"]'
                    );
                }

                if (!empty($fractionsData)) {
                    /** @var SimplexmlElement $fractionsData */
                    $fractionsData = $fractionsData[0];
                    $currencyData->setDecimalDigits((int) (string) $fractionsData->attributes()->digits);
                }

                $currencies[$currencyCode] = $currencyData;
            }
            $localeData->setCurrencies($currencies);
        }

        return $localeData;
    }

    /**
     * Extract all existing digits sets from supplemental xml data.
     *
     * @return array
     *               eg.:
     *               [
     *               'latn'     => '0123456789',
     *               'arab'     => '٠١٢٣٤٥٦٧٨٩',
     *               'fullwide' => '0123456789',
     *               ]
     */
    protected function getDigitsData()
    {
        $digitsSets = [];
        $results = $this->numberingSystemsXml->numberingSystems->xpath('//numberingSystem[@type="numeric"]');
        foreach ($results as $numberingSystem) {
            $systemId = (string) $numberingSystem['id'];
            $digits = (string) $numberingSystem['digits'];
            $digitsSets[$systemId] = $digits;
        }

        return $digitsSets;
    }

    /**
     * @param string $currencyCode currency iso code
     * @param SimpleXMLElement $supplementalData xml bloc from CLDR
     * @param int $currencyActiveDateThreshold timestamp after which currency should be used
     *
     * @return bool
     */
    protected function shouldCurrencyBeReturned($currencyCode, SimplexmlElement $supplementalData, $currencyActiveDateThreshold)
    {
        // dont store test currency
        if ($currencyCode == self::CURRENCY_CODE_TEST) {
            return false;
        }
        // check if currency is still active in one territory
        $currencyDates = $supplementalData->xpath('//region/currency[@iso4217="' . $currencyCode . '"]');
        if (empty($currencyDates)) {
            // no territory with dates means currency was never used
            return false;
        }

        return $this->isCurrencyActiveSomewhere($currencyDates, $currencyActiveDateThreshold);
    }

    /**
     * check if currency is still in use in some territory
     *
     * @param array $currencyDates
     * @param int $currencyActiveDateThreshold timestamp after which currency should be used
     *
     * @return bool
     */
    protected function isCurrencyActiveSomewhere(array $currencyDates, $currencyActiveDateThreshold)
    {
        foreach ($currencyDates as $currencyDate) {
            if (empty($currencyDate->attributes()->to)) {
                // no date "to": currency is active in some territory
                return true;
            }

            // date "to" given: check if currency was active in near past to propose it
            $dateTo = \DateTime::createFromFormat('Y-m-d', $currencyDate->attributes()->to);
            if (false !== $dateTo && $dateTo->getTimestamp() > $currencyActiveDateThreshold) {
                return true;
            }
        }

        return false;
    }
}

xxxxx1.0, XXX xxxx