Hook List
The module system provides two types of hooks: event hooks (PHP callbacks)
and display hooks (Smarty template injection points).
Catalog source: Module::HOOKS, getHookCatalog(), and
getDisplayHookCatalog() in core/Module.php.
Display hooks render HTML into store / admin templates via
{$hooks.*} or {$adminHooks.*}.
Event Hooks
Register listeners inside your module's boot() method using
Module::registerHook(). Only hooks listed in Module::HOOKS are accepted.
| Hook Name | When It Fires | Arguments |
|---|---|---|
smarty.assign |
During Module::bootstrap() — after all enabled modules are loaded |
$smarty instance |
head.assets |
When front-end CSS/JS assets are collected via Module::getHeadAssets() |
&$assets array with css and js keys |
footer.html |
Legacy footer HTML injection (prefer display hooks instead) | — |
admin.menu |
Admin sidebar menu is built (registerAdminMenuLink or registerHook) |
&$items menu items array |
order.placed |
After a new order is successfully created (checkout / POS) | Order data array |
order.updated |
When an order is updated (admin / API / status change) | $order, previous status / context extras |
product.updated |
When a product is saved (admin, Web API, quick stock, bulk tools) | $idProduct, $product, $isNew |
cart.changed |
After the cart contents change (add / update / remove) | Cart summary array from Cart::getSummary() |
form.captcha.validate |
Form submit CAPTCHA check (Captcha::validate()) |
$form name, &$error string |
product.filter.sql |
Before catalog product SQL runs — modules can alter SQL / params | &$sql, &$params, filter context array |
catalog.filter.context |
Reserved catalog filter context hook (registered in HOOKS) |
Context payload (when fired by callers) |
Display Hooks (Front)
Assigned per module in admin and stored in module_display_hooks.
Output is available in Smarty as {$hooks.hook_name}
(dotted names nest, e.g. {$hooks.head.top}).
| Hook Name | Location | Smarty Variable |
|---|---|---|
footer |
Store footer | {$hooks.footer} |
header |
Top bar / header | {$hooks.header} |
main_menu |
Main category menu | {$hooks.main_menu} |
mobile_menu |
Mobile drawer menu | {$hooks.mobile_menu} |
head.top |
Inside <head> (top) |
{$hooks.head.top} |
home |
Home page body | {$hooks.home} |
home_slider |
Home page top slider | {$hooks.home_slider} |
home_promo_slider |
Home promo / campaign slider | {$hooks.home_promo_slider} |
home_bottom |
Home page bottom section | {$hooks.home_bottom} |
catalog_filters |
Category / catalog filters | {$hooks.catalog_filters} |
product |
Product listing context (needs id_product) |
{$hooks.product} |
product_detail |
Product detail page | {$hooks.product_detail} |
product_tab |
Product tab button | {$hooks.product_tab} |
product_tab_content |
Product tab content panel | {$hooks.product_tab_content} |
product_inf |
Product detail info block | {$hooks.product_inf} |
order_payment |
Checkout payment step | {$hooks.order_payment} |
order_confirmation |
Order confirmation page | {$hooks.order_confirmation} |
auth_social |
Login / register — social buttons | {$hooks.auth_social} |
contact_form |
Contact form — CAPTCHA / extra fields | {$hooks.contact_form} |
auth_login |
Login form — CAPTCHA | {$hooks.auth_login} |
auth_register |
Register form — CAPTCHA | {$hooks.auth_register} |
Display Hooks (Admin)
Admin hooks use {$adminHooks.*} (via Module::renderAdminHooks()).
Implement renderAdminDisplayHook() in your module for hooks starting with admin_.
| Hook Name | Location | Smarty Variable |
|---|---|---|
admin_login |
Admin login form — CAPTCHA | {$adminHooks.admin_login} |
admin_product_button |
Product edit — next to Save | {$adminHooks.admin_product_button} |
admin_order_detail |
Admin order detail | {$adminHooks.admin_order_detail} |
admin_header |
Admin content top (all pages) | {$adminHooks.admin_header} |
admin_footer |
Admin footer (all pages) | {$adminHooks.admin_footer} |
admin_dashboard_top |
Dashboard — top | {$adminHooks.admin_dashboard_top} |
admin_dashboard_kpi |
Dashboard — below KPI cards | {$adminHooks.admin_dashboard_kpi} |
admin_dashboard_main_left |
Dashboard — left column | {$adminHooks.admin_dashboard_main_left} |
admin_dashboard_main_right |
Dashboard — right column | {$adminHooks.admin_dashboard_main_right} |
admin_dashboard_bottom |
Dashboard — page bottom | {$adminHooks.admin_dashboard_bottom} |
Module::refreshHook($smarty, $hookName, $context) or admin render):
product, product_tab, product_tab_content,
product_inf, order_payment, order_confirmation,
auth_social, admin_product_button, admin_order_detail,
admin_header, admin_footer, and all
admin_dashboard_* hooks.
Declaring Display Hooks in Your Module
In your module class, define which display hooks are supported and which are enabled by default on install:
$displayHooks— hook name => description (shown in admin)$defaultDisplayHooks— hooks auto-assigned oninstall()renderDisplayHook($hook, $context)— front HTMLrenderAdminDisplayHook($hook, $context)— admin HTML foradmin_*hooks
Assigning Hooks via Admin
Hook assignments are saved with Module::setDisplayHooks($moduleName, $hookNames).
Only hooks listed in both $displayHooks and the global display hook catalog are accepted.
<?php
// ── Event hooks in boot() ───────────────────────────────────────
public function boot(): void
{
Module::registerHook('order.placed', function (array $order): void {
Logger::info('Order placed: ' . ($order['id_order'] ?? ''));
});
Module::registerHook('order.updated', function (array $order, $oldStatus = null): void {
// status / cargo / content edits
});
Module::registerHook('product.updated', function (int $idProduct, $product = null, $isNew = false): void {
// sync external catalog, clear caches, etc.
});
Module::registerHook('cart.changed', function (array $cart): void {
// abandoned-cart tracking, analytics
});
Module::registerHook('form.captcha.validate', function (string $form, string &$error): void {
// set $error when CAPTCHA fails
});
Module::registerHook('smarty.assign', function ($smarty): void {
if ($smarty) {
$smarty->assign('myModuleEnabled', true);
}
});
Module::registerHook('head.assets', function (array &$assets): void {
$assets['css'][] = 'https://cdn.example.com/extra.css';
});
}
// ── Display hooks: declare + render ────────────────────────────
public array $displayHooks = [
'footer' => 'Footer block',
'product_detail' => 'Product detail section',
'auth_login' => 'Login CAPTCHA',
];
public array $defaultDisplayHooks = ['footer'];
public function renderDisplayHook(string $hook, array $context = []): ?string
{
return match ($hook) {
'footer' => $this->renderFrontTemplate('footer', [
'message' => Settings::get('MY_MODULE_TEXT'),
]),
'product_detail' => $this->renderFrontTemplate('product_detail', [
'id_product' => $context['id_product'] ?? 0,
]),
default => null,
};
}
{* assets/templates/front/footer.tpl *}
<div class="my-module-footer">
{if $message}
<p>{$message|escape}</p>
{/if}
</div>
<?php
// Call from product detail controller after $smarty is ready:
Module::refreshHook($smarty, 'product_detail', [
'id_product' => (int) $product['id_product'],
]);
// Smarty template:
// {$hooks.product_detail}
<?php
public array $displayHooks = [
'admin_order_detail' => 'Extra block on order detail',
'admin_dashboard_top' => 'Dashboard banner',
];
public function renderAdminDisplayHook(string $hook, array $context = []): ?string
{
return match ($hook) {
'admin_order_detail' => $this->renderAdminTemplate('order-detail', $context),
'admin_dashboard_top' => $this->renderAdminTemplate('dashboard-top', $context),
default => null,
};
}
<?php
// Minimum setup inside {name}.php:
public array $displayHooks = [
'footer' => 'Shown in store footer',
];
public array $defaultDisplayHooks = ['footer'];
public function renderDisplayHook(string $hook, array $context = []): ?string
{
if ($hook !== 'footer') {
return null;
}
return $this->renderFrontTemplate('footer', $context);
}