Permalink
Browse files

Environment based local.xml merging

Support merging an additional local.xml file based on the value of
the MAGE_APPLICATION_ENV environment variable.
The name of the file will be built as follows:

'app/etc/local.' . $_SERVER['MAGE_APPLICATION_ENV'] . '.xml'

The value of the variable is checked to contain only letters,
characters, underscores and dashes.
The file will be merged after the regular local.xml file.

The background idea is described by Matthias Zeis at
magento#7
  • Loading branch information...
1 parent 93f38e9 commit a60099d859f1d0962557660007bfcb4cf62943b9 @Vinai committed Jul 11, 2012
Showing with 112 additions and 18 deletions.
  1. +112 −18 app/code/core/Mage/Core/Model/Config.php
@@ -48,7 +48,7 @@ class Mage_Core_Model_Config extends Mage_Core_Model_Config_Base
* array(
* $sectionName => $recursionLevel
* )
- * Recursion level provide availability cache subnodes separatly
+ * Recursion level provide availability cache subnodes separately
*
* @var array
*/
@@ -147,7 +147,7 @@ class Mage_Core_Model_Config extends Mage_Core_Model_Config_Base
protected $_cachePartsForSave = array();
/**
- * Empty configuration object for loading and megring configuration parts
+ * Empty configuration object for loading and merging configuration parts
*
* @var Mage_Core_Model_Config_Base
*/
@@ -161,6 +161,20 @@ class Mage_Core_Model_Config extends Mage_Core_Model_Config_Base
protected $_isLocalConfigLoaded = false;
/**
+ * Ordered list of config files loaded as the local configuration
+ *
+ * @var array
+ */
+ protected $_localConfigFiles = null;
+
+ /**
+ * Temporary model cache to avoid multiple parsing of local.xml files.
+ *
+ * @var Mage_Core_Model_Config_Base
+ */
+ protected $_localConfigMergeCache = null;
+
+ /**
* Flag which allow to use modules from local code pool
*
* @var bool
@@ -253,11 +267,13 @@ public function init($options=array())
$cacheLoad = $this->loadModulesCache();
if ($cacheLoad) {
+ $this->_cleanLoadCache();
return $this;
}
$this->loadModules();
$this->loadDb();
$this->saveCache();
+ $this->_cleanLoadCache();
return $this;
}
@@ -269,16 +285,29 @@ public function init($options=array())
public function loadBase()
{
$etcDir = $this->getOptions()->getEtcDir();
- $files = glob($etcDir.DS.'*.xml');
- $this->loadFile(current($files));
- while ($file = next($files)) {
- $merge = clone $this->_prototype;
- $merge->loadFile($file);
- $this->extend($merge);
- }
- if (in_array($etcDir.DS.'local.xml', $files)) {
- $this->_isLocalConfigLoaded = true;
- }
+ $localConfigs = $this->_getLocalConfigFiles();
+
+ $files = glob($etcDir . DS . '*.xml');
+ $file = current($files);
+ do {
+ // Skip local.xml config files initially
+ if (in_array($file, $localConfigs)) {
+ continue;
+ }
+ if ($this->getNode()) {
+ // Extend current XML with following files
+ $merge = clone $this->_prototype;
+ $merge->loadFile($file);
+ $this->extend($merge);
+ } else {
+ // Load the first file directly
+ $this->loadFile($file);
+ }
+ } while ($file = next($files));
+
+ // Load local.xml configuration files last so they have a higher priority
+ $this->loadLocalConfig();
+
return $this;
}
@@ -315,16 +344,12 @@ public function loadModules()
$this->_loadDeclaredModules();
$resourceConfig = sprintf('config.%s.xml', $this->_getResourceConnectionModel('core'));
- $this->loadModulesConfiguration(array('config.xml',$resourceConfig), $this);
+ $this->loadModulesConfiguration(array('config.xml', $resourceConfig), $this);
/**
* Prevent local.xml directives overwriting
*/
- $mergeConfig = clone $this->_prototype;
- $this->_isLocalConfigLoaded = $mergeConfig->loadFile($this->getOptions()->getEtcDir().DS.'local.xml');
- if ($this->_isLocalConfigLoaded) {
- $this->extend($mergeConfig);
- }
+ $this->loadLocalConfig();
$this->applyExtends();
Magento_Profiler::stop('load_modules');
@@ -333,6 +358,75 @@ public function loadModules()
}
/**
+ * Return a list of local.xml config files
+ *
+ * The environment dependant local configuration file can be specified
+ * using the environment variable $_SERVER['MAGE_APPLICATION_ENV'];
+ *
+ * @return array
+ */
+ protected function _getLocalConfigFiles()
+ {
+ if (!isset($this->_localConfigFiles)) {
+ $this->_localConfigFiles = array($this->getOptions()->getEtcDir() . DS . 'local.xml');
+ $env = false;
+ if (isset($_SERVER) && is_array($_SERVER) && isset($_SERVER['MAGE_APPLICATION_ENV'])) {
+ $env = $_SERVER['MAGE_APPLICATION_ENV'];
+ }
+ if (isset($env) && is_string($env)) {
+ if (preg_match('/^[a-z0-9_-]+$/', $env)) {
+ $file = $this->getOptions()->getEtcDir() . DS . 'local.' . $env . '.xml';
+ if (file_exists($file)) {
+ $this->_localConfigFiles[] = $file;
+ }
+ }
+ }
+ }
+ return $this->_localConfigFiles;
+ }
+
+ /**
+ * Load the local.xml file, followed by a local.$env.xml file if configured
+ *
+ * @return Mage_Core_Model_Config
+ */
+ public function loadLocalConfig()
+ {
+ if (is_null($this->_localConfigMergeCache)) {
+ $this->_localConfigMergeCache = clone $this->_prototype;
+ foreach ($this->_getLocalConfigFiles() as $file) {
+ if ($this->_localConfigMergeCache->getNode()) {
+ $mergeConfig = clone $this->_prototype;
+ $result = $mergeConfig->loadFile($file);
+ if ($result) {
+ $this->_localConfigMergeCache->extend($mergeConfig);
+ }
+ } else {
+ $result = $this->_localConfigMergeCache->loadFile($file);
+ }
+ // At least one local.xml config file needs to be loaded
+ $this->_isLocalConfigLoaded = $this->_isLocalConfigLoaded || $result;
+ }
+ }
+ if ($this->_isLocalConfigLoaded) {
+ $this->extend($this->_localConfigMergeCache);
+ }
+ return $this;
+ }
+
+ /**
+ * Unset the local config merge cache instance
+ *
+ * @return Mage_Core_Model_Config
+ * @see self::loadLocalConfig()
+ */
+ protected function _cleanLoadCache()
+ {
+ $this->_localConfigMergeCache = null;
+ return $this;
+ }
+
+ /**
* Check if local configuration (DB connection, etc) is loaded
*
* @return bool

0 comments on commit a60099d

Please sign in to comment.