Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Fixes ENV overriding config #4261

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 0 additions & 5 deletions .phpstan.dist.baseline.neon
Original file line number Diff line number Diff line change
Expand Up @@ -2165,11 +2165,6 @@ parameters:
count: 1
path: app/code/core/Mage/Core/Model/Config.php

-
message: "#^Method Mage_Core_Model_Config\\:\\:getNode\\(\\) should return Mage_Core_Model_Config_Element but returns Varien_Simplexml_Element\\|false\\.$#"
count: 1
path: app/code/core/Mage/Core/Model/Config.php

-
message: "#^Return type \\(Mage_Core_Model_App\\) of method Mage_Core_Model_Config\\:\\:_saveCache\\(\\) should be compatible with return type \\(bool\\) of method Varien_Simplexml_Config\\:\\:_saveCache\\(\\)$#"
count: 1
Expand Down
10 changes: 10 additions & 0 deletions app/code/core/Mage/Adminhtml/Block/System/Config/Form/Field.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ public function render(Varien_Data_Form_Element_Abstract $element)
$options = $element->getValues();

$addInheritCheckbox = false;
$checkboxLabel = '';
if ($element->getCanUseWebsiteValue()) {
$addInheritCheckbox = true;
$checkboxLabel = $this->__('Use Website');
Expand All @@ -55,6 +56,15 @@ public function render(Varien_Data_Form_Element_Abstract $element)
$checkboxLabel = $this->__('Use Default');
}

$envConfig = Mage::getConfig()->getEnvOverriddenConfigPaths();
$envConfigIds = array_combine(str_replace('/', '_', array_keys($envConfig)), array_values($envConfig));
if (array_key_exists($element->getId(), $envConfigIds)) {
$addInheritCheckbox = false;
$element->setDisabled(true);
$element->setScopeLabel('[ENV]');
$element->setValue($envConfigIds[$element->getId()]);
}

if ($addInheritCheckbox) {
$inherit = $element->getInherit() == 1 ? 'checked="checked"' : '';
if ($inherit) {
Expand Down
14 changes: 12 additions & 2 deletions app/code/core/Mage/Core/Helper/EnvironmentConfigLoader.php
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@ class Mage_Core_Helper_EnvironmentConfigLoader extends Mage_Core_Helper_Abstract
*/
public function overrideEnvironment(Varien_Simplexml_Config $xmlConfig)
{
if (!$xmlConfig instanceof Mage_Core_Model_Config) {
return;
}

$env = $this->getEnv();

foreach ($env as $configKey => $value) {
Expand All @@ -66,20 +70,25 @@ public function overrideEnvironment(Varien_Simplexml_Config $xmlConfig)
list($configKeyParts, $scope) = $this->getConfigKey($configKey);

switch ($scope) {
default:
case static::CONFIG_KEY_DEFAULT:
list($unused1, $unused2, $section, $group, $field) = $configKeyParts;
$path = $this->buildPath($section, $group, $field);
$xmlConfig->setNode($this->buildNodePath($scope, $path), $value);
$nodePath = $this->buildNodePath($scope, $path);
$xmlConfig->setNode('stores/' . $nodePath, $value);
break;

case static::CONFIG_KEY_WEBSITES:
case static::CONFIG_KEY_STORES:
list($unused1, $unused2, $code, $section, $group, $field) = $configKeyParts;
$path = $this->buildPath($section, $group, $field);
$nodePath = sprintf('%s/%s/%s', strtolower($scope), strtolower($code), $path);
$xmlConfig->setNode($nodePath, $value);
break;
}

$xmlConfig->addEnvOverriddenConfigPaths($path, $value);
$xmlConfig->addEnvOverriddenConfigPaths($nodePath, $value);
$xmlConfig->setNode($nodePath, $value);
}
}

Expand All @@ -94,6 +103,7 @@ public function setEnvStore(array $envStorage): void
public function getEnv(): array
{
if (empty($this->envStore)) {
// phpcs:ignore Ecg.Security.ForbiddenFunction.Found
$this->envStore = getenv();
}
return $this->envStore;
Expand Down
41 changes: 37 additions & 4 deletions app/code/core/Mage/Core/Model/Config.php
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,7 @@ class Mage_Core_Model_Config extends Mage_Core_Model_Config_Base
* Active modules array per namespace
* @var array
*/
// phpcs:ignore Ecg.PHP.PrivateClassMember.PrivateClassMemberError
private $_moduleNamespaces = null;

/**
Expand All @@ -249,6 +250,11 @@ class Mage_Core_Model_Config extends Mage_Core_Model_Config_Base
*/
protected $_allowedModules = [];

/**
* Config paths overloaded by ENV
*/
protected array $envOverriddenConfigPaths = [];

/**
* Class construct
*
Expand All @@ -257,7 +263,9 @@ class Mage_Core_Model_Config extends Mage_Core_Model_Config_Base
public function __construct($sourceData = null)
{
$this->setCacheId('config_global');
// phpcs:ignore Ecg.Classes.ObjectInstantiation.DirectInstantiation
$this->_options = new Mage_Core_Model_Config_Options($sourceData);
// phpcs:ignore Ecg.Classes.ObjectInstantiation.DirectInstantiation
$this->_prototype = new Mage_Core_Model_Config_Base();
$this->_cacheChecksum = null;
parent::__construct($sourceData);
Expand Down Expand Up @@ -338,6 +346,7 @@ public function init($options = [])
public function loadBase()
{
$etcDir = $this->getOptions()->getEtcDir();
// phpcs:ignore Ecg.Security.ForbiddenFunction.Found
$files = glob($etcDir . DS . '*.xml');
$this->loadFile(current($files));
while ($file = next($files)) {
Expand Down Expand Up @@ -381,7 +390,7 @@ public function loadModules()
$this->_loadDeclaredModules();

$resourceConfig = sprintf('config.%s.xml', $this->_getResourceConnectionModel('core'));
$this->loadModulesConfiguration(['config.xml',$resourceConfig], $this);
$this->loadModulesConfiguration(['config.xml', $resourceConfig], $this);

/**
* Prevent local.xml directives overwriting
Expand Down Expand Up @@ -473,6 +482,7 @@ protected function _canUseLocalModules()
}

if ($disableLocalModules === true) {
// phpcs:ignore Ecg.Security.ForbiddenFunction.Found
set_include_path(
BP . DS . 'app' . DS . 'code' . DS . 'community' . PS .
BP . DS . 'app' . DS . 'code' . DS . 'core' . PS .
Expand Down Expand Up @@ -521,6 +531,7 @@ public function getCacheSaveLock($waitTime = null, $ignoreFailure = false)
if (!Mage::app()->useCache('config')) {
return;
}
// phpcs:ignore Ecg.Security.ForbiddenFunction.Found
$waitTime = $waitTime ?: (getenv('MAGE_CONFIG_CACHE_LOCK_WAIT') ?: (PHP_SAPI === 'cli' ? 60 : 3));
$connection = Mage::getSingleton('core/resource')->getConnection('core_write');
if (!$connection->fetchOne("SELECT GET_LOCK('core_config_cache_save_lock', ?)", [$waitTime])) {
Expand All @@ -530,7 +541,9 @@ public function getCacheSaveLock($waitTime = null, $ignoreFailure = false)
throw new Exception('Could not get lock on cache save operation.');
} else {
Mage::log(sprintf('Failed to get cache save lock in %d seconds.', $waitTime), Zend_Log::NOTICE);
// phpcs:ignore Ecg.Security.IncludeFile.IncludeFileDetected
require Mage::getBaseDir() . DS . 'errors' . DS . '503.php';
// phpcs:ignore Ecg.Security.LanguageConstruct.ExitUsage
die();
}
}
Expand Down Expand Up @@ -739,7 +752,7 @@ public function getSectionNode($path)
* Returns node found by the $path and scope info
*
* @inheritDoc
* @return Mage_Core_Model_Config_Element
* @return Mage_Core_Model_Config_Element|false
*/
public function getNode($path = null, $scope = '', $scopeCode = null)
{
Expand Down Expand Up @@ -805,6 +818,7 @@ public function setNode($path, $value, $overwrite = true)
protected function _getDeclaredModuleFiles()
{
$etcDir = $this->getOptions()->getEtcDir();
// phpcs:ignore Ecg.Security.ForbiddenFunction.Found
$moduleFiles = glob($etcDir . DS . 'modules' . DS . '*.xml');

if (!$moduleFiles) {
Expand All @@ -818,6 +832,7 @@ protected function _getDeclaredModuleFiles()

foreach ($moduleFiles as $v) {
$name = explode(DIRECTORY_SEPARATOR, $v);
// phpcs:ignore Ecg.Performance.Loop.ArraySize
$name = substr($name[count($name) - 1], 0, -4);

if (array_key_exists($name, self::MAGE_MODULES)) {
Expand Down Expand Up @@ -875,6 +890,7 @@ protected function _isAllowedModule($moduleName)
* @param null $mergeConfig deprecated
* @return $this|void
*/
// phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClass
protected function _loadDeclaredModules($mergeConfig = null)
{
$moduleFiles = $this->_getDeclaredModuleFiles();
Expand All @@ -884,8 +900,10 @@ protected function _loadDeclaredModules($mergeConfig = null)

Varien_Profiler::start('config/load-modules-declaration');

// phpcs:ignore Ecg.Classes.ObjectInstantiation.DirectInstantiation
$unsortedConfig = new Mage_Core_Model_Config_Base();
$unsortedConfig->loadString('<config/>');
// phpcs:ignore Ecg.Classes.ObjectInstantiation.DirectInstantiation
$fileConfig = new Mage_Core_Model_Config_Base();

// load modules declarations
Expand Down Expand Up @@ -917,6 +935,7 @@ protected function _loadDeclaredModules($mergeConfig = null)
$moduleDepends = $this->_sortModuleDepends($moduleDepends);

// create sorted config
// phpcs:ignore Ecg.Classes.ObjectInstantiation.DirectInstantiation
$sortedConfig = new Mage_Core_Model_Config_Base();
$sortedConfig->loadString('<config><modules/></config>');

Expand Down Expand Up @@ -1035,9 +1054,9 @@ public function determineOmittedNamespace($name, $asFullModuleName = false)

/**
* Iterate all active modules "etc" folders and combine data from
* specidied xml file name to one object
* specified xml file name to one object
*
* @param string $fileName
* @param string|array $fileName
* @param null|Mage_Core_Model_Config_Base|Varien_Simplexml_Config $mergeToObject
* @param Varien_Simplexml_Config|null $mergeModel
* @return Mage_Core_Model_Config_Base|Varien_Simplexml_Config
Expand Down Expand Up @@ -1097,10 +1116,13 @@ public function getTempVarDir()
public function getDistroServerVars()
{
if (!$this->_distroServerVars) {
// phpcs:ignore Ecg.Security.Superglobal.SuperglobalUsageWarning
if (isset($_SERVER['SCRIPT_NAME']) && isset($_SERVER['HTTP_HOST'])) {
// phpcs:ignore Ecg.Security.Superglobal.SuperglobalUsageWarning
$secure = (!empty($_SERVER['HTTPS']) && ($_SERVER['HTTPS'] != 'off')) || $_SERVER['SERVER_PORT'] == '443';
$scheme = ($secure ? 'https' : 'http') . '://' ;

// phpcs:ignore Ecg.Security.Superglobal.SuperglobalUsageWarning
$hostArr = explode(':', $_SERVER['HTTP_HOST']);
$host = $hostArr[0];
$port = isset(
Expand Down Expand Up @@ -1822,4 +1844,15 @@ protected function _isNodeNameHasUpperCase(Mage_Core_Model_Config_Element $event
{
return (strtolower($event->getName()) !== (string)$event->getName());
}

public function getEnvOverriddenConfigPaths(): array
{
return $this->envOverriddenConfigPaths;
}

public function addEnvOverriddenConfigPaths(string $path, string $value): Mage_Core_Model_Config
{
$this->envOverriddenConfigPaths[$path] = $value;
return $this;
}
}
15 changes: 12 additions & 3 deletions app/code/core/Mage/Core/Model/Store.php
Original file line number Diff line number Diff line change
Expand Up @@ -337,13 +337,22 @@ public function getCode()
*/
public function getConfig($path)
{
$config = Mage::getConfig();
$fullPath = 'stores/' . $this->getCode() . '/' . $path;
$envConfig = $config->getEnvOverriddenConfigPaths();

if (array_key_exists($fullPath, $envConfig)) {
return $envConfig[$fullPath];
}

if (array_key_exists($path, $envConfig)) {
return $envConfig[$path];
}

if (isset($this->_configCache[$path])) {
return $this->_configCache[$path];
}

$config = Mage::getConfig();

$fullPath = 'stores/' . $this->getCode() . '/' . $path;
$data = $config->getNode($fullPath);
if (!$data && !Mage::isInstalled()) {
$data = $config->getNode('default/' . $path);
Expand Down
2 changes: 2 additions & 0 deletions lib/Varien/Data/Form/Element/Abstract.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@
* @method bool getNoSpan()
* @method $this setName(string $value)
* @method bool getRequired()
* @method string getScopeLabel()
* @method $this setScopeLabel(string $value)
* @method string getValue()
* @method array getValues()
* @method $this setValues(array|int|string $value)
Expand Down
15 changes: 15 additions & 0 deletions phpunit.xml.dist
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,21 @@
</testsuite>
</testsuites>

<php>
<env name="OPENMAGE_CONFIG__DEFAULT__GENERAL__STORE_INFORMATION__NAME" value="ENV default"/>
<env name="OPENMAGE_CONFIG__DEFAULT__GENERAL__FOO-BAR__NAME" value="ENV default dashes"/>
<env name="OPENMAGE_CONFIG__DEFAULT__GENERAL__FOO_BAR__NAME" value="ENV default underscore"/>
<env name="OPENMAGE_CONFIG__DEFAULT__GENERAL__ST" value="ENV default invalid"/>
<env name="OPENMAGE_CONFIG__WEBSITES__BASE__GENERAL__STORE_INFORMATION__NAME" value="ENV website"/>
<env name="OPENMAGE_CONFIG__WEBSITES__BASE-AT__GENERAL__STORE_INFORMATION__NAME" value="ENV website dashes"/>
<env name="OPENMAGE_CONFIG__WEBSITES__BASE_CH__GENERAL__STORE_INFORMATION__NAME" value="ENV website underscore"/>
<env name="OPENMAGE_CONFIG__WEBSITES__BASE__GENERAL__ST" value="ENV website invalid"/>
<env name="OPENMAGE_CONFIG__STORES__GERMAN__GENERAL__STORE_INFORMATION__NAME" value="ENV store"/>
<env name="OPENMAGE_CONFIG__STORES__GERMAN-AT__GENERAL__STORE_INFORMATION__NAME" value="ENV store dashes"/>
<env name="OPENMAGE_CONFIG__STORES__GERMAN_CH__GENERAL__STORE_INFORMATION__NAME" value="ENV store underscore"/>
<env name="OPENMAGE_CONFIG__STORES__GERMAN__GENERAL__ST" value="ENV store invalid"/>
</php>

<coverage
includeUncoveredFiles="true"
processUncoveredFiles="false"
Expand Down
Loading
Loading