Search code examples
moduleprestashopprestashop-1.6multistore

Managing multiple stores in prestashop module


I have a Prestashop 1.6 module. It works for one store, however I have the need to make it work on other stores I created with the multistore functionality.

By "make it work" I mean that I would like to be able to separate configurations for each different store, so that each store has its own plugin configuration without sharing a single configuration with every store on the website. Currently the plugin has just a single configuration, if I change it inside one of the stores, the change affects all other stores.

This is the code:

<?php
/**
 * 2007-2015 PrestaShop
 *
 * 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 [email protected] so we can send you a copy immediately.
 *
 * @author    PrestaShop SA <[email protected]>
 * @copyright 2007-2015 PrestaShop SA
 * @license   http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
 * International Registered Trademark & Property of PrestaShop SA
 */

class Homecategories extends Module
{
    public function __construct()
    {
        $this->name = 'homecategories';
        $this->tab = 'front_office_features';
        $this->version = '1.0';
        $this->need_instance = 0;

        parent::__construct();

        $this->page = basename(__FILE__, '.php');
        $this->displayName = $this->l('Homepage Categories Customized');
        $this->description = $this->l('Displays categories on your homepage');
    }

    public function install() {
        Configuration::updateValue('HOMEPAGE_CATEGORIES_IDS', '');
        Configuration::updateValue('HOMEPAGE_CATEGORIES_PROD_COUNT', 4);
        return parent::install() &&
        $this->registerHook('displayHomeTab') &&
        $this->registerHook('displayHomeTabContent') &&
        $this->registerHook('displayHeader');
    }

    public function uninstall() {
        $this->unregisterHook('displayHomeTab') &&
        $this->unregisterHook('displayHomeTabContent') &&
        $this->unregisterHook('displayHeader') &&
        parent::uninstall();
    }

    public function hookDisplayHeader() {
        $this->context->controller->addCSS(_PS_THEME_DIR_.'/css/category.css', 'all');
        $this->context->controller->addCSS(_THEME_CSS_DIR_.'product_list.css');
    }

    public function hookDisplayHome($params) {
        $root_cat = Category::getRootCategory($this->context->cookie->id_lang);
        $prodCount = (int)Configuration::get('HOMEPAGE_CATEGORIES_PROD_COUNT');
        $categoryIds = Configuration::get('HOMEPAGE_CATEGORIES_IDS');
        if(!empty($categoryIds) && trim($categoryIds) != '') {
            $idsArray = explode(',', $categoryIds);
            $allProducts = array();

            foreach($idsArray as $id) {
                $category = new Category($id, (int)$this->context->language->id);

                $products = $category->getProducts((int)$this->context->language->id, 1, 10000);
                shuffle($products);
                for($i = 0; $i<$prodCount; $i++) {
                    $allProducts[] = $products[$i];
                }
            }

            $this->context->smarty->assign(
                array(
                    'products' => $allProducts,
                    'prodCount' => $prodCount,
                    'add_prod_display' => Configuration::get('PS_ATTRIBUTE_CATEGORY_DISPLAY'),
                )
            );
        }
        return $this->display(__FILE__, '/views/templates/hooks/homecategories.tpl');
    }



    public function renderForm() {
        $fields_form = array(
            'form' => array(
                'legend' => array(
                    'title' => $this->l('Settings'),
                    'icon' => 'icon-cogs'
                ),
                'description' => $this->l('Display custom categories on home page.'),
                'input' => array(
                    array(
                        'type' => 'text',
                        'label' => $this->l('Categories ID'),
                        'name' => 'HOMEPAGE_CATEGORIES_IDS',
                        'class' => 'fixed-width-xs',
                        'desc' => ''//$this->l('Insert how many products you\'d like to display for each category.'),
                    ),
                    array(
                        'type' => 'text',
                        'label' => $this->l('Products per category'),
                        'name' => 'HOMEPAGE_CATEGORIES_PROD_COUNT',
                        'class' => 'fixed-width-xs',
                        'desc' => ''//$this->l('Insert how many products you\'d like to display for each category.'),
                    )
                ),
                'submit' => array(
                    'title' => $this->l('Save'),
                )
            ),
        );

        $helper = new HelperForm();
        $helper->show_toolbar = false;
        $helper->table = $this->table;
        $lang = new Language((int)Configuration::get('PS_LANG_DEFAULT'));
        $helper->default_form_language = $lang->id;
        $helper->allow_employee_form_lang = Configuration::get('PS_BO_ALLOW_EMPLOYEE_FORM_LANG') ? Configuration::get('PS_BO_ALLOW_EMPLOYEE_FORM_LANG') : 0;
        $this->fields_form = array();
        $helper->id = (int)Tools::getValue('id_carrier');
        $helper->identifier = $this->identifier;
        $helper->submit_action = 'submitHomepageCategories';
        $helper->currentIndex = $this->context->link->getAdminLink('AdminModules', false).'&configure='.$this->name.'&tab_module='.$this->tab.'&module_name='.$this->name;
        $helper->token = Tools::getAdminTokenLite('AdminModules');
        $helper->tpl_vars = array(
            'fields_value' => $this->getConfigFieldsValues(),
            'languages' => $this->context->controller->getLanguages(),
            'id_language' => $this->context->language->id
        );

        return $helper->generateForm(array($fields_form));
    }

    public function getConfigFieldsValues() {
        return array(
            'HOMEPAGE_CATEGORIES_PROD_COUNT' => Tools::getValue('HOMEPAGE_CATEGORIES_PROD_COUNT', (int)Configuration::get('HOMEPAGE_CATEGORIES_PROD_COUNT')),
            'HOMEPAGE_CATEGORIES_IDS' => Tools::getValue('HOMEPAGE_CATEGORIES_IDS', Configuration::get('HOMEPAGE_CATEGORIES_IDS')),
        );
    }

    public function getContent() {
        $output = '';
        $errors = array();
        if (Tools::isSubmit('submitHomepageCategories')) {
            $ids = str_replace('/\s+/g', '', Tools::getValue('HOMEPAGE_CATEGORIES_IDS'));
            $idsArray = explode(',', $ids);
            foreach($idsArray as $id) {
                if(!Validate::isInt($id) || (int)$id < 0) {
                    $errors[] = $this->l('All IDs must be positive integers. Unrecognized value: ') . $id;
                }
            }
            $prodCount = trim(Tools::getValue('HOMEPAGE_CATEGORIES_PROD_COUNT'));
            if (!Validate::isInt($prodCount) || (int)$prodCount <= 0)
                $errors[] = $this->l('Product count must be a positive non-zero integer.');
            if (isset($errors) && count($errors))
                $output = $this->displayError(implode('<br />', $errors));
            else {
                Configuration::updateValue('HOMEPAGE_CATEGORIES_IDS', $ids);
                Configuration::updateValue('HOMEPAGE_CATEGORIES_PROD_COUNT', (int)$prodCount);
                Tools::clearCache(Context::getContext()->smarty, $this->getTemplatePath('homecategories.tpl'));
                $errors[] = $ids;
                $output = $this->displayConfirmation($this->l('Your settings have been updated.'));
            }
        }

        return $output.$this->renderForm();
    }


    public function hookDisplayHomeTabContent($params) {
        return $this->hookDisplayHome($params);
    }
    public function hookLeftColumn($params) {
        return $this->hookDiplayHome($params);
    }

    public function hookRightColumn($params) {
        return $this->hookDisplayHome($params);
    }

    public function hookDisplayTopColumn($params) {
        return $this->hookDisplayHome($params);
    }

    public function hookDisplayHomeTab($params) {
        return $this->display(__FILE__, 'tab.tpl', $this->getCacheId('homefeatured-tab'));
    }
}

What I tried:

  • I tried adding the shop ID as described in the documentation, by changing every occurrence of

    Configuration::get('KEY'); 
    

    to

    Configuration::get('KEY', null, null, (int)$this->context->shop->id);
    

    and

    Configuration::updateValue('KEY', 'VALUE');
    

    to

    Configuration::updateValue('KEY', 'VALUE', false, null, (int)$this->context->shop->id)
    

    It didn't work, values were still shared between stores

  • Since the first option didn't work, I thought about giving fields different names by naming them KEY_1 for shop 1, KEY_2 for shop 2, etc. I thought this would have solved the issue, so I changed every occurrence of

    Configuration::get('KEY'); 
    

    to

    Configuration::get('KEY_' . (int)$this->context->shop->id);
    

    and

    Configuration::updateValue('KEY_' . (int)$this->context->shop->id, 'VALUE');
    

    to

    Configuration::updateValue('KEY', 'VALUE', false, null, (int)$this->context->shop->id)
    

The result was the same.

I dumped $this->context->shop and found out that the id attribute is always 1, regardless of the store I'm in. The shop ID seems to be always the same even if I change store, so that property is not safe at all.

What should I do? Am I missing something? How can I create different configurations for each store instead of having just one shared between all stores?


Solution

  • By using Configuration::get('KEY'); and Configuration::updateValue('KEY', 'VALUE'); it will get and update the key based on your current context. This means that to change the values for another store, in admin you just select that store in the available select box (usually at the top near the notifications).

    The employee context shop is not based on the url you access the admin. It will default to the main one, if you haven't previously selected another one.

    On the other hand, you could write your module to have all the options, instead of changing the context shop, by using the Configuration::updateValue('KEY', 'VALUE', false, null, (int)$id_shop) and Configuration::get($key, null, null, $id_shop) in a foreach with all shops.

    The context shop in the front office (front end), on the other hand, is set depending on the url you access it.