Skip to content
Vincent Garcia edited this page Mar 20, 2023 · 4 revisions

In order to do several actions in PrestaShop, theps_mbo module is using hooks (Developer doc for hooks).

Hooks implementation

The module use a lot of hooks, so to have a clean code structure, and to avoid making the root ps_mbo.php file bigger and bigger we choose to separate hooks in PHP Traits.

The UseHooks trait

PrestaShop\Module\Mbo\Traits\UseHooks is the base to register new hooks.

The Traits/Hooks folder

Every registered hook is a separate trait, and is stored in this folder.

Both, file and trait names, must be Use{PascalCaseHookName} in order to be loaded correctly :

  • UseDisplayBackOfficeEmployeeMenu for displayBackOfficeEmployeeMenu
  • UseDashboardZoneOne for dashboardZoneOne
  • ...

Then, the minimum is to have the hook function in it :

  • hookDisplayBackOfficeEmployeeMenu for UseDisplayBackOfficeEmployeeMenu
  • hookDashboardZoneOne for UseDashboardZoneOne
  • ...

Here an example of a valid hook :

<?php
declare(strict_types=1);

namespace PrestaShop\Module\Mbo\Traits\Hooks;

trait UseDashboardZoneTwo
{
    /**
     * Display addons link on the middle column of the dashboard
     *
     * @param array $params
     *
     * @return false|string
     */
    public function hookDashboardZoneTwo(array $params)
    {
        $this->context->smarty->assign(
            [
                'shop_context' => json_encode($this->get('mbo.cdc.context_builder')->getViewContext()),
                'cdcErrorUrl' => $this->get('router')->generate('admin_mbo_module_cdc_error'),
            ]
        );

        return $this->display($this->name, 'dashboard-zone-two.tpl');
    }
}

How can I install my hooks ?

This is done through the method registerHook by the Module Core. But, no need to list all hooks there is an helper UseHooks::getHooksNames

How can I add or remove hooks ?

If you add new hooks, or remove some between module versions, you can just call UseHooks::updateHooks in your upgrade file.

<?php 

function upgrade_module_x_x_x(Module $module): bool
{
    $module->updateHooks();
}

The actionAdminControllerSetMedia special case

This hook allows us to register JS & CSS file in the current page.

As we may want to separate files for each usage, we don't want to register all assets in this trait.

For instance, if we have a specific CSS file to be loaded only on the dashboard for something displayed by another hook, we want to have the logic which register this file in the dashboard hook trait.

So, the UseActionAdminControllerSetMedia trait is designed to be called by other traits to register their assets. Other hooks can call boot{HookClassName} function, documented just below to register a callback which will be executed on the actionAdminControllerSetMedia hook runtime.

Let's look at an example :

// In ps_mbo/Traits/Hooks/UseDashboardZoneOne.php
// Declaring the boot{HookClassName} function
public function bootUseDashboardZoneOne(): void
{
    // Be sure the addAdminControllerMedia function exists (created in the UseActionAdminControllerSetMedia trait)
    if (method_exists($this, 'addAdminControllerMedia')) {
        // Register a callback to be called by the actionAdminControllerSetMedia hook when needed
        $this->addAdminControllerMedia('loadMediaDashboardZoneOne');
    }
}

And then, on actionAdminControllerSetMedia runtime each callback will be called to register assets.

// Still in ps_mbo/Traits/Hooks/UseDashboardZoneOne.php
protected function loadMediaDashboardZoneOne(): void
{
    // Assets need to be displayed only when on dashboard
    if (\Tools::getValue('controller') === 'AdminDashboard') {
        $this->context->controller->addJs($this->getPathUri() . 'views/js/cdc-error-templating.js');
        $this->context->controller->addCss($this->getPathUri() . 'views/css/cdc-error-templating.css');
    }
}

If you want to register assets globally, you can add them directly to the loadMediaForAdminControllerSetMedia function in the UseActionAdminControllerSetMedia trait.

The boot{HookClassName} function

In some cases, we want to make some operations linked to the hook, but external of the actual hook runtime.

The classic case is to register assets, as seen just above.

The boot functions are executed on each module load, in the __construct method, when the module is active.

The {hookClassName}ExtraOperations function

This method is called only once, when the hook is registered. It can allow you to make some special configurations, in DB for instance.

Registered hooks

They are listed in the ps_mbo/Traits/Hooks folder.

Triggered hooks

actionMboRecommendedModules

This hook sends to you some data :

 Hook::exec('actionMboRecommendedModules', [
    'recommendedModulesDisplayed' => &$recommendedModulesDisplayed,
    'controller' => $controller,
 ]);
  • recommendedModulesDisplayed => Boolean, always true
  • controler => String, the current controller name

So you can choose, for a given controller, to hide the recommended modules section.

If your set the $recommendedModulesDisplayed to false it will :

  • Recommended modules are displayed as button in the navbar : completely hide the button
  • Displayed in page, under content : it will move them in a modal, and add the button "Recommended modules & Services" in the navbar instead.