Search code examples
moduleprestashopmultistore

Prestashop 1.7.7 - HelperForm in a Multistore Context


I'm testing a first simple version for a Multistore-compatible module. It has just two settings, which have to be saved differently depending on the current shop Context (a single shop mainly). Now, I know that from 1.7.8 there are additional checkbox for each setting in the BO Form, but I have to manage to get it work also for 1.7.7. Now, both Configuration::updateValue() and Configuration::get() should be multistore-ready, meaning that they update or retrieve the value only for the current context, so it should be fine. The weird thing is that, after installing the test module, if I go to the configuration page, it automatically redirects to an All-Shop context and, if I try to manually switch (from the dropdown in the top right), it shows a blank page. Same thing happens if I try to deactivate the bottom checkbox "Activate this module in the context of: all shops".

Here is my code:

class TestModule extends Module
{
    public function __construct()
    {
        $this->name = 'testmodule';
        $this->tab = 'front_office_features';
        $this->version = '1.0.0';
        $this->author = 'Test';
        $this->need_instance = 1;
        $this->ps_versions_compliancy = [
            'min' => '1.7.0.0',
            'max' => '1.7.8.0',
        ];
        $this->bootstrap = true;

        parent::__construct();
        $this->displayName = $this->l("Test Module");
        $this->description = $this->l('Collection of custom test extensions');
        $this->confirmUninstall = $this->l('Are you sure you want to uninstall?');

        if (!Configuration::get('TESTM_v')) {
            $this->warning = $this->l('No version provided');
        }
    }

    public function install()
    {
        if (Shop::isFeatureActive()) {
            Shop::setContext(Shop::CONTEXT_ALL);
        }

        return (
            parent::install() 
            && $this->registerHook('header')
            && $this->registerHook('backOfficeHeader')
            && Configuration::updateValue('TESTM_v', $this->version)
        ); 
    }

    public function uninstall()
    {
        if (Shop::isFeatureActive()) {
            Shop::setContext(Shop::CONTEXT_ALL);
        }

        return (
            parent::uninstall() 
            && $this->unregisterHook('header')
            && $this->unregisterHook('backOfficeHeader')
            && Configuration::deleteByName('TESTM_v')
        );
    }

    public function getContent()
    {

        // this part is executed only when the form is submitted
        if (Tools::isSubmit('submit' . $this->name)) {
            // retrieve the value set by the user
            $configValue1 = (string) Tools::getValue('TESTM_CONFIG_1');
            $configValue2 = (string) Tools::getValue('TESTM_CONFIG_2');

            // check that the value 1 is valid
            if (empty($configValue1)) {
                // invalid value, show an error
                $output = $this->displayError($this->l('Invalid Configuration value'));
            } else {
                // value is ok, update it and display a confirmation message
                Configuration::updateValue('TESTM_CONFIG_1', $configValue1);
                $output = $this->displayConfirmation($this->l('Settings updated'));
            }

            // check that the value 2 is valid
            Configuration::updateValue('TESTM_CONFIG_2', $configValue2);
            $output = $this->displayConfirmation($this->l('Settings updated'));
        }
        // display any message, then the form
        return $output . $this->displayForm();
    }

    public function displayForm()
    {    
        // Init Fields form array
        $form = [
            'form' => [
                'legend' => [
                    'title' => $this->l('Settings'),
                ],
                'input' => [
                    [
                        'type' => 'text',
                        'label' => $this->l('Custom CSS file-name.'),
                        'name' => 'TESTM_CONFIG_1',
                        'size' => 20,
                        'required' => true,
                    ],
                    [
                        'type' => 'switch',
                        'label' => $this->l('Enable custom CSS loading.'),
                        'name' => 'TESTM_CONFIG_2',
                        'is_bool' => true,
                        'desc' => $this->l('required'),
                        'values' => array(
                            array(
                                'id' => 'sw1_on',
                                'value' => 1,
                                'label' => $this->l('Enabled')
                            ),
                            array(
                                'id' => 'sw1_off',
                                'value' => 0,
                                'label' => $this->l('Disabled')
                            )
                        )
                    ],
                ],
                'submit' => [
                    'title' => $this->l('Save'),
                    'class' => 'btn btn-default pull-right',
                ],
            ],
        ];

        $helper = new HelperForm();

        // Module, token and currentIndex
        $helper->table = $this->table;
        $helper->name_controller = $this->name;
        $helper->token = Tools::getAdminTokenLite('AdminModules');
        $helper->currentIndex = AdminController::$currentIndex . '&' . http_build_query(['configure' => $this->name]);
        $helper->submit_action = 'submit' . $this->name;

        // Default language
        $helper->default_form_language = (int) Configuration::get('PS_LANG_DEFAULT');

        // Load current value into the form or take default
        $helper->fields_value['TESTM_CONFIG_1'] = Tools::getValue('TESTM_CONFIG_1', Configuration::get('TESTM_CONFIG_1'));
        $helper->fields_value['TESTM_CONFIG_2'] = Tools::getValue('TESTM_CONFIG_2', Configuration::get('TESTM_CONFIG_2'));

        return $helper->generateForm([$form]);
    }

    /**
     * Custom CSS & JavaScript Hook for FO
     */
    public function hookHeader()
    {
        //$this->context->controller->addJS($this->_path.'/views/js/front.js');
        if (Configuration::get('TESTM_CONFIG_2') == 1) {
            $this->context->controller->addCSS($this->_path.'/views/css/'.((string)Configuration::get('TESTM_CONFIG_1')));
        } else {
            $this->context->controller->removeCSS($this->_path.'/views/css/'.((string)Configuration::get('TESTM_CONFIG_1')));
        }
    }
}

As you can see it's a pretty simple setting: just load a custom CSS file and choose if loading it or not. I've red official PS Docs per Multistore handling and searched online, but cannot find an answer to this specific problem. I've also tried to add:

if (Shop::isFeatureActive()) {
    $currentIdShop = Shop::getContextShopID();
    Shop::setContext(Shop::CONTEXT_SHOP, $currentIdShop);
 }

To the 'displayForm()' function, but without results.

Thank you in advance.


Solution

  • It seemsit was a caching error. After trying many variations, I can confirm that the first solution I've tried was the correct one, meaning that:

    if (Shop::isFeatureActive()) {
        $currentIdShop = Shop::getContextShopID();
        Shop::setContext(Shop::CONTEXT_SHOP, $currentIdShop);
     }
    

    needs to be added ad the beginning of the "displayForm()" function for it to work when selecting a single shop. Values are now correctly saved in the database. With a little bit extra logic it can be arranged to behave differently (if needed) when saving for "All shops" context.