'advblocklink', 'primary' => 'id_link', 'multilang' => TRUE, 'fields' => array( 'id_link' => array('type' => self::TYPE_INT, 'validate' => 'isInt'), 'id_parent' => array('type' => self::TYPE_INT, 'validate' => 'isInt'), 'external' => array('type' => self::TYPE_INT, 'validate' => 'isInt'), 'active' => array('type' => self::TYPE_INT, 'validate' => 'isInt'), 'position' => array('type' => self::TYPE_INT, 'validate' => 'isInt'), // Lang fields 'url' => array('type' => self::TYPE_STRING, 'lang' => TRUE, 'validate' => 'isUrl', 'required' => FALSE, 'size' => 255), 'title' => array('type' => self::TYPE_STRING, 'lang' => TRUE, 'validate' => 'isGenericName', 'required' => TRUE, 'size' => 255) ) ); public function __construct($id = NULL, $id_lang = NULL, $id_shop = NULL) { parent::__construct($id, $id_lang, $id_shop); } public function add($null_values = false, $autodate = true) { $this->position = $this->getHigherPosition($this->id_parent)+1; $result = parent::add($null_values, $autodate); //Add and remove shop association if($result && Shop::isFeatureActive()) { //Delete record if shop has been removed from the list $result &= Db::getInstance()->delete($this->def['table'].'_shop', '`'.$this->def['primary'].'` ='.(int)$this->id.' AND id_shop NOT IN ('.implode(', ', $this->id_shop_list).')'); // Insert new record if shop has been added in the list $insert=''; foreach ($this->id_shop_list as $id_shop) { if($insert != '') $insert .= ', '; $insert .= '('.(int)$this->id.' , '.$id_shop.') '; } $result &= Db::getInstance()->execute(' INSERT IGNORE INTO `'._DB_PREFIX_.$this->def['table'].'_shop` (`'.$this->def['primary'].'`, `id_shop`) VALUES '.$insert ); } Hook::exec('actionRefreshBLocklink'); return $result; } public function update($null_values = FALSE) { // check if the object has a different parent $old_id_parent = -1; $old_object = new AdvLink((int)$this->id); if (Validate::isLoadedObject($old_object)) { $old_id_parent = $old_object->id_parent; if ($old_id_parent != $this->id_parent) { $this->position = $this->getHigherPosition($this->id_parent)+1; } } // update the object $result = parent::update($null_values); //Add and remove shop association if($result && Shop::isFeatureActive()) { //Delete record if shop has been removed from the list $result &= Db::getInstance()->delete($this->def['table'].'_shop', '`'.$this->def['primary'].'` ='.(int)$this->id.' AND id_shop NOT IN ('.implode(', ', $this->id_shop_list).')'); // Insert new record if shop has been added in the list $insert=''; foreach ($this->id_shop_list as $id_shop) { if($insert != '') $insert .= ', '; $insert .= '('.(int)$this->id.' , '.$id_shop.') '; } $result &= Db::getInstance()->execute(' INSERT IGNORE INTO `'._DB_PREFIX_.$this->def['table'].'_shop` (`'.$this->def['primary'].'`, `id_shop`) VALUES '.$insert ); } // update links position of previous parent and the new one if ($result && $old_id_parent != -1) { $this->refreshPositions($old_id_parent); $this->refreshPositions(); } Hook::exec('actionRefreshBLocklink'); return $result; } public function delete() { $this->has_error = FALSE; $nb_sublinks = $this->getNbSubLinks($this->id); if ($nb_sublinks>0) { $this->has_error = TRUE; return FALSE; } if (parent::delete()) { $this->refreshPositions(); return true; } return false; } public function getNbSubLinks($id_link) { return Db::getInstance()->getValue( 'SELECT COUNT(*) FROM `'._DB_PREFIX_.'advblocklink` WHERE `id_parent` = '.(int)$id_link ); } public function hasError() { return $this->has_error; } public static function getPath($id_parent, $id_lang) { $links = []; while ($id_parent) { $obj = new AdvLink((int)$id_parent, (int)$id_lang); $links[] = ['id_link' => $obj->id, 'title' => $obj->title ]; $id_parent = $obj->id_parent; } return array_reverse($links); } public static function getBlockLinks() { $context = Context::getContext(); $menuLinks = self::getLinks(0, $context); foreach($menuLinks as $i => $link) { $menuLinks[$i]['children'] = self::getLinks($link['id_link'], $context); $menuLinks[$i]['nbChildren'] = count($menuLinks[$i]['children']); foreach($menuLinks[$i]['children'] as $y => $children) { $menuLinks[$i]['children'][$y]['children'] = self::getLinks($children['id_link'], $context); } } return $menuLinks; } public static function getLinks($id_parent, $context) { $links = Db::getInstance()->executeS(' SELECT adv.`id_link`, `title`, `url`, `external` FROM `'._DB_PREFIX_.'advblocklink` adv JOIN `'._DB_PREFIX_.'advblocklink_lang` advl ON adv.`id_link` = advl.`id_link` AND id_lang = '. (int)($context->cookie->id_lang) . ' WHERE `id_parent` = ' . (int)$id_parent . ' ORDER BY `position` ASC '); return $links; } public static function getLinksTree(&$links, $id_parent, $id_lang, $id_link_to_exclude=-1, $level=-1) { $level++; $sql = ' SELECT adv.`id_link`, `title`, `id_parent` FROM `'._DB_PREFIX_.'advblocklink` adv JOIN `'._DB_PREFIX_.'advblocklink_lang` advl ON adv.`id_link` = advl.`id_link` AND id_lang = '. (int)($id_lang) . ' WHERE `id_parent` = ' . (int)$id_parent; if ($id_link_to_exclude!=-1) { $sql .= ' AND adv.`id_link` <> '.(int)$id_link_to_exclude; } $sql .= ' ORDER BY `position` ASC'; $rows = Db::getInstance()->executeS($sql); foreach($rows as &$row) { $row['level'] = $level; $links[] = $row; if ($row['id_link']!=$id_link_to_exclude) { self::getLinksTree($links, $row['id_link'], $id_lang, $id_link_to_exclude, $level); } } } public function cleanPositions(){ return Db::getInstance()->execute('UPDATE `'._DB_PREFIX_.'advblocklink` SET `position`= `position` - 1 WHERE `id_link` = '.(int)$this->id_link.' AND `position` > '.(int)$this->position); } public function updatePosition($way, $position) { $sql = 'SELECT `position`, `id_link` FROM `'._DB_PREFIX_.'advblocklink` WHERE `id_parent` = '.(int)$this->id_parent.' ORDER BY `position` ASC'; if (!$res = Db::getInstance()->executeS($sql)) return false; foreach ($res as $row) if ((int)$row['id_link'] == (int)$this->id_link) $moved_row = $row; if (!isset($moved_row) || !isset($position)) return false; // < and > statements rather than BETWEEN operator // since BETWEEN is treated differently according to databases $res = Db::getInstance()->execute(' UPDATE `'._DB_PREFIX_.'advblocklink` SET `position`= `position` '.($way ? '- 1' : '+ 1').' WHERE `id_parent` = '.(int)$this->id_parent.' AND `position` '.($way ? '> '.(int)$moved_row['position'].' AND `position` <= '.(int)$position : '< '.(int)$moved_row['position'].' AND `position` >= '.(int)$position) ) && Db::getInstance()->execute(' UPDATE `'._DB_PREFIX_.'advblocklink` SET `position` = '.(int)$position.' WHERE `id_link`='.(int)$moved_row['id_link'] ); $this->refreshPositions(); Hook::exec('actionRefreshBLocklink'); return $res; } public function refreshPositions($id_parent=-1){ $sql = 'SELECT `id_link` FROM `'._DB_PREFIX_.'advblocklink` WHERE `id_parent` = '.($id_parent>-1 ? $id_parent : (int)$this->id_parent).' ORDER BY `position` ASC'; if (!$blocks = Db::getInstance()->executeS($sql)) return false; $pos=0; foreach ($blocks as $block) { Db::getInstance()->execute(' UPDATE `'._DB_PREFIX_.'advblocklink` SET `position` = '.(int)$pos.' WHERE `id_link`='.(int)$block['id_link']); $pos++; } } public function getHigherPosition($id_parent) { $sql = 'SELECT MAX(`position`) FROM `'._DB_PREFIX_.'advblocklink` WHERE `id_parent` = '.(int)$id_parent; $position = DB::getInstance()->getValue($sql); return (is_numeric($position)) ? $position : -1; } public static function refreshPositionsAll(){ $obj = new AdvLink(null); $sql = 'SELECT DISTINCT id_parent FROM `'._DB_PREFIX_.'advblocklink`'; $rows = Db::getInstance()->executeS($sql); foreach ($rows as $row) { $obj->refreshPositions($row['id_parent']); } } }