diff --git a/config/allowed_files.php b/config/allowed_files.php
index 553def5..fa1363b 100644
--- a/config/allowed_files.php
+++ b/config/allowed_files.php
@@ -334,6 +334,10 @@
'views/templates/hook/prettyblocks/prettyblock_login.tpl',
'views/templates/hook/prettyblocks/prettyblock_lookbook.tpl',
'views/templates/hook/prettyblocks/prettyblock_masonry_gallery.tpl',
+ 'views/templates/hook/prettyblocks/prettyblock_megamenu_column.tpl',
+ 'views/templates/hook/prettyblocks/prettyblock_megamenu_item.tpl',
+ 'views/templates/hook/prettyblocks/prettyblock_megamenu_item_image.tpl',
+ 'views/templates/hook/prettyblocks/prettyblock_megamenu_item_link.tpl',
'views/templates/hook/prettyblocks/prettyblock_modal.tpl',
'views/templates/hook/prettyblocks/prettyblock_mystery_boxes.tpl',
'views/templates/hook/prettyblocks/prettyblock_latest_guides.tpl',
diff --git a/everblock.php b/everblock.php
index 636a774..1ce0bde 100644
--- a/everblock.php
+++ b/everblock.php
@@ -645,6 +645,13 @@ public function checkHooks()
$hook->description = 'This hook triggers before special event block is rendered';
$hook->save();
}
+ if (!Hook::getIdByName('beforeRenderingEverblockMegamenuItem')) {
+ $hook = new Hook();
+ $hook->name = 'beforeRenderingEverblockMegamenuItem';
+ $hook->title = 'Before rendering mega menu item block';
+ $hook->description = 'This hook triggers before mega menu item block is rendered';
+ $hook->save();
+ }
$this->registerHook('beforeRenderingEverblockProductHighlight');
$this->registerHook('beforeRenderingEverblockCategoryTabs');
$this->registerHook('beforeRenderingEverblockCategoryPrice');
@@ -653,6 +660,7 @@ public function checkHooks()
$this->registerHook('beforeRenderingEverblockCategoryProducts');
$this->registerHook('beforeRenderingEverblockSpecialEvent');
$this->registerHook('beforeRenderingEverblockEverblock');
+ $this->registerHook('beforeRenderingEverblockMegamenuItem');
} else {
$this->unregisterHook('beforeRenderingEverblockProductHighlight');
$this->unregisterHook('beforeRenderingEverblockCategoryTabs');
@@ -662,6 +670,7 @@ public function checkHooks()
$this->unregisterHook('beforeRenderingEverblockCategoryProducts');
$this->unregisterHook('beforeRenderingEverblockSpecialEvent');
$this->unregisterHook('beforeRenderingEverblockEverblock');
+ $this->unregisterHook('beforeRenderingEverblockMegamenuItem');
}
// Vérifier si l'onglet "AdminEverBlockParent" existe déjà
$id_tab = Tab::getIdFromClassName('AdminEverBlockParent');
@@ -5865,6 +5874,136 @@ public function hookBeforeRenderingEverblockCategoryProducts($params)
return ['products' => $products];
}
+ public function hookBeforeRenderingEverblockMegamenuItem($params)
+ {
+ $menuId = (int) ($params['block']['id_prettyblocks'] ?? 0);
+ if ($menuId <= 0) {
+ return ['columns' => []];
+ }
+
+ $idLang = (int) $this->context->language->id;
+ $idShop = (int) $this->context->shop->id;
+
+ $columns = $this->getPrettyblocksByCode('megamenu_column', $idLang, $idShop);
+ $links = $this->getPrettyblocksByCode('megamenu_item_link', $idLang, $idShop);
+ $images = $this->getPrettyblocksByCode('megamenu_item_image', $idLang, $idShop);
+
+ $columns = array_filter($columns, function (array $column) use ($menuId): bool {
+ $parentId = $this->normalizePrettyblocksRelationId($column['settings']['parent_menu'] ?? null);
+ return $parentId === $menuId;
+ });
+
+ $linksByColumn = [];
+ foreach ($links as $link) {
+ $parentId = $this->normalizePrettyblocksRelationId($link['settings']['parent_column'] ?? null);
+ if ($parentId <= 0) {
+ continue;
+ }
+ $link['settings']['url'] = $this->normalizePrettyblocksLink($link['settings']['url'] ?? '');
+ $linksByColumn[$parentId][] = $link;
+ }
+
+ $imagesByColumn = [];
+ foreach ($images as $image) {
+ $parentId = $this->normalizePrettyblocksRelationId($image['settings']['parent_column'] ?? null);
+ if ($parentId <= 0) {
+ continue;
+ }
+ $image['settings']['url'] = $this->normalizePrettyblocksLink($image['settings']['url'] ?? '');
+ $imagesByColumn[$parentId][] = $image;
+ }
+
+ foreach ($columns as &$column) {
+ $columnId = (int) $column['id_prettyblocks'];
+ $column['settings']['title_url'] = $this->normalizePrettyblocksLink(
+ $column['settings']['title_url'] ?? ''
+ );
+ $column['links'] = $this->sortPrettyblocksByOrder($linksByColumn[$columnId] ?? []);
+ $column['images'] = $this->sortPrettyblocksByOrder($imagesByColumn[$columnId] ?? []);
+ }
+ unset($column);
+
+ $columns = $this->sortPrettyblocksByOrder(array_values($columns));
+
+ return ['columns' => $columns];
+ }
+
+ private function getPrettyblocksByCode(string $code, int $idLang, int $idShop): array
+ {
+ $query = 'SELECT id_prettyblocks, config, position'
+ . ' FROM ' . _DB_PREFIX_ . 'prettyblocks'
+ . ' WHERE code = "' . pSQL($code) . '"'
+ . ' AND id_lang = ' . $idLang
+ . ' AND id_shop = ' . $idShop;
+
+ $rows = Db::getInstance()->executeS($query);
+ if (!is_array($rows)) {
+ return [];
+ }
+
+ $blocks = [];
+ foreach ($rows as $row) {
+ $settings = json_decode((string) ($row['config'] ?? ''), true);
+ if (!is_array($settings)) {
+ $settings = [];
+ }
+ $blocks[] = [
+ 'id_prettyblocks' => (int) ($row['id_prettyblocks'] ?? 0),
+ 'settings' => $settings,
+ 'position' => (int) ($row['position'] ?? 0),
+ ];
+ }
+
+ return $blocks;
+ }
+
+ private function normalizePrettyblocksRelationId($value): int
+ {
+ if (is_array($value)) {
+ if (isset($value['id'])) {
+ return (int) $value['id'];
+ }
+ if (isset($value['value'])) {
+ return (int) $value['value'];
+ }
+ }
+
+ return (int) $value;
+ }
+
+ private function normalizePrettyblocksLink($value): string
+ {
+ if (is_array($value)) {
+ if (isset($value['url'])) {
+ return (string) $value['url'];
+ }
+ if (isset($value['link'])) {
+ return (string) $value['link'];
+ }
+ if (isset($value['href'])) {
+ return (string) $value['href'];
+ }
+ }
+
+ return (string) $value;
+ }
+
+ private function sortPrettyblocksByOrder(array $items): array
+ {
+ usort($items, function (array $left, array $right): int {
+ $leftOrder = isset($left['settings']['order']) ? (int) $left['settings']['order'] : 0;
+ $rightOrder = isset($right['settings']['order']) ? (int) $right['settings']['order'] : 0;
+
+ if ($leftOrder === $rightOrder) {
+ return ($left['position'] ?? 0) <=> ($right['position'] ?? 0);
+ }
+
+ return $leftOrder <=> $rightOrder;
+ });
+
+ return $items;
+ }
+
public function hookDisplayReassurance($params)
{
if (!isset($this->context->controller) || !is_object($this->context->controller)) {
diff --git a/src/Service/EverblockPrettyBlocks.php b/src/Service/EverblockPrettyBlocks.php
index 6c89b50..167e0b9 100644
--- a/src/Service/EverblockPrettyBlocks.php
+++ b/src/Service/EverblockPrettyBlocks.php
@@ -22,6 +22,7 @@
use Configuration;
use Context;
+use Db;
use EverBlockClass;
use Everblock\Tools\Service\EverblockCache;
use EverblockShortcode;
@@ -52,6 +53,7 @@ class EverblockPrettyBlocks
'beforeRenderingEverblockGuidedSelector',
'beforeRenderingEverblockLookbook',
'beforeRenderingEverblockCategoryProducts',
+ 'beforeRenderingEverblockMegamenuItem',
];
public function registerBlockToZone($zone_name, $code, $id_lang, $id_shop)
@@ -137,6 +139,43 @@ private static function getEverblockPageChoices(Context $context, Module $module
return $choices;
}
+ private static function getPrettyblocksChoicesByCode(
+ Context $context,
+ Module $module,
+ string $code,
+ string $labelField
+ ): array {
+ $choices = [
+ '' => $module->l('Select an item'),
+ ];
+
+ $query = 'SELECT id_prettyblocks, config'
+ . ' FROM ' . _DB_PREFIX_ . 'prettyblocks'
+ . ' WHERE code = "' . pSQL($code) . '"'
+ . ' AND id_lang = ' . (int) $context->language->id
+ . ' AND id_shop = ' . (int) $context->shop->id;
+
+ $rows = Db::getInstance()->executeS($query);
+ if (!is_array($rows)) {
+ return $choices;
+ }
+
+ foreach ($rows as $row) {
+ $id = (int) ($row['id_prettyblocks'] ?? 0);
+ $config = json_decode((string) ($row['config'] ?? ''), true);
+ $label = '';
+ if (is_array($config)) {
+ $label = (string) ($config[$labelField] ?? '');
+ }
+ if ($label === '') {
+ $label = $module->l('Item') . ' #' . $id;
+ }
+ $choices[$id] = $id . ' - ' . $label;
+ }
+
+ return $choices;
+ }
+
public static function getEverPrettyBlocks($context)
{
$cacheId = 'EverblockPrettyBlocks_getEverPrettyBlocks_'
@@ -209,6 +248,10 @@ public static function getEverPrettyBlocks($context)
$pagesGuideTemplate = 'module:' . $module->name . '/views/templates/hook/prettyblocks/prettyblock_pages_guide.tpl';
$guidesSelectionTemplate = 'module:' . $module->name . '/views/templates/hook/prettyblocks/prettyblock_guides_selection.tpl';
$latestGuidesTemplate = 'module:' . $module->name . '/views/templates/hook/prettyblocks/prettyblock_latest_guides.tpl';
+ $megamenuItemTemplate = 'module:' . $module->name . '/views/templates/hook/prettyblocks/prettyblock_megamenu_item.tpl';
+ $megamenuColumnTemplate = 'module:' . $module->name . '/views/templates/hook/prettyblocks/prettyblock_megamenu_column.tpl';
+ $megamenuItemLinkTemplate = 'module:' . $module->name . '/views/templates/hook/prettyblocks/prettyblock_megamenu_item_link.tpl';
+ $megamenuItemImageTemplate = 'module:' . $module->name . '/views/templates/hook/prettyblocks/prettyblock_megamenu_item_image.tpl';
$slotMachineDefaultStartDate = date('Y-m-d 00:00:00');
$slotMachineDefaultEndDate = date('Y-m-d 23:59:59', strtotime('+30 days'));
$slotMachineDefaultWinningCombinations = json_encode(
@@ -261,6 +304,18 @@ public static function getEverPrettyBlocks($context)
$everblockChoices[$eblock['id_everblock']] = $eblock['id_everblock'] . ' - ' . $eblock['name'];
}
$everblockPageChoices = self::getEverblockPageChoices($context, $module);
+ $megamenuParentChoices = self::getPrettyblocksChoicesByCode(
+ $context,
+ $module,
+ 'megamenu_item',
+ 'label'
+ );
+ $megamenuColumnChoices = self::getPrettyblocksChoicesByCode(
+ $context,
+ $module,
+ 'megamenu_column',
+ 'title'
+ );
$allHooks = Hook::getHooks(false, true);
$prettyBlocksHooks = [];
foreach ($allHooks as $hook) {
@@ -368,6 +423,192 @@ public static function getEverPrettyBlocks($context)
], $module),
],
];
+ $blocks[] = [
+ 'name' => $module->l('Mega menu item'),
+ 'description' => $module->l('Top-level mega menu entry'),
+ 'code' => 'megamenu_item',
+ 'tab' => 'general',
+ 'icon_path' => $defaultLogo,
+ 'need_reload' => true,
+ 'templates' => [
+ 'default' => $megamenuItemTemplate,
+ ],
+ 'config' => [
+ 'fields' => [
+ 'label' => [
+ 'type' => 'text',
+ 'label' => $module->l('Label'),
+ 'default' => '',
+ ],
+ 'url' => [
+ 'type' => 'text',
+ 'label' => $module->l('Link (optional)'),
+ 'default' => '',
+ ],
+ 'is_mega' => [
+ 'type' => 'switch',
+ 'label' => $module->l('Enable mega menu'),
+ 'default' => true,
+ ],
+ 'full_width' => [
+ 'type' => 'switch',
+ 'label' => $module->l('Full width dropdown'),
+ 'default' => false,
+ ],
+ 'position' => [
+ 'type' => 'text',
+ 'label' => $module->l('Position'),
+ 'default' => '0',
+ ],
+ 'active' => [
+ 'type' => 'switch',
+ 'label' => $module->l('Active'),
+ 'default' => true,
+ ],
+ ],
+ ],
+ ];
+ $blocks[] = [
+ 'name' => $module->l('Mega menu column'),
+ 'description' => $module->l('Column for a mega menu'),
+ 'code' => 'megamenu_column',
+ 'tab' => 'general',
+ 'icon_path' => $defaultLogo,
+ 'need_reload' => true,
+ 'templates' => [
+ 'default' => $megamenuColumnTemplate,
+ ],
+ 'config' => [
+ 'fields' => [
+ 'parent_menu' => [
+ 'type' => 'select',
+ 'label' => $module->l('Parent menu'),
+ 'choices' => $megamenuParentChoices,
+ 'default' => '',
+ ],
+ 'title' => [
+ 'type' => 'text',
+ 'label' => $module->l('Column title'),
+ 'default' => '',
+ ],
+ 'title_url' => [
+ 'type' => 'text',
+ 'label' => $module->l('Title link (optional)'),
+ 'default' => '',
+ ],
+ 'width' => [
+ 'type' => 'select',
+ 'label' => $module->l('Column width'),
+ 'choices' => [
+ '3' => $module->l('3 columns'),
+ '4' => $module->l('4 columns'),
+ '6' => $module->l('6 columns'),
+ '12' => $module->l('12 columns'),
+ ],
+ 'default' => '3',
+ ],
+ 'order' => [
+ 'type' => 'text',
+ 'label' => $module->l('Order'),
+ 'default' => '0',
+ ],
+ ],
+ ],
+ ];
+ $blocks[] = [
+ 'name' => $module->l('Mega menu link'),
+ 'description' => $module->l('Link item inside a mega menu column'),
+ 'code' => 'megamenu_item_link',
+ 'tab' => 'general',
+ 'icon_path' => $defaultLogo,
+ 'need_reload' => true,
+ 'templates' => [
+ 'default' => $megamenuItemLinkTemplate,
+ ],
+ 'config' => [
+ 'fields' => [
+ 'parent_column' => [
+ 'type' => 'select',
+ 'label' => $module->l('Parent column'),
+ 'choices' => $megamenuColumnChoices,
+ 'default' => '',
+ ],
+ 'label' => [
+ 'type' => 'text',
+ 'label' => $module->l('Label'),
+ 'default' => '',
+ ],
+ 'url' => [
+ 'type' => 'text',
+ 'label' => $module->l('Link'),
+ 'default' => '',
+ ],
+ 'icon' => [
+ 'type' => 'text',
+ 'label' => $module->l('Icon (optional)'),
+ 'default' => '',
+ ],
+ 'highlight' => [
+ 'type' => 'switch',
+ 'label' => $module->l('Highlight'),
+ 'default' => false,
+ ],
+ 'order' => [
+ 'type' => 'text',
+ 'label' => $module->l('Order'),
+ 'default' => '0',
+ ],
+ ],
+ ],
+ ];
+ $blocks[] = [
+ 'name' => $module->l('Mega menu image'),
+ 'description' => $module->l('Image item inside a mega menu column'),
+ 'code' => 'megamenu_item_image',
+ 'tab' => 'general',
+ 'icon_path' => $defaultLogo,
+ 'need_reload' => true,
+ 'templates' => [
+ 'default' => $megamenuItemImageTemplate,
+ ],
+ 'config' => [
+ 'fields' => [
+ 'parent_column' => [
+ 'type' => 'select',
+ 'label' => $module->l('Parent column'),
+ 'choices' => $megamenuColumnChoices,
+ 'default' => '',
+ ],
+ 'image' => [
+ 'type' => 'fileupload',
+ 'label' => $module->l('Image'),
+ 'default' => [
+ 'url' => '',
+ ],
+ ],
+ 'title' => [
+ 'type' => 'text',
+ 'label' => $module->l('Title'),
+ 'default' => '',
+ ],
+ 'url' => [
+ 'type' => 'text',
+ 'label' => $module->l('Link'),
+ 'default' => '',
+ ],
+ 'cta_label' => [
+ 'type' => 'text',
+ 'label' => $module->l('CTA label'),
+ 'default' => '',
+ ],
+ 'order' => [
+ 'type' => 'text',
+ 'label' => $module->l('Order'),
+ 'default' => '0',
+ ],
+ ],
+ ],
+ ];
$blocks[] = [
'name' => $module->l('Title'),
'description' => $module->l('Display a customizable heading'),
diff --git a/views/templates/hook/prettyblocks/prettyblock_megamenu_column.tpl b/views/templates/hook/prettyblocks/prettyblock_megamenu_column.tpl
new file mode 100644
index 0000000..fe0c0aa
--- /dev/null
+++ b/views/templates/hook/prettyblocks/prettyblock_megamenu_column.tpl
@@ -0,0 +1,21 @@
+{*
+ * 2019-2025 Team Ever
+ *
+ * NOTICE OF LICENSE
+ *
+ * This source file is subject to the Academic Free License (AFL 3.0)
+ * that is bundled with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://opensource.org/licenses/afl-3.0.php
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@prestashop.com so we can send you a copy immediately.
+ *
+ * @author Team Ever