Skip to content

Commit 00a6bbe

Browse files
authored
Merge branch '2.4-develop' into AC-1059_Move-PHPCompatibility-rules-from-magento-tests
2 parents 8418b3a + eadd3a9 commit 00a6bbe

File tree

8 files changed

+185
-220
lines changed

8 files changed

+185
-220
lines changed

app/code/Magento/Deploy/Model/Plugin/ConfigChangeDetector.php

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
namespace Magento\Deploy\Model\Plugin;
88

99
use Magento\Deploy\Model\DeploymentConfig\ChangeDetector;
10+
use Magento\Framework\App\DeploymentConfig;
1011
use Magento\Framework\App\FrontControllerInterface;
1112
use Magento\Framework\App\RequestInterface;
1213
use Magento\Framework\Exception\LocalizedException;
@@ -20,19 +21,26 @@
2021
*/
2122
class ConfigChangeDetector
2223
{
24+
private const DEPLOYMENT_BLUE_GREEN_ENABLED = 'deployment/blue_green/enabled';
25+
2326
/**
2427
* Configuration data changes detector.
2528
*
2629
* @var ChangeDetector
2730
*/
2831
private $changeDetector;
2932

33+
/** @var DeploymentConfig */
34+
private $deploymentConfig;
35+
3036
/**
31-
* @param ChangeDetector $changeDetector configuration data changes detector
37+
* @param ChangeDetector $changeDetector
38+
* @param DeploymentConfig $deploymentConfig
3239
*/
33-
public function __construct(ChangeDetector $changeDetector)
40+
public function __construct(ChangeDetector $changeDetector, DeploymentConfig $deploymentConfig)
3441
{
3542
$this->changeDetector = $changeDetector;
43+
$this->deploymentConfig = $deploymentConfig;
3644
}
3745

3846
/**
@@ -46,7 +54,9 @@ public function __construct(ChangeDetector $changeDetector)
4654
*/
4755
public function beforeDispatch(FrontControllerInterface $subject, RequestInterface $request)
4856
{
49-
if ($this->changeDetector->hasChanges()) {
57+
if (!$this->deploymentConfig->get(self::DEPLOYMENT_BLUE_GREEN_ENABLED)
58+
&& $this->changeDetector->hasChanges()
59+
) {
5060
throw new LocalizedException(
5161
__(
5262
'The configuration file has changed.'

app/code/Magento/Deploy/Test/Unit/Model/Plugin/ConfigChangeDetectorTest.php

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
use Magento\Deploy\Model\DeploymentConfig\ChangeDetector;
1111
use Magento\Deploy\Model\Plugin\ConfigChangeDetector;
12+
use Magento\Framework\App\DeploymentConfig;
1213
use Magento\Framework\App\FrontControllerInterface;
1314
use Magento\Framework\App\RequestInterface;
1415
use PHPUnit\Framework\MockObject\MockObject;
@@ -36,6 +37,11 @@ class ConfigChangeDetectorTest extends TestCase
3637
*/
3738
private $requestMock;
3839

40+
/**
41+
* @var DeploymentConfig|mixed|MockObject
42+
*/
43+
private $deploymentConfig;
44+
3945
/**
4046
* @return void
4147
*/
@@ -48,8 +54,14 @@ protected function setUp(): void
4854
->getMockForAbstractClass();
4955
$this->requestMock = $this->getMockBuilder(RequestInterface::class)
5056
->getMockForAbstractClass();
57+
$this->deploymentConfig =$this->getMockBuilder(DeploymentConfig::class)
58+
->disableOriginalConstructor()
59+
->getMock();
5160

52-
$this->configChangeDetectorPlugin = new ConfigChangeDetector($this->changeDetectorMock);
61+
$this->configChangeDetectorPlugin = new ConfigChangeDetector(
62+
$this->changeDetectorMock,
63+
$this->deploymentConfig
64+
);
5365
}
5466

5567
/**
@@ -65,8 +77,6 @@ public function testBeforeDispatchWithoutException()
6577

6678
/**
6779
* @return void
68-
* @codingStandardsIgnoreStart
69-
* @codingStandardsIgnoreEnd
7080
*/
7181
public function testBeforeDispatchWithException()
7282
{
@@ -80,4 +90,13 @@ public function testBeforeDispatchWithException()
8090
->willReturn(true);
8191
$this->configChangeDetectorPlugin->beforeDispatch($this->frontControllerMock, $this->requestMock);
8292
}
93+
94+
public function testBeforeDispatchWithBlueGreen()
95+
{
96+
$this->deploymentConfig->expects($this->atLeastOnce())
97+
->method('get')
98+
->with('deployment/blue_green/enabled')
99+
->willReturn(1);
100+
$this->configChangeDetectorPlugin->beforeDispatch($this->frontControllerMock, $this->requestMock);
101+
}
83102
}

lib/internal/Magento/Framework/App/DeploymentConfig.php

Lines changed: 46 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@
1919
*/
2020
class DeploymentConfig
2121
{
22+
private const MAGENTO_ENV_PREFIX = 'MAGENTO_DC_';
23+
private const ENV_NAME_PATTERN = '~^#env\(\s*(?<name>\w+)\s*(,\s*"(?<default>[^"]+)")?\)$~';
24+
private const OVERRIDE_KEY = self::MAGENTO_ENV_PREFIX . '_OVERRIDE';
25+
2226
/**
2327
* Configuration reader
2428
*
@@ -140,6 +144,19 @@ public function isDbAvailable()
140144
return isset($this->data['db']);
141145
}
142146

147+
/**
148+
* Get additional configuration from env variable MAGENTO_DC__OVERRIDE
149+
*
150+
* Data should be JSON encoded
151+
*
152+
* @return array
153+
*/
154+
private function getEnvOverride() : array
155+
{
156+
$env = getenv(self::OVERRIDE_KEY);
157+
return !empty($env) ? (json_decode($env, true) ?? []) : [];
158+
}
159+
143160
/**
144161
* Loads the configuration data
145162
*
@@ -150,12 +167,26 @@ public function isDbAvailable()
150167
private function load()
151168
{
152169
if (empty($this->data)) {
153-
$this->data = $this->reader->load();
154-
if ($this->overrideData) {
155-
$this->data = array_replace($this->data, $this->overrideData);
156-
}
170+
$this->data = array_replace(
171+
$this->reader->load(),
172+
$this->overrideData ?? [],
173+
$this->getEnvOverride()
174+
);
157175
// flatten data for config retrieval using get()
158176
$this->flatData = $this->flattenParams($this->data);
177+
178+
// allow reading values from env variables by convention
179+
// MAGENTO_DC_{path}, like db/connection/default/host =>
180+
// can be overwritten by MAGENTO_DC_DB__CONNECTION__DEFAULT__HOST
181+
foreach (getenv() as $key => $value) {
182+
if (false !== \strpos($key, self::MAGENTO_ENV_PREFIX)
183+
&& $key !== self::OVERRIDE_KEY
184+
) {
185+
// convert MAGENTO_DC_DB__CONNECTION__DEFAULT__HOST into db/connection/default/host
186+
$flatKey = strtolower(str_replace([self::MAGENTO_ENV_PREFIX, '__'], ['', '/'], $key));
187+
$this->flatData[$flatKey] = $value;
188+
}
189+
}
159190
}
160191
}
161192

@@ -187,9 +218,19 @@ private function flattenParams(array $params, $path = null, array &$flattenResul
187218
//phpcs:ignore Magento2.Exceptions.DirectThrow
188219
throw new RuntimeException(new Phrase("Key collision '%1' is already defined.", [$newPath]));
189220
}
190-
$flattenResult[$newPath] = $param;
221+
191222
if (is_array($param)) {
223+
$flattenResult[$newPath] = $param;
192224
$this->flattenParams($param, $newPath, $flattenResult);
225+
} else {
226+
// allow reading values from env variables
227+
// value need to be specified in %env(NAME, "default value")% format
228+
// like #env(DB_PASSWORD), #env(DB_NAME, "test")
229+
if (preg_match(self::ENV_NAME_PATTERN, $param, $matches)) {
230+
$param = getenv($matches['name']) ?: ($matches['default'] ?? null);
231+
}
232+
233+
$flattenResult[$newPath] = $param;
193234
}
194235
}
195236

lib/internal/Magento/Framework/App/Test/Unit/DeploymentConfigTest.php

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,16 @@ public function testKeyCollision(array $data): void
147147
$object->get();
148148
}
149149

150+
protected function tearDown(): void
151+
{
152+
foreach (array_keys(getenv()) as $key) {
153+
if (false !== \strpos($key, 'MAGENTO_DC')) {
154+
putenv($key);
155+
}
156+
}
157+
parent::tearDown();
158+
}
159+
150160
/**
151161
* @return array
152162
*/
@@ -178,4 +188,44 @@ public function testIsDbAvailable(): void
178188
$this->_deploymentConfig->resetData();
179189
$this->assertTrue($this->_deploymentConfig->isDbAvailable());
180190
}
191+
192+
public function testNoEnvVariables()
193+
{
194+
$this->reader->expects($this->once())->method('load')->willReturn(['a'=>'b']);
195+
$this->assertSame('b', $this->_deploymentConfig->get('a'));
196+
}
197+
198+
public function testEnvVariables()
199+
{
200+
$this->reader->expects($this->once())->method('load')->willReturn([]);
201+
putenv('MAGENTO_DC__OVERRIDE={"a": "c"}');
202+
$this->assertSame('c', $this->_deploymentConfig->get('a'));
203+
}
204+
205+
public function testEnvVariablesWithNoBaseConfig()
206+
{
207+
$this->reader->expects($this->once())->method('load')->willReturn(['a'=>'b']);
208+
putenv('MAGENTO_DC_A=c');
209+
putenv('MAGENTO_DC_B__B__B=D');
210+
$this->assertSame('c', $this->_deploymentConfig->get('a'));
211+
$this->assertSame('D', $this->_deploymentConfig->get('b/b/b'));
212+
}
213+
214+
public function testEnvVariablesSubstitution()
215+
{
216+
$this->reader->expects($this->once())
217+
->method('load')
218+
->willReturn(
219+
[
220+
'a'=>'#env(MAGENTO_DC____A)',
221+
'b'=>'#env(MAGENTO_DC____B, "test")',
222+
'c'=>'#env(MAGENTO_DC____D, "e$%^&")'
223+
]
224+
);
225+
putenv('MAGENTO_DC____A=c');
226+
putenv('MAGENTO_DC____B=D');
227+
$this->assertSame('c', $this->_deploymentConfig->get('a'));
228+
$this->assertSame('D', $this->_deploymentConfig->get('b'), 'return value from env');
229+
$this->assertSame('e$%^&', $this->_deploymentConfig->get('c'), 'return default value');
230+
}
181231
}

lib/internal/Magento/Framework/Cache/Backend/RemoteSynchronizedCache.php

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -34,13 +34,6 @@ class RemoteSynchronizedCache extends \Zend_Cache_Backend implements \Zend_Cache
3434
*/
3535
private $remote;
3636

37-
/**
38-
* Cache invalidation time
39-
*
40-
* @var \Zend_Cache_Backend_ExtendedInterface
41-
*/
42-
protected $cacheInvalidationTime;
43-
4437
/**
4538
* Suffix for hash to compare data version in cache storage.
4639
*/
@@ -52,7 +45,9 @@ class RemoteSynchronizedCache extends \Zend_Cache_Backend implements \Zend_Cache
5245
private const REMOTE_SYNC_LOCK_PREFIX = 'rsl::';
5346

5447
/**
55-
* @inheritdoc
48+
* Available options
49+
*
50+
* @var array available options
5651
*/
5752
protected $_options = [
5853
'remote_backend' => '',
@@ -64,6 +59,7 @@ class RemoteSynchronizedCache extends \Zend_Cache_Backend implements \Zend_Cache
6459
'local_backend_custom_naming' => true,
6560
'local_backend_autoload' => true,
6661
'use_stale_cache' => false,
62+
'cleanup_percentage' => 95,
6763
];
6864

6965
/**
@@ -76,7 +72,7 @@ class RemoteSynchronizedCache extends \Zend_Cache_Backend implements \Zend_Cache
7672
/**
7773
* Sign for locks, helps to avoid removing a lock that was created by another client
7874
*
79-
* @string
75+
* @var string
8076
*/
8177
private $lockSign;
8278

@@ -264,7 +260,7 @@ public function save($data, $id, $tags = [], $specificLifetime = false)
264260
*/
265261
private function checkIfLocalCacheSpaceExceeded()
266262
{
267-
return $this->getFillingPercentage() >= 95;
263+
return $this->getFillingPercentage() >= ($this->_options['cleanup_percentage'] ?? 95);
268264
}
269265

270266
/**

lib/internal/Magento/Framework/Module/Plugin/DbStatusValidator.php

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
*/
66
namespace Magento\Framework\Module\Plugin;
77

8+
use Magento\Framework\App\DeploymentConfig;
89
use Magento\Framework\Cache\FrontendInterface as FrontendCacheInterface;
910
use Magento\Framework\Module\DbVersionInfo;
1011
use Magento\Framework\App\FrontController;
@@ -17,6 +18,8 @@
1718
*/
1819
class DbStatusValidator
1920
{
21+
private const DEPLOYMENT_BLUE_GREEN_ENABLED = 'deployment/blue_green/enabled';
22+
2023
/**
2124
* @var FrontendCacheInterface
2225
*/
@@ -27,14 +30,24 @@ class DbStatusValidator
2730
*/
2831
private $dbVersionInfo;
2932

33+
/**
34+
* @var DeploymentConfig
35+
*/
36+
private $deploymentConfig;
37+
3038
/**
3139
* @param FrontendCacheInterface $cache
3240
* @param DbVersionInfo $dbVersionInfo
41+
* @param DeploymentConfig $deploymentConfig
3342
*/
34-
public function __construct(FrontendCacheInterface $cache, DbVersionInfo $dbVersionInfo)
35-
{
43+
public function __construct(
44+
FrontendCacheInterface $cache,
45+
DbVersionInfo $dbVersionInfo,
46+
DeploymentConfig $deploymentConfig
47+
) {
3648
$this->cache = $cache;
3749
$this->dbVersionInfo = $dbVersionInfo;
50+
$this->deploymentConfig = $deploymentConfig;
3851
}
3952

4053
/**
@@ -49,6 +62,10 @@ public function __construct(FrontendCacheInterface $cache, DbVersionInfo $dbVers
4962
*/
5063
public function beforeDispatch(FrontController $subject, RequestInterface $request)
5164
{
65+
if ($this->deploymentConfig->get(self::DEPLOYMENT_BLUE_GREEN_ENABLED)) {
66+
return;
67+
}
68+
5269
if (!$this->cache->load('db_is_up_to_date')) {
5370
list($versionTooLowErrors, $versionTooHighErrors) = array_values($this->getGroupedDbVersionErrors());
5471
if ($versionTooHighErrors) {

0 commit comments

Comments
 (0)