* @copyright 2007-2015 PrestaShop SA * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) * International Registered Trademark & Property of PrestaShop SA */ class TabCore extends ObjectModel { /** @var string Displayed name*/ public $name; /** @var string Class and file name*/ public $class_name; public $module; /** @var int parent ID */ public $id_parent; /** @var int position */ public $position; /** @var bool active */ public $active = true; /** @var int hide_host_mode */ public $hide_host_mode = false; const TAB_MODULE_LIST_URL = _PS_TAB_MODULE_LIST_URL_; /** * @see ObjectModel::$definition */ public static $definition = array( 'table' => 'tab', 'primary' => 'id_tab', 'multilang' => true, 'fields' => array( 'id_parent' => array('type' => self::TYPE_INT, 'validate' => 'isInt'), 'position' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedInt'), 'module' => array('type' => self::TYPE_STRING, 'validate' => 'isTabName', 'size' => 64), 'class_name' => array('type' => self::TYPE_STRING, 'required' => true, 'size' => 64), 'active' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), 'hide_host_mode' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), /* Lang fields */ 'name' => array('type' => self::TYPE_STRING, 'lang' => true, 'required' => true, 'validate' => 'isTabName', 'size' => 64), ), ); protected static $_getIdFromClassName = null; /** * additionnal treatments for Tab when creating new one : * - generate a new position * - add access for admin profile * * @param bool $autodate * @param bool $null_values * @return int id_tab */ public function add($autodate = true, $null_values = false) { // @retrocompatibility with old menu (before 1.5.0.9) $retro = array( 'AdminPayment' => 'AdminParentModules', 'AdminOrders' => 'AdminParentOrders', 'AdminCustomers' => 'AdminParentCustomer', 'AdminShipping' => 'AdminParentShipping', 'AdminPreferences' => 'AdminParentPreferences', 'AdminStats' => 'AdminParentStats', 'AdminEmployees' => 'AdminAdmin', ); $class_name = Tab::getClassNameById($this->id_parent); if (isset($retro[$class_name])) { $this->id_parent = Tab::getIdFromClassName($retro[$class_name]); } self::$_cache_tabs = array(); // Set good position for new tab $this->position = Tab::getNewLastPosition($this->id_parent); $this->module = Tools::strtolower($this->module); // Add tab if (parent::add($autodate, $null_values)) { //forces cache to be reloaded self::$_getIdFromClassName = null; return Tab::initAccess($this->id); } return false; } public function save($null_values = false, $autodate = true) { self::$_getIdFromClassName = null; return parent::save(); } /** When creating a new tab $id_tab, this add default rights to the table access * * @todo this should not be public static but protected * @param int $id_tab * @param Context $context * @return bool true if succeed */ public static function initAccess($id_tab, Context $context = null) { if (!$context) { $context = Context::getContext(); } if (!$context->employee || !$context->employee->id_profile) { return false; } /* Profile selection */ $profiles = Db::getInstance()->executeS('SELECT `id_profile` FROM '._DB_PREFIX_.'profile WHERE `id_profile` != 1'); if (!$profiles || empty($profiles)) { return true; } /* Query definition */ $query = 'REPLACE INTO `'._DB_PREFIX_.'access` (`id_profile`, `id_tab`, `view`, `add`, `edit`, `delete`) VALUES '; $query .= '(1, '.(int)$id_tab.', 1, 1, 1, 1),'; foreach ($profiles as $profile) { $rights = $profile['id_profile'] == $context->employee->id_profile ? 1 : 0; $query .= '('.(int)$profile['id_profile'].', '.(int)$id_tab.', '.(int)$rights.', '.(int)$rights.', '.(int)$rights.', '.(int)$rights.'),'; } $query = trim($query, ', '); return Db::getInstance()->execute($query); } public function delete() { if (Db::getInstance()->execute('DELETE FROM '._DB_PREFIX_.'access WHERE `id_tab` = '.(int)$this->id) && parent::delete()) { if (is_array(self::$_getIdFromClassName) && isset(self::$_getIdFromClassName[strtolower($this->class_name)])) { self::$_getIdFromClassName = null; } return $this->cleanPositions($this->id_parent); } return false; } /** * Get tab id * * @return int tab id */ public static function getCurrentTabId() { $id_tab = Tab::getIdFromClassName(Tools::getValue('controller')); // retro-compatibility 1.4/1.5 if (empty($id_tab)) { $id_tab = Tab::getIdFromClassName(Tools::getValue('tab')); } return $id_tab; } /** * Get tab parent id * * @return int tab parent id */ public static function getCurrentParentId() { $cache_id = 'getCurrentParentId_'.Tools::strtolower(Tools::getValue('controller')); if (!Cache::isStored($cache_id)) { $value = Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' SELECT `id_parent` FROM `'._DB_PREFIX_.'tab` WHERE LOWER(class_name) = \''.pSQL(Tools::strtolower(Tools::getValue('controller'))).'\''); if (!$value) { $value = -1; } Cache::store($cache_id, $value); return $value; } return Cache::retrieve($cache_id); } /** * Get tab * * @return array tab */ public static function getTab($id_lang, $id_tab) { $cache_id = 'Tab::getTab_'.(int)$id_lang.'-'.(int)$id_tab; if (!Cache::isStored($cache_id)) { /* Tabs selection */ $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow(' SELECT * FROM `'._DB_PREFIX_.'tab` t LEFT JOIN `'._DB_PREFIX_.'tab_lang` tl ON (t.`id_tab` = tl.`id_tab` AND tl.`id_lang` = '.(int)$id_lang.') WHERE t.`id_tab` = '.(int)$id_tab.(defined('_PS_HOST_MODE_') ? ' AND `hide_host_mode` = 0' : '') ); Cache::store($cache_id, $result); return $result; } return Cache::retrieve($cache_id); } /** * Return the list of tab used by a module * * @return array */ public static function getModuleTabList() { $list = array(); $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' SELECT t.`class_name`, t.`module` FROM `'._DB_PREFIX_.'tab` t WHERE t.`module` IS NOT NULL AND t.`module` != ""'); if (is_array($result)) { foreach ($result as $detail) { $list[strtolower($detail['class_name'])] = $detail; } } return $list; } /** * Get tabs * * @return array tabs */ protected static $_cache_tabs = array(); public static function getTabs($id_lang, $id_parent = null) { if (!isset(self::$_cache_tabs[$id_lang])) { self::$_cache_tabs[$id_lang] = array(); // Keep t.*, tl.name instead of only * because if translations are missing, the join on tab_lang will overwrite the id_tab in the results $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' SELECT t.*, tl.name FROM `'._DB_PREFIX_.'tab` t LEFT JOIN `'._DB_PREFIX_.'tab_lang` tl ON (t.`id_tab` = tl.`id_tab` AND tl.`id_lang` = '.(int)$id_lang.') WHERE 1 '.(defined('_PS_HOST_MODE_') ? ' AND `hide_host_mode` = 0' : '').' ORDER BY t.`position` ASC' ); if (is_array($result)) { foreach ($result as $row) { if (!isset(self::$_cache_tabs[$id_lang][$row['id_parent']])) { self::$_cache_tabs[$id_lang][$row['id_parent']] = array(); } self::$_cache_tabs[$id_lang][$row['id_parent']][] = $row; } } } if ($id_parent === null) { $array_all = array(); foreach (self::$_cache_tabs[$id_lang] as $array_parent) { $array_all = array_merge($array_all, $array_parent); } return $array_all; } return (isset(self::$_cache_tabs[$id_lang][$id_parent]) ? self::$_cache_tabs[$id_lang][$id_parent] : array()); } /** * Get tab id from name * * @param string $class_name * @return int id_tab */ public static function getIdFromClassName($class_name) { $class_name = strtolower($class_name); if (self::$_getIdFromClassName === null) { self::$_getIdFromClassName = array(); $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS('SELECT id_tab, class_name FROM `'._DB_PREFIX_.'tab`', true, false); if (is_array($result)) { foreach ($result as $row) { self::$_getIdFromClassName[strtolower($row['class_name'])] = $row['id_tab']; } } } return (isset(self::$_getIdFromClassName[$class_name]) ? (int)self::$_getIdFromClassName[$class_name] : false); } /** * Get collection from module name * * @param $module string Module name * @param null $id_lang integer Language ID * @return array|PrestaShopCollection Collection of tabs (or empty array) */ public static function getCollectionFromModule($module, $id_lang = null) { if (is_null($id_lang)) { $id_lang = Context::getContext()->language->id; } if (!Validate::isModuleName($module)) { return array(); } $tabs = new PrestaShopCollection('Tab', (int)$id_lang); $tabs->where('module', '=', $module); return $tabs; } /** * Enabling tabs for module * * @param $module string Module Name * @return bool Status */ public static function enablingForModule($module) { $tabs = Tab::getCollectionFromModule($module); if (!empty($tabs)) { foreach ($tabs as $tab) { $tab->active = 1; $tab->save(); } return true; } return false; } /** * Disabling tabs for module * * @param $module string Module name * @return bool Status */ public static function disablingForModule($module) { $tabs = Tab::getCollectionFromModule($module); if (!empty($tabs)) { foreach ($tabs as $tab) { $tab->active = 0; $tab->save(); } return true; } return false; } /** * Get Instance from tab class name * * @param $class_name string Name of tab class * @param $id_lang integer id_lang * @return Tab Tab object (empty if bad id or class name) */ public static function getInstanceFromClassName($class_name, $id_lang = null) { $id_tab = (int)Tab::getIdFromClassName($class_name); return new Tab($id_tab, $id_lang); } public static function getNbTabs($id_parent = null) { return (int)Db::getInstance()->getValue(' SELECT COUNT(*) FROM `'._DB_PREFIX_.'tab` t '.(!is_null($id_parent) ? 'WHERE t.`id_parent` = '.(int)$id_parent : '') ); } /** * return an available position in subtab for parent $id_parent * * @param mixed $id_parent * @return int */ public static function getNewLastPosition($id_parent) { return (Db::getInstance()->getValue(' SELECT IFNULL(MAX(position),0)+1 FROM `'._DB_PREFIX_.'tab` WHERE `id_parent` = '.(int)$id_parent )); } public function move($direction) { $nb_tabs = Tab::getNbTabs($this->id_parent); if ($direction != 'l' && $direction != 'r') { return false; } if ($nb_tabs <= 1) { return false; } if ($direction == 'l' && $this->position <= 1) { return false; } if ($direction == 'r' && $this->position >= $nb_tabs) { return false; } $new_position = ($direction == 'l') ? $this->position - 1 : $this->position + 1; Db::getInstance()->execute(' UPDATE `'._DB_PREFIX_.'tab` t SET position = '.(int)$this->position.' WHERE id_parent = '.(int)$this->id_parent.' AND position = '.(int)$new_position ); $this->position = $new_position; return $this->update(); } public function cleanPositions($id_parent) { $result = Db::getInstance()->executeS(' SELECT `id_tab` FROM `'._DB_PREFIX_.'tab` WHERE `id_parent` = '.(int)$id_parent.' ORDER BY `position` '); $sizeof = count($result); for ($i = 0; $i < $sizeof; ++$i) { Db::getInstance()->execute(' UPDATE `'._DB_PREFIX_.'tab` SET `position` = '.($i + 1).' WHERE `id_tab` = '.(int)$result[$i]['id_tab'] ); } return true; } public function updatePosition($way, $position) { if (!$res = Db::getInstance()->executeS(' SELECT t.`id_tab`, t.`position`, t.`id_parent` FROM `'._DB_PREFIX_.'tab` t WHERE t.`id_parent` = '.(int)$this->id_parent.' ORDER BY t.`position` ASC' )) { return false; } foreach ($res as $tab) { if ((int)$tab['id_tab'] == (int)$this->id) { $moved_tab = $tab; } } if (!isset($moved_tab) || !isset($position)) { return false; } // < and > statements rather than BETWEEN operator // since BETWEEN is treated differently according to databases $result = (Db::getInstance()->execute(' UPDATE `'._DB_PREFIX_.'tab` SET `position`= `position` '.($way ? '- 1' : '+ 1').' WHERE `position` '.($way ? '> '.(int)$moved_tab['position'].' AND `position` <= '.(int)$position : '< '.(int)$moved_tab['position'].' AND `position` >= '.(int)$position).' AND `id_parent`='.(int)$moved_tab['id_parent']) && Db::getInstance()->execute(' UPDATE `'._DB_PREFIX_.'tab` SET `position` = '.(int)$position.' WHERE `id_parent` = '.(int)$moved_tab['id_parent'].' AND `id_tab`='.(int)$moved_tab['id_tab'])); return $result; } public static function checkTabRights($id_tab) { static $tabAccesses = null; if (Context::getContext()->employee->id_profile == _PS_ADMIN_PROFILE_) { return true; } if ($tabAccesses === null) { $tabAccesses = Profile::getProfileAccesses(Context::getContext()->employee->id_profile); } if (isset($tabAccesses[(int)$id_tab]['view'])) { return ($tabAccesses[(int)$id_tab]['view'] === '1'); } return false; } public static function recursiveTab($id_tab, $tabs) { $admin_tab = Tab::getTab((int)Context::getContext()->language->id, $id_tab); $tabs[] = $admin_tab; if ($admin_tab['id_parent'] > 0) { $tabs = Tab::recursiveTab($admin_tab['id_parent'], $tabs); } return $tabs; } /** * Overrides update to set position to last when changing parent tab * * @see ObjectModel::update * @param bool $null_values * @return bool */ public function update($null_values = false) { $current_tab = new Tab($this->id); if ($current_tab->id_parent != $this->id_parent) { $this->position = Tab::getNewLastPosition($this->id_parent); } self::$_cache_tabs = array(); return parent::update($null_values); } public static function getTabByIdProfile($id_parent, $id_profile) { return Db::getInstance()->executeS(' SELECT t.`id_tab`, t.`id_parent`, tl.`name`, a.`id_profile` FROM `'._DB_PREFIX_.'tab` t LEFT JOIN `'._DB_PREFIX_.'access` a ON (a.`id_tab` = t.`id_tab`) LEFT JOIN `'._DB_PREFIX_.'tab_lang` tl ON (t.`id_tab` = tl.`id_tab` AND tl.`id_lang` = '.(int)Context::getContext()->language->id.') WHERE a.`id_profile` = '.(int)$id_profile.' AND t.`id_parent` = '.(int)$id_parent.' AND a.`view` = 1 AND a.`edit` = 1 AND a.`delete` = 1 AND a.`add` = 1 AND t.`id_parent` != 0 AND t.`id_parent` != -1 '.(defined('_PS_HOST_MODE_') ? ' AND `hide_host_mode` = 0' : '').' ORDER BY t.`id_parent` ASC '); } /** * @since 1.5.0 */ public static function getClassNameById($id_tab) { return Db::getInstance()->getValue('SELECT class_name FROM '._DB_PREFIX_.'tab WHERE id_tab = '.(int)$id_tab); } public static function getTabModulesList($id_tab) { $modules_list = array('default_list' => array(), 'slider_list' => array()); $xml_tab_modules_list = false; if (file_exists(_PS_ROOT_DIR_.Module::CACHE_FILE_TAB_MODULES_LIST)) { $xml_tab_modules_list = @simplexml_load_file(_PS_ROOT_DIR_.Module::CACHE_FILE_TAB_MODULES_LIST); } $class_name = null; $display_type = 'default_list'; if ($xml_tab_modules_list) { foreach ($xml_tab_modules_list->tab as $tab) { foreach ($tab->attributes() as $key => $value) { if ($key == 'class_name') { $class_name = (string)$value; } } if (Tab::getIdFromClassName((string)$class_name) == $id_tab) { foreach ($tab->attributes() as $key => $value) { if ($key == 'display_type') { $display_type = (string)$value; } } foreach ($tab->children() as $module) { $modules_list[$display_type][(int)$module['position']] = (string)$module['name']; } ksort($modules_list[$display_type]); } } } return $modules_list; } }