Magento:禁用任何特定商店的模块

时间:2011-05-11 09:32:03

标签: configuration magento module

假设我有3家商店。

我想禁用商店2中的模块。我只希望在商店1和商店3中启用它。

我看到我能做到: -

  • 转到系统 - >配置 - >高级

  • 当前配置范围下拉列表中选择所需的商店。

但这并不完全有效。

并且,我也不想在模块代码本身中检查存储,或者为模块创建系统配置字段以检查/取消选中存储以启用/禁用。

我期待的是在 app / etc / modules / MyNamespace_MyModule.xml 中添加一些代码。我们可以这样做吗?

5 个答案:

答案 0 :(得分:16)

要禁用商店范围内的模块,我发现可以这样做:

将app / code / core / 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;
}

新代码将使该方法还检查模块xml文件中的新节点&lt; restricted&gt;。如果节点存在,则该值将是您不希望模块加载的以逗号分隔的商店代码列表。如果您有多个商店,则应使用当前商店代码设置$ _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的商店中,模块甚至不会加载。 &lt;受限制&gt; tag是完全可选的,如果省略它,模块将按正常情况加载。

答案 1 :(得分:4)

此配置仅禁用前端布局中的模块输出,但模块控制器,事件观察器,管理页面等仍然有效。

另外,不要忘记在布局文件定义中指定模块名称,否则将为特定商店加载所有布局文件内容:

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

如果您正在开发模块并希望在特定商店的前端禁用其功能,那么您应该创建“是/否”类型的配置字段并通过Mage :: getStoreConfigFlag('config'检查其值/ field / path')在模块代码中。

答案 2 :(得分:2)

我正在使用Eric解决方案一段时间。在我的情况下,我在我的一个商店中禁用了负责分层导航的某个模块 - 因此返回到默认的分层导航行为。

它看起来像是在工作,但过了一段时间我发现分层导航选项停止出现在应有的位置。很快我就注意到,实际上不应该在这家商店工作的模块继续工作。然后我意识到,当我禁用配置缓存时,Eric的解决方案可以正常工作,但是再次启用后它会停止。

过了一段时间,我意识到必须以这种方式工作,启用配置缓存,因为Eric的解决方案仅在生成此xml时包含(或不包含)全局xml中的指定配置文件。然后它只缓存并从缓存中调用。所以当它从网站生成时应该使用一些模块,它被包含在内,然后也在网站上使用,而不是假设使用它。

无论如何,我根据Eric的代码(在模块配置中使用受限)制定了另一个解决方案。我认为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;
}

答案 3 :(得分:1)

我的客户安装的Magento 1.8.1.0有一个有问题的模块,在多商店设置中打破了另一个网站的菜单。 Eric Hainer发布的上述解决方案对于此安装并不起作用,所以我稍微改了一下:

我使用$_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>

明显改变&#34; www.site1.com&#34;,&#34; www.site2.com&#34;,&#34; www.site3.com&#34;与您自己的位置。

感谢Eric的想法:)

答案 4 :(得分:0)