From ed834b0893a21e947ab5ec0c151d9ac5144bba87 Mon Sep 17 00:00:00 2001 From: gskema Date: Sun, 19 Jun 2016 22:47:17 +0300 Subject: [PATCH 1/6] [*] MO: Use hashtag as href if top menu URL is empty --- modules/cttopmenu/views/templates/hook/tree_item.tpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/cttopmenu/views/templates/hook/tree_item.tpl b/modules/cttopmenu/views/templates/hook/tree_item.tpl index 618ac69f..3f6f5aa9 100644 --- a/modules/cttopmenu/views/templates/hook/tree_item.tpl +++ b/modules/cttopmenu/views/templates/hook/tree_item.tpl @@ -1,5 +1,5 @@
  • - + {if !empty($item.icon)}{/if} {$item.name|escape:'html':'UTF-8'} From 346d62c180e7280c0457d1f10de903d9ffd28535 Mon Sep 17 00:00:00 2001 From: gskema Date: Sun, 19 Jun 2016 22:47:41 +0300 Subject: [PATCH 2/6] [+] MO: Add menu item type: category list --- modules/cttopmenu/classes/CTTopMenuItem.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/modules/cttopmenu/classes/CTTopMenuItem.php b/modules/cttopmenu/classes/CTTopMenuItem.php index 7a152236..6c0b8cf2 100644 --- a/modules/cttopmenu/classes/CTTopMenuItem.php +++ b/modules/cttopmenu/classes/CTTopMenuItem.php @@ -12,6 +12,7 @@ class CTTopMenuItem extends ObjectModel const TYPE_PRODUCT = 1; const TYPE_CATEGORY = 2; const TYPE_CATEGORY_TREE = 3; + const TYPE_CATEGORY_LIST = 11; const TYPE_CMS = 4; const TYPE_CMS_CATEGORY = 5; const TYPE_CMS_CATEGORY_TREE = 6; @@ -72,6 +73,7 @@ class CTTopMenuItem extends ObjectModel self::TYPE_PRODUCT, self::TYPE_CATEGORY, self::TYPE_CATEGORY_TREE, + self::TYPE_CATEGORY_LIST, self::TYPE_CMS, self::TYPE_CMS_CATEGORY, self::TYPE_CMS_CATEGORY_TREE, From 5c187dbf6b169020c41c394393b85b0bf5f53d7a Mon Sep 17 00:00:00 2001 From: gskema Date: Sun, 19 Jun 2016 23:31:01 +0300 Subject: [PATCH 3/6] [+] MO: Add menu item type: category list to Admin controller --- .../controllers/admin/AdminCTTopMenuItemController.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/modules/cttopmenu/controllers/admin/AdminCTTopMenuItemController.php b/modules/cttopmenu/controllers/admin/AdminCTTopMenuItemController.php index abdae7f0..a7cacf1f 100644 --- a/modules/cttopmenu/controllers/admin/AdminCTTopMenuItemController.php +++ b/modules/cttopmenu/controllers/admin/AdminCTTopMenuItemController.php @@ -55,6 +55,9 @@ public function __construct() 'tree_max_depth' => true, ), ), + CTTopMenuItem::TYPE_CATEGORY_LIST => array( + 'name' => $this->l('Category List'), + ), CTTopMenuItem::TYPE_CMS => array( 'name' => $this->l('CMS Link'), 'entity_name' => $this->l('CMS'), From 567e32d19b5dc805d492be56196410acd88b9c74 Mon Sep 17 00:00:00 2001 From: gskema Date: Sun, 19 Jun 2016 23:31:26 +0300 Subject: [PATCH 4/6] [*] MO: Generate flat category list menu item --- modules/cttopmenu/cttopmenu.php | 89 +++++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) diff --git a/modules/cttopmenu/cttopmenu.php b/modules/cttopmenu/cttopmenu.php index b92e8e75..1c3203a1 100644 --- a/modules/cttopmenu/cttopmenu.php +++ b/modules/cttopmenu/cttopmenu.php @@ -364,6 +364,8 @@ public function buildMenuItem(array $menuItem, $id_shop, $id_lang) return $this->buildCategoryLink($menuItem, $id_shop, $id_lang); case CTTopMenuItem::TYPE_CATEGORY_TREE: return $this->buildCategoryTree($menuItem, $id_shop, $id_lang); + case CTTopMenuItem::TYPE_CATEGORY_LIST: + return $this->buildCategoryList($menuItem, $id_shop, $id_lang); case CTTopMenuItem::TYPE_CMS: return $this->buildCmsLink($menuItem, $id_shop, $id_lang); case CTTopMenuItem::TYPE_CMS_CATEGORY: @@ -590,6 +592,53 @@ protected function buildCategoryTreeItem(array $category, $id_shop, $id_lang, $d ); } + protected function buildCategoryList(array $menuItem, $id_shop, $id_lang) + { + $name = $menuItem['name']; + $url = $menuItem['url']; + $title = $menuItem['title']; + + if (empty($name)) { + $name = $this->l('Categories'); + } + + if (empty($title)) { + $title = $this->l('A list of all categories'); + } + + $subItems = array(); + foreach ($this->getFlatCategoryListIds($id_shop, $id_lang, true) as $id_category) { + + $category = new Category($id_category, $id_lang, $id_shop); + + $subItems[] = array( + 'name' => $category->name, + 'url' => $this->context->link->getCategoryLink($category, null, $id_lang, null, $id_shop), + 'title' => $category->name, + 'icon' => '', + 'no_follow' => false, + 'id' => '', + 'entity_id' => 'cat-'.$category->id, + 'class' => '', + 'type' => 'category-list-link', + 'sub_items' => array(), + ); + } + + return array( + 'name' => $name, + 'url' => $url, + 'title' => $title, + 'icon' => $menuItem['icon'], + 'no_follow' => $menuItem['no_follow'], + 'id' => $menuItem['id_ct_top_menu_item'], + 'entity_id' => '', + 'class' => $menuItem['class'], + 'type' => 'category-list', + 'sub_items' => $subItems, + ); + } + /** * Builds menu item * @@ -1015,4 +1064,44 @@ protected function buildSupplierList(array $menuItem, $id_lang) 'sub_items' => $subItems, ); } + + /** + * Returns a flat list of IDs of all categories in the shop, ordered by name + * + * @param int $id_shop + * @param int $id_lang + * @param bool|null $active + * + * @return array + * @throws PrestaShopDatabaseException + */ + protected function getFlatCategoryListIds($id_shop, $id_lang, $active = null) + { + $id_category_root = 2; + + $sql = new DbQuery(); + $sql->select('c.id_category') + ->from('category', 'c') + ->leftJoin( + 'category_lang', + 'cl', + 'c.id_category = cl.id_category AND cl.id_lang = '.(int)$id_lang.' AND cl.id_shop = '.(int)$id_shop + ) + ->innerJoin('category_shop', 'cs', 'c.id_category = cs.id_category AND cs.id_shop = '.(int)$id_shop) + ->where('c.id_category > '.$id_category_root) + ->orderBy('cl.name ASC'); + + if ($active !== null) { + $sql->where('active = '.(int)boolval($active)); + } + + $rows = (array)Db::getInstance()->executeS($sql); + + $categoryIds = []; + foreach ($rows as $row) { + $categoryIds[] = (int)$row['id_category']; + } + + return $categoryIds; + } } From 6b9cb51f03d718e47f734d36bb679631a802099a Mon Sep 17 00:00:00 2001 From: gskema Date: Tue, 28 Jun 2016 21:13:34 +0300 Subject: [PATCH 5/6] [*] MO: Use category tree builder then flatten the result --- modules/cttopmenu/classes/CTTopMenuItem.php | 26 ++--- .../admin/AdminCTTopMenuItemController.php | 20 ++-- modules/cttopmenu/cttopmenu.php | 103 ++++++------------ 3 files changed, 56 insertions(+), 93 deletions(-) diff --git a/modules/cttopmenu/classes/CTTopMenuItem.php b/modules/cttopmenu/classes/CTTopMenuItem.php index 6c0b8cf2..8fc25409 100644 --- a/modules/cttopmenu/classes/CTTopMenuItem.php +++ b/modules/cttopmenu/classes/CTTopMenuItem.php @@ -8,18 +8,18 @@ class CTTopMenuItem extends ObjectModel /** * Menu item types */ - const TYPE_CUSTOM_LINK = 0; - const TYPE_PRODUCT = 1; - const TYPE_CATEGORY = 2; - const TYPE_CATEGORY_TREE = 3; - const TYPE_CATEGORY_LIST = 11; - const TYPE_CMS = 4; - const TYPE_CMS_CATEGORY = 5; - const TYPE_CMS_CATEGORY_TREE = 6; - const TYPE_MANUFACTURER = 7; - const TYPE_MANUFACTURER_LIST = 8; - const TYPE_SUPPLIER = 9; - const TYPE_SUPPLIER_LIST = 10; + const TYPE_CUSTOM_LINK = 0; + const TYPE_PRODUCT = 1; + const TYPE_CATEGORY = 2; + const TYPE_CATEGORY_TREE = 3; + const TYPE_CATEGORY_FLAT_TREE = 11; + const TYPE_CMS = 4; + const TYPE_CMS_CATEGORY = 5; + const TYPE_CMS_CATEGORY_TREE = 6; + const TYPE_MANUFACTURER = 7; + const TYPE_MANUFACTURER_LIST = 8; + const TYPE_SUPPLIER = 9; + const TYPE_SUPPLIER_LIST = 10; /** @var int */ public $type = 0; @@ -73,7 +73,7 @@ class CTTopMenuItem extends ObjectModel self::TYPE_PRODUCT, self::TYPE_CATEGORY, self::TYPE_CATEGORY_TREE, - self::TYPE_CATEGORY_LIST, + self::TYPE_CATEGORY_FLAT_TREE, self::TYPE_CMS, self::TYPE_CMS_CATEGORY, self::TYPE_CMS_CATEGORY_TREE, diff --git a/modules/cttopmenu/controllers/admin/AdminCTTopMenuItemController.php b/modules/cttopmenu/controllers/admin/AdminCTTopMenuItemController.php index a7cacf1f..0d80048f 100644 --- a/modules/cttopmenu/controllers/admin/AdminCTTopMenuItemController.php +++ b/modules/cttopmenu/controllers/admin/AdminCTTopMenuItemController.php @@ -55,8 +55,13 @@ public function __construct() 'tree_max_depth' => true, ), ), - CTTopMenuItem::TYPE_CATEGORY_LIST => array( - 'name' => $this->l('Category List'), + CTTopMenuItem::TYPE_CATEGORY_FLAT_TREE => array( + 'name' => $this->l('Category Flat Tree'), + 'entity_name' => $this->l('Category'), + 'fields' => array( + 'entity_id' => true, + 'tree_max_depth' => true, + ), ), CTTopMenuItem::TYPE_CMS => array( 'name' => $this->l('CMS Link'), @@ -103,14 +108,9 @@ public function __construct() ); // Write ID column so we can use this array as option list in fields form - $this->menuItemTypes = array_map( - function ($value, $key) { - $value['id'] = $key; - return $value; - }, - $this->menuItemTypes, - array_keys($this->menuItemTypes) - ); + foreach ($this->menuItemTypes as $menuItemTypeKey => &$menuItemType) { + $menuItemType['id'] = $menuItemTypeKey; + } } /** diff --git a/modules/cttopmenu/cttopmenu.php b/modules/cttopmenu/cttopmenu.php index 1c3203a1..9589452c 100644 --- a/modules/cttopmenu/cttopmenu.php +++ b/modules/cttopmenu/cttopmenu.php @@ -364,8 +364,8 @@ public function buildMenuItem(array $menuItem, $id_shop, $id_lang) return $this->buildCategoryLink($menuItem, $id_shop, $id_lang); case CTTopMenuItem::TYPE_CATEGORY_TREE: return $this->buildCategoryTree($menuItem, $id_shop, $id_lang); - case CTTopMenuItem::TYPE_CATEGORY_LIST: - return $this->buildCategoryList($menuItem, $id_shop, $id_lang); + case CTTopMenuItem::TYPE_CATEGORY_FLAT_TREE: + return $this->buildCategoryFlatTree($menuItem, $id_shop, $id_lang); case CTTopMenuItem::TYPE_CMS: return $this->buildCmsLink($menuItem, $id_shop, $id_lang); case CTTopMenuItem::TYPE_CMS_CATEGORY: @@ -592,51 +592,33 @@ protected function buildCategoryTreeItem(array $category, $id_shop, $id_lang, $d ); } - protected function buildCategoryList(array $menuItem, $id_shop, $id_lang) + /** + * Builds a menu tree where subcategories of a given category + * are a flattened + * + * @param array $menuItem + * @param int $id_shop + * @param int $id_lang + * + * @return array + */ + protected function buildCategoryFlatTree(array $menuItem, $id_shop, $id_lang) { - $name = $menuItem['name']; - $url = $menuItem['url']; - $title = $menuItem['title']; + $tree = $this->buildCategoryTree($menuItem, $id_shop, $id_lang); + $tree['type'] = 'category-flat-tree'; - if (empty($name)) { - $name = $this->l('Categories'); + $treeSubItems = array(); + foreach ($tree['sub_items'] as $subItemKey => $subItemTree) { + $treeSubItems = array_merge($treeSubItems, $this->flattenMenuItemTree($subItemTree)); } - if (empty($title)) { - $title = $this->l('A list of all categories'); - } - - $subItems = array(); - foreach ($this->getFlatCategoryListIds($id_shop, $id_lang, true) as $id_category) { + usort($treeSubItems, function ($a, $b) { + return ($a['name'] < $b['name']) ? -1 : 1; + }); - $category = new Category($id_category, $id_lang, $id_shop); - - $subItems[] = array( - 'name' => $category->name, - 'url' => $this->context->link->getCategoryLink($category, null, $id_lang, null, $id_shop), - 'title' => $category->name, - 'icon' => '', - 'no_follow' => false, - 'id' => '', - 'entity_id' => 'cat-'.$category->id, - 'class' => '', - 'type' => 'category-list-link', - 'sub_items' => array(), - ); - } + $tree['sub_items'] = $treeSubItems; - return array( - 'name' => $name, - 'url' => $url, - 'title' => $title, - 'icon' => $menuItem['icon'], - 'no_follow' => $menuItem['no_follow'], - 'id' => $menuItem['id_ct_top_menu_item'], - 'entity_id' => '', - 'class' => $menuItem['class'], - 'type' => 'category-list', - 'sub_items' => $subItems, - ); + return $tree; } /** @@ -1066,42 +1048,23 @@ protected function buildSupplierList(array $menuItem, $id_lang) } /** - * Returns a flat list of IDs of all categories in the shop, ordered by name + * Flattens the menu tree to a flat list (array) * - * @param int $id_shop - * @param int $id_lang - * @param bool|null $active + * @param array $menuItem * * @return array - * @throws PrestaShopDatabaseException */ - protected function getFlatCategoryListIds($id_shop, $id_lang, $active = null) + protected function flattenMenuItemTree(array $menuItem) { - $id_category_root = 2; - - $sql = new DbQuery(); - $sql->select('c.id_category') - ->from('category', 'c') - ->leftJoin( - 'category_lang', - 'cl', - 'c.id_category = cl.id_category AND cl.id_lang = '.(int)$id_lang.' AND cl.id_shop = '.(int)$id_shop - ) - ->innerJoin('category_shop', 'cs', 'c.id_category = cs.id_category AND cs.id_shop = '.(int)$id_shop) - ->where('c.id_category > '.$id_category_root) - ->orderBy('cl.name ASC'); - - if ($active !== null) { - $sql->where('active = '.(int)boolval($active)); - } + $menuItemList = array(); - $rows = (array)Db::getInstance()->executeS($sql); - - $categoryIds = []; - foreach ($rows as $row) { - $categoryIds[] = (int)$row['id_category']; + foreach ($menuItem['sub_items'] as $menuSubItem) { + $menuItemList = array_merge($menuItemList, $this->flattenMenuItemTree($menuSubItem)); } - return $categoryIds; + $menuItem['sub_items'] = array(); + $menuItemList[] = $menuItem; + + return $menuItemList; } } From fabc6940bcbf1f81c7dd46d0addbaed2647e0911 Mon Sep 17 00:00:00 2001 From: gskema Date: Tue, 28 Jun 2016 21:14:10 +0300 Subject: [PATCH 6/6] [*] MO: Change cttopmenu version to 1.1.0 --- modules/cttopmenu/config.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/cttopmenu/config.xml b/modules/cttopmenu/config.xml index afee2939..cc1e6dcb 100644 --- a/modules/cttopmenu/config.xml +++ b/modules/cttopmenu/config.xml @@ -2,11 +2,11 @@ cttopmenu - + 1 1 - + \ No newline at end of file