Your IP : 216.73.216.38
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
/**
* Implementation of the @magentoConfigFixture DocBlock annotation
*/
namespace Magento\TestFramework\Annotation;
use Magento\Framework\App\Config\MutableScopeConfigInterface;
use Magento\Framework\App\Config\ScopeConfigInterface;
use Magento\Framework\Exception\LocalizedException;
use Magento\Store\Model\ScopeInterface;
use Magento\TestFramework\Annotation\TestCaseAnnotation;
use Magento\TestFramework\Fixture\Parser\Config as ConfigFixtureParser;
use Magento\TestFramework\Fixture\ParserInterface;
use Magento\TestFramework\Helper\Bootstrap;
use Magento\TestFramework\Workaround\Override\Fixture\Resolver;
use PHPUnit\Framework\TestCase;
/**
* Handler which works with magentoConfigFixture annotations
*/
class ConfigFixture
{
public const ANNOTATION = 'magentoConfigFixture';
/**
* Test instance that is available between 'startTest' and 'stopTest' events
*
* @var TestCase
*/
protected $_currentTest;
/**
* Original values for global configuration options that need to be restored
*
* @var array
*/
protected $globalConfigValues = [];
/**
* Original values for website-scoped configuration options that need to be restored
*
* @var array
*/
protected $websiteConfigValues = [];
/**
* Original values for store-scoped configuration options that need to be restored
*
* @var array
*/
protected $storeConfigValues = [];
/**
* Retrieve configuration node value
*
* @param string $configPath
* @param string|bool|null $scopeCode
* @return string
*/
protected function _getConfigValue($configPath, $scopeCode = null)
{
return $this->getScopeConfigValue($configPath, ScopeInterface::SCOPE_STORE, $scopeCode);
}
/**
* Retrieve scope configuration node value
*
* @param string $configPath
* @param string $scopeType
* @param string|null $scopeCode
* @return mixed|null
*/
protected function getScopeConfigValue(string $configPath, string $scopeType, string $scopeCode = null)
{
$result = null;
if ($scopeCode !== false) {
$scopeConfig = $this->getScopeConfig();
$result = $scopeConfig->getValue($configPath, $scopeType, $scopeCode);
}
return $result;
}
/**
* Assign configuration node value
*
* @param string $configPath
* @param string $value
* @param string|bool|null $storeCode
* @return void
*/
protected function _setConfigValue($configPath, $value, $storeCode = false)
{
$scopeType = $storeCode === false ? ScopeConfigInterface::SCOPE_TYPE_DEFAULT : ScopeInterface::SCOPE_STORE;
$this->setScopeConfigValue($configPath, $value, $scopeType, $storeCode);
}
/**
* Set config scope value
*
* @param string $configPath
* @param string|null $value
* @param string $scopeType
* @param string|null $scopeCode
* @return void
*/
protected function setScopeConfigValue(
string $configPath,
?string $value,
string $scopeType,
?string $scopeCode
): void {
$config = $this->getMutableScopeConfig();
if (strpos($configPath, 'default/') === 0) {
$configPath = substr($configPath, 8);
$config->setValue($configPath, $value, ScopeConfigInterface::SCOPE_TYPE_DEFAULT);
} else {
$config->setValue($configPath, $value, $scopeType, $scopeCode);
}
}
/**
* Get mutable config object
*
* @return MutableScopeConfigInterface
*/
protected function getMutableScopeConfig(): MutableScopeConfigInterface
{
return Bootstrap::getObjectManager()->get(MutableScopeConfigInterface::class);
}
/**
* Get config object
*
* @return ScopeConfigInterface
*/
protected function getScopeConfig(): ScopeConfigInterface
{
return Bootstrap::getObjectManager()->get(ScopeConfigInterface::class);
}
/**
* Assign required config values and save original ones
*
* @param TestCase $test
* @return void
* @SuppressWarnings(PHPMD.UnusedLocalVariable)
*/
protected function _assignConfigData(TestCase $test)
{
$resolver = Resolver::getInstance();
$annotations = TestCaseAnnotation::getInstance()->getAnnotations($test);
$existingFixtures = array_merge(
$annotations['method'][self::ANNOTATION] ?? [],
$this->getConfigFixturesFromAttribute($test)
);
/* Need to be applied even test does not have added fixtures because fixture can be added via config */
$testAnnotations = $resolver->applyConfigFixtures(
$test,
$existingFixtures,
self::ANNOTATION
);
foreach ($testAnnotations as $configPathAndValue) {
if (preg_match('/^[^\/]+?(?=_store\s)/', $configPathAndValue, $matches)) {
$this->setStoreConfigValue($matches ?? [], $configPathAndValue);
} elseif (preg_match('/^[^\/]+?(?=_website\s)/', $configPathAndValue, $matches)) {
$this->setWebsiteConfigValue($matches ?? [], $configPathAndValue);
} else {
$this->setGlobalConfigValue($configPathAndValue);
}
}
}
/**
* Sets store-scoped config value
*
* @param array $matches
* @param string $configPathAndValue
* @return void
* @SuppressWarnings(PHPMD.UnusedLocalVariable)
*/
protected function setStoreConfigValue(array $matches, $configPathAndValue): void
{
$storeCode = $matches[0] != 'current' ? $matches[0] : null;
$parts = preg_split('/\s+/', $configPathAndValue, 3);
list($configScope, $configPath, $requiredValue) = $parts + ['', '', ''];
$originalValue = $this->_getConfigValue($configPath, $storeCode);
$this->storeConfigValues[$storeCode][$configPath] = $originalValue;
$this->_setConfigValue($configPath, $requiredValue, $storeCode);
}
/**
* Sets website-scoped config value
*
* @param array $matches
* @param string $configPathAndValue
* @return void
* @SuppressWarnings(PHPMD.UnusedLocalVariable)
*/
protected function setWebsiteConfigValue(array $matches, $configPathAndValue): void
{
$websiteCode = $matches[0] != 'current' ? $matches[0] : null;
$parts = preg_split('/\s+/', $configPathAndValue, 3);
list($configScope, $configPath, $requiredValue) = $parts + ['', '', ''];
$originalValue = $this->getScopeConfigValue($configPath, ScopeInterface::SCOPE_WEBSITES, $websiteCode);
$this->websiteConfigValues[$websiteCode][$configPath] = $originalValue;
$this->setScopeConfigValue($configPath, $requiredValue, ScopeInterface::SCOPE_WEBSITES, $websiteCode);
}
/**
* Sets global config value
*
* @param string $configPathAndValue
* @return void
*/
protected function setGlobalConfigValue($configPathAndValue): void
{
/* Global config value */
list($configPath, $requiredValue) = preg_split('/\s+/', $configPathAndValue, 2);
$configPath = str_starts_with($configPath, 'default/') ? substr($configPath, 8) : $configPath;
$originalValue = $this->_getConfigValue($configPath);
$this->globalConfigValues[$configPath] = $originalValue;
$this->_setConfigValue($configPath, $requiredValue);
}
/**
* Restore original values for changed config options
*
* @return void
*/
protected function _restoreConfigData()
{
/* Restore global values */
foreach ($this->globalConfigValues as $configPath => $originalValue) {
$this->_setConfigValue($configPath, $originalValue);
}
$this->globalConfigValues = [];
/* Restore store-scoped values */
foreach ($this->storeConfigValues as $storeCode => $originalData) {
foreach ($originalData as $configPath => $originalValue) {
if (empty($storeCode)) {
$storeCode = null;
}
$this->setScopeConfigValue($configPath, $originalValue, ScopeInterface::SCOPE_STORES, $storeCode);
}
}
$this->storeConfigValues = [];
/* Restore website-scoped values */
foreach ($this->websiteConfigValues as $websiteCode => $originalData) {
foreach ($originalData as $configPath => $originalValue) {
if (empty($websiteCode)) {
$websiteCode = null;
}
$this->setScopeConfigValue($configPath, $originalValue, ScopeInterface::SCOPE_WEBSITES, $websiteCode);
}
}
$this->websiteConfigValues = [];
}
/**
* Handler for 'startTest' event
*
* @param TestCase $test
* @return void
*/
public function startTest(TestCase $test)
{
$this->_currentTest = $test;
$this->_assignConfigData($test);
}
/**
* Handler for 'endTest' event
*
* @param TestCase $test
* @return void
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*/
public function endTest(TestCase $test)
{
$this->_currentTest = null;
$this->_restoreConfigData();
}
/**
* Reassign configuration data whenever application is reset
*
* @return void
*/
public function initStoreAfter()
{
/* process events triggered from within a test only */
if ($this->_currentTest) {
$this->_assignConfigData($this->_currentTest);
}
}
/**
* Returns config fixtures defined using Config attribute
*
* @param TestCase $test
* @return array
* @throws LocalizedException
*/
private function getConfigFixturesFromAttribute(TestCase $test): array
{
$parser = Bootstrap::getObjectManager()->get(ConfigFixtureParser::class);
$configs = [];
foreach ($parser->parse($test, ParserInterface::SCOPE_METHOD) as $data) {
$configs[] = sprintf(
'%s%s %s',
$data['scopeType'] === ScopeConfigInterface::SCOPE_TYPE_DEFAULT
? 'default/'
: ($data['scopeValue'] ?? 'current') . '_' . $data['scopeType'] . ' ',
$data['path'],
$data['value'],
);
}
return $configs;
}
}