Newwebshop/classes/Configuration.php

621 lines
19 KiB
PHP

<?php
/**
* Copyright seit 2024 Webshop System
*
* Zentrale Konfigurationsverwaltung (Key-Value)
* Vollständig PrestaShop-kompatibel mit erweiterten Funktionen
*
* @author Webshop System
* @license GPL v3
*/
class Configuration extends ObjectModel
{
public $id;
/** @var string Key */
public $name;
public $id_shop_group;
public $id_shop;
/** @var string|array<string> Value */
public $value;
/** @var string Object creation date */
public $date_add;
/** @var string Object last modification date */
public $date_upd;
/**
* @see ObjectModel::$definition
*/
public static $definition = [
'table' => 'configuration',
'primary' => 'id_configuration',
'multilang' => true,
'fields' => [
'name' => ['type' => self::TYPE_STRING, 'validate' => 'isConfigName', 'required' => true, 'size' => 254],
'id_shop_group' => ['type' => self::TYPE_NOTHING, 'validate' => 'isUnsignedId'],
'id_shop' => ['type' => self::TYPE_NOTHING, 'validate' => 'isUnsignedId'],
'value' => ['type' => self::TYPE_STRING, 'size' => 65535],
'date_add' => ['type' => self::TYPE_DATE, 'validate' => 'isDate'],
'date_upd' => ['type' => self::TYPE_DATE, 'validate' => 'isDate'],
],
];
/** @var array|null Configuration cache */
protected static $_cache = null;
/** @var array|null Configuration cache with optimised key order */
protected static $_new_cache_shop = null;
protected static $_new_cache_group = null;
protected static $_new_cache_global = null;
protected static $_initialized = false;
/** @var array Vars types */
protected static $types = [];
protected $webserviceParameters = [
'fields' => [
'value' => [],
],
];
/**
* Default configuration data
*/
protected static $data = [
'WS_COUNTRY_DEFAULT' => 1,
'WS_LANG_DEFAULT' => 1,
'WS_TIMEZONE' => 'Europe/Berlin',
'WS_LOCALE_LANGUAGE' => 'de',
'WS_LOCALE_COUNTRY' => 'DE',
'WS_COOKIE_LIFETIME_BO' => 24,
'WS_COOKIE_LIFETIME_FO' => 24,
'WS_COOKIE_SAMESITE' => 'Lax',
'WS_SSL_ENABLED' => false,
];
/**
* Get fields lang
*/
public function getFieldsLang()
{
if (!is_array($this->value)) {
return true;
}
return parent::getFieldsLang();
}
/**
* Return ID a configuration key.
*/
public static function getIdByName($key, $idShopGroup = null, $idShop = null)
{
if ($idShop === null) {
$idShop = Shop::getContextShopID(true);
}
if ($idShopGroup === null) {
$idShopGroup = Shop::getContextShopGroupID(true);
}
return self::getIdByNameFromGivenContext($key, $idShopGroup, $idShop);
}
/**
* Get ID by name from given context
*/
public static function getIdByNameFromGivenContext(string $key, ?int $idShopGroup, ?int $idShop): int
{
$sql = 'SELECT `' . bqSQL(self::$definition['primary']) . '`
FROM `' . _DB_PREFIX_ . bqSQL(self::$definition['table']) . '`
WHERE name = \'' . pSQL($key) . '\'
' . Configuration::sqlRestriction($idShopGroup, $idShop);
return (int) Db::getInstance()->getValue($sql);
}
/**
* Is the configuration loaded.
*/
public static function configurationIsLoaded()
{
return self::$_initialized;
}
/**
* Reset static cache
*/
public static function resetStaticCache()
{
self::$_cache = null;
self::$_new_cache_shop = null;
self::$_new_cache_group = null;
self::$_new_cache_global = null;
self::$_initialized = false;
}
/**
* Load all configuration data.
*/
public static function loadConfiguration()
{
$sql = 'SELECT c.`name`, cl.`id_lang`, IF(cl.`id_lang` IS NULL, c.`value`, cl.`value`) AS value, c.id_shop_group, c.id_shop
FROM `' . _DB_PREFIX_ . bqSQL(self::$definition['table']) . '` c
LEFT JOIN `' . _DB_PREFIX_ . bqSQL(self::$definition['table']) . '_lang` cl ON (c.`' . bqSQL(
self::$definition['primary']
) . '` = cl.`' . bqSQL(self::$definition['primary']) . '`)';
$db = Db::getInstance();
$results = $db->executeS($sql);
if ($results) {
foreach ($results as $row) {
$lang = ($row['id_lang']) ? $row['id_lang'] : 0;
self::$types[$row['name']] = (bool) $lang;
if (!isset(self::$_cache[self::$definition['table']][$lang])) {
self::$_cache[self::$definition['table']][$lang] = [
'global' => [],
'group' => [],
'shop' => [],
];
}
if ($row['value'] === null) {
$row['value'] = '';
}
if ($row['id_shop']) {
self::$_cache[self::$definition['table']][$lang]['shop'][$row['id_shop']][$row['name']] = $row['value'];
self::$_new_cache_shop[$row['name']][$lang][$row['id_shop']] = $row['value'];
} elseif ($row['id_shop_group']) {
self::$_cache[self::$definition['table']][$lang]['group'][$row['id_shop_group']][$row['name']] = $row['value'];
self::$_new_cache_group[$row['name']][$lang][$row['id_shop_group']] = $row['value'];
} else {
self::$_cache[self::$definition['table']][$lang]['global'][$row['name']] = $row['value'];
self::$_new_cache_global[$row['name']][$lang] = $row['value'];
}
}
self::$_initialized = true;
}
}
/**
* Get a single configuration value (in one language only).
*/
public static function get($key, $idLang = null, $idShopGroup = null, $idShop = null, $default = false)
{
// Init the cache on demand
if (!self::$_initialized) {
Configuration::loadConfiguration();
}
$idLang = self::isLangKey($key) ? (int) $idLang : 0;
if (self::$_new_cache_shop === null) {
$idShop = 0;
} elseif ($idShop === null || !Shop::isFeatureActive()) {
$idShop = Shop::getContextShopID(true);
}
if (self::$_new_cache_group === null) {
$idShopGroup = 0;
} elseif ($idShopGroup === null || !Shop::isFeatureActive()) {
$idShopGroup = Shop::getContextShopGroupID(true);
}
if ($idShop && Configuration::hasKey($key, $idLang, null, $idShop)) {
return self::$_new_cache_shop[$key][$idLang][$idShop];
} elseif ($idShopGroup && Configuration::hasKey($key, $idLang, $idShopGroup)) {
return self::$_new_cache_group[$key][$idLang][$idShopGroup];
} elseif (Configuration::hasKey($key, $idLang)) {
return self::$_new_cache_global[$key][$idLang];
}
return $default;
}
/**
* Get global value
*/
public static function getGlobalValue($key, $idLang = null)
{
return self::get($key, $idLang, 0, 0);
}
/**
* Get config in multiple langs
*/
public static function getConfigInMultipleLangs($key, $idShopGroup = null, $idShop = null)
{
$languages = Language::getLanguages(false);
$res = [];
foreach ($languages as $lang) {
$res[$lang['id_lang']] = self::get($key, $lang['id_lang'], $idShopGroup, $idShop);
}
return $res;
}
/**
* Get multi shop values
*/
public static function getMultiShopValues($key, $idLang = null)
{
$shops = Shop::getShops(false, null, true);
$res = [];
foreach ($shops as $shop) {
$res[$shop['id_shop']] = self::get($key, $idLang, $shop['id_shop_group'], $shop['id_shop']);
}
return $res;
}
/**
* Get multiple
*/
public static function getMultiple($keys, $idLang = null, $idShopGroup = null, $idShop = null)
{
if (!is_array($keys)) {
return false;
}
$res = [];
foreach ($keys as $key) {
$res[$key] = self::get($key, $idLang, $idShopGroup, $idShop);
}
return $res;
}
/**
* Has key
*/
public static function hasKey($key, $idLang = null, $idShopGroup = null, $idShop = null)
{
if (!$idLang) {
$idLang = 0;
}
if ($idShop && isset(self::$_new_cache_shop[$key][$idLang][$idShop])) {
return true;
} elseif ($idShopGroup && isset(self::$_new_cache_group[$key][$idLang][$idShopGroup])) {
return true;
} elseif (isset(self::$_new_cache_global[$key][$idLang])) {
return true;
}
return false;
}
/**
* Set configuration value
*/
public static function set($key, $values, $idShopGroup = null, $idShop = null)
{
if (!$key) {
return false;
}
if ($idShop === null) {
$idShop = Shop::getContextShopID(true);
}
if ($idShopGroup === null) {
$idShopGroup = Shop::getContextShopGroupID(true);
}
if (!is_array($values)) {
$values = [$values];
}
if (self::isLangKey($key)) {
$res = true;
foreach ($values as $idLang => $value) {
$res &= self::updateValue($key, $value, false, $idShopGroup, $idShop, $idLang);
}
} else {
$res = self::updateValue($key, $values[0], false, $idShopGroup, $idShop);
}
return $res;
}
/**
* Update global value
*/
public static function updateGlobalValue($key, $values, $html = false)
{
return self::updateValue($key, $values, $html, 0, 0);
}
/**
* Update value
*/
public static function updateValue($key, $values, $html = false, $idShopGroup = null, $idShop = null, $idLang = null)
{
if (!$key) {
return false;
}
if ($idShop === null) {
$idShop = Shop::getContextShopID(true);
}
if ($idShopGroup === null) {
$idShopGroup = Shop::getContextShopGroupID(true);
}
// Update cache
if (self::isLangKey($key)) {
if ($idLang === null) {
$idLang = Context::getContext()->language->id;
}
if (self::$_new_cache_global !== null) {
self::$_new_cache_global[$key][$idLang] = $values;
}
if (self::$_new_cache_group !== null && $idShopGroup) {
self::$_new_cache_group[$key][$idLang][$idShopGroup] = $values;
}
if (self::$_new_cache_shop !== null && $idShop) {
self::$_new_cache_shop[$key][$idLang][$idShop] = $values;
}
} else {
if (self::$_new_cache_global !== null) {
self::$_new_cache_global[$key][0] = $values;
}
if (self::$_new_cache_group !== null && $idShopGroup) {
self::$_new_cache_group[$key][0][$idShopGroup] = $values;
}
if (self::$_new_cache_shop !== null && $idShop) {
self::$_new_cache_shop[$key][0][$idShop] = $values;
}
}
// Update database
$sql = 'SELECT `' . bqSQL(self::$definition['primary']) . '`
FROM `' . _DB_PREFIX_ . bqSQL(self::$definition['table']) . '`
WHERE name = \'' . pSQL($key) . '\'
' . Configuration::sqlRestriction($idShopGroup, $idShop);
$configuration = Db::getInstance()->getRow($sql);
if ($configuration) {
$result = true;
if (self::isLangKey($key)) {
$sql = 'UPDATE `' . _DB_PREFIX_ . bqSQL(self::$definition['table']) . '_lang`
SET value = \'' . pSQL($values, $html) . '\'
WHERE `' . bqSQL(self::$definition['primary']) . '` = ' . (int) $configuration[self::$definition['primary']] . '
AND `id_lang` = ' . (int) $idLang;
$result &= Db::getInstance()->execute($sql);
} else {
$sql = 'UPDATE `' . _DB_PREFIX_ . bqSQL(self::$definition['table']) . '`
SET value = \'' . pSQL($values, $html) . '\', date_upd = NOW()
WHERE `' . bqSQL(self::$definition['primary']) . '` = ' . (int) $configuration[self::$definition['primary']];
$result &= Db::getInstance()->execute($sql);
}
} else {
$result = self::insertNewConfiguration($key, $values, $html, $idShopGroup, $idShop, $idLang);
}
return $result;
}
/**
* Insert new configuration
*/
protected static function insertNewConfiguration($key, $values, $html, $idShopGroup, $idShop, $idLang)
{
$newConfig = new Configuration();
$newConfig->name = $key;
$newConfig->id_shop_group = $idShopGroup;
$newConfig->id_shop = $idShop;
if (self::isLangKey($key)) {
$newConfig->value = $values;
$newConfig->id_lang = $idLang;
} else {
$newConfig->value = $values;
}
return $newConfig->add();
}
/**
* Delete by name
*/
public static function deleteByName($key)
{
$sql = 'DELETE FROM `' . _DB_PREFIX_ . bqSQL(self::$definition['table']) . '`
WHERE name = \'' . pSQL($key) . '\'';
$result = Db::getInstance()->execute($sql);
if (self::isLangKey($key)) {
$sql = 'DELETE FROM `' . _DB_PREFIX_ . bqSQL(self::$definition['table']) . '_lang`
WHERE `' . bqSQL(self::$definition['primary']) . '` NOT IN
(SELECT `' . bqSQL(self::$definition['primary']) . '` FROM `' . _DB_PREFIX_ . bqSQL(self::$definition['table']) . '`)';
$result &= Db::getInstance()->execute($sql);
}
// Update cache
if (self::$_new_cache_global !== null && isset(self::$_new_cache_global[$key])) {
unset(self::$_new_cache_global[$key]);
}
if (self::$_new_cache_group !== null && isset(self::$_new_cache_group[$key])) {
unset(self::$_new_cache_group[$key]);
}
if (self::$_new_cache_shop !== null && isset(self::$_new_cache_shop[$key])) {
unset(self::$_new_cache_shop[$key]);
}
return $result;
}
/**
* Delete from context
*/
public static function deleteFromContext($key, ?int $idShopGroup = null, ?int $idShop = null)
{
if ($idShop === null) {
$idShop = Shop::getContextShopID(true);
}
if ($idShopGroup === null) {
$idShopGroup = Shop::getContextShopGroupID(true);
}
self::deleteFromGivenContext($key, $idShopGroup, $idShop);
}
/**
* Delete from given context
*/
public static function deleteFromGivenContext(string $key, ?int $idShopGroup, ?int $idShop): void
{
$sql = 'DELETE FROM `' . _DB_PREFIX_ . bqSQL(self::$definition['table']) . '`
WHERE name = \'' . pSQL($key) . '\'
' . Configuration::sqlRestriction($idShopGroup, $idShop);
Db::getInstance()->execute($sql);
}
/**
* Delete by ID
*/
public static function deleteById(int $configurationId): void
{
$sql = 'DELETE FROM `' . _DB_PREFIX_ . bqSQL(self::$definition['table']) . '`
WHERE `' . bqSQL(self::$definition['primary']) . '` = ' . (int) $configurationId;
Db::getInstance()->execute($sql);
$sql = 'DELETE FROM `' . _DB_PREFIX_ . bqSQL(self::$definition['table']) . '_lang`
WHERE `' . bqSQL(self::$definition['primary']) . '` = ' . (int) $configurationId;
Db::getInstance()->execute($sql);
}
/**
* Has context
*/
public static function hasContext($key, $idLang, $context)
{
if (is_array($context)) {
$idShop = (int) $context['shop_id'];
$idShopGroup = (int) $context['shop_group_id'];
} else {
$idShop = Shop::getContextShopID(true);
$idShopGroup = Shop::getContextShopGroupID(true);
}
if ($idShop && Configuration::hasKey($key, $idLang, null, $idShop)) {
return true;
} elseif ($idShopGroup && Configuration::hasKey($key, $idLang, $idShopGroup)) {
return true;
} elseif (Configuration::hasKey($key, $idLang)) {
return true;
}
return false;
}
/**
* Is overriden by current context
*/
public static function isOverridenByCurrentContext($key)
{
$idContextLang = Context::getContext()->language->id;
$currentShopId = Shop::getContextShopID(true);
$currentShopGroupId = Shop::getContextShopGroupID(true);
if ($currentShopId && Configuration::hasKey($key, $idContextLang, null, $currentShopId)) {
return true;
} elseif ($currentShopGroupId && Configuration::hasKey($key, $idContextLang, $currentShopGroupId)) {
return true;
}
return false;
}
/**
* Is lang key
*/
public static function isLangKey($key)
{
return isset(self::$types[$key]) && self::$types[$key];
}
/**
* Is catalog mode
*/
public static function isCatalogMode()
{
return (bool) self::get('PS_CATALOG_MODE');
}
/**
* Show prices
*/
public static function showPrices()
{
return !self::isCatalogMode();
}
/**
* SQL restriction
*/
protected static function sqlRestriction($idShopGroup, $idShop)
{
if ($idShop) {
return ' AND id_shop = ' . (int) $idShop;
} elseif ($idShopGroup) {
return ' AND id_shop_group = ' . (int) $idShopGroup . ' AND (id_shop IS NULL OR id_shop = 0)';
} else {
return ' AND (id_shop_group IS NULL OR id_shop_group = 0) AND (id_shop IS NULL OR id_shop = 0)';
}
}
/**
* Get webservice object list
*/
public function getWebserviceObjectList($sqlJoin, $sqlFilter, $sqlSort, $sqlLimit)
{
$sql = 'SELECT DISTINCT main.`' . bqSQL(self::$definition['primary']) . '` as `' . bqSQL(self::$definition['primary']) . '` ' . $sqlJoin . ' WHERE 1 ' . $sqlFilter;
if ($sqlSort) {
$sql .= $sqlSort;
}
if ($sqlLimit) {
$sql .= $sqlLimit;
}
return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql);
}
/**
* Get configuration (simple method)
*/
public static function get($key)
{
// Check cache first
if (isset(self::$data[$key])) {
return self::$data[$key];
}
// Load from database
if (!self::$_initialized) {
self::loadConfiguration();
}
return self::get($key, null, null, null, null);
}
/**
* Set configuration (simple method)
*/
public static function set($key, $value)
{
// Update cache
self::$data[$key] = $value;
// Update database
return self::set($key, [$value]);
}
}