'shop', 'primary' => 'id_shop', 'fields' => [ 'active' => ['type' => self::TYPE_BOOL, 'validate' => 'isBool'], 'deleted' => ['type' => self::TYPE_BOOL, 'validate' => 'isBool'], 'name' => ['type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'required' => true, 'size' => 64], 'color' => ['type' => self::TYPE_STRING, 'validate' => 'isColor', 'size' => 50], 'id_category' => ['type' => self::TYPE_INT, 'required' => true], 'theme_name' => ['type' => self::TYPE_STRING, 'validate' => 'isThemeName', 'size' => 255], 'id_shop_group' => ['type' => self::TYPE_INT, 'required' => true], ], ]; /** @var array|null List of shops cached */ protected static $shops; /** @var array|null List of shop group IDs cached */ protected static $shopGroupIds = null; protected static $asso_tables = []; protected static $id_shop_default_tables = []; protected static $initialized = false; protected $webserviceParameters = [ 'fields' => [ 'id_shop_group' => ['xlink_resource' => 'shop_groups'], 'id_category' => [], ], ]; /** @var int|null Store the current context of shop (CONTEXT_ALL, CONTEXT_GROUP, CONTEXT_SHOP) */ protected static $context; /** @var int|null ID shop in the current context (will be empty if context is not CONTEXT_SHOP) */ protected static $context_id_shop; /** @var int|null ID shop group in the current context (will be empty if context is CONTEXT_ALL) */ protected static $context_id_shop_group; /** @var ShopGroup|null Context shop group kept as cache */ protected static $context_shop_group = null; /** @var bool|null is multistore activated */ protected static $feature_active; /** @var Theme|null */ public $theme; /** * There are 3 kinds of shop context : shop, group shop and general. */ public const CONTEXT_SHOP = 1; public const CONTEXT_GROUP = 2; public const CONTEXT_ALL = 3; /** * Some data can be shared between shops, like customers or orders. */ public const SHARE_CUSTOMER = 'share_customer'; public const SHARE_ORDER = 'share_order'; public const SHARE_STOCK = 'share_stock'; /** * Konstruktor */ public function __construct($id = null, $id_lang = null, $id_shop = null) { parent::__construct($id, $id_lang, $id_shop); if ($this->id) { $this->setUrl(); if ($this->theme == null) { $this->setTheme(); } } } /** * Initialize an array with all the multistore associations in the database. */ protected static function init() { Shop::$id_shop_default_tables = ['product', 'category']; $asso_tables = [ 'carrier' => ['type' => 'shop'], 'carrier_lang' => ['type' => 'fk_shop'], 'category' => ['type' => 'shop'], 'category_lang' => ['type' => 'fk_shop'], 'cms' => ['type' => 'shop'], 'cms_lang' => ['type' => 'fk_shop'], 'cms_category' => ['type' => 'shop'], 'cms_category_lang' => ['type' => 'fk_shop'], 'contact' => ['type' => 'shop'], 'country' => ['type' => 'shop'], 'currency' => ['type' => 'shop'], 'employee' => ['type' => 'shop'], 'hook_module' => ['type' => 'fk_shop'], 'hook_module_exceptions' => ['type' => 'fk_shop', 'primary' => 'id_hook_module_exceptions'], 'image' => ['type' => 'shop'], 'lang' => ['type' => 'shop'], 'meta_lang' => ['type' => 'fk_shop'], 'module' => ['type' => 'shop'], 'module_currency' => ['type' => 'fk_shop'], 'module_country' => ['type' => 'fk_shop'], 'module_group' => ['type' => 'fk_shop'], 'product' => ['type' => 'shop'], 'product_attribute' => ['type' => 'shop'], 'product_lang' => ['type' => 'fk_shop'], 'customization_field_lang' => ['type' => 'fk_shop'], 'store' => ['type' => 'shop'], 'webservice_account' => ['type' => 'shop'], 'warehouse' => ['type' => 'shop'], 'stock_available' => ['type' => 'fk_shop', 'primary' => 'id_stock_available'], 'carrier_tax_rules_group_shop' => ['type' => 'fk_shop'], 'attribute' => ['type' => 'shop'], 'feature' => ['type' => 'shop'], 'group' => ['type' => 'shop'], 'attribute_group' => ['type' => 'shop'], 'tax_rules_group' => ['type' => 'shop'], 'zone' => ['type' => 'shop'], 'manufacturer' => ['type' => 'shop'], 'supplier' => ['type' => 'shop'], ]; foreach ($asso_tables as $table_name => $table_details) { Shop::addTableAssociation($table_name, $table_details); } Shop::$initialized = true; } /** * Set URL */ public function setUrl() { $cache_id = 'Shop::setUrl_' . (int) $this->id; if (!Cache::isStored($cache_id)) { $row = Db::getInstance()->getRow(' SELECT su.physical_uri, su.virtual_uri, su.domain, su.domain_ssl FROM ' . _DB_PREFIX_ . 'shop s LEFT JOIN ' . _DB_PREFIX_ . 'shop_url su ON (s.id_shop = su.id_shop) WHERE s.id_shop = ' . (int) $this->id . ' AND s.active = 1 AND s.deleted = 0 AND su.main = 1'); Cache::store($cache_id, $row); } else { $row = Cache::retrieve($cache_id); } if (!$row) { return false; } $this->physical_uri = $row['physical_uri']; $this->virtual_uri = $row['virtual_uri']; $this->domain = $row['domain']; $this->domain_ssl = $row['domain_ssl']; return true; } /** * Add a shop, and clear the cache. */ public function add($autodate = true, $null_values = false) { $res = parent::add($autodate, $null_values); if ($res) { Shop::cacheShops(true); } return $res; } /** * Associate super admins */ public function associateSuperAdmins() { $employees = Employee::getEmployeesByProfile(_PS_ADMIN_PROFILE_); foreach ($employees as $employee) { $employee = new Employee($employee['id_employee']); $employee->associateTo($this->id); } } /** * Delete shop */ public function delete() { if (!$this->hasDependency($this->id)) { $res = parent::delete(); if ($res) { Shop::cacheShops(true); } return $res; } return false; } /** * Has dependency */ public static function hasDependency($id_shop) { $dependency = false; $nbr_dependency = Shop::getTotalShops(1); if ($nbr_dependency == 1) { $dependency = true; } return $dependency; } /** * Initialize */ public static function initialize() { if (Shop::$initialized) { return; } Shop::init(); // Load shops Shop::cacheShops(); // Set context if (!Shop::getContext()) { if (Shop::isFeatureActive()) { Shop::setContext(Shop::CONTEXT_SHOP, 1); } else { Shop::setContext(Shop::CONTEXT_ALL); } } } /** * Get address */ public function getAddress() { if (!isset($this->address)) { $this->address = new Address(Configuration::get('PS_SHOP_ADDR1', null, null, $this->id)); } return $this->address; } /** * Set theme */ public function setTheme() { $this->theme = new Theme($this->theme_name); } /** * Get base URI */ public function getBaseURI() { return $this->physical_uri; } /** * Get base URL */ public function getBaseURL($auto_secure_mode = true, $add_base_uri = true) { $url = $this->domain; if ($auto_secure_mode && Tools::usingSecureMode()) { $url = $this->domain_ssl; } if ($add_base_uri) { $url .= $this->getBaseURI(); } return $url; } /** * Get group */ public function getGroup() { if (!$this->group) { $this->group = new ShopGroup($this->id_shop_group); } return $this->group; } /** * Get category */ public function getCategory() { return new Category($this->id_category); } /** * Get URLs */ public function getUrls() { $sql = 'SELECT * FROM ' . _DB_PREFIX_ . 'shop_url WHERE id_shop = ' . (int) $this->id; return Db::getInstance()->executeS($sql); } /** * Is default shop */ public function isDefaultShop() { return $this->id == 1; } /** * Get asso table */ public static function getAssoTable($table) { if (!Shop::$initialized) { Shop::init(); } return isset(Shop::$asso_tables[$table]) ? Shop::$asso_tables[$table] : false; } /** * Check ID shop default */ public static function checkIdShopDefault($table) { if (!Shop::$initialized) { Shop::init(); } return in_array($table, Shop::$id_shop_default_tables); } /** * Get asso tables */ public static function getAssoTables() { if (!Shop::$initialized) { Shop::init(); } return Shop::$asso_tables; } /** * Add table association */ public static function addTableAssociation($table_name, $table_details) { if (!Shop::$initialized) { Shop::init(); } Shop::$asso_tables[$table_name] = $table_details; } /** * Is table associated */ public static function isTableAssociated($table) { if (!Shop::$initialized) { Shop::init(); } return isset(Shop::$asso_tables[$table]); } /** * Cache shops */ public static function cacheShops($refresh = false) { if (!is_null(Shop::$shops) && !$refresh) { return Shop::$shops; } Shop::$shops = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' SELECT s.*, su.domain, su.domain_ssl, su.physical_uri, su.virtual_uri FROM ' . _DB_PREFIX_ . 'shop s LEFT JOIN ' . _DB_PREFIX_ . 'shop_url su ON (s.id_shop = su.id_shop) WHERE s.active = 1 AND s.deleted = 0 AND (su.main = 1 OR su.main IS NULL) ORDER BY s.name ASC'); return Shop::$shops; } /** * Get complete list of shops ID */ public static function getCompleteListOfShopsID() { $cache_id = 'Shop::getCompleteListOfShopsID'; if (!Cache::isStored($cache_id)) { $sql = 'SELECT id_shop FROM ' . _DB_PREFIX_ . 'shop WHERE active = 1 AND deleted = 0'; $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql); $array = []; foreach ($result as $row) { $array[] = (int) $row['id_shop']; } Cache::store($cache_id, $array); } return Cache::retrieve($cache_id); } /** * Get shops */ public static function getShops($active = true, $id_shop_group = null, $get_as_list_id = false) { $sql = 'SELECT s.*, su.domain, su.domain_ssl, su.physical_uri, su.virtual_uri FROM ' . _DB_PREFIX_ . 'shop s LEFT JOIN ' . _DB_PREFIX_ . 'shop_url su ON (s.id_shop = su.id_shop) WHERE s.active = ' . (int) $active . ' AND s.deleted = 0 AND (su.main = 1 OR su.main IS NULL)'; if ($id_shop_group) { $sql .= ' AND s.id_shop_group = ' . (int) $id_shop_group; } $sql .= ' ORDER BY s.name ASC'; $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql); if ($get_as_list_id) { $array = []; foreach ($result as $row) { $array[$row['id_shop']] = $row['id_shop']; } return $array; } return $result; } /** * Get URLs shared cart */ public function getUrlsSharedCart() { if (!$this->getGroup()->share_order) { return false; } $sql = 'SELECT DISTINCT su.domain, su.domain_ssl, su.physical_uri, su.virtual_uri FROM ' . _DB_PREFIX_ . 'shop s LEFT JOIN ' . _DB_PREFIX_ . 'shop_url su ON (s.id_shop = su.id_shop) WHERE s.id_shop_group = ' . (int) $this->id_shop_group . ' AND s.active = 1 AND s.deleted = 0 AND (su.main = 1 OR su.main IS NULL)'; return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql); } /** * Get shops collection */ public static function getShopsCollection($active = true, $id_shop_group = null) { $shops = new PrestaShopCollection('Shop'); $shops->where('active', '=', $active); $shops->where('deleted', '=', 0); if ($id_shop_group) { $shops->where('id_shop_group', '=', $id_shop_group); } return $shops; } /** * Get shop */ public static function getShop($shop_id) { if (!Shop::$initialized) { Shop::init(); } foreach (Shop::$shops as $shop) { if ($shop['id_shop'] == $shop_id) { return $shop; } } return false; } /** * Get ID by name */ public static function getIdByName($name) { $sql = 'SELECT id_shop FROM ' . _DB_PREFIX_ . 'shop WHERE name = \'' . pSQL($name) . '\''; $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($sql); return $result; } /** * Get total shops */ public static function getTotalShops($active = true, $id_shop_group = null) { $sql = 'SELECT COUNT(*) FROM ' . _DB_PREFIX_ . 'shop s WHERE s.active = ' . (int) $active . ' AND s.deleted = 0'; if ($id_shop_group) { $sql .= ' AND s.id_shop_group = ' . (int) $id_shop_group; } return Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($sql); } /** * Get group from shop */ public static function getGroupFromShop($shop_id, $as_id = true) { $sql = 'SELECT id_shop_group FROM ' . _DB_PREFIX_ . 'shop WHERE id_shop = ' . (int) $shop_id; $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($sql); if ($as_id) { return $result; } else { return new ShopGroup($result); } } /** * Get group ID from shop ID */ public static function getGroupIdFromShopId(int $shopId): ?int { $sql = 'SELECT id_shop_group FROM ' . _DB_PREFIX_ . 'shop WHERE id_shop = ' . (int) $shopId; $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($sql); return $result ? (int) $result : null; } /** * Get shared shops */ public static function getSharedShops($shop_id, $type) { $sql = 'SELECT DISTINCT s.id_shop FROM ' . _DB_PREFIX_ . 'shop s LEFT JOIN ' . _DB_PREFIX_ . 'shop_group sg ON (s.id_shop_group = sg.id_shop_group) WHERE sg.' . pSQL($type) . ' = 1 AND s.id_shop != ' . (int) $shop_id; return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql); } /** * Get context list shop ID */ public static function getContextListShopID($share = false) { if (Shop::getContext() == Shop::CONTEXT_SHOP) { $list = (int) Shop::getContextShopID(); } elseif (Shop::getContext() == Shop::CONTEXT_GROUP) { $list = Shop::getShops(true, Shop::getContextShopGroupID(), true); } else { $list = Shop::getCompleteListOfShopsID(); } if ($share) { $list = Shop::getSharedShops(Shop::getContextShopID(), $share); } return $list; } /** * Get shop by ID */ public static function getShopById($id, $identifier, $table) { $key = 'Shop::getShopById_' . $table . '_' . $identifier . '_' . $id; if (!Cache::isStored($key)) { $sql = 'SELECT id_shop FROM ' . _DB_PREFIX_ . $table . '_shop WHERE ' . pSQL($identifier) . ' = ' . (int) $id; $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($sql); Cache::store($key, $result); } return Cache::retrieve($key); } /** * Set context */ public static function setContext($type, $id = null) { Shop::$context = $type; Shop::$context_id_shop = null; Shop::$context_id_shop_group = null; switch ($type) { case Shop::CONTEXT_SHOP: Shop::$context_id_shop = (int) $id; break; case Shop::CONTEXT_GROUP: Shop::$context_id_shop_group = (int) $id; break; default: Shop::$context = Shop::CONTEXT_ALL; } } /** * Get context */ public static function getContext() { return Shop::$context; } /** * Reset static cache */ public static function resetStaticCache() { Shop::$shops = null; Shop::$shopGroupIds = null; Shop::$context = null; Shop::$context_id_shop = null; Shop::$context_id_shop_group = null; Shop::$context_shop_group = null; Shop::$feature_active = null; } /** * Reset context */ public static function resetContext() { Shop::$context = null; Shop::$context_id_shop = null; Shop::$context_id_shop_group = null; Shop::$context_shop_group = null; } /** * Get context type */ public function getContextType() { return Shop::getContext(); } /** * Get context shop ID */ public static function getContextShopID($null_value_without_multishop = false) { if ($null_value_without_multishop && !Shop::isFeatureActive()) { return null; } return Shop::$context_id_shop; } /** * Get contextual shop ID */ public function getContextualShopId() { if (Shop::getContext() == Shop::CONTEXT_SHOP) { return (int) Shop::getContextShopID(); } return (int) $this->id; } /** * Get context shop group ID */ public static function getContextShopGroupID($null_value_without_multishop = false) { if ($null_value_without_multishop && !Shop::isFeatureActive()) { return null; } return Shop::$context_id_shop_group; } /** * Get context shop group */ public static function getContextShopGroup() { if (!Shop::$context_shop_group) { Shop::$context_shop_group = new ShopGroup(Shop::getContextShopGroupID()); } return Shop::$context_shop_group; } /** * Add SQL restriction */ public static function addSqlRestriction($share = false, $alias = null) { if (!$alias) { $alias = 's'; } if (Shop::getContext() == Shop::CONTEXT_SHOP) { $restriction = ' AND ' . $alias . '.id_shop = ' . (int) Shop::getContextShopID(); } elseif (Shop::getContext() == Shop::CONTEXT_GROUP) { $restriction = ' AND ' . $alias . '.id_shop IN (' . implode(', ', Shop::getContextListShopID($share)) . ')'; } else { $restriction = ''; } return $restriction; } /** * Add SQL association */ public static function addSqlAssociation($table, $alias, $inner_join = true, $on = null, $force_not_default = false) { $table_alias = $table . '_shop'; if (strpos($table, '.') !== false) { $table_alias = $table; } $asso_table = Shop::getAssoTable($table); if ($asso_table === false || $asso_table['type'] != 'shop') { return; } $join = ''; if (Shop::getContext() == Shop::CONTEXT_SHOP) { if ($inner_join) { $join .= ' INNER JOIN'; } else { $join .= ' LEFT JOIN'; } $join .= ' `' . _DB_PREFIX_ . $table_alias . '` ' . $alias . ' ON (a.id_' . $table . ' = ' . $alias . '.id_' . $table . ' AND ' . $alias . '.id_shop = ' . (int) Shop::getContextShopID() . ')'; } elseif (Shop::getContext() == Shop::CONTEXT_GROUP) { if ($inner_join) { $join .= ' INNER JOIN'; } else { $join .= ' LEFT JOIN'; } $join .= ' `' . _DB_PREFIX_ . $table_alias . '` ' . $alias . ' ON (a.id_' . $table . ' = ' . $alias . '.id_' . $table . ' AND ' . $alias . '.id_shop IN (' . implode(', ', Shop::getContextListShopID()) . '))'; } else { if ($inner_join) { $join .= ' INNER JOIN'; } else { $join .= ' LEFT JOIN'; } $join .= ' `' . _DB_PREFIX_ . $table_alias . '` ' . $alias . ' ON (a.id_' . $table . ' = ' . $alias . '.id_' . $table . ')'; } return $join; } /** * Add SQL restriction on lang */ public static function addSqlRestrictionOnLang($alias = null, $id_shop = null) { if (!$alias) { $alias = 'l'; } if (Shop::getContext() == Shop::CONTEXT_SHOP) { $restriction = ' AND ' . $alias . '.id_shop = ' . (int) Shop::getContextShopID(); } elseif (Shop::getContext() == Shop::CONTEXT_GROUP) { $restriction = ' AND ' . $alias . '.id_shop IN (' . implode(', ', Shop::getContextListShopID()) . ')'; } else { $restriction = ''; } return $restriction; } /** * Get tree */ public static function getTree() { $tree = []; $sql = 'SELECT s.id_shop, s.name, sg.id_shop_group, sg.name as group_name FROM ' . _DB_PREFIX_ . 'shop s LEFT JOIN ' . _DB_PREFIX_ . 'shop_group sg ON (s.id_shop_group = sg.id_shop_group) WHERE s.active = 1 AND s.deleted = 0 ORDER BY sg.name, s.name'; $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql); foreach ($result as $row) { if (!isset($tree[$row['id_shop_group']])) { $tree[$row['id_shop_group']] = [ 'id' => $row['id_shop_group'], 'name' => $row['group_name'], 'shops' => [], ]; } $tree[$row['id_shop_group']]['shops'][] = [ 'id' => $row['id_shop'], 'name' => $row['name'], ]; } return $tree; } /** * Is feature active */ public static function isFeatureActive() { if (Shop::$feature_active === null) { Shop::$feature_active = Configuration::get('PS_MULTISHOP_FEATURE_ACTIVE') && Shop::getTotalShops() > 1; } return Shop::$feature_active; } /** * Copy shop data */ public function copyShopData($old_id, $tables_import = false, $deleted = false) { // Copy shop data $sql = 'SELECT * FROM ' . _DB_PREFIX_ . 'shop WHERE id_shop = ' . (int) $old_id; $old_shop = Db::getInstance()->getRow($sql); if ($old_shop) { $this->id_shop_group = $old_shop['id_shop_group']; $this->id_category = $old_shop['id_category']; $this->theme_name = $old_shop['theme_name']; $this->name = $old_shop['name'] . ' (Copy)'; $this->color = $old_shop['color']; $this->active = $old_shop['active']; $this->deleted = $deleted ? 1 : 0; } return true; } /** * Get categories */ public static function getCategories($id = 0, $only_id = true) { $sql = 'SELECT c.id_category, c.name FROM ' . _DB_PREFIX_ . 'category c LEFT JOIN ' . _DB_PREFIX_ . 'category_shop cs ON (c.id_category = cs.id_category) WHERE cs.id_shop = ' . (int) $id . ' ORDER BY c.name ASC'; $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql); if ($only_id) { $array = []; foreach ($result as $row) { $array[] = $row['id_category']; } return $array; } return $result; } /** * Get entity IDs */ public static function getEntityIds($entity, $id_shop, $active = false, $delete = false) { $sql = 'SELECT e.id_' . pSQL($entity) . ' FROM ' . _DB_PREFIX_ . pSQL($entity) . ' e LEFT JOIN ' . _DB_PREFIX_ . pSQL($entity) . '_shop es ON (e.id_' . pSQL($entity) . ' = es.id_' . pSQL($entity) . ') WHERE es.id_shop = ' . (int) $id_shop; if ($active) { $sql .= ' AND e.active = 1'; } if ($delete) { $sql .= ' AND e.deleted = 1'; } else { $sql .= ' AND e.deleted = 0'; } $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql); $array = []; foreach ($result as $row) { $array[] = $row['id_' . $entity]; } return $array; } /** * Find shop by host */ private static function findShopByHost($host) { $sql = 'SELECT s.id_shop FROM ' . _DB_PREFIX_ . 'shop s LEFT JOIN ' . _DB_PREFIX_ . 'shop_url su ON (s.id_shop = su.id_shop) WHERE su.domain = \'' . pSQL($host) . '\' AND s.active = 1 AND s.deleted = 0'; return Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($sql); } /** * Initialize (simple method) */ public static function initialize() { // TODO: Mandantenfähigkeit später return new Shop(1); } /** * Get base URI (simple method) */ public function getBaseURI() { return $this->physical_uri; } /** * Get group (simple method) */ public function getGroup() { // Dummy-Objekt für Gruppenfunktionen return (object)[ 'id' => 1, 'share_order' => false ]; } /** * Get URLs shared cart (simple method) */ public function getUrlsSharedCart() { // Dummy für getUrlsSharedCart return [$this->domain]; } }