Skip to content
Code-Schnipsel Gruppen Projekte
Handler.php 15,2 KiB
Newer Older
  • Learn to ignore specific revisions
  • <?php
    
    namespace QUI\ERP\Currency;
    
    
    use function class_exists;
    
    use function is_a;
    use function is_array;
    
    Patrick Müller's avatar
    Patrick Müller committed
    use function is_string;
    use function json_decode;
    use function json_encode;
    use function mb_strtolower;
    
    use function mb_substr;
    
    /**
     * Currency class
     * Conversion and currency sign
     *
     * @author  www.pcsg.de (Henning Leutz)
     * @package quiqqer/currency
     */
    class Handler
    {
    
    Patrick Müller's avatar
    Patrick Müller committed
        /**
         * Currency types.
         */
        const CURRENCY_TYPE_DEFAULT = 'default';
    
    
        /**
         * currency temp list
         *
         * @var array
         */
    
        protected static array $currencies = [];
    
    Henning Leutz's avatar
    Henning Leutz committed
        /**
    
    Henning Leutz's avatar
    Henning Leutz committed
         */
    
        protected static ?Currency $Default = null;
    
        /**
         * Return the real table name
         *
         * @return string
         */
    
        public static function table(): string
    
        {
            return QUI::getDBTableName('currency');
        }
    
    
    Henning Leutz's avatar
    Henning Leutz committed
         * Create a new currency
         *
    
         * @param string $currency - currency code
    
    Henning Leutz's avatar
    Henning Leutz committed
         * @param integer|float $rate - currency exchange rate, default = 1
    
    Patrick Müller's avatar
    Patrick Müller committed
         * @param string $type (optional) - Currency type
    
         * @throws QUI\Exception
         */
    
    Patrick Müller's avatar
    Patrick Müller committed
        public static function createCurrency(string $currency, $rate = 1, string $type = self::CURRENCY_TYPE_DEFAULT)
    
            QUI\Permissions\Permission::checkPermission('currency.create');
    
    Henning Leutz's avatar
    Henning Leutz committed
            $Currency = null;
    
            try {
                $Currency = self::getCurrency($currency);
            } catch (QUI\Exception $Exception) {
            }
    
            if (!is_null($Currency)) {
    
    Henning Leutz's avatar
    Henning Leutz committed
                throw new QUI\Exception([
    
    Henning Leutz's avatar
    Henning Leutz committed
                    'quiqqer/currency',
                    'exception.already.exists',
    
    Henning Leutz's avatar
    Henning Leutz committed
                    ['currency' => $currency]
                ]);
    
    Henning Leutz's avatar
    Henning Leutz committed
            }
    
            if (!is_numeric($rate)) {
    
    Henning Leutz's avatar
    Henning Leutz committed
                throw new QUI\Exception([
    
    Henning Leutz's avatar
    Henning Leutz committed
                    'quiqqer/currency',
                    'exception.currency.rate.wrong.format'
    
    Henning Leutz's avatar
    Henning Leutz committed
                ]);
    
    Henning Leutz's avatar
    Henning Leutz committed
            }
    
    Henning Leutz's avatar
    Henning Leutz committed
            QUI::getDataBase()->insert(self::table(), [
    
    Henning Leutz's avatar
    Henning Leutz committed
                'currency' => $currency,
    
                'rate' => (float)$rate,
                'type' => self::existsCurrencyType($type) ? $type : self::CURRENCY_TYPE_DEFAULT
    
    Henning Leutz's avatar
    Henning Leutz committed
            ]);
    
    Henning Leutz's avatar
    Henning Leutz committed
    
            // create translations
    
    Henning Leutz's avatar
    Henning Leutz committed
            $languageData = [
    
    Henning Leutz's avatar
    Henning Leutz committed
                'datatype' => 'js,php'
    
    Henning Leutz's avatar
    Henning Leutz committed
            ];
    
    Henning Leutz's avatar
    Henning Leutz committed
    
    
    Henning Leutz's avatar
    Henning Leutz committed
            $localeGroup = 'quiqqer/currency';
    
            $localeText = 'currency.' . $currency . '.text';
            $localeSign = 'currency.' . $currency . '.sign';
    
    Henning Leutz's avatar
    Henning Leutz committed
            $textData = QUI\Translator::getVarData($localeGroup, $localeText);
            $signData = QUI\Translator::getVarData($localeGroup, $localeSign);
    
    
            foreach (QUI::availableLanguages() as $language) {
                if (!isset($textData[$language])) {
                    $textData[$language] = $currency;
                }
    
                if (!isset($signData[$language])) {
                    $signData[$language] = mb_substr($currency, 0, 1);
                }
            }
    
    
    
            // text
            try {
                QUI\Translator::add(
                    'quiqqer/currency',
                    'currency.' . $currency . '.text',
                    'quiqqer/currency'
                );
            } catch (QUI\Exception $e) {
            }
    
    
            if (!empty($textData)) {
    
                QUI\Translator::edit(
    
    Henning Leutz's avatar
    Henning Leutz committed
                    'quiqqer/currency',
    
                    'currency.' . $currency . '.text',
    
                    'quiqqer/currency',
    
    Henning Leutz's avatar
    Henning Leutz committed
                );
            }
    
    
            // sign
            try {
                QUI\Translator::add(
                    'quiqqer/currency',
                    'currency.' . $currency . '.sign',
                    'quiqqer/currency'
                );
            } catch (QUI\Exception $e) {
            }
    
    
    
            if (!empty($signData)) {
    
                QUI\Translator::edit(
    
    Henning Leutz's avatar
    Henning Leutz committed
                    'quiqqer/currency',
    
                    'currency.' . $currency . '.sign',
    
                    'quiqqer/currency',
                    $signData
    
    Henning Leutz's avatar
    Henning Leutz committed
                );
            }
    
    
            QUI\Translator::publish('quiqqer/currency');
    
        /**
         * Delete a currency
         *
         * @param string $currency - currency code
         * @throws QUI\Exception
         */
    
        public static function deleteCurrency(string $currency)
    
            QUI\Permissions\Permission::checkPermission('currency.delete');
    
    Henning Leutz's avatar
    Henning Leutz committed
            QUI::getDataBase()->delete(self::table(), [
    
                'currency' => $currency
    
    Henning Leutz's avatar
    Henning Leutz committed
            ]);
    
    
            QUI\Translator::delete(
                'quiqqer/currency',
                'currency.' . $currency . '.text'
            );
    
            QUI\Translator::delete(
                'quiqqer/currency',
                'currency.' . $currency . '.sign'
            );
    
            QUI\Translator::publish('quiqqer/currency');
    
        /**
         * Return the default currency
         *
         * @return Currency
    
        public static function getDefaultCurrency(): ?Currency
    
            if (self::$Default === null) {
    
    Henning Leutz's avatar
    Henning Leutz committed
                try {
                    $Config = QUI::getPackage('quiqqer/currency')->getConfig();
    
    Henning Leutz's avatar
    Henning Leutz committed
                    self::$Default = self::getCurrency(
                        $Config->getValue('currency', 'defaultCurrency')
                    );
                } catch (QUI\Exception $Exception) {
    
                    QUI\System\Log::addError('Default currency is missing');
    
    Henning Leutz's avatar
    Henning Leutz committed
    
    
                    try {
                        self::$Default = self::getCurrency('EUR');
                    } catch (QUI\Exception $Exception) {
                        if ($Exception->getCode() === 404) {
                            // add EUR
    
                            self::createCurrency('EUR');
    
                            self::$Default = self::getCurrency('EUR');
                        }
                    }
    
    Henning Leutz's avatar
    Henning Leutz committed
                }
    
    Henning Leutz's avatar
    Henning Leutz committed
            }
    
            return self::$Default;
        }
    
    
        /**
         * Return the currency of the user
         * - This currency can be switched, so the user can get the prices in its currency
         *
         * @param null|QUI\Interfaces\Users\User $User - optional
         * @return Currency|null
         */
    
        public static function getUserCurrency(QUI\Interfaces\Users\User $User = null): ?Currency
    
        {
            if ($User === null) {
                $User = QUI::getUserBySession();
            }
    
            if (!$User->getAttribute('quiqqer.erp.currency')) {
    
                $Currency = self::getUserCurrencyByCountry($User);
    
                if ($Currency) {
                    return $Currency;
                }
    
    
                return self::getCurrency(
                    $User->getAttribute('quiqqer.erp.currency')
                );
            } catch (Exception $Exception) {
    
                QUI\System\Log::writeDebugException($Exception);
            }
    
    
            $Currency = self::getUserCurrencyByCountry($User);
    
            if ($Currency) {
                return $Currency;
            }
    
            return null;
        }
    
        /**
         * Return the currency of the user by its country
         *
         * @param null $User
         * @return Currency|null
         */
    
        public static function getUserCurrencyByCountry($User = null): ?Currency
    
        {
            if ($User === null) {
                $User = QUI::getUserBySession();
            }
    
            try {
    
                $Config = QUI::getPackage('quiqqer/currency')->getConfig();
    
                $allowed = $Config->getValue('currency', 'allowedCurrencies');
                $allowed = explode(',', trim($allowed));
                $allowed = array_flip($allowed);
    
    
                $Country = $User->getCountry();
    
                if (!$Country) {
                    return null;
                }
    
    
                $Currency = $Country->getCurrency();
    
                if (isset($allowed[$Currency->getCode()])) {
                    return $Currency;
                }
    
            } catch (Exception $Exception) {
    
                QUI\System\Log::writeDebugException($Exception);
            }
    
    
    Henning Leutz's avatar
    Henning Leutz committed
        /**
         * Return all allowed currencies
         *
    
         * @return Currency[] - [Currency, Currency, Currency]
    
    Henning Leutz's avatar
    Henning Leutz committed
         */
    
        public static function getAllowedCurrencies(): array
    
    Henning Leutz's avatar
    Henning Leutz committed
        {
    
            try {
                $Config = QUI::getPackage('quiqqer/currency')->getConfig();
                $allowed = $Config->getValue('currency', 'allowedCurrencies');
    
                $allowed = explode(',', trim($allowed));
                $list = [];
    
                $default = self::getDefaultCurrency()->getCode();
    
                if (!in_array($default, $allowed)) {
                    $allowed[] = $default;
                }
            } catch (QUI\Exception $e) {
                QUI\System\Log::addError($e->getMessage());
                return [];
    
    Henning Leutz's avatar
    Henning Leutz committed
            foreach ($allowed as $currency) {
                try {
                    $list[] = self::getCurrency($currency);
                } catch (QUI\Exception $Exception) {
                }
            }
    
            return $list;
    
        }
    
        /**
         * Return the currency db data
         *
         * @return array
         */
    
        public static function getData(): array
    
        {
            if (!self::$currencies) {
    
                try {
                    $data = QUI::getDataBase()->fetch([
                        'from' => self::table()
                    ]);
                } catch (QUI\Exception $Exception) {
                    QUI\System\Log::addError($Exception->getMessage());
    
                    return [];
                }
    
    
                foreach ($data as $entry) {
    
    Patrick Müller's avatar
    Patrick Müller committed
                    $entry['type'] = mb_strtolower($entry['type']);
    
                    if (!empty($entry['customData'])) {
                        $entry['customData'] = json_decode($entry['customData'], true);
                    }
    
    
                    self::$currencies[$entry['currency']] = $entry;
                }
            }
    
            return self::$currencies;
        }
    
        /**
         * Return a currency
         *
    
         * @param Currency|string|array $currency
    
         * @return Currency
         * @throws QUI\Exception
         */
    
        public static function getCurrency(Currency|string|array $currency): Currency
    
            if ($currency instanceof Currency) {
                return $currency;
            }
    
    
            $data = self::getData();
            $code = null;
    
            if (is_string($currency)) {
    
            } elseif (is_array($currency) && isset($currency['code'])) {
    
    Patrick Müller's avatar
    Patrick Müller committed
                $class = Currency::class;
    
                if (!empty($data[$code]['type'])) {
                    $class = self::getCurrencyClassByType($data[$code]['type']);
                }
    
                return new $class($data[$code]);
    
            }
    
            throw new QUI\Exception(
    
    Henning Leutz's avatar
    Henning Leutz committed
                ['quiqqer/currency', 'currency.not.found'],
    
                404
            );
        }
    
        /**
         * Check if an exchange rate for the currency exists
         *
         * @param string $currency - currency name
         *
         * @return bool
         */
    
        public static function existCurrency(string $currency): bool
    
        {
            $data = self::getData();
    
            return isset($data[$currency]);
        }
    
        /**
         * Return all currency entries
         *
    
         * @param Locale|boolean $Locale - optional, for translation
    
        public static function getCurrencies($Locale = false): array
    
        {
            if (!$Locale) {
                $Locale = QUI::getLocale();
            }
    
    
            $cacheName = 'quiqqer/currency/list';
            $cacheNameLang = 'quiqqer/currency/list/' . $Locale->getCurrent();
    
    
            try {
                return QUI\Cache\Manager::get($cacheNameLang);
            } catch (QUI\Exception $Exception) {
            }
    
            try {
                $currencies = QUI\Cache\Manager::get($cacheName);
            } catch (QUI\Exception $Exception) {
    
    Henning Leutz's avatar
    Henning Leutz committed
                $currencies = [];
    
                $data = self::getData();
    
    
                foreach ($data as $entry) {
                    $currencies[] = $entry['currency'];
                }
            }
    
    
    Henning Leutz's avatar
    Henning Leutz committed
            $result = [];
    
    
            foreach ($currencies as $currency) {
    
                try {
                    $Currency = self::getCurrency($currency);
                } catch (QUI\Exception $Exception) {
                    continue;
                }
    
    
    Patrick Müller's avatar
    Patrick Müller committed
                $result[$currency] = $Currency->toArray();
    
    
        /**
         * @param $currency
         * @param $data
         *
         * @throws QUI\Database\Exception
         * @throws QUI\Exception
         */
        public static function updateCurrency($currency, $data)
        {
            QUI\Permissions\Permission::checkPermission('currency.edit');
    
    
            // check if currency exists
            self::getCurrency($currency);
    
    
            $dbData = [];
    
            if (isset($data['autoupdate'])) {
                $dbData['autoupdate'] = empty($data['autoupdate']) ? 0 : 1;
            }
    
    
    Patrick Müller's avatar
    Patrick Müller committed
            if (!empty($data['type']) && is_string($data['type']) && self::existsCurrencyType($data['type'])) {
                $dbData['type'] = $data['type'];
            }
    
            if (!empty($data['customData'])) {
                $dbData['customData'] = json_encode($data['customData']);
            }
    
            if (isset($data['rate'])) {
                $dbData['rate'] = floatval($data['rate']);
            }
    
    
            if (isset($data['precision'])) {
                $dbData['precision'] = (int)$data['precision'];
            }
    
    
            QUI::getDataBase()->update(
                Handler::table(),
                $dbData,
                ['currency' => $currency]
            );
    
    Patrick Müller's avatar
    Patrick Müller committed
    
            QUI\Cache\Manager::clear('quiqqer/currency/list');
        }
    
        // region Currency types
    
        /**
         * @param string $type
         * @return string - Class path
         */
        protected static function getCurrencyClassByType(string $type): string
        {
            foreach (self::getCurrencyTypes() as $currencyType) {
                if ($currencyType['type'] === $type) {
                    return $currencyType['class'];
                }
            }
    
            return Currency::class;
        }
    
        /**
         * @param string $type
         * @return bool
         */
        protected static function existsCurrencyType(string $type): bool
        {
            foreach (self::getCurrencyTypes() as $currencyType) {
                if ($currencyType['type'] === $type) {
                    return true;
                }
            }
    
            return false;
        }
    
        /**
         * Get available currency types (provided by <currency> package.xml providers).
         *
         * @return array
         * [
         *     'type' => 'xyz',
         *     'typeTitle' => 'Currency Type XYZ',
         *     'class' => Class path,
         *     'settingsFormHtml' => string|null
         * ]
         */
        public static function getCurrencyTypes(): array
        {
            // @todo cache einbauen
    
    
            $packages = QUI::getPackageManager()->getInstalled();
    
    Patrick Müller's avatar
    Patrick Müller committed
            $currencyTypes = [];
    
            foreach ($packages as $installedPackage) {
                try {
                    $Package = QUI::getPackage($installedPackage['name']);
    
                    if (!$Package->isQuiqqerPackage()) {
                        continue;
                    }
    
                    $packageProvider = $Package->getProvider();
    
                    if (empty($packageProvider['currency'])) {
                        continue;
                    }
    
                    foreach ($packageProvider['currency'] as $class) {
    
                        if (!class_exists($class)) {
    
    Patrick Müller's avatar
    Patrick Müller committed
                            continue;
                        }
    
    
                        if (!is_a($class, CurrencyInterface::class, true)) {
    
    Patrick Müller's avatar
    Patrick Müller committed
                            continue;
                        }
    
                        $currencyTypes[] = [
    
                            'type' => $class::getCurrencyType(),
                            'typeTitle' => $class::getCurrencyTypeTitle(),
                            'class' => $class,
    
    Patrick Müller's avatar
    Patrick Müller committed
                            'settingsFormHtml' => $class::getExtraSettingsFormHtml()
                        ];
                    }
                } catch (QUI\Exception $Exception) {
    
                    QUI\System\Log::addNotice($Exception->getMessage());
    
    Patrick Müller's avatar
    Patrick Müller committed
                }
            }
    
            return $currencyTypes;
    
    Patrick Müller's avatar
    Patrick Müller committed
        // endregion