Magento: отключить модуль для любого конкретного магазина
Предположим, у меня есть 3 магазина.
Я хочу отключить модуль в Store 2. Я хочу, чтобы он был включен только в Store 1 и Store 3.
Я вижу, что могу это сделать: -
Но это не работает полностью.
И я также не хочу проверять хранилище в самом коде модуля или создавать поле конфигурации системы для проверки/снятия блокировки памяти для включения/отключения.
Я ожидаю, добавив код в приложение /etc/modules/MyNamespace _MyModule.xml. Можем ли мы это сделать?
Ответы
Ответ 1
Эта конфигурация просто отключает вывод модуля в макете для интерфейса, но контроллеры модулей, наблюдатели событий, страницы администрирования и т.д. все еще работают.
Также не забудьте указать имя вашего модуля в определении файлов макетов, иначе все содержимое файла макета будет загружено для определенного хранилища:
<config>
<layout>
<module_alias module="Module_Name">
<file>yourlayoutfile.xml</file>
</module_alias>
</layout>
</config>
Если вы разрабатываете модуль и хотите отключить его функциональность на фронте для определенного хранилища, тогда вы должны создать поле конфигурации типа "Да/Нет" и проверить его значение через Mage:: getStoreConfigFlag ('config/field/path ') в вашем модульном коде.
Ответ 2
Чтобы отключить модуль в области хранилища, я нашел возможным сделать это следующим образом:
Переместить приложение/код/ядро /Mage/Core/Model/Config.php в app/code/local/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;
}
Новый код заставит этот метод также проверять наличие нового node в XML файле модуля, <limited> . Если существует node, значение будет представлять собой список кодов магазинов, разделенных запятыми, которые вы НЕ хотите, чтобы модуль загружался. Если у вас несколько магазинов, переменная $_SERVER "MAGE_RUN_CODE" должна быть установлена с текущим кодом хранилища. Если он не установлен, script будет возвращаться к предположению, что код хранилища является "по умолчанию", что является тем, что по умолчанию, если только по какой-то причудливой причине вы не решили изменить это в бэкэнд.
Файл 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. < ограниченный > тег полностью необязателен, если вы его опустите, модуль будет загружаться, как обычно.
Ответ 3
Я некоторое время использовал решение Эрика. В моем случае я отключил определенный модуль, ответственный за многоуровневую навигацию, в одном из моих магазинов - таким образом, вернувшись к поведению Layered Navigation по умолчанию.
И это выглядело как его работа, но через некоторое время я заметил, что многоуровневые опции навигации перестали появляться там, где они должны. Вскоре я заметил, что на самом деле модуль, который не должен работать в этом магазине, продолжал работать. Тогда я понял, что когда я отключу кеширование конфигурации, решение Eric работает, но после включения его снова он останавливается.
Через некоторое время я понял, что это должно было работать так, с включенным кешем конфигурации, потому что решение Eric включает (или не) указанные файлы конфигурации в глобальном 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 = '';
}
}
}
}
Это условие Pneumatig связано с тем, что все мои модули начинаются с названия компании, поэтому я хотел избежать ненужной обработки, но ее необязательный, код должен работать без него, или вы можете изменить его на что-либо еще.
Затем я получаю фактическое имя модуля [Company] _ [Module], а затем проверяю, разрешено ли его в _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;
}
Ответ 4
У моих клиентов установка 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" с вашими собственными местоположениями.
Спасибо за идею Эрика:)
Ответ 5
Также интересное решение,
http://inchoo.net/ecommerce/magento/how-to-activatedeactivate-magento-module-per-a-website-level/