772 lines
18 KiB
PHP
772 lines
18 KiB
PHP
<?php
|
|
|
|
use KupShop\KupShopBundle\Config;
|
|
use KupShop\KupShopBundle\Context\LanguageContext;
|
|
use KupShop\KupShopBundle\Util\Compat\ServiceContainer;
|
|
use KupShop\KupShopBundle\Util\Contexts;
|
|
use Query\Operator;
|
|
|
|
/**
|
|
* @property string $order_not_in_store Deprecated, use `order_availability` instead
|
|
*/
|
|
#[\AllowDynamicProperties]
|
|
class SettingsBase extends \KupShop\KupShopBundle\Template\ArrayAccess
|
|
{
|
|
use DatabaseCommunication;
|
|
|
|
public const ORDER_AVAILABILITY_ALL = 'all';
|
|
public const ORDER_AVAILABILITY_IN_STORE = 'in_store';
|
|
public const ORDER_AVAILABILITY_IN_STORE_OR_SUPPLIER_STORE = 'in_store_or_supplier_store';
|
|
/**
|
|
* Singleton instance.
|
|
*
|
|
* @var Settings
|
|
*/
|
|
private static $instance = [];
|
|
|
|
/**
|
|
* @var varchar(10)
|
|
*/
|
|
public $lang = 'czech';
|
|
|
|
/**
|
|
* @var enum('0','1')
|
|
*/
|
|
public $shop_status = '1';
|
|
|
|
/**
|
|
* Shop description.
|
|
*
|
|
* @var varchar
|
|
*/
|
|
public $shop_title;
|
|
public $shop_description;
|
|
public $shop_keywords;
|
|
public $index_title;
|
|
public $index_description;
|
|
public $index_keywords;
|
|
public $shop_firm_name;
|
|
public $shop_firm_owner;
|
|
public $shop_email;
|
|
public $shop_phone;
|
|
public $shop_fax;
|
|
public $shop_address;
|
|
public $shop_ico;
|
|
public $shop_dic;
|
|
public $shop_vat_payer = 'Y';
|
|
public $shop_orders_finished;
|
|
public $shop_due_days = 14;
|
|
public $review_automatic_confirm;
|
|
|
|
/**
|
|
* Bank account.
|
|
*
|
|
* @var varchar(6)
|
|
*/
|
|
public $bank_account_prefix;
|
|
public $bank_account_number;
|
|
public $bank_code;
|
|
public $bank_var_symbol;
|
|
public $bank_konst_symbol;
|
|
public $bank_name;
|
|
public $bank_iban;
|
|
public $bank_swift;
|
|
|
|
/**
|
|
* @var enum('Y','N')
|
|
*/
|
|
public $figure_photos = 'Y';
|
|
|
|
/**
|
|
* @var enum('Y','N')
|
|
*/
|
|
public $figure_prices = 'Y';
|
|
|
|
/**
|
|
* @var tinyint(2)
|
|
*/
|
|
public $cat_show_products = 20;
|
|
|
|
/**
|
|
* @var tinyint(2)
|
|
*/
|
|
public $cat_show_products_search;
|
|
|
|
/**
|
|
* @var enum('Y','N')
|
|
*/
|
|
public $cat_show_empty = 'Y';
|
|
|
|
/**
|
|
* @var enum('1','2')
|
|
*/
|
|
public $cat_show_style = 1;
|
|
|
|
/**
|
|
* @var int(4)
|
|
*/
|
|
public $delete_cart_logged = 0;
|
|
|
|
/**
|
|
* @var int(4)
|
|
*/
|
|
public $delete_cart_notlogged = 0;
|
|
|
|
/**
|
|
* @var char(3)
|
|
*/
|
|
public $currency = 'Kč';
|
|
/**
|
|
* @var int
|
|
*/
|
|
public $rate = 1;
|
|
|
|
/**
|
|
* @var enum('','status','delete')
|
|
*/
|
|
public $prod_do_after_order = 'status';
|
|
|
|
/** @var enum('Y','N') */
|
|
public $admin_ean_check = 'Y';
|
|
|
|
/**
|
|
* @var enum('Y','N')
|
|
*/
|
|
public $prod_show_price_vat = 'Y';
|
|
public $prod_prefer_price_vat = 'N';
|
|
public $prod_show_not_in_store = 'Y';
|
|
public $prod_show_not_in_category = 'Y';
|
|
public $prod_show_admin_hidden = 'N';
|
|
public string $order_availability = self::ORDER_AVAILABILITY_IN_STORE;
|
|
|
|
/**
|
|
* @var varchar(10)
|
|
*/
|
|
public $date_format = '%e.%c.%Y';
|
|
|
|
/**
|
|
* @var varchar(10)
|
|
*/
|
|
public $time_format = '%H:%i:%s';
|
|
|
|
/**
|
|
* @var tinytext
|
|
*/
|
|
public $order_shopkeeper_mail;
|
|
public $order_from_mail;
|
|
|
|
/**
|
|
* Automatic mail sending.
|
|
*
|
|
* @var enum('Y','N')
|
|
*/
|
|
public $order_send_to_shopkeeper = 'Y';
|
|
public $order_send_received_mail = 'Y';
|
|
public $order_send_status_mail = 'Y';
|
|
|
|
/**
|
|
* Array with custom settings from yml shop config.
|
|
*
|
|
* @var array
|
|
*/
|
|
public $custom;
|
|
|
|
/**
|
|
* Mail after order received.
|
|
*
|
|
* @deprecated
|
|
*
|
|
* @var tinytext
|
|
*/
|
|
private $order_received_subject;
|
|
/**
|
|
* @deprecated
|
|
*
|
|
* @var null
|
|
*/
|
|
private $order_received_text;
|
|
|
|
/**
|
|
* Mail for order confirmation.
|
|
*
|
|
* @deprecated
|
|
*
|
|
* @var tinytext
|
|
*/
|
|
private $order_template_text;
|
|
|
|
/**
|
|
* Mail for order status change.
|
|
*
|
|
* @deprecated
|
|
*
|
|
* @var tinytext
|
|
*/
|
|
private $order_status_subject;
|
|
|
|
/**
|
|
* @deprecated
|
|
*
|
|
* @var null
|
|
*/
|
|
private $order_status_text;
|
|
|
|
/**
|
|
* Custom messages to user.
|
|
*
|
|
* @deprecated
|
|
*
|
|
* @var array
|
|
*/
|
|
private $order_messages = [];
|
|
|
|
/**
|
|
* Custom templates of product descriptions.
|
|
*
|
|
* @var array
|
|
*/
|
|
public $product_templates = [];
|
|
/**
|
|
* @var int
|
|
*/
|
|
public $price_round = 0;
|
|
|
|
/**
|
|
* @var int
|
|
*/
|
|
public $price_round_order;
|
|
|
|
/**
|
|
* @var string ('up','down','math')
|
|
*/
|
|
public $price_round_direction = 'up';
|
|
|
|
/**
|
|
* @var string (0, 2, 'dynamic')
|
|
*/
|
|
public $price_precision;
|
|
|
|
/**
|
|
* @var string
|
|
*/
|
|
public $price_decimal_mark = ',';
|
|
|
|
/**
|
|
* @var enum('Y','N')
|
|
*/
|
|
public $prod_subtract_from_store = 'Y';
|
|
|
|
/**
|
|
* @var enum('Y','N')
|
|
*/
|
|
public $shop_out_of_order = 'N';
|
|
|
|
/**
|
|
* @var enum('Y','N')
|
|
*/
|
|
public $shop_closed = 'N';
|
|
|
|
/**
|
|
* @var enum('Y','N')
|
|
*/
|
|
public $orders_closed = 'N';
|
|
|
|
public $cookie_bar = [];
|
|
|
|
/**
|
|
* @var enum('Y','N')
|
|
*/
|
|
public $prod_in_feed_all = 'N';
|
|
|
|
public $user_rights_version = 99;
|
|
public $page_divide = 30;
|
|
|
|
public $terms_and_conditions_file;
|
|
public $invoice_name;
|
|
|
|
public $currency_code = 'CZK';
|
|
public $currencies = [];
|
|
|
|
public $email;
|
|
|
|
public $telfa;
|
|
|
|
public $analytics;
|
|
public $balikonos;
|
|
public $info_panel;
|
|
|
|
public $sort_in_cat_by_in_store = 'Y';
|
|
|
|
public $order_multiple_paid_status = 'N';
|
|
|
|
public $eshop_live = 'Y';
|
|
|
|
public $highlight_order_rows = 'N';
|
|
|
|
public $orders_only_active_custom = 'N';
|
|
public $orders_only_active_custom_filter = [];
|
|
|
|
/**
|
|
* List of fields that should not be saved.
|
|
*
|
|
* @var unknown_type
|
|
*/
|
|
public static $doNotSerializeFields = ['id', 'is_default', 'name', 'doNotSerializeFields', '_language'];
|
|
|
|
public function __construct()
|
|
{
|
|
}
|
|
|
|
public static function getDefault()
|
|
{
|
|
return self::getFromCache(
|
|
static::getLanguage()
|
|
);
|
|
}
|
|
|
|
/**
|
|
* @return mixed|Settings|null
|
|
*/
|
|
public static function getFromCache($languageID)
|
|
{
|
|
$cacheName = 'settings-'.$languageID;
|
|
if (empty(self::$instance[$languageID])) {
|
|
if ((self::$instance[$languageID] = getCache($cacheName)) == false) {
|
|
self::$instance[$languageID] = self::createFromDB($languageID);
|
|
|
|
setCache($cacheName, self::$instance[$languageID], 3600);
|
|
}
|
|
|
|
if (!self::$instance[$languageID] instanceof self) {
|
|
clearCache($cacheName);
|
|
}
|
|
}
|
|
|
|
return self::$instance[$languageID];
|
|
}
|
|
|
|
/**
|
|
* Creates Settings object from database.
|
|
*
|
|
* @param string $languageID
|
|
*
|
|
* @return Settings
|
|
*
|
|
* @throws Exception
|
|
*/
|
|
public static function createFromDB($languageID = null, bool $withDisabledAutoload = false)
|
|
{
|
|
$SQL = sqlQueryBuilder()
|
|
->select('key_name, value')
|
|
->from('settings')
|
|
->sendToMaster();
|
|
if (!$withDisabledAutoload) {
|
|
$SQL = $SQL->where(Operator::equals(['autoload' => 1]));
|
|
}
|
|
$SQL = $SQL->execute();
|
|
$decoded = false;
|
|
|
|
if ($languageID && findModule(Modules::TRANSLATIONS)
|
|
&& ($languageID != ServiceContainer::getService(LanguageContext::class)->getDefaultId())) {
|
|
try {
|
|
$settingsTranslations = ServiceContainer::getService(\KupShop\I18nBundle\Translations\SettingsTranslation::class);
|
|
|
|
if ($SQLTranslations = $settingsTranslations->setLanguageId($languageID)->fetch($withDisabledAutoload)) {
|
|
$SQL = $SQLTranslations;
|
|
$decoded = true;
|
|
}
|
|
$SQL[] = ['key_name' => '_language', 'value' => $languageID];
|
|
} catch (Exception $e) {
|
|
// Ignore translations error
|
|
}
|
|
}
|
|
|
|
$settings = new Settings();
|
|
foreach ($SQL as $value) {
|
|
if ($decoded) {
|
|
$settings->{$value['key_name']} = $value['value'];
|
|
} else {
|
|
$settings->{$value['key_name']} = json_decode($value['value'], true);
|
|
}
|
|
}
|
|
|
|
if (!empty($settings->custom)) {
|
|
$settings->custom = (new \KupShop\KupShopBundle\Util\System\CustomSettingsWrapper())->setObject($settings->custom);
|
|
}
|
|
|
|
if ($settings instanceof self) {
|
|
return $settings;
|
|
}
|
|
|
|
throw new Exception('Error loading settings');
|
|
}
|
|
|
|
/**
|
|
* Creates Settings object from serialized string.
|
|
*
|
|
* @param string $str
|
|
*
|
|
* @return Settings
|
|
*
|
|
* @throws Exception
|
|
*/
|
|
public static function createFromString($str)
|
|
{
|
|
$settings = unserialize($str);
|
|
|
|
if ($settings instanceof self) {
|
|
return $settings;
|
|
}
|
|
|
|
throw new Exception('Error loading settings');
|
|
}
|
|
|
|
/**
|
|
* Updates settings fields from supplied array.
|
|
*
|
|
* @param array $data
|
|
* @param bool $force
|
|
*
|
|
* @return bool
|
|
*/
|
|
public function loadFromArray($data, $force = false)
|
|
{
|
|
foreach ($data as $key => $value) {
|
|
// If $force is not set, allow update only "safe" fields
|
|
if (!$force && array_search($key, Settings::$doNotSerializeFields)) {
|
|
continue;
|
|
}
|
|
|
|
$this->{$key} = $value;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Overrides stored singleton instance.
|
|
*/
|
|
public static function setDefault($instance)
|
|
{
|
|
self::$instance = $instance;
|
|
}
|
|
|
|
/**
|
|
* Stores Settings to database.
|
|
*
|
|
* @deprecated Místo tohodle používej saveValue(key, value). Tahle metoda je šílená, nebezpečná, příjde se snadno o data.
|
|
*/
|
|
public function saveToDB($settings = null, ?array $disable_autoload = null)
|
|
{
|
|
// Sanity check. Ensure this settings are not from language
|
|
if (!empty($this->_language)) {
|
|
// Když dostaneš tuhle exception znamená to, že eshop naloadoval settingy z ne-default jazyka a zkouší je uložit přes saveToDB()
|
|
// To je samozřejmě špatně, protože by tím propsal ty jazykový settingy do hlavních.
|
|
// TODO: Handlovat languageSettingy a ukládat do translation table
|
|
throw new \Exception('Language settings can not be saved to main settings');
|
|
}
|
|
|
|
self::clearCache(true);
|
|
|
|
if (empty($settings)) {
|
|
$settings = get_object_vars($this);
|
|
}
|
|
|
|
$ret = null;
|
|
|
|
foreach ($settings as $key => $value) {
|
|
$ret = $this->saveValue($key, $value, !isset($disable_autoload[$key]));
|
|
}
|
|
|
|
return $ret;
|
|
}
|
|
|
|
public function saveValue($key, $value, bool $autoload = true)
|
|
{
|
|
$ret = false;
|
|
|
|
if (!in_array($key, Settings::$doNotSerializeFields) && !is_numeric($key)) {
|
|
$ret = sqlQuery('INSERT INTO settings (key_name, value, autoload) VALUES (:key_name, :value, :autoload)
|
|
ON DUPLICATE KEY UPDATE value=:value, autoload=:autoload', ['key_name' => $key, 'value' => json_encode($value), 'autoload' => (int) $autoload]);
|
|
}
|
|
|
|
return $ret;
|
|
}
|
|
|
|
public function loadValue($key)
|
|
{
|
|
$qb = sqlQueryBuilder()
|
|
->select('s.value')
|
|
->from('settings', 's')
|
|
->where(Operator::equals(['s.key_name' => $key]))
|
|
->sendToMaster();
|
|
|
|
if (findModule(Modules::TRANSLATIONS)) {
|
|
$activeLangId = static::getLanguage();
|
|
if (Contexts::get(LanguageContext::class)->getDefaultId() != $activeLangId) {
|
|
$qb = $qb->leftJoin('s', 'settings_translations', 'st', 'st.key_name = s.key_name AND st.id_language = :idlanguage')
|
|
->select('COALESCE(st.value, s.value) as value')
|
|
->setParameter('idlanguage', $activeLangId);
|
|
}
|
|
}
|
|
|
|
return json_decode($qb->execute()->fetchOne(), true);
|
|
}
|
|
|
|
public function deleteValue($key)
|
|
{
|
|
if (!empty($this->{$key})) {
|
|
unset($this->{$key});
|
|
}
|
|
|
|
$this->deleteSQL('settings', ['key_name' => $key]);
|
|
}
|
|
|
|
public function updateValue($key, array $newValue)
|
|
{
|
|
$value = json_decode(
|
|
sqlQueryBuilder()->select('value')->from('settings')
|
|
->where(Operator::equals(['key_name' => $key]))
|
|
->sendToMaster()->execute()->fetchOne(),
|
|
true
|
|
);
|
|
$value = array_replace_recursive($value, $newValue);
|
|
$this->saveValue($key, $value);
|
|
$this->{$key} = $value;
|
|
self::clearCache();
|
|
}
|
|
|
|
/**
|
|
* Get array describing custom settings for this eshop.
|
|
*/
|
|
public function getCustomSettings()
|
|
{
|
|
return [];
|
|
}
|
|
|
|
/**
|
|
* Get array describing custom settings for this eshop.
|
|
*/
|
|
public function getYmlCustomSettings()
|
|
{
|
|
$params = ServiceContainer::getContainer()->getParameterBag()->all();
|
|
$params = array_filter($params, function ($key) {
|
|
return \KupShop\KupShopBundle\Util\StringUtil::startsWith($key, 'kupshop.custom_settings');
|
|
}, ARRAY_FILTER_USE_KEY);
|
|
$ymlCustomSettings = [];
|
|
foreach ($params as $customSettings) {
|
|
$ymlCustomSettings = array_merge($ymlCustomSettings, $customSettings);
|
|
}
|
|
|
|
return $ymlCustomSettings;
|
|
}
|
|
|
|
public static function clearCache($clearInstance = false)
|
|
{
|
|
foreach (Contexts::get(LanguageContext::class)->getAll() as $language) {
|
|
clearCache('settings-'.$language->getId());
|
|
}
|
|
|
|
if ($clearInstance) {
|
|
self::$instance = [];
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @deprecated
|
|
*
|
|
* @param string|null $languageID
|
|
*
|
|
* @return array
|
|
*/
|
|
public function getOrderStatusMessages($status, $languageID = null)
|
|
{
|
|
$messages = $this->getMailClass()->getOrderStatusMessagesByStatus($status, $languageID);
|
|
$messages = array_combine(array_column($messages, 'name'), $messages);
|
|
|
|
return $messages;
|
|
}
|
|
|
|
/**
|
|
* @deprecated
|
|
*
|
|
* @return object
|
|
*/
|
|
private function getMailClass()
|
|
{
|
|
if (!$this->email) {
|
|
/* @var \KupShop\KupShopBundle\Util\Mail\Email $email */
|
|
$this->email = ServiceContainer::getService("KupShop\KupShopBundle\Util\Mail\Email");
|
|
}
|
|
|
|
return $this->email;
|
|
}
|
|
|
|
/**
|
|
* @deprecated
|
|
*/
|
|
public function getTemplate()
|
|
{
|
|
return $this->getMailClass()->getBasicTemplate();
|
|
}
|
|
|
|
/**
|
|
* @deprecated
|
|
*/
|
|
public function stripEmail($email)
|
|
{
|
|
return $this->getMailClass()::stripEmail($email);
|
|
}
|
|
|
|
public static function getTimeFormat()
|
|
{
|
|
$dbcfg = Settings::getDefault();
|
|
|
|
switch ($dbcfg['time_format']) {
|
|
case '%k:%i:%s':
|
|
return 'G:i:s';
|
|
break;
|
|
case '%H:%i':
|
|
return 'H:i';
|
|
break;
|
|
case '%k:%i':
|
|
return 'G:i';
|
|
break;
|
|
case '%H:%i:%s':
|
|
default:
|
|
return 'H:i:s';
|
|
break;
|
|
}
|
|
}
|
|
|
|
public static function getDateFormat()
|
|
{
|
|
$dbcfg = Settings::getDefault();
|
|
|
|
switch ($dbcfg['date_format']) {
|
|
case '%e.%c.%y':
|
|
return 'j.n.y';
|
|
break;
|
|
case '%d.%m.%Y':
|
|
return 'd.m.Y';
|
|
break;
|
|
case '%d/%m/%Y':
|
|
return 'd/m/Y';
|
|
break;
|
|
case '%d/%m/%y':
|
|
return 'd/m/y';
|
|
break;
|
|
case '%e.%c.%Y':
|
|
default:
|
|
return 'j.n.Y';
|
|
break;
|
|
}
|
|
}
|
|
|
|
private static function getLanguage(): string
|
|
{
|
|
if (isAdministration()) {
|
|
return Config::get()['Lang']['admin'] ?? Contexts::get(LanguageContext::class)->getDefaultId();
|
|
}
|
|
|
|
return Contexts::get(LanguageContext::class)->getActiveId();
|
|
}
|
|
|
|
/**
|
|
* @deprecated
|
|
*/
|
|
public function getOrderMessages(): array
|
|
{
|
|
return $this->order_messages;
|
|
}
|
|
|
|
/**
|
|
* @deprecated
|
|
*/
|
|
public function getOrderReceivedSubject()
|
|
{
|
|
return $this->order_received_subject;
|
|
}
|
|
|
|
/**
|
|
* @deprecated
|
|
*/
|
|
public function getOrderReceivedText()
|
|
{
|
|
return $this->order_received_text;
|
|
}
|
|
|
|
/**
|
|
* @deprecated
|
|
*/
|
|
public function getOrderTemplateText()
|
|
{
|
|
return $this->order_template_text;
|
|
}
|
|
|
|
/**
|
|
* @deprecated
|
|
*/
|
|
public function getOrderStatusSubject()
|
|
{
|
|
return $this->order_status_subject;
|
|
}
|
|
|
|
/**
|
|
* @deprecated
|
|
*/
|
|
public function getOrderStatusText()
|
|
{
|
|
return $this->order_status_text;
|
|
}
|
|
|
|
public function &offsetGet(mixed $offset): mixed
|
|
{
|
|
return $this->__get($offset);
|
|
}
|
|
|
|
public function offsetExists($offset): bool
|
|
{
|
|
if ($offset === 'order_not_in_store') {
|
|
return true;
|
|
}
|
|
|
|
return parent::offsetExists($offset);
|
|
}
|
|
|
|
public function &__get(string $name): mixed
|
|
{
|
|
// emulate getting of deprecated `order_not_in_store`
|
|
if ($name === 'order_not_in_store') {
|
|
$result = 'N';
|
|
if ($this->order_availability === self::ORDER_AVAILABILITY_ALL) {
|
|
$result = 'Y';
|
|
}
|
|
|
|
return $result;
|
|
}
|
|
|
|
if (!property_exists($this, $name)) {
|
|
$this->{$name} = null;
|
|
}
|
|
|
|
return $this->{$name};
|
|
}
|
|
|
|
public function __set(string $name, $value)
|
|
{
|
|
// emulate setting of deprecated `order_not_in_store`
|
|
if ($name === 'order_not_in_store') {
|
|
$this->order_availability = $value === 'Y' ? self::ORDER_AVAILABILITY_ALL : (findModule(Modules::PRODUCTS_SUPPLIERS) ? self::ORDER_AVAILABILITY_IN_STORE_OR_SUPPLIER_STORE : self::ORDER_AVAILABILITY_IN_STORE);
|
|
}
|
|
|
|
$this->{$name} = $value;
|
|
}
|
|
}
|
|
|
|
if (empty($subclass)) {
|
|
class Settings extends SettingsBase
|
|
{
|
|
}
|
|
}
|