Magento: отключить модуль для любого конкретного магазина - PullRequest
12 голосов
/ 11 мая 2011

Предположим, у меня 3 магазина.

Я хочу отключить модуль в Магазине 2. Я хочу, чтобы он был включен только в Магазине 1 и Магазине 3.

Я вижу, что яможно сделать это: -

  • Переход к Система -> Конфигурация -> Дополнительно

  • Выбор нужного магазина из Текущая область конфигурации раскрывающийся список.

Но это не работает полностью.

И я также не хочу проверять хранилище в модулесам кодируйте или создайте поле конфигурации системы, чтобы модуль включал / отключал сохранение хранилища для включения / выключения.

Я ожидаю добавления некоторого кода в app / etc / modules / MyNamespace_MyModule.xml .Можем ли мы сделать это таким образом?

Ответы [ 5 ]

16 голосов
/ 07 июня 2012

Чтобы отключить модуль в области видимости магазина, я обнаружил, что это можно сделать так:

Переместите приложение / код / ​​ядро ​​/ Mage / Core / Model / Config.php в приложение / код / ​​локальное / Mage / Core / Model / Config.php

Внутри Config.php найдите метод «loadModulesConfiguration». Ничего не меняйте, но добавьте следующий код, чтобы метод выглядел следующим образом.

public function loadModulesConfiguration($fileName, $mergeToObject = null, $mergeModel=null)
{
    $disableLocalModules = !$this->_canUseLocalModules();

    if ($mergeToObject === null) {
        $mergeToObject = clone $this->_prototype;
        $mergeToObject->loadString('<config/>');
    }
    if ($mergeModel === null) {
        $mergeModel = clone $this->_prototype;
    }
    $modules = $this->getNode('modules')->children();
    foreach ($modules as $modName=>$module) {
        if ($module->is('active')) {
            // Begin additional code
            if((bool)$module->restricted) {
                $restricted = explode(',', (string)$module->restricted);
                $runCode = (isset($_SERVER['MAGE_RUN_CODE']) ? $_SERVER['MAGE_RUN_CODE'] : 'default');
                if(in_array($runCode, $restricted)) {
                    continue;
                }
            }
            // End additional code
            if ($disableLocalModules && ('local' === (string)$module->codePool)) {
                continue;
            }
            if (!is_array($fileName)) {
                $fileName = array($fileName);
            }

            foreach ($fileName as $configFile) {
                $configFile = $this->getModuleDir('etc', $modName).DS.$configFile;
                if ($mergeModel->loadFile($configFile)) {
                    $mergeToObject->extend($mergeModel, true);
                }
            }
        }
    }
    return $mergeToObject;
}

Новый код заставит метод также проверять наличие нового узла в файле xml модуля, . Если узел существует, значение будет разделенным запятыми списком кодов хранилища, на которые вы НЕ хотите, чтобы модуль загружался. Если у вас есть несколько хранилищ, переменная $ _SERVER «MAGE_RUN_CODE» должна быть установлена ​​с текущим кодом хранилища. Если он не установлен, сценарий откажется от предположения, что код хранилища «по умолчанию», то есть по умолчанию, если только по какой-то странной причине вы не решите изменить его в бэкэнде.

XML-файл модулей может выглядеть следующим образом:

<?xml version="1.0"?>
<config>
    <modules>
        <MyPackage_MyModule>
            <active>false</active>
            <restricted>mystore1,mystore4,mystore5</restricted>
            <codePool>local</codePool>
        </MyPackage_MyModule>
    </modules>
</config>

При этом модуль даже не будет загружаться в магазинах с кодом магазина mystore1, mystore4 или mystore5. Тег не является обязательным, если вы его опустите, модуль загрузится как обычно.

5 голосов
/ 11 мая 2011

Эта конфигурация просто отключает вывод модуля в макете для внешнего интерфейса, но контроллеры модулей, наблюдатели событий, страницы администратора и т. Д. Все еще работают.

Также не забудьте указать имя модуля в определении файлов макета, в противном случаевсе содержимое файла макета будет загружено для определенного магазина:

<config>
   <layout>
       <module_alias module="Module_Name">
           <file>yourlayoutfile.xml</file>
       </module_alias>
   </layout>
</config>

Если вы разрабатываете модуль и хотите полностью отключить его функциональность на интерфейсе для конкретного магазина, вам следует создать поле конфигурациитипа «Да / Нет» и проверьте его значение с помощью Mage :: getStoreConfigFlag ('config / field / path') в коде вашего модуля.

2 голосов
/ 23 января 2015

Я некоторое время использовал решение Эрика. В моем случае я отключил определенный модуль, отвечающий за многоуровневую навигацию, в одном из моих магазинов - таким образом, вернулся к режиму многоуровневой навигации по умолчанию.

И это выглядело, как будто оно работает, но через некоторое время я заметил, что многоуровневые параметры навигации перестали появляться там, где и должны. Вскоре я заметил, что на самом деле модуль, который не должен работать в этом магазине, продолжал работать. Затем я понял, что когда я отключаю кеш конфигурации, решение Эрика работает, но после повторного включения останавливается.

Через некоторое время я понял, что это должно работать именно так, с включенным кешем конфигурации, потому что решение Эрика включает (или нет) указанные файлы конфигурации в глобальный xml только во время генерации этого xml. Затем он кэшируется и вызывается только из кэша. Поэтому, когда он был создан с сайта, который должен использовать какой-то модуль, он был включен, а затем использован также на сайте, который не должен был его использовать.

В любом случае, я разработал другое решение, основанное на коде Эрика (используя с ограничением в конфигурации модулей). Я думал, что Magento должен решить, что загружать, когда запрашивается класс. Затем он может проверить текущее значение MAGE_RUN_CODE и использовать его динамически.

В Mage_Core_Model_Config существует метод, который отвечает за получение имени класса: getGroupedClassName .

Вот код, который я там использовал:

if (strpos($className, 'Pneumatig_') !== false) {
    $var = substr($className, 0, strpos($className, '_', strpos($className, '_') + 1));
    if (isset($this->_xml->modules->$var)) { 
        if ((bool)$this->_xml->modules->$var->restricted === true) {
            $code = isset($_SERVER['MAGE_RUN_CODE']) ? $_SERVER['MAGE_RUN_CODE'] : 'default';
            if (strpos((string)$this->_xml->modules->$var->restricted, $code) !== false) {
                $className = '';
            }
        }
    }
}

Это Пневматическое условие состоит в том, что все мои модули начинаются с названия компании, поэтому я хотел избежать ненужной обработки, но необязательный код должен работать без него, или вы можете изменить его на что-нибудь еще.

Затем я получаю фактическое имя модуля [Компания] _ [Модуль] , а затем проверяю, включено ли оно в _xml (который является текущим объектом конфигурации). Если он ограничен, я очищаю $ className , поэтому он заставляет Magento загрузить значение по умолчанию в следующей строке.

И этот код добавляется непосредственно перед тем, как пустое условие:

    // Second - if entity is not rewritten then use class prefix to form class name
    if (empty($className)) {
        if (!empty($config)) {
            $className = $config->getClassName();
        }
        if (empty($className)) {
            $className = 'mage_'.$group.'_'.$groupType;
        }
        if (!empty($class)) {
            $className .= '_'.$class;
        }
        $className = uc_words($className);
    }

    $this->_classNameCache[$groupRootNode][$group][$class] = $className;
    return $className;

И для вашего удобства я вставляю целые getGroupedClassName код:

public function getGroupedClassName($groupType, $classId, $groupRootNode=null)
{
    if (empty($groupRootNode)) {
        $groupRootNode = 'global/'.$groupType.'s';
    }

    $classArr = explode('/', trim($classId));
    $group = $classArr[0];
    $class = !empty($classArr[1]) ? $classArr[1] : null;

    if (isset($this->_classNameCache[$groupRootNode][$group][$class])) {
        return $this->_classNameCache[$groupRootNode][$group][$class];
    }

    $config = $this->_xml->global->{$groupType.'s'}->{$group};

    // First - check maybe the entity class was rewritten
    $className = null;
    if (isset($config->rewrite->$class)) {
        $className = (string)$config->rewrite->$class;
    } else {
        /**
         * Backwards compatibility for pre-MMDB extensions.
         * In MMDB release resource nodes <..._mysql4> were renamed to <..._resource>. So <deprecatedNode> is left
         * to keep name of previously used nodes, that still may be used by non-updated extensions.
         */
        if (isset($config->deprecatedNode)) {
            $deprecatedNode = $config->deprecatedNode;
            $configOld = $this->_xml->global->{$groupType.'s'}->$deprecatedNode;
            if (isset($configOld->rewrite->$class)) {
                $className = (string) $configOld->rewrite->$class;
            }
        }
    }

    //START CHECKING IF CLASS MODULE IS ENABLED
    if (strpos($className, 'Pneumatig_') !== false) {
        $var = substr($className, 0, strpos($className, '_', strpos($className, '_') + 1));
        if (isset($this->_xml->modules->$var)) { 
            if ((bool)$this->_xml->modules->$var->restricted === true) {
                $code = isset($_SERVER['MAGE_RUN_CODE']) ? $_SERVER['MAGE_RUN_CODE'] : 'default';
                if (strpos((string)$this->_xml->modules->$var->restricted, $code) !== false) {
                    $className = '';
                }
            }
        }
    }
    //END CHECKING IF CLASS MODULE IS ENABLED

    // Second - if entity is not rewritten then use class prefix to form class name
    if (empty($className)) {
        if (!empty($config)) {
            $className = $config->getClassName();
        }
        if (empty($className)) {
            $className = 'mage_'.$group.'_'.$groupType;
        }
        if (!empty($class)) {
            $className .= '_'.$class;
        }
        $className = uc_words($className);
    }

    $this->_classNameCache[$groupRootNode][$group][$class] = $className;
    return $className;
}
1 голос
/ 03 сентября 2014

Мои клиенты устанавливают Magento 1.8.1.0 с проблемным модулем, который нарушает меню другого сайта при настройке нескольких магазинов. Вышеуказанное Эриком Хайнером решение не сработало для этой установки, поэтому я слегка изменил его:

Вместо использования $_SERVER['MAGE_RUN_CODE'] я использовал $_SERVER['SERVER_NAME']. Работал как шарм. :)

Так что вместо:

$runCode = (isset($_SERVER['MAGE_RUN_CODE']) ? $_SERVER['MAGE_RUN_CODE'] : 'default');

использование:

$runCode = (isset($_SERVER['SERVER_NAME']) ? $_SERVER['SERVER_NAME'] : 'www.site1.com');

и вместо:

<restricted>mystore1,mystore4,mystore5</restricted>

использование:

<restricted>www.site2.com,www.site3.com</restricted>

очевидно меняя "www.site1.com", "www.site2.com" и "www.site3.com" в зависимости от вашего местоположения.

Спасибо за идею, Эрик:)

0 голосов
/ 11 ноября 2013
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...