diff --git a/app/code/Magento/Backend/App/Config.php b/app/code/Magento/Backend/App/Config.php index 0edfd070faa5689b23b2577eda73e8b3dec860f5..f0bae2a9d3c6fc64d0f6a3b26ce60043c05b06da 100644 --- a/app/code/Magento/Backend/App/Config.php +++ b/app/code/Magento/Backend/App/Config.php @@ -10,57 +10,66 @@ namespace Magento\Backend\App; +use Magento\Config\App\Config\Type\System; use Magento\Framework\App\Config\ScopeConfigInterface; /** - * Backend config accessor + * Backend config accessor. */ class Config implements ConfigInterface { /** - * @var \Magento\Framework\App\Config\ScopePool + * @var \Magento\Framework\App\Config */ - protected $_scopePool; + protected $appConfig; /** - * @param \Magento\Framework\App\Config\ScopePool $scopePool + * @var array */ - public function __construct(\Magento\Framework\App\Config\ScopePool $scopePool) + private $data; + + /** + * @param \Magento\Framework\App\Config $appConfig + * @return void + */ + public function __construct(\Magento\Framework\App\Config $appConfig) { - $this->_scopePool = $scopePool; + $this->appConfig = $appConfig; } /** - * Retrieve config value by path and scope - * - * @param string $path - * @return mixed + * @inheritdoc */ public function getValue($path) { - return $this->_scopePool->getScope(ScopeConfigInterface::SCOPE_TYPE_DEFAULT, null)->getValue($path); + if (isset($this->data[$path])) { + return $this->data[$path]; + } + + $configPath = ScopeConfigInterface::SCOPE_TYPE_DEFAULT; + if ($path) { + $configPath .= '/' . $path; + } + return $this->appConfig->get(System::CONFIG_TYPE, $configPath); } /** - * Set config value in the corresponding config scope - * - * @param string $path - * @param mixed $value - * @return void + * @inheritdoc */ public function setValue($path, $value) { - $this->_scopePool->getScope(ScopeConfigInterface::SCOPE_TYPE_DEFAULT, null)->setValue($path, $value); + $this->data[$path] = $value; } /** - * Retrieve config flag - * - * @param string $path - * @return bool + * @inheritdoc */ public function isSetFlag($path) { - return !!$this->_scopePool->getScope(ScopeConfigInterface::SCOPE_TYPE_DEFAULT, null)->getValue($path); + $configPath = ScopeConfigInterface::SCOPE_TYPE_DEFAULT; + if ($path) { + $configPath .= '/' . $path; + } + return (bool) $this->appConfig->get(System::CONFIG_TYPE, $configPath); } } diff --git a/app/code/Magento/Backend/App/ConfigInterface.php b/app/code/Magento/Backend/App/ConfigInterface.php index 4000b54cc983406a7e0707fe29a633f03d659e5a..5e73225a6aa694fff6f4afcb9ee6804b7faf9931 100644 --- a/app/code/Magento/Backend/App/ConfigInterface.php +++ b/app/code/Magento/Backend/App/ConfigInterface.php @@ -15,6 +15,8 @@ interface ConfigInterface /** * Retrieve config value by path * + * Path should looks like keys imploded by "/". For example scopes/stores/admin + * * @param string $path * @return mixed * @api @@ -24,6 +26,7 @@ interface ConfigInterface /** * Set config value * + * @deprecated * @param string $path * @param mixed $value * @return void @@ -34,6 +37,8 @@ interface ConfigInterface /** * Retrieve config flag * + * Path should looks like keys imploded by "/". For example scopes/stores/admin + * * @param string $path * @return bool * @api diff --git a/app/code/Magento/Backend/Test/Unit/App/ConfigTest.php b/app/code/Magento/Backend/Test/Unit/App/ConfigTest.php index b2ece9e3ce2e5296e6b62176193778f13b221b82..7bff61aede734af0911499f4d581b3addff1799c 100644 --- a/app/code/Magento/Backend/Test/Unit/App/ConfigTest.php +++ b/app/code/Magento/Backend/Test/Unit/App/ConfigTest.php @@ -7,12 +7,18 @@ namespace Magento\Backend\Test\Unit\App; use Magento\Backend\App\Config; +/** + * Test reading by path and reading flag from config + * + * @see \Magento\Backend\App\Config + * @package Magento\Backend\Test\Unit\App + */ class ConfigTest extends \PHPUnit_Framework_TestCase { /** - * @var \Magento\Framework\App\Config\ScopePool|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\App\Config|\PHPUnit_Framework_MockObject_MockObject */ - protected $sectionPool; + protected $appConfig; /** * @var Config @@ -21,102 +27,64 @@ class ConfigTest extends \PHPUnit_Framework_TestCase protected function setUp() { - $this->sectionPool = $this->getMock( - \Magento\Framework\App\Config\ScopePool::class, - ['getScope', 'clean'], + $this->appConfig = $this->getMock( + \Magento\Framework\App\Config::class, + ['get'], [], '', false ); - $this->model = new \Magento\Backend\App\Config($this->sectionPool); + $this->model = new \Magento\Backend\App\Config($this->appConfig); } public function testGetValue() { $expectedValue = 'some value'; $path = 'some path'; - $configData = $this->getConfigDataMock('getValue'); - $configData->expects( - $this->once() - )->method( - 'getValue' - )->with( - $this->equalTo($path) - )->will( - $this->returnValue($expectedValue) - ); - $this->sectionPool->expects( + $this->appConfig->expects( $this->once() )->method( - 'getScope' + 'get' )->with( - $this->equalTo('default'), + $this->equalTo('system'), + $this->equalTo('default/' . $path), $this->isNull() )->will( - $this->returnValue($configData) + $this->returnValue($expectedValue) ); $this->assertEquals($expectedValue, $this->model->getValue($path)); } - public function testSetValue() - { - $value = 'some value'; - $path = 'some path'; - $configData = $this->getConfigDataMock('setValue'); - $configData->expects($this->once())->method('setValue')->with($this->equalTo($path), $this->equalTo($value)); - $this->sectionPool->expects( - $this->once() - )->method( - 'getScope' - )->with( - $this->equalTo('default'), - $this->isNull() - )->will( - $this->returnValue($configData) - ); - $this->model->setValue($path, $value); - } - /** + * @param string $configPath * @param mixed $configValue * @param bool $expectedResult * @dataProvider isSetFlagDataProvider */ - public function testIsSetFlag($configValue, $expectedResult) + public function testIsSetFlag($configPath, $configValue, $expectedResult) { - $path = 'some path'; - $configData = $this->getConfigDataMock('getValue'); - $configData->expects( - $this->once() + $this->appConfig->expects( + $this->any() )->method( - 'getValue' + 'get' )->with( - $this->equalTo($path) + $this->equalTo('system'), + $this->equalTo('default/' . $configPath) )->will( $this->returnValue($configValue) ); - $this->sectionPool->expects( - $this->once() - )->method( - 'getScope' - )->with( - $this->equalTo('default'), - $this->isNull() - )->will( - $this->returnValue($configData) - ); - $this->assertEquals($expectedResult, $this->model->isSetFlag($path)); + $this->assertEquals($expectedResult, $this->model->isSetFlag($configPath)); } public function isSetFlagDataProvider() { return [ - [0, false], - [true, true], - ['0', false], - ['', false], - ['some string', true], - [1, true] + ['a', 0, false], + ['b', true, true], + ['c', '0', false], + ['d', '', false], + ['e', 'some string', true], + ['f', 1, true] ]; } diff --git a/app/code/Magento/Catalog/Model/System/Config/Backend/Catalog/Url/Rewrite/Suffix.php b/app/code/Magento/Catalog/Model/System/Config/Backend/Catalog/Url/Rewrite/Suffix.php index c1f37eca1c55c7b81cf4b14a034738c5211b7085..e441d703dcd9c52111541b14db1711706737b01f 100644 --- a/app/code/Magento/Catalog/Model/System/Config/Backend/Catalog/Url/Rewrite/Suffix.php +++ b/app/code/Magento/Catalog/Model/System/Config/Backend/Catalog/Url/Rewrite/Suffix.php @@ -41,9 +41,9 @@ class Suffix extends \Magento\Framework\App\Config\Value protected $resource; /** - * @var \Magento\Framework\App\Config\ScopePool + * @var \Magento\Framework\App\Config */ - private $scopePool; + private $appConfig; /** * @param \Magento\Framework\Model\Context $context @@ -83,17 +83,17 @@ class Suffix extends \Magento\Framework\App\Config\Value /** * Get instance of ScopePool * - * @return \Magento\Framework\App\Config\ScopePool + * @return \Magento\Framework\App\Config * @deprecated */ - private function getScopePool() + private function getAppConfig() { - if ($this->scopePool === null) { - $this->scopePool = \Magento\Framework\App\ObjectManager::getInstance()->get( - \Magento\Framework\App\Config\ScopePool::class + if ($this->appConfig === null) { + $this->appConfig = \Magento\Framework\App\ObjectManager::getInstance()->get( + \Magento\Framework\App\Config::class ); } - return $this->scopePool; + return $this->appConfig; } /** @@ -177,7 +177,7 @@ class Suffix extends \Magento\Framework\App\Config\Value if ($this->getValue() !== null) { $suffix = $this->getValue(); } else { - $this->getScopePool()->clean(); + $this->getAppConfig()->clean(); $suffix = $this->_config->getValue($this->getPath()); } foreach ($entities as $urlRewrite) { diff --git a/app/code/Magento/Catalog/Model/Template/Filter.php b/app/code/Magento/Catalog/Model/Template/Filter.php index cbabe53c3bca175b0a22f5aefba77fc0e1db00f6..3d9695c183fe3d63ba69dfd831971fced7da8980 100644 --- a/app/code/Magento/Catalog/Model/Template/Filter.php +++ b/app/code/Magento/Catalog/Model/Template/Filter.php @@ -14,6 +14,11 @@ */ namespace Magento\Catalog\Model\Template; +/** + * Work with catalog(store, website) urls + * + * @package Magento\Catalog\Model\Template + */ class Filter extends \Magento\Framework\Filter\Template { /** diff --git a/app/code/Magento/CatalogUrlRewrite/Model/Category/Plugin/Store/View.php b/app/code/Magento/CatalogUrlRewrite/Model/Category/Plugin/Store/View.php index ea28b20f3f8f6d58211377bd9b16034d8f04a23c..01ef3e4ff8be217883ae1109e1d778b03dc316e2 100644 --- a/app/code/Magento/CatalogUrlRewrite/Model/Category/Plugin/Store/View.php +++ b/app/code/Magento/CatalogUrlRewrite/Model/Category/Plugin/Store/View.php @@ -5,6 +5,7 @@ */ namespace Magento\CatalogUrlRewrite\Model\Category\Plugin\Store; +use Magento\Catalog\Model\Category; use Magento\Catalog\Model\CategoryFactory; use Magento\Catalog\Model\ProductFactory; use Magento\CatalogUrlRewrite\Model\CategoryUrlRewriteGenerator; @@ -13,6 +14,13 @@ use Magento\Framework\Model\AbstractModel; use Magento\UrlRewrite\Model\UrlPersistInterface; use Magento\UrlRewrite\Service\V1\Data\UrlRewrite; +/** + * Plugin which is listening store resource model and on save or on delete replace catalog url rewrites + * + * @see \Magento\Store\Model\ResourceModel\Store + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + * @package Magento\CatalogUrlRewrite\Model\Category\Plugin\Store + */ class View { /** @var UrlPersistInterface */ @@ -30,6 +38,11 @@ class View /** @var ProductUrlRewriteGenerator */ protected $productUrlRewriteGenerator; + /** + * @var AbstractModel + */ + private $origStore; + /** * @param UrlPersistInterface $urlPersist * @param CategoryFactory $categoryFactory @@ -52,34 +65,48 @@ class View } /** - * Perform updating url for categories and products assigned to the store view - * - * @param \Magento\Store\Model\ResourceModel\Store $subject - * @param \Magento\Store\Model\ResourceModel\Store $result + * @param \Magento\Store\Model\ResourceModel\Store $object * @param AbstractModel $store + * @return void + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + */ + public function beforeSave( + \Magento\Store\Model\ResourceModel\Store $object, + AbstractModel $store + ) { + $this->origStore = $store; + } + + /** + * Regenerate urls on store after save + * + * @param \Magento\Store\Model\ResourceModel\Store $object + * @param \Magento\Store\Model\ResourceModel\Store $store * @return \Magento\Store\Model\ResourceModel\Store * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ public function afterSave( - \Magento\Store\Model\ResourceModel\Store $subject, - \Magento\Store\Model\ResourceModel\Store $result, - AbstractModel $store + \Magento\Store\Model\ResourceModel\Store $object, + \Magento\Store\Model\ResourceModel\Store $store ) { - if ($store->isObjectNew() || $store->dataHasChangedFor('group_id')) { - if (!$store->isObjectNew()) { - $this->urlPersist->deleteByData([UrlRewrite::STORE_ID => $store->getId()]); + if ($this->origStore->isObjectNew() || $this->origStore->dataHasChangedFor('group_id')) { + if (!$this->origStore->isObjectNew()) { + $this->urlPersist->deleteByData([UrlRewrite::STORE_ID => $this->origStore->getId()]); } $this->urlPersist->replace( - $this->generateCategoryUrls($store->getRootCategoryId(), $store->getId()) + $this->generateCategoryUrls($this->origStore->getRootCategoryId(), $this->origStore->getId()) ); $this->urlPersist->replace( - $this->generateProductUrls($store->getWebsiteId(), $store->getOrigData('website_id'), $store->getId()) + $this->generateProductUrls( + $this->origStore->getWebsiteId(), + $this->origStore->getOrigData('website_id'), + $this->origStore->getId() + ) ); } - - return $result; + return $store; } /** @@ -101,7 +128,6 @@ class View ->addCategoryIds() ->addAttributeToSelect(['name', 'url_path', 'url_key', 'visibility']) ->addWebsiteFilter($websiteIds); - foreach ($collection as $product) { $product->setStoreId($storeId); /** @var \Magento\Catalog\Model\Product $product */ @@ -110,7 +136,6 @@ class View $this->productUrlRewriteGenerator->generate($product) ); } - return $urls; } @@ -131,7 +156,6 @@ class View $this->categoryUrlRewriteGenerator->generate($category) ); } - return $urls; } diff --git a/app/code/Magento/CatalogUrlRewrite/Test/Unit/Model/Category/Plugin/Store/ViewTest.php b/app/code/Magento/CatalogUrlRewrite/Test/Unit/Model/Category/Plugin/Store/ViewTest.php index d30c2dde6e033fd3f3d10300ed59aa7a6c249916..ac2e42ebea7834a8b35cff1ee26dd2a936479ce3 100644 --- a/app/code/Magento/CatalogUrlRewrite/Test/Unit/Model/Category/Plugin/Store/ViewTest.php +++ b/app/code/Magento/CatalogUrlRewrite/Test/Unit/Model/Category/Plugin/Store/ViewTest.php @@ -137,6 +137,17 @@ class ViewTest extends \PHPUnit_Framework_TestCase public function testAfterSave() { + $origStoreMock = $this->getMockBuilder(\Magento\Store\Model\Store::class) + ->disableOriginalConstructor() + ->getMock(); + $reflectionStore = new \ReflectionClass($this->plugin); + $origStore = $reflectionStore->getProperty('origStore'); + $origStore->setAccessible(true); + $origStore->setValue($this->plugin, $origStoreMock); + $origStoreMock->expects($this->atLeastOnce()) + ->method('isObjectNew') + ->willReturn(true); + $this->abstractModelMock->expects($this->any()) ->method('isObjectNew') ->willReturn(true); diff --git a/app/code/Magento/Cms/Test/Unit/Model/Template/FilterTest.php b/app/code/Magento/Cms/Test/Unit/Model/Template/FilterTest.php index cb0b184051b0f94cb1ffa625de0bfe8d8fcce660..90760f3b43247f18935d9fdeecea4a080ee38fff 100644 --- a/app/code/Magento/Cms/Test/Unit/Model/Template/FilterTest.php +++ b/app/code/Magento/Cms/Test/Unit/Model/Template/FilterTest.php @@ -6,6 +6,8 @@ namespace Magento\Cms\Test\Unit\Model\Template; /** + * Work with catalog(store, website) urls + * * @covers \Magento\Cms\Model\Template\Filter */ class FilterTest extends \PHPUnit_Framework_TestCase diff --git a/app/code/Magento/Config/App/Config/Source/ModularConfigSource.php b/app/code/Magento/Config/App/Config/Source/ModularConfigSource.php new file mode 100644 index 0000000000000000000000000000000000000000..b86c9144fac40416f4e4b13aa91a4638cabf7cb2 --- /dev/null +++ b/app/code/Magento/Config/App/Config/Source/ModularConfigSource.php @@ -0,0 +1,44 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Config\App\Config\Source; + +use Magento\Framework\App\Config\ConfigSourceInterface; +use Magento\Framework\DataObject; +use Magento\Framework\App\Config\Initial\Reader; + +/** + * Class for retrieving initial configuration from modules + */ +class ModularConfigSource implements ConfigSourceInterface +{ + /** + * @var Reader + */ + private $reader; + + /** + * @param Reader $reader + */ + public function __construct(Reader $reader) + { + $this->reader = $reader; + } + + /** + * Get initial data + * + * @param string $path Format is scope type and scope code separated by slash: e.g. "type/code" + * @return array + */ + public function get($path = '') + { + $data = new DataObject($this->reader->read()); + if ($path !== '') { + $path = '/' . $path; + } + return $data->getData('data' . $path) ?: []; + } +} diff --git a/app/code/Magento/Config/App/Config/Source/RuntimeConfigSource.php b/app/code/Magento/Config/App/Config/Source/RuntimeConfigSource.php new file mode 100644 index 0000000000000000000000000000000000000000..7cd3a8ef76d4e06f1168e01de49c2645c931dc58 --- /dev/null +++ b/app/code/Magento/Config/App/Config/Source/RuntimeConfigSource.php @@ -0,0 +1,98 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Config\App\Config\Source; + +use Magento\Framework\App\Config\ConfigSourceInterface; +use Magento\Framework\App\Config\ScopeCodeResolver; +use Magento\Framework\App\Config\ScopeConfigInterface; +use Magento\Framework\DataObject; +use Magento\Config\Model\ResourceModel\Config\Data\CollectionFactory; +use Magento\Framework\App\Config\Scope\Converter; + +/** + * Class for retrieving runtime configuration from database. + */ +class RuntimeConfigSource implements ConfigSourceInterface +{ + /** + * @var CollectionFactory + */ + private $collectionFactory; + + /** + * @var Converter + */ + private $converter; + + /** + * @var ScopeCodeResolver + */ + private $scopeCodeResolver; + + /** + * @param CollectionFactory $collectionFactory + * @param ScopeCodeResolver $scopeCodeResolver + * @param Converter $converter + */ + public function __construct( + CollectionFactory $collectionFactory, + ScopeCodeResolver $scopeCodeResolver, + Converter $converter + ) { + $this->collectionFactory = $collectionFactory; + $this->converter = $converter; + $this->scopeCodeResolver = $scopeCodeResolver; + } + + /** + * Get initial data. + * + * @param string $path Format is scope type and scope code separated by slash: e.g. "type/code" + * @return array + */ + public function get($path = '') + { + $data = new DataObject($this->loadConfig()); + return $data->getData($path) ?: []; + } + + /** + * Load config from database. + * + * Load collection from db and presents it in array with path keys, like: + * * scope/key/key * + * + * @return array + */ + private function loadConfig() + { + try { + $collection = $this->collectionFactory->create(); + } catch (\DomainException $e) { + $collection = []; + } + $config = []; + foreach ($collection as $item) { + if ($item->getScope() === ScopeConfigInterface::SCOPE_TYPE_DEFAULT) { + $config[$item->getScope()][$item->getPath()] = $item->getValue(); + } else { + $code = $this->scopeCodeResolver->resolve($item->getScope(), $item->getScopeId()); + $config[$item->getScope()][$code][$item->getPath()] = $item->getValue(); + } + } + + foreach ($config as $scope => &$item) { + if ($scope === ScopeConfigInterface::SCOPE_TYPE_DEFAULT) { + $item = $this->converter->convert($item); + } else { + foreach ($item as &$scopeItems) { + $scopeItems = $this->converter->convert($scopeItems); + } + } + } + return $config; + } +} diff --git a/app/code/Magento/Config/App/Config/Type/System.php b/app/code/Magento/Config/App/Config/Type/System.php new file mode 100644 index 0000000000000000000000000000000000000000..4a3c6da8379153a240e4869592fcef31788df608 --- /dev/null +++ b/app/code/Magento/Config/App/Config/Type/System.php @@ -0,0 +1,127 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Config\App\Config\Type; + +use Magento\Framework\App\Config\ConfigTypeInterface; +use Magento\Framework\App\Config\ConfigSourceInterface; +use Magento\Framework\App\Config\Spi\PostProcessorInterface; +use Magento\Framework\Cache\FrontendInterface; +use Magento\Framework\DataObject; +use Magento\Framework\Serialize\Serializer\Serialize; +use Magento\Framework\Serialize\SerializerInterface; +use Magento\Store\Model\Config\Processor\Fallback; + +/** + * Class process source, cache them and retrieve value by path + * + * @package Magento\Config\App\Config\Type + */ +class System implements ConfigTypeInterface +{ + const CACHE_TAG = 'config_scopes'; + + const CONFIG_TYPE = 'system'; + + /** + * @var ConfigSourceInterface + */ + private $source; + + /** + * @var DataObject[] + */ + private $data; + + /** + * @var PostProcessorInterface + */ + private $postProcessor; + + /** + * @var FrontendInterface + */ + private $cache; + + /** + * @var int + */ + private $cachingNestedLevel; + + /** + * @var Fallback + */ + private $fallback; + + /** + * @var Serialize + */ + private $serializer; + + /** + * System constructor. + * @param ConfigSourceInterface $source + * @param PostProcessorInterface $postProcessor + * @param Fallback $fallback + * @param FrontendInterface $cache + * @param int $cachingNestedLevel + * @param Serialize $serializer + */ + public function __construct( + ConfigSourceInterface $source, + PostProcessorInterface $postProcessor, + Fallback $fallback, + FrontendInterface $cache, + Serialize $serializer, + $cachingNestedLevel = 1 + ) { + $this->source = $source; + $this->postProcessor = $postProcessor; + $this->cache = $cache; + $this->cachingNestedLevel = $cachingNestedLevel; + $this->fallback = $fallback; + $this->serializer = $serializer; + } + + /** + * @inheritdoc + */ + public function get($path = '') + { + if ($path === null) { + $path = ''; + } + if (!$this->data) { + $data = $this->cache->load(self::CONFIG_TYPE); + if (!$data) { + $data = $this->fallback->process($this->source->get()); + $this->data = new DataObject($data); + //Placeholder processing need system config - so we need to save intermediate result + $data = $this->postProcessor->process($data); + $this->data = new DataObject($data); + $this->cache->save( + $this->serializer->serialize($this->data->getData()), + self::CONFIG_TYPE, + [self::CACHE_TAG] + ); + } else { + $this->data = new DataObject($this->serializer->unserialize($data)); + } + } + + return $this->data->getData($path); + } + + /** + * Clean cache and global variables cache + * + * @return void + */ + public function clean() + { + $this->data = null; + $this->cache->clean(\Zend_Cache::CLEANING_MODE_MATCHING_TAG, [self::CACHE_TAG]); + } +} diff --git a/app/code/Magento/Config/Block/System/Config/Form.php b/app/code/Magento/Config/Block/System/Config/Form.php index 9ac2016d8897a667a1c19a3d9995c633ae96371a..d1a0da2a700a3f628c83ac2d61029bc915cd3ba6 100644 --- a/app/code/Magento/Config/Block/System/Config/Form.php +++ b/app/code/Magento/Config/Block/System/Config/Form.php @@ -5,6 +5,11 @@ */ namespace Magento\Config\Block\System\Config; +use Magento\Config\App\Config\Type\System; +use Magento\Config\Model\Config\Reader\Source\Deployed\SettingChecker; +use Magento\Framework\App\DeploymentConfig; +use Magento\Framework\App\ObjectManager; + /** * System config form block * @@ -96,6 +101,16 @@ class Form extends \Magento\Backend\Block\Widget\Form\Generic */ protected $_fieldFactory; + /** + * @var SettingChecker + */ + private $settingChecker; + + /** + * @var DeploymentConfig + */ + private $appConfig; + /** * @param \Magento\Backend\Block\Template\Context $context * @param \Magento\Framework\Registry $registry @@ -129,6 +144,18 @@ class Form extends \Magento\Backend\Block\Widget\Form\Generic ]; } + /** + * @deprecated + * @return SettingChecker + */ + private function getSettingChecker() + { + if ($this->settingChecker === null) { + $this->settingChecker = ObjectManager::getInstance()->get(SettingChecker::class); + } + return $this->settingChecker; + } + /** * Initialize objects required to render config form * @@ -305,25 +332,27 @@ class Form extends \Magento\Backend\Block\Widget\Form\Generic $labelPrefix = '' ) { $inherit = true; - $data = null; - if (array_key_exists($path, $this->_configData)) { - $data = $this->_configData[$path]; - $inherit = false; - - if ($field->hasBackendModel()) { - $backendModel = $field->getBackendModel(); - $backendModel->setPath($path) - ->setValue($data) - ->setWebsite($this->getWebsiteCode()) - ->setStore($this->getStoreCode()) - ->afterLoad(); - $data = $backendModel->getValue(); + $data = $this->getAppConfigDataValue($path); + if ($data === null) { + if (array_key_exists($path, $this->_configData)) { + $data = $this->_configData[$path]; + $inherit = false; + + if ($field->hasBackendModel()) { + $backendModel = $field->getBackendModel(); + $backendModel->setPath($path) + ->setValue($data) + ->setWebsite($this->getWebsiteCode()) + ->setStore($this->getStoreCode()) + ->afterLoad(); + $data = $backendModel->getValue(); + } + + } elseif ($field->getConfigPath() !== null) { + $data = $this->getConfigValue($field->getConfigPath()); + } else { + $data = $this->getConfigValue($path); } - - } elseif ($field->getConfigPath() !== null) { - $data = $this->getConfigValue($field->getConfigPath()); - } else { - $data = $this->getConfigValue($path); } $fieldRendererClass = $field->getFrontendModel(); if ($fieldRendererClass) { @@ -344,6 +373,9 @@ class Form extends \Magento\Backend\Block\Widget\Form\Generic $sharedClass = $this->_getSharedCssClass($field); $requiresClass = $this->_getRequiresCssClass($field, $fieldPrefix); + $isReadOnly = $this->getSettingChecker()->isReadOnly($path, $this->getScope(), $this->getScopeCode()); + $canUseDefault = $this->canUseDefaultValue($field->showInDefault()); + $canUseWebsite = $this->canUseWebsiteValue($field->showInWebsite()); $formField = $fieldset->addField( $elementId, $field->getType(), @@ -360,9 +392,11 @@ class Form extends \Magento\Backend\Block\Widget\Form\Generic 'scope' => $this->getScope(), 'scope_id' => $this->getScopeId(), 'scope_label' => $this->getScopeLabel($field), - 'can_use_default_value' => $this->canUseDefaultValue($field->showInDefault()), - 'can_use_website_value' => $this->canUseWebsiteValue($field->showInWebsite()), - 'can_restore_to_default' => $this->isCanRestoreToDefault($field->canRestore()) + 'can_use_default_value' => $canUseDefault, + 'can_use_website_value' => $canUseWebsite, + 'can_restore_to_default' => $this->isCanRestoreToDefault($field->canRestore()), + 'disabled' => $isReadOnly, + 'is_disable_inheritance' => $isReadOnly ] ); $field->populateInput($formField); @@ -689,4 +723,39 @@ class Form extends \Magento\Backend\Block\Widget\Form\Generic } return $requiresClass; } + + /** + * Retrieve Deployment Configuration object. + * + * @deprecated + * @return DeploymentConfig + */ + private function getAppConfig() + { + if ($this->appConfig === null) { + $this->appConfig = ObjectManager::getInstance()->get(DeploymentConfig::class); + } + return $this->appConfig; + } + + /** + * Retrieve deployment config data value by path + * + * @param string $path + * @return null|string + */ + private function getAppConfigDataValue($path) + { + $appConfig = $this->getAppConfig()->get(System::CONFIG_TYPE); + $scope = $this->getScope(); + $scopeId = $this->getScopeId(); + if ($scope === 'default') { + $data = isset($appConfig[$scope][$path]) ? $appConfig[$scope][$path] : null; + } else { + $data = isset($appConfig[$scope][$scopeId][$path]) + ? $appConfig[$scope][$scopeId][$path] + : null; + } + return $data; + } } diff --git a/app/code/Magento/Config/Block/System/Config/Form/Field.php b/app/code/Magento/Config/Block/System/Config/Form/Field.php index 0af9706b9372863887defb27b100a1631786f637..fe0d17e87bd5e1c05cec4047e9a200918d19b45a 100644 --- a/app/code/Magento/Config/Block/System/Config/Form/Field.php +++ b/app/code/Magento/Config/Block/System/Config/Form/Field.php @@ -15,6 +15,8 @@ namespace Magento\Config\Block\System\Config\Form; /** + * Render field html element in Stores Configuration + * * @SuppressWarnings(PHPMD.CouplingBetweenObjects) * @SuppressWarnings(PHPMD.NumberOfChildren) */ @@ -97,6 +99,7 @@ class Field extends \Magento\Backend\Block\Template implements \Magento\Framewor $htmlId = $element->getHtmlId(); $namePrefix = preg_replace('#\[value\](\[\])?$#', '', $element->getName()); $checkedHtml = $element->getInherit() == 1 ? 'checked="checked"' : ''; + $disabled = $element->getIsDisableInheritance() == true ? ' disabled="disabled"' : ''; $html = '<td class="use-default">'; $html .= '<input id="' . @@ -105,7 +108,7 @@ class Field extends \Magento\Backend\Block\Template implements \Magento\Framewor $namePrefix . '[inherit]" type="checkbox" value="1"' . ' class="checkbox config-inherit" ' . - $checkedHtml . + $checkedHtml . $disabled . ' onclick="toggleValueElements(this, Element.previous(this.parentNode))" /> '; $html .= '<label for="' . $htmlId . '_inherit" class="inherit">' . $this->_getInheritCheckboxLabel( $element diff --git a/app/code/Magento/Config/Model/Config/Backend/Store.php b/app/code/Magento/Config/Model/Config/Backend/Store.php index d33f5e5143daa665918a200ef9500c18eb8cd5d8..02f4ab96b5e5e1ae92851a0c7f3f48d0fcde246b 100644 --- a/app/code/Magento/Config/Model/Config/Backend/Store.php +++ b/app/code/Magento/Config/Model/Config/Backend/Store.php @@ -45,11 +45,6 @@ class Store extends \Magento\Framework\App\Config\Value */ public function afterSave() { - $this->_mutableConfig->setValue( - \Magento\Store\Model\Store::XML_PATH_STORE_IN_URL, - $this->getValue(), - \Magento\Store\Model\ScopeInterface::SCOPE_STORE - ); $this->_cacheManager->clean(); return parent::afterSave(); } diff --git a/app/code/Magento/Config/Model/Config/Loader.php b/app/code/Magento/Config/Model/Config/Loader.php index 7ce3254a475746f3de1e4635dab55fed9eaedde4..4b10ffd6ea9d839cb013902356cb9e9134d2dde3 100644 --- a/app/code/Magento/Config/Model/Config/Loader.php +++ b/app/code/Magento/Config/Model/Config/Loader.php @@ -9,6 +9,11 @@ */ namespace Magento\Config\Model\Config; +/** + * Class which can read config by paths + * + * @package Magento\Config\Model\Config + */ class Loader { /** diff --git a/app/code/Magento/Config/Model/Config/Reader/Source/Deployed/SettingChecker.php b/app/code/Magento/Config/Model/Config/Reader/Source/Deployed/SettingChecker.php new file mode 100644 index 0000000000000000000000000000000000000000..48b82086ad8b10d3b0241d2502b6199ab2584ab1 --- /dev/null +++ b/app/code/Magento/Config/Model/Config/Reader/Source/Deployed/SettingChecker.php @@ -0,0 +1,72 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Config\Model\Config\Reader\Source\Deployed; + +use Magento\Config\Model\Config\Reader; +use Magento\Framework\App\Config\ScopeCodeResolver; +use Magento\Framework\App\Config\ScopeConfigInterface; +use Magento\Framework\App\DeploymentConfig; +use Magento\Framework\App\ObjectManager; + +/** + * Class for checking settings that defined in config file + */ +class SettingChecker +{ + /** + * @var DeploymentConfig + */ + private $config; + + /** + * @var ScopeCodeResolver + */ + private $scopeCodeResolver; + + /** + * @param DeploymentConfig $config + * @param ScopeCodeResolver $scopeCodeResolver + */ + public function __construct( + DeploymentConfig $config, + ScopeCodeResolver $scopeCodeResolver + ) { + $this->config = $config; + $this->scopeCodeResolver = $scopeCodeResolver; + } + + /** + * Resolve path by scope and scope code + * + * @param string $scope + * @param string $scopeCode + * @return string + */ + private function resolvePath($scope, $scopeCode) + { + $scopePath = 'system/' . $scope; + + if ($scope != ScopeConfigInterface::SCOPE_TYPE_DEFAULT) { + $scopePath .= '/' . $this->scopeCodeResolver->resolve($scope, $scopeCode); + } + + return $scopePath; + } + + /** + * Check that setting defined in deployed configuration + * + * @param string $path + * @param string $scope + * @param string $scopeCode + * @return boolean + */ + public function isReadOnly($path, $scope, $scopeCode) + { + $config = $this->config->get($this->resolvePath($scope, $scopeCode) . "/" . $path); + return $config !== null; + } +} diff --git a/app/code/Magento/Config/Test/Unit/App/Config/Source/ModularConfigSourceTest.php b/app/code/Magento/Config/Test/Unit/App/Config/Source/ModularConfigSourceTest.php new file mode 100644 index 0000000000000000000000000000000000000000..204bafcd0261c2bb283a978fab372c6afbf0d7b8 --- /dev/null +++ b/app/code/Magento/Config/Test/Unit/App/Config/Source/ModularConfigSourceTest.php @@ -0,0 +1,43 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Config\Test\Unit\App\Config\Source; + +use Magento\Config\App\Config\Source\ModularConfigSource; +use Magento\Framework\App\Config\Initial\Reader; + +/** + * Test config source that is retrieved from config.xml + * + * @package Magento\Config\Test\Unit\App\Config\Source + */ +class ModularConfigSourceTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var Reader|\PHPUnit_Framework_MockObject_MockObject + */ + private $reader; + + /** + * @var ModularConfigSource + */ + private $source; + + public function setUp() + { + $this->reader = $this->getMockBuilder(Reader::class) + ->disableOriginalConstructor() + ->getMock(); + $this->source = new ModularConfigSource($this->reader); + } + + public function testGet() + { + $this->reader->expects($this->once()) + ->method('read') + ->willReturn(['data' => ['path' => 'value']]); + $this->assertEquals('value', $this->source->get('path')); + } +} diff --git a/app/code/Magento/Config/Test/Unit/App/Config/Source/RuntimeConfigSourceTest.php b/app/code/Magento/Config/Test/Unit/App/Config/Source/RuntimeConfigSourceTest.php new file mode 100644 index 0000000000000000000000000000000000000000..a750bdb32744f23bf6172d1c1034998cb7f66759 --- /dev/null +++ b/app/code/Magento/Config/Test/Unit/App/Config/Source/RuntimeConfigSourceTest.php @@ -0,0 +1,136 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Config\Test\Unit\App\Config\Source; + +use Magento\Config\App\Config\Source\RuntimeConfigSource; +use Magento\Config\Model\ResourceModel\Config\Data\CollectionFactory; +use Magento\Framework\App\Config\Scope\Converter; +use Magento\Framework\App\Config\ScopeCodeResolver; +use Magento\Framework\App\Config\ScopeConfigInterface; +use Magento\Framework\App\Config\Value; + +/** + * Test Class for retrieving runtime configuration from database. + * @package Magento\Config\Test\Unit\App\Config\Source + */ +class RuntimeConfigSourceTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var CollectionFactory|\PHPUnit_Framework_MockObject_MockObject + */ + private $collectionFactory; + + /** + * @var ScopeCodeResolver|\PHPUnit_Framework_MockObject_MockObject + */ + private $scopeCodeResolver; + + /** + * @var Converter|\PHPUnit_Framework_MockObject_MockObject + */ + private $converter; + + /** + * @var Value|\PHPUnit_Framework_MockObject_MockObject + */ + private $configItem; + + /** + * @var Value|\PHPUnit_Framework_MockObject_MockObject + */ + private $configItemTwo; + + /** + * @var RuntimeConfigSource + */ + private $configSource; + + public function setUp() + { + $this->collectionFactory = $this->getMockBuilder(CollectionFactory::class) + ->disableOriginalConstructor() + ->setMethods(['create']) + ->getMock(); + $this->scopeCodeResolver = $this->getMockBuilder(ScopeCodeResolver::class) + ->disableOriginalConstructor() + ->getMock(); + $this->converter = $this->getMockBuilder(Converter::class) + ->disableOriginalConstructor() + ->getMock(); + $this->configItem = $this->getMockBuilder(Value::class) + ->disableOriginalConstructor() + ->setMethods(['getScope', 'getPath', 'getValue']) + ->getMock(); + $this->configItemTwo = $this->getMockBuilder(Value::class) + ->disableOriginalConstructor() + ->setMethods(['getScope', 'getPath', 'getValue', 'getScopeId']) + ->getMock(); + $this->configSource = new RuntimeConfigSource( + $this->collectionFactory, + $this->scopeCodeResolver, + $this->converter + ); + } + + public function testGet() + { + $scope = 'websites'; + $scopeCode = 'myWebsites'; + $this->collectionFactory->expects($this->once()) + ->method('create') + ->willReturn([$this->configItem, $this->configItemTwo]); + $this->configItem->expects($this->exactly(2)) + ->method('getScope') + ->willReturn(ScopeConfigInterface::SCOPE_TYPE_DEFAULT); + $this->configItem->expects($this->once()) + ->method('getPath') + ->willReturn('dev/test/setting'); + $this->configItem->expects($this->once()) + ->method('getValue') + ->willReturn(true); + + $this->configItemTwo->expects($this->exactly(3)) + ->method('getScope') + ->willReturn($scope); + $this->configItemTwo->expects($this->once()) + ->method('getScopeId') + ->willReturn($scopeCode); + $this->configItemTwo->expects($this->once()) + ->method('getPath') + ->willReturn('dev/test/setting2'); + $this->configItemTwo->expects($this->once()) + ->method('getValue') + ->willReturn(false); + $this->scopeCodeResolver->expects($this->once()) + ->method('resolve') + ->with($scope, $scopeCode) + ->willReturnArgument(1); + $this->converter->expects($this->exactly(2)) + ->method('convert') + ->withConsecutive( + [['dev/test/setting' => true]], + [['dev/test/setting2' => false]] + ) + ->willReturnOnConsecutiveCalls( + ['dev/test/setting' => true], + ['dev/test/setting2' => false] + ); + + $this->assertEquals( + [ + 'default' => [ + 'dev/test/setting' => true + ], + 'websites' => [ + 'myWebsites' => [ + 'dev/test/setting2' => false + ] + ] + ], + $this->configSource->get() + ); + } +} diff --git a/app/code/Magento/Config/Test/Unit/App/Config/Type/SystemTest.php b/app/code/Magento/Config/Test/Unit/App/Config/Type/SystemTest.php new file mode 100644 index 0000000000000000000000000000000000000000..be541228bf6d88a5ad7e459ba77a34e896c863a1 --- /dev/null +++ b/app/code/Magento/Config/Test/Unit/App/Config/Type/SystemTest.php @@ -0,0 +1,141 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Config\Test\Unit\App\Config\Type; + +use Magento\Config\App\Config\Type\System; +use Magento\Framework\App\Config\ConfigSourceInterface; +use Magento\Framework\App\Config\Spi\PostProcessorInterface; +use Magento\Framework\App\ObjectManager; +use Magento\Framework\Cache\FrontendInterface; +use Magento\Framework\Serialize\Serializer\Serialize; +use Magento\Store\Model\Config\Processor\Fallback; + +/** + * Test how Class process source, cache them and retrieve value by path + * @package Magento\Config\Test\Unit\App\Config\Type + */ +class SystemTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var ConfigSourceInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $source; + + /** + * @var PostProcessorInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $postProcessor; + + /** + * @var Fallback|\PHPUnit_Framework_MockObject_MockObject + */ + private $fallback; + + /** + * @var FrontendInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $cache; + + /** + * @var System + */ + private $configType; + + /** + * @var Serialize|\PHPUnit_Framework_MockObject_MockObject + */ + private $serializer; + + public function setUp() + { + $this->source = $this->getMockBuilder(ConfigSourceInterface::class) + ->getMockForAbstractClass(); + $this->postProcessor = $this->getMockBuilder(PostProcessorInterface::class) + ->getMockForAbstractClass(); + $this->fallback = $this->getMockBuilder(Fallback::class) + ->disableOriginalConstructor() + ->getMock(); + $this->cache = $this->getMockBuilder(FrontendInterface::class) + ->getMockForAbstractClass(); + $this->serializer = $this->getMockBuilder(Serialize::class) + ->disableOriginalConstructor() + ->getMock(); + $this->configType = new System( + $this->source, + $this->postProcessor, + $this->fallback, + $this->cache, + $this->serializer + ); + } + + /** + * @param bool $isCached + * @dataProvider getDataProvider + */ + public function testGet($isCached) + { + $path = 'default/dev/unsecure/url'; + $url = 'http://magento.test/'; + $data = [ + 'default' => [ + 'dev' => [ + 'unsecure' => [ + 'url' => $url + ] + ] + ] + ]; + + $this->cache->expects($this->once()) + ->method('load') + ->with(System::CONFIG_TYPE) + ->willReturn($isCached ? $data : null); + + if ($isCached) { + $this->serializer->expects($this->once()) + ->method('unserialize') + ->willReturn($data); + } + + if (!$isCached) { + $this->serializer->expects($this->once()) + ->method('serialize') + ->willReturn(serialize($data)); + $this->source->expects($this->once()) + ->method('get') + ->willReturn($data); + $this->fallback->expects($this->once()) + ->method('process') + ->with($data) + ->willReturnArgument(0); + $this->postProcessor->expects($this->once()) + ->method('process') + ->with($data) + ->willReturnArgument(0); + $this->cache->expects($this->once()) + ->method('save') + ->with( + serialize($data), + System::CONFIG_TYPE, + [System::CACHE_TAG] + ); + } + + $this->assertEquals($url, $this->configType->get($path)); + } + + /** + * @return array + */ + public function getDataProvider() + { + return [ + [true], + [false] + ]; + } +} diff --git a/app/code/Magento/Config/Test/Unit/Block/System/Config/Form/FieldTest.php b/app/code/Magento/Config/Test/Unit/Block/System/Config/Form/FieldTest.php index ccd5beb12cdf74197dfd9c63bdd8839e80d8f02c..f0643fc3b1c73c46c0a2c899b8769ea8142adfb4 100644 --- a/app/code/Magento/Config/Test/Unit/Block/System/Config/Form/FieldTest.php +++ b/app/code/Magento/Config/Test/Unit/Block/System/Config/Form/FieldTest.php @@ -5,6 +5,11 @@ */ namespace Magento\Config\Test\Unit\Block\System\Config\Form; +/** + * Test how class render field html element in Stores Configuration + * + * @package Magento\Config\Test\Unit\Block\System\Config\Form + */ class FieldTest extends \PHPUnit_Framework_TestCase { /** @@ -69,6 +74,7 @@ class FieldTest extends \PHPUnit_Framework_TestCase 'getScope', 'getScopeLabel', 'getInherit', + 'getIsDisableInheritance', 'getCanUseWebsiteValue', 'getCanUseDefaultValue', 'setDisabled', @@ -185,6 +191,7 @@ class FieldTest extends \PHPUnit_Framework_TestCase $this->_elementMock->expects($this->any())->method('getCanUseWebsiteValue')->will($this->returnValue(true)); $this->_elementMock->expects($this->any())->method('getCanUseDefaultValue')->will($this->returnValue(true)); $this->_elementMock->expects($this->once())->method('setDisabled')->with(true); + $this->_elementMock->expects($this->once())->method('getIsDisableInheritance')->willReturn(true); $expected = '<td class="use-default">'; $expected .= '<input id="' . @@ -192,7 +199,7 @@ class FieldTest extends \PHPUnit_Framework_TestCase '_inherit" name="' . $this->_testData['name'] . '[inherit]" type="checkbox" value="1"' . - ' class="checkbox config-inherit" checked="checked"' . + ' class="checkbox config-inherit" checked="checked"' . ' disabled="disabled"' . ' onclick="toggleValueElements(this, Element.previous(this.parentNode))" /> '; $expected .= '<label for="' . $this->_testData['htmlId'] . '_inherit" class="inherit">Use Website</label>'; diff --git a/app/code/Magento/Config/Test/Unit/Block/System/Config/FormTest.php b/app/code/Magento/Config/Test/Unit/Block/System/Config/FormTest.php index 788c7788cccd19f880c72c43b8c6f47e00c545d6..2c671914f264b04ec34508d919a23c67bf64abad 100644 --- a/app/code/Magento/Config/Test/Unit/Block/System/Config/FormTest.php +++ b/app/code/Magento/Config/Test/Unit/Block/System/Config/FormTest.php @@ -8,6 +8,15 @@ namespace Magento\Config\Test\Unit\Block\System\Config; +use Magento\Config\Model\Config\Reader\Source\Deployed\SettingChecker; +use Magento\Framework\App\DeploymentConfig; + +/** + * Test System config form block + * + * @package Magento\Config\Test\Unit\Block\System\Config + */ + /** * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ @@ -178,6 +187,20 @@ class FormTest extends \PHPUnit_Framework_TestCase $this->_objectBuilder = $this->getMockBuilder(\Magento\Config\Block\System\Config\Form::class) ->setConstructorArgs($objectArguments) ->setMethods(['something']); + $deploymentConfigMock = $this->getMockBuilder(DeploymentConfig::class) + ->disableOriginalConstructor() + ->getMock(); + $deploymentConfigMock->expects($this->any()) + ->method('get') + ->willReturn([]); + + $objectManagerMock = $this->getMock(\Magento\Framework\ObjectManagerInterface::class); + $objectManagerMock->expects($this->any()) + ->method('get') + ->willReturnMap([ + [DeploymentConfig::class, $deploymentConfigMock] + ]); + \Magento\Framework\App\ObjectManager::setInstance($objectManagerMock); $this->object = $helper->getObject(\Magento\Config\Block\System\Config\Form::class, $data); $this->object->setData('scope_id', 1); } @@ -549,10 +572,12 @@ class FormTest extends \PHPUnit_Framework_TestCase 'field_config' => 'fieldData', 'scope' => 'stores', 'scope_id' => 1, - 'scope_label' => '[GLOBAL]', + 'scope_label' => __('[GLOBAL]'), 'can_use_default_value' => false, 'can_use_website_value' => false, 'can_restore_to_default' => false, + 'disabled' => false, + 'is_disable_inheritance' => false ]; $formFieldMock->expects($this->once())->method('setRenderer')->with($fieldRendererMock); @@ -571,6 +596,18 @@ class FormTest extends \PHPUnit_Framework_TestCase $fieldMock->expects($this->once())->method('populateInput'); + + $settingChecker = $this->getMockBuilder(SettingChecker::class) + ->disableOriginalConstructor() + ->getMock(); + $settingChecker->expects($this->once()) + ->method('isReadOnly') + ->willReturn(false); + $reflection = new \ReflectionClass(get_class($this->object)); + $reflectionProperty = $reflection->getProperty('settingChecker'); + $reflectionProperty->setAccessible(true); + $reflectionProperty->setValue($this->object, $settingChecker); + $this->object->initFields($fieldsetMock, $groupMock, $sectionMock, $fieldPrefix, $labelPrefix); } diff --git a/app/code/Magento/Config/Test/Unit/Model/Config/LoaderTest.php b/app/code/Magento/Config/Test/Unit/Model/Config/LoaderTest.php index 6047aa4c06afb4dfd7e1dab451aa8c93e4010755..69d4b01526a216f1e97b588fd14af0f9066ac3a3 100644 --- a/app/code/Magento/Config/Test/Unit/Model/Config/LoaderTest.php +++ b/app/code/Magento/Config/Test/Unit/Model/Config/LoaderTest.php @@ -5,6 +5,9 @@ */ namespace Magento\Config\Test\Unit\Model\Config; +/** + * @package Magento\Config\Test\Unit\Model\Config + */ class LoaderTest extends \PHPUnit_Framework_TestCase { /** @@ -32,7 +35,6 @@ class LoaderTest extends \PHPUnit_Framework_TestCase false ); $this->_model = new \Magento\Config\Model\Config\Loader($this->_configValueFactory); - $this->_configCollection = $this->getMock( \Magento\Config\Model\ResourceModel\Config\Data\Collection::class, [], diff --git a/app/code/Magento/Config/Test/Unit/Model/Config/Reader/Source/Deployed/SettingCheckerTest.php b/app/code/Magento/Config/Test/Unit/Model/Config/Reader/Source/Deployed/SettingCheckerTest.php new file mode 100644 index 0000000000000000000000000000000000000000..2e746eae410f414788a7b5277e331be7075e6655 --- /dev/null +++ b/app/code/Magento/Config/Test/Unit/Model/Config/Reader/Source/Deployed/SettingCheckerTest.php @@ -0,0 +1,71 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Config\Test\Unit\Model\Config\Reader\Source\Deployed; + +use Magento\Config\Model\Config\Reader; +use Magento\Config\Model\Config\Reader\Source\Deployed\SettingChecker; +use Magento\Framework\App\Config\ScopeCodeResolver; +use Magento\Framework\App\Config; +use Magento\Framework\App\DeploymentConfig; + +/** + * Test class for checking settings that defined in config file + * + * @package Magento\Config\Test\Unit\Model\Config\Reader\Source\Deployed + */ +class SettingCheckerTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var Config|\PHPUnit_Framework_MockObject_MockObject + */ + private $config; + + /** + * @var SettingChecker + */ + private $checker; + + /** + * @var ScopeCodeResolver | \PHPUnit_Framework_MockObject_MockObject + */ + private $scopeCodeResolver; + + public function setUp() + { + $this->config = $this->getMockBuilder(DeploymentConfig::class) + ->disableOriginalConstructor() + ->getMock(); + $this->scopeCodeResolver = $this->getMockBuilder(ScopeCodeResolver::class) + ->disableOriginalConstructor() + ->getMock(); + $this->checker = new SettingChecker($this->config, $this->scopeCodeResolver); + } + + public function testIsDefined() + { + $path = 'general/web/locale'; + $scope = 'website'; + $scopeCode = 'myWebsite'; + $scopeCodeId = '4'; + + $this->config->expects($this->once()) + ->method('get') + ->willReturn([ + $scope => [ + $scopeCode => [ + $path => 'value' + ], + ], + ]); + + $this->scopeCodeResolver->expects($this->once()) + ->method('resolve') + ->with($scope, $scopeCodeId) + ->willReturn($scopeCode); + + $this->assertTrue($this->checker->isReadOnly($path, $scope, $scopeCodeId)); + } +} diff --git a/app/code/Magento/Config/composer.json b/app/code/Magento/Config/composer.json index b14dd825b0d12d819fd511222e80de12a7cf8c3a..ab9c95e1166536ebb71adf36a1b5f1b9aea06b68 100644 --- a/app/code/Magento/Config/composer.json +++ b/app/code/Magento/Config/composer.json @@ -11,6 +11,9 @@ "magento/module-backend": "100.2.*", "magento/module-media-storage": "100.2.*" }, + "suggest": { + "magento/module-deploy": "100.2.*" + }, "type": "magento2-module", "version": "100.2.0-dev", "license": [ diff --git a/app/code/Magento/Config/etc/di.xml b/app/code/Magento/Config/etc/di.xml index 9a72ebcb16609caa28ce328c2b3c2ebcb43c9e0d..4f9eae24b55f611db54f3f5423c3944f7d93a7f6 100644 --- a/app/code/Magento/Config/etc/di.xml +++ b/app/code/Magento/Config/etc/di.xml @@ -69,4 +69,97 @@ <argument name="resourceCollection" xsi:type="object">Magento\Config\Model\ResourceModel\Config\Data\Collection\Proxy</argument> </arguments> </type> + <type name="Magento\Framework\App\Config"> + <arguments> + <argument name="types" xsi:type="array"> + <item name="system" xsi:type="object">Magento\Config\App\Config\Type\System</item> + </argument> + </arguments> + </type> + <type name="Magento\Config\App\Config\Type\System"> + <arguments> + <argument name="source" xsi:type="object">systemConfigSourceAggregatedProxy</argument> + <argument name="postProcessor" xsi:type="object">systemConfigPostProcessorCompositeProxy</argument> + <argument name="cache" xsi:type="object">Magento\Framework\App\Cache\Type\Config</argument> + </arguments> + </type> + <virtualType name="modulesDataProviderProxy" type="Magento\Framework\App\Config\InitialConfigSource\Proxy"> + <arguments> + <argument name="instanceName" xsi:type="string">modulesDataProvider</argument> + </arguments> + </virtualType> + <virtualType name="modulesDataProvider" type="Magento\Framework\App\Config\InitialConfigSource"> + <arguments> + <argument name="reader" xsi:type="object">Magento\Framework\App\DeploymentConfig\Reader</argument> + <argument name="configType" xsi:type="const">Magento\Framework\Config\ConfigOptionsListConstants::KEY_MODULES</argument> + <argument name="fileKey" xsi:type="const">Magento\Framework\Config\File\ConfigFilePool::APP_CONFIG</argument> + </arguments> + </virtualType> + <virtualType name="systemConfigPostProcessorCompositeProxy" type="Magento\Framework\App\Config\PostProcessorComposite\Proxy"> + <arguments> + <argument name="instanceName" xsi:type="string">systemConfigPostProcessorComposite</argument> + </arguments> + </virtualType> + <virtualType name="systemConfigSourceAggregatedProxy" type="Magento\Framework\App\Config\ConfigSourceAggregated\Proxy"> + <arguments> + <argument name="instanceName" xsi:type="string">systemConfigSourceAggregated</argument> + </arguments> + </virtualType> + <virtualType name="systemConfigPostProcessorComposite" type="Magento\Framework\App\Config\PostProcessorComposite"> + <arguments> + <argument name="processors" xsi:type="array"> + <item name="placeholder" xsi:type="object">Magento\Store\Model\Config\Processor\Placeholder</item> + <item name="metadata" xsi:type="object">Magento\Framework\App\Config\MetadataConfigTypeProcessor</item> + </argument> + </arguments> + </virtualType> + <virtualType name="systemConfigSourceAggregated" type="Magento\Framework\App\Config\ConfigSourceAggregated"> + <arguments> + <argument name="sources" xsi:type="array"> + <item name="modular" xsi:type="array"> + <item name="source" xsi:type="object">Magento\Config\App\Config\Source\ModularConfigSource</item> + <item name="sortOrder" xsi:type="string">10</item> + </item> + <item name="dynamic" xsi:type="array"> + <item name="source" xsi:type="object">Magento\Config\App\Config\Source\RuntimeConfigSource</item> + <item name="sortOrder" xsi:type="string">100</item> + </item> + <item name="initial" xsi:type="array"> + <item name="source" xsi:type="object">systemConfigInitialDataProvider</item> + <item name="sortOrder" xsi:type="string">1000</item> + </item> + </argument> + </arguments> + </virtualType> + <virtualType name="systemConfigInitialDataProvider" type="Magento\Framework\App\Config\InitialConfigSource"> + <arguments> + <argument name="reader" xsi:type="object">Magento\Framework\App\DeploymentConfig\Reader</argument> + <argument name="configType" xsi:type="const">Magento\Config\App\Config\Type\System::CONFIG_TYPE</argument> + <argument name="fileKey" xsi:type="const">Magento\Framework\Config\File\ConfigFilePool::APP_CONFIG</argument> + </arguments> + </virtualType> + <virtualType name="appDumpSystemSource" type="Magento\Framework\App\Config\ConfigSourceAggregated"> + <arguments> + <argument name="sources" xsi:type="array"> + <item name="initial" xsi:type="array"> + <item name="source" xsi:type="object">systemConfigInitialDataProvider</item> + <item name="sortOrder" xsi:type="string">10</item> + </item> + <item name="dynamic" xsi:type="array"> + <item name="source" xsi:type="object">Magento\Config\App\Config\Source\RuntimeConfigSource</item> + <item name="sortOrder" xsi:type="string">1000</item> + </item> + </argument> + </arguments> + </virtualType> + <type name="Magento\Deploy\Console\Command\App\ApplicationDumpCommand"> + <arguments> + <argument name="sources" xsi:type="array"> + <item name="system" xsi:type="array"> + <item name="source" xsi:type="object">appDumpSystemSource</item> + <item name="namespace" xsi:type="const">Magento\Config\App\Config\Type\System::CONFIG_TYPE</item> + </item> + </argument> + </arguments> + </type> </config> diff --git a/app/code/Magento/ConfigurableProduct/Test/Unit/Controller/Adminhtml/Product/Initialization/Helper/Plugin/UpdateConfigurationsTest.php b/app/code/Magento/ConfigurableProduct/Test/Unit/Controller/Adminhtml/Product/Initialization/Helper/Plugin/UpdateConfigurationsTest.php index def49f42fa960b738fe952be4a2d18bada61ffd2..79d77c66e0d05427c9a89e6fb14cbee7cbc3327e 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Unit/Controller/Adminhtml/Product/Initialization/Helper/Plugin/UpdateConfigurationsTest.php +++ b/app/code/Magento/ConfigurableProduct/Test/Unit/Controller/Adminhtml/Product/Initialization/Helper/Plugin/UpdateConfigurationsTest.php @@ -13,6 +13,11 @@ use Magento\ConfigurableProduct\Model\Product\VariationHandler; use Magento\Catalog\Controller\Adminhtml\Product\Initialization\Helper as ProductInitializationHelper; use Magento\Catalog\Model\Product; +/** + * Class UpdateConfigurationsTest + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + * @package Magento\ConfigurableProduct\Test\Unit\Controller\Adminhtml\Product\Initialization\Helper\Plugin + */ class UpdateConfigurationsTest extends \PHPUnit_Framework_TestCase { /** @@ -69,10 +74,14 @@ class UpdateConfigurationsTest extends \PHPUnit_Framework_TestCase ); } - public function testAfterInitialize() + /** + * Prepare configurable matrix + * + * @return array + */ + private function getConfigurableMatrix() { - $productMock = $this->getProductMock(); - $configurableMatrix = [ + return [ [ 'newProduct' => true, 'id' => 'product1' @@ -109,6 +118,12 @@ class UpdateConfigurationsTest extends \PHPUnit_Framework_TestCase 'weight' => '5.55', ], ]; + } + + public function testAfterInitialize() + { + $productMock = $this->getProductMock(); + $configurableMatrix = $this->getConfigurableMatrix(); $configurations = [ 'product2' => [ 'status' => 'simple2_status', diff --git a/app/code/Magento/Cron/Model/Config/Reader/Db.php b/app/code/Magento/Cron/Model/Config/Reader/Db.php index 1a58c14470038f7d81568cbbdb9c7407683967bd..9602775f18106aaf02ff6f70f0d44e2e8aa4912b 100644 --- a/app/code/Magento/Cron/Model/Config/Reader/Db.php +++ b/app/code/Magento/Cron/Model/Config/Reader/Db.php @@ -5,6 +5,8 @@ */ namespace Magento\Cron\Model\Config\Reader; +use Magento\Framework\App\Config; + /** * Reader for cron parameters from data base storage */ @@ -22,17 +24,22 @@ class Db */ protected $_reader; + /** + * @var Config + */ + private $config; + /** * Initialize parameters * - * @param \Magento\Framework\App\Config\Scope\ReaderInterface $defaultReader + * @param Config $config * @param \Magento\Cron\Model\Config\Converter\Db $converter */ public function __construct( - \Magento\Framework\App\Config\Scope\ReaderInterface $defaultReader, + Config $config, \Magento\Cron\Model\Config\Converter\Db $converter ) { - $this->_reader = $defaultReader; + $this->config = $config; $this->_converter = $converter; } @@ -43,6 +50,6 @@ class Db */ public function get() { - return $this->_converter->convert($this->_reader->read()); + return $this->_converter->convert($this->config->get('system/default')); } } diff --git a/app/code/Magento/Cron/Test/Unit/Model/Config/Reader/DbTest.php b/app/code/Magento/Cron/Test/Unit/Model/Config/Reader/DbTest.php index e93978d9683664f9378be0be1142667cac1dae99..6205c993524e4492912a3b96921b2958d8bcc984 100644 --- a/app/code/Magento/Cron/Test/Unit/Model/Config/Reader/DbTest.php +++ b/app/code/Magento/Cron/Test/Unit/Model/Config/Reader/DbTest.php @@ -5,12 +5,20 @@ */ namespace Magento\Cron\Test\Unit\Model\Config\Reader; +use Magento\Framework\App\Config; +use Magento\GoogleAdwords\Block\Code; + +/** + * Test reading for cron parameters from data base storage + * + * @package Magento\Cron\Test\Unit\Model\Config\Reader + */ class DbTest extends \PHPUnit_Framework_TestCase { /** - * @var \Magento\Store\Model\Config\Reader\DefaultReader|\PHPUnit_Framework_MockObject_MockObject + * @var Config | \PHPUnit_Framework_MockObject_MockObject */ - protected $_defaultReader; + protected $config; /** * @var \Magento\Cron\Model\Config\Converter\Db|\PHPUnit_Framework_MockObject_MockObject @@ -27,11 +35,11 @@ class DbTest extends \PHPUnit_Framework_TestCase */ protected function setUp() { - $this->_defaultReader = $this->getMockBuilder( - \Magento\Store\Model\Config\Reader\DefaultReader::class - )->disableOriginalConstructor()->getMock(); + $this->config = $this->getMockBuilder(Config::class) + ->disableOriginalConstructor() + ->getMock(); $this->_converter = new \Magento\Cron\Model\Config\Converter\Db(); - $this->_reader = new \Magento\Cron\Model\Config\Reader\Db($this->_defaultReader, $this->_converter); + $this->_reader = new \Magento\Cron\Model\Config\Reader\Db($this->config, $this->_converter); } /** @@ -42,7 +50,7 @@ class DbTest extends \PHPUnit_Framework_TestCase $job1 = ['schedule' => ['cron_expr' => '* * * * *']]; $job2 = ['schedule' => ['cron_expr' => '1 1 1 1 1']]; $data = ['crontab' => ['default' => ['jobs' => ['job1' => $job1, 'job2' => $job2]]]]; - $this->_defaultReader->expects($this->once())->method('read')->will($this->returnValue($data)); + $this->config->expects($this->once())->method('get')->with('system/default')->will($this->returnValue($data)); $expected = [ 'default' => [ 'job1' => ['schedule' => $job1['schedule']['cron_expr']], diff --git a/app/code/Magento/Cron/etc/di.xml b/app/code/Magento/Cron/etc/di.xml index 740eff2aed432694f9e4ef836ef799c1ab9eb19a..d5624e96765c58bd699eebc29c14c7fe76037b7a 100644 --- a/app/code/Magento/Cron/etc/di.xml +++ b/app/code/Magento/Cron/etc/di.xml @@ -8,11 +8,6 @@ <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd"> <preference for="Magento\Cron\Model\ConfigInterface" type="Magento\Cron\Model\Config" /> <preference for="Magento\Framework\Shell\CommandRendererInterface" type="Magento\Framework\Shell\CommandRenderer" /> - <type name="Magento\Cron\Model\Config\Reader\Db"> - <arguments> - <argument name="defaultReader" xsi:type="object">Magento\Store\Model\Config\Reader\DefaultReader</argument> - </arguments> - </type> <type name="Magento\Config\Model\Config\Structure\Converter"> <plugin name="cron_backend_config_structure_converter_plugin" type="Magento\Cron\Model\Backend\Config\Structure\Converter" /> </type> diff --git a/app/code/Magento/Deploy/Console/Command/App/ApplicationDumpCommand.php b/app/code/Magento/Deploy/Console/Command/App/ApplicationDumpCommand.php new file mode 100644 index 0000000000000000000000000000000000000000..b4e4fef8fb2f941eaa56cc33b2df65f783fa0413 --- /dev/null +++ b/app/code/Magento/Deploy/Console/Command/App/ApplicationDumpCommand.php @@ -0,0 +1,83 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Deploy\Console\Command\App; + +use Magento\Framework\App\Config\Reader\Source\SourceInterface; +use Magento\Framework\App\DeploymentConfig\Writer; +use Magento\Framework\Config\File\ConfigFilePool; +use Magento\Framework\Console\Cli; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; + +/** + * Command for dump application state + */ +class ApplicationDumpCommand extends Command +{ + /** + * @var Writer + */ + private $writer; + + /** + * @var SourceInterface[] + */ + private $sources; + + /** + * ApplicationDumpCommand constructor. + * + * @param Writer $writer + * @param array $sources + */ + public function __construct( + Writer $writer, + array $sources + ) { + parent::__construct(); + $this->writer = $writer; + $this->sources = $sources; + } + + /** + * {@inheritdoc} + */ + protected function configure() + { + $this->setName('app:config:dump'); + $this->setDescription('Create dump of application'); + parent::configure(); + } + + /** + * Dump Application + * + * @param InputInterface $input + * @param OutputInterface $output + * @return boolean + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + $dump = []; + foreach ($this->sources as $sourceData) { + /** @var SourceInterface $source */ + $source = $sourceData['source']; + $namespace = $sourceData['namespace']; + $dump[$namespace] = $source->get(); + } + + $this->writer + ->saveConfig( + [ConfigFilePool::APP_CONFIG => $dump], + true, + ConfigFilePool::LOCAL + ); + $output->writeln('<info>Done.</info>'); + return Cli::RETURN_SUCCESS; + } +} diff --git a/app/code/Magento/Deploy/Model/Deploy/LocaleDeploy.php b/app/code/Magento/Deploy/Model/Deploy/LocaleDeploy.php index aa112a700133185cf06980fb6b465de509630371..c879a512d26c29c99c0152eda2e7fab148422fd8 100644 --- a/app/code/Magento/Deploy/Model/Deploy/LocaleDeploy.php +++ b/app/code/Magento/Deploy/Model/Deploy/LocaleDeploy.php @@ -6,11 +6,13 @@ namespace Magento\Deploy\Model\Deploy; +use Magento\Framework\App\ObjectManager; use Magento\Framework\App\Utility\Files; use Magento\Framework\App\View\Asset\Publisher; use Magento\Framework\View\Asset\ContentProcessorException; use Magento\Framework\View\Asset\PreProcessor\AlternativeSourceInterface; use Magento\Framework\View\Design\Theme\ThemeProviderInterface; +use Magento\Framework\View\Design\Theme\ListInterface; use Symfony\Component\Console\Output\OutputInterface; use Magento\Framework\Config\Theme; use Magento\Deploy\Console\Command\DeployStaticOptionsInterface as Options; @@ -20,6 +22,8 @@ use Psr\Log\LoggerInterface; use Magento\Framework\Console\Cli; /** + * Class which allows deploy by locales + * * @SuppressWarnings(PHPMD.CouplingBetweenObjects) * @SuppressWarnings(PHPMD.TooManyFields) */ @@ -115,6 +119,11 @@ class LocaleDeploy implements DeployInterface */ private $alternativeSources; + /** + * @var ListInterface + */ + private $themeList; + /** * @var array */ @@ -242,7 +251,10 @@ class LocaleDeploy implements DeployInterface private function deployRequireJsConfig($area, $themePath) { if (!$this->getOption(Options::DRY_RUN) && !$this->getOption(Options::NO_JAVASCRIPT)) { - $design = $this->designFactory->create()->setDesignTheme($themePath, $area); + + /** @var \Magento\Framework\View\Design\ThemeInterface $theme */ + $theme = $this->getThemeList()->getThemeByFullPath($area . '/' . $themePath); + $design = $this->designFactory->create()->setDesignTheme($theme, $area); $assetRepo = $this->assetRepoFactory->create(['design' => $design]); /** @var \Magento\RequireJs\Model\FileManager $fileManager */ $fileManager = $this->fileManagerFactory->create( @@ -450,4 +462,16 @@ class LocaleDeploy implements DeployInterface } return $ancestorThemeFullPath; } + + /** + * @deprecated + * @return ListInterface + */ + private function getThemeList() + { + if ($this->themeList === null) { + $this->themeList = ObjectManager::getInstance()->get(ListInterface::class); + } + return $this->themeList; + } } diff --git a/app/code/Magento/Deploy/Test/Unit/Console/Command/ApplicationDumpCommandTest.php b/app/code/Magento/Deploy/Test/Unit/Console/Command/ApplicationDumpCommandTest.php new file mode 100644 index 0000000000000000000000000000000000000000..686cf19d8f3113371339c29187c51ceae3cbf313 --- /dev/null +++ b/app/code/Magento/Deploy/Test/Unit/Console/Command/ApplicationDumpCommandTest.php @@ -0,0 +1,91 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Deploy\Test\Unit\Console\Command; + +use Magento\Deploy\Console\Command\App\ApplicationDumpCommand; +use Magento\Framework\App\Config\Reader\Source\SourceInterface; +use Magento\Framework\App\DeploymentConfig\Writer; +use Magento\Framework\Config\File\ConfigFilePool; +use Magento\Framework\Console\Cli; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; + +/** + * Test command for dump application state + */ +class ApplicationDumpCommandTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var InputInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $input; + + /** + * @var OutputInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $output; + + /** + * @var Writer|\PHPUnit_Framework_MockObject_MockObject + */ + private $writer; + + /** + * @var SourceInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $source; + + /** + * @var ApplicationDumpCommand + */ + private $command; + + public function setUp() + { + $this->input = $this->getMockBuilder(InputInterface::class) + ->getMockForAbstractClass(); + $this->output = $this->getMockBuilder(OutputInterface::class) + ->getMockForAbstractClass(); + $this->writer = $this->getMockBuilder(Writer::class) + ->disableOriginalConstructor() + ->getMock(); + $this->source = $this->getMockBuilder(SourceInterface::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->command = new ApplicationDumpCommand($this->writer, [[ + 'namespace' => 'system', + 'source' => $this->source + ]]); + } + + public function testExport() + { + $dump = [ + 'system' => ['systemDATA'] + ]; + $data = [ConfigFilePool::APP_CONFIG => $dump]; + $this->source + ->expects($this->once()) + ->method('get') + ->willReturn(['systemDATA']); + $this->output->expects($this->once()) + ->method('writeln') + ->with('<info>Done.</info>'); + $this->writer->expects($this->once()) + ->method('saveConfig') + ->with($data); + $method = new \ReflectionMethod(ApplicationDumpCommand::class, 'execute'); + $method->setAccessible(true); + $this->assertEquals( + Cli::RETURN_SUCCESS, + $method->invokeArgs( + $this->command, + [$this->input, $this->output] + ) + ); + } +} diff --git a/app/code/Magento/Deploy/Test/Unit/Model/Deploy/LocaleDeployTest.php b/app/code/Magento/Deploy/Test/Unit/Model/Deploy/LocaleDeployTest.php index 757da133ddbc3df30eac5a590c1c8dbf00fd002a..f43c8f111146c500fd824c67f3b128a5b6110574 100644 --- a/app/code/Magento/Deploy/Test/Unit/Model/Deploy/LocaleDeployTest.php +++ b/app/code/Magento/Deploy/Test/Unit/Model/Deploy/LocaleDeployTest.php @@ -5,210 +5,134 @@ */ namespace Magento\Deploy\Test\Unit\Model\Deploy; +use Magento\Deploy\Model\Deploy\LocaleDeploy; use Magento\Framework\App\Utility\Files; use Magento\Framework\App\View\Asset\Publisher; use Magento\Framework\Translate\Js\Config; use Magento\Framework\View\Asset\Minification; use Magento\Framework\View\Asset\Repository; use Magento\Framework\View\Asset\RepositoryFactory; +use Magento\RequireJs\Model\FileManagerFactory; +use Magento\Framework\RequireJs\ConfigFactory; +use Magento\Framework\View\Asset\Bundle\Manager; +use Magento\Framework\View\Design\Theme\ThemeProviderInterface; +use Magento\Framework\View\DesignInterfaceFactory; +use Magento\Framework\Locale\ResolverInterface; +use Magento\Framework\View\Design\Theme\ListInterface; use Psr\Log\LoggerInterface; use Symfony\Component\Console\Output\OutputInterface; /** + * Test class which allows deploy by locales * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class LocaleDeployTest extends \PHPUnit_Framework_TestCase { /** - * @var \PHPUnit_Framework_MockObject_MockObject|Config + * @var string */ - private $jsTranslationMock; + private $area; /** - * @var \PHPUnit_Framework_MockObject_MockObject|Minification + * @var string */ - private $minificationMock; + private $locale; /** - * @var \PHPUnit_Framework_MockObject_MockObject|RepositoryFactory + * @var string */ - private $assetRepoFactoryMock; + private $themePath; /** - * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\RequireJs\Model\FileManagerFactory + * @var \Magento\Deploy\Model\Deploy\LocaleDeploy */ - private $fileManagerFactoryMock; - - /** - * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Framework\RequireJs\ConfigFactory - */ - private $configFactoryMock; - - /** - * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Framework\View\Asset\Bundle\Manager - */ - private $bundleManagerMock; - - /** - * @var \PHPUnit_Framework_MockObject_MockObject|Files - */ - private $filesUtilMock; - - /** - * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Framework\View\DesignInterfaceFactory - */ - private $designFactoryMock; - - /** - * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Framework\Locale\ResolverInterface - */ - private $localeResolverMock; - - /** - * @var \PHPUnit_Framework_MockObject_MockObject|OutputInterface - */ - private $outputMock; - - /** - * @var \PHPUnit_Framework_MockObject_MockObject|LoggerInterface - */ - private $loggerMock; - - /** - * @var \PHPUnit_Framework_MockObject_MockObject - */ - private $assetRepoMock; - - /** - * @var \PHPUnit_Framework_MockObject_MockObject - */ - private $assetPublisherMock; - - /** - * @var \PHPUnit_Framework_MockObject_MockObject - */ - private $themeProviderMock; + private $model; protected function setUp() { - $this->outputMock = $this->getMock(OutputInterface::class, [], [], '', false); - $this->loggerMock = $this->getMock(LoggerInterface::class, [], [], '', false); - $this->filesUtilMock = $this->getMock(Files::class, [], [], '', false); - $this->assetRepoMock = $this->getMock(Repository::class, [], [], '', false); - $this->minificationMock = $this->getMock(Minification::class, [], [], '', false); - $this->jsTranslationMock = $this->getMock(Config::class, [], [], '', false); - $this->assetPublisherMock = $this->getMock(Publisher::class, [], [], '', false); - $this->assetRepoFactoryMock = $this->getMock( - RepositoryFactory::class, - ['create'], - [], - '', - false - ); - $this->fileManagerFactoryMock = $this->getMock( - \Magento\RequireJs\Model\FileManagerFactory::class, - ['create'], - [], - '', - false - ); - $this->configFactoryMock = $this->getMock( - \Magento\Framework\RequireJs\ConfigFactory::class, - ['create'], - [], - '', - false - ); - $this->bundleManagerMock = $this->getMock( - \Magento\Framework\View\Asset\Bundle\Manager::class, - [], - [], - '', - false - ); - $this->themeProviderMock = $this->getMock( - \Magento\Framework\View\Design\Theme\ThemeProviderInterface::class, - [], - [], - '', - false - ); - $this->designFactoryMock = $this->getMock( - \Magento\Framework\View\DesignInterfaceFactory::class, - ['create'], - [], - '', - false - ); - $this->localeResolverMock = $this->getMock( - \Magento\Framework\Locale\ResolverInterface::class, - [], - [], - '', - false - ); - } - - public function testDeploy() - { - $area = 'adminhtml'; - $themePath = '/theme/path'; - $locale = 'en_US'; - + $this->area = 'adminhtml'; + $this->themePath = '/theme/path'; + $this->locale = 'en_US'; + + $outputMock = $this->getMock(OutputInterface::class, [], [], '', false); + $jsTranslationMock = $this->getMock(Config::class, [], [], '', false); + $jsTranslationMock->expects($this->once())->method('dictionaryEnabled')->willReturn(false); + $minificationMock = $this->getMock(Minification::class, [], [], '', false); + $minificationMock->expects($this->once())->method('isEnabled')->with('js')->willReturn(true); + + $themeMock = $this->getMockBuilder(\Magento\Framework\View\Design\ThemeInterface::class) + ->disableOriginalConstructor() + ->getMock(); $designMock = $this->getMock(\Magento\Framework\View\DesignInterface::class, [], [], '', false); + $designMock->expects($this->once())->method('setDesignTheme')->with($themeMock, $this->area)->willReturnSelf(); $assetRepoMock = $this->getMock(Repository::class, [], [], '', false); - $requireJsConfigMock = $this->getMock(\Magento\Framework\RequireJs\Config::class, [], [], '', false); - $fileManagerMock = $this->getMock(\Magento\RequireJs\Model\FileManager::class, [], [], '', false); - - $model = $this->getModel([\Magento\Deploy\Console\Command\DeployStaticOptionsInterface::NO_JAVASCRIPT => 0]); - - $this->localeResolverMock->expects($this->once())->method('setLocale')->with($locale); - $this->designFactoryMock->expects($this->once())->method('create')->willReturn($designMock); - $designMock->expects($this->once())->method('setDesignTheme')->with($themePath, $area)->willReturnSelf(); - $this->assetRepoFactoryMock->expects($this->once())->method('create')->with(['design' => $designMock]) + $assetRepoFactoryMock = $this->getMock(RepositoryFactory::class, ['create'], [], '', false); + $assetRepoFactoryMock->expects($this->once()) + ->method('create') + ->with(['design' => $designMock]) ->willReturn($assetRepoMock); - $this->configFactoryMock->expects($this->once())->method('create')->willReturn($requireJsConfigMock); - $this->fileManagerFactoryMock->expects($this->once())->method('create')->willReturn($fileManagerMock); + $fileManagerMock = $this->getMock(\Magento\RequireJs\Model\FileManager::class, [], [], '', false); $fileManagerMock->expects($this->once())->method('createRequireJsConfigAsset')->willReturnSelf(); - $this->filesUtilMock->expects($this->once())->method('getStaticPreProcessingFiles')->willReturn([]); - $this->filesUtilMock->expects($this->once())->method('getStaticLibraryFiles')->willReturn([]); - - $this->jsTranslationMock->expects($this->once())->method('dictionaryEnabled')->willReturn(false); - $this->minificationMock->expects($this->once())->method('isEnabled')->with('js')->willReturn(true); $fileManagerMock->expects($this->once())->method('createMinResolverAsset')->willReturnSelf(); + $fileManagerFactoryMock = $this->getMock(FileManagerFactory::class, ['create'], [], '', false); + $fileManagerFactoryMock->expects($this->once())->method('create')->willReturn($fileManagerMock); - $this->bundleManagerMock->expects($this->once())->method('flush'); - - $this->assertEquals( - \Magento\Framework\Console\Cli::RETURN_SUCCESS, - $model->deploy($area, $themePath, $locale) + $requireJsConfigMock = $this->getMock(\Magento\Framework\RequireJs\Config::class, [], [], '', false); + $configFactoryMock = $this->getMock(ConfigFactory::class, ['create'], [], '', false); + $configFactoryMock->expects($this->once())->method('create')->willReturn($requireJsConfigMock); + + $assetPublisherMock = $this->getMock(Publisher::class, [], [], '', false); + + $bundleManagerMock = $this->getMock(Manager::class, [], [], '', false); + $bundleManagerMock->expects($this->once())->method('flush'); + + $themeProviderMock = $this->getMock(ThemeProviderInterface::class, [], [], '', false); + $loggerMock = $this->getMock(LoggerInterface::class, [], [], '', false); + + $filesUtilMock = $this->getMock(Files::class, [], [], '', false); + $filesUtilMock->expects($this->once())->method('getStaticPreProcessingFiles')->willReturn([]); + $filesUtilMock->expects($this->once())->method('getStaticLibraryFiles')->willReturn([]); + + $designFactoryMock = $this->getMock(DesignInterfaceFactory::class, ['create'], [], '', false); + $designFactoryMock->expects($this->once())->method('create')->willReturn($designMock); + + $localeResolverMock = $this->getMock(ResolverInterface::class, [], [], '', false); + $localeResolverMock->expects($this->once())->method('setLocale')->with($this->locale); + + $themeList = $this->getMock(ListInterface::class, [], [], '', false); + $themeList->expects($this->once())->method('getThemeByFullPath') + ->with($this->area . '/' . $this->themePath) + ->willReturn($themeMock); + + $this->model = new LocaleDeploy( + $outputMock, + $jsTranslationMock, + $minificationMock, + $assetRepoMock, + $assetRepoFactoryMock, + $fileManagerFactoryMock, + $configFactoryMock, + $assetPublisherMock, + $bundleManagerMock, + $themeProviderMock, + $loggerMock, + $filesUtilMock, + $designFactoryMock, + $localeResolverMock, + [], + [\Magento\Deploy\Console\Command\DeployStaticOptionsInterface::NO_JAVASCRIPT => 0] ); + $property = new \ReflectionProperty(get_class($this->model), 'themeList'); + $property->setAccessible(true); + $property->setValue($this->model, $themeList); } - /** - * @param array $options - * @return \Magento\Deploy\Model\Deploy\LocaleDeploy - */ - private function getModel($options = []) + public function testDeploy() { - return new \Magento\Deploy\Model\Deploy\LocaleDeploy( - $this->outputMock, - $this->jsTranslationMock, - $this->minificationMock, - $this->assetRepoMock, - $this->assetRepoFactoryMock, - $this->fileManagerFactoryMock, - $this->configFactoryMock, - $this->assetPublisherMock, - $this->bundleManagerMock, - $this->themeProviderMock, - $this->loggerMock, - $this->filesUtilMock, - $this->designFactoryMock, - $this->localeResolverMock, - [], - $options + $this->assertEquals( + \Magento\Framework\Console\Cli::RETURN_SUCCESS, + $this->model->deploy($this->area, $this->themePath, $this->locale) ); } } diff --git a/app/code/Magento/Deploy/etc/di.xml b/app/code/Magento/Deploy/etc/di.xml index 52c880c28d0a71ad7eaeb34b6c2096c6c7b5060a..f230238364ab788907753388d9594e2eece7c97d 100644 --- a/app/code/Magento/Deploy/etc/di.xml +++ b/app/code/Magento/Deploy/etc/di.xml @@ -23,9 +23,9 @@ <type name="Magento\Framework\Console\CommandListInterface"> <arguments> <argument name="commands" xsi:type="array"> - <item name="staticContentDeployCommand" xsi:type="object">Magento\Deploy\Console\Command\DeployStaticContentCommand</item> <item name="setModeCommand" xsi:type="object">Magento\Deploy\Console\Command\SetModeCommand</item> <item name="showModeCommand" xsi:type="object">Magento\Deploy\Console\Command\ShowModeCommand</item> + <item name="dumpApplicationCommand" xsi:type="object">\Magento\Deploy\Console\Command\App\ApplicationDumpCommand</item> </argument> </arguments> </type> diff --git a/app/code/Magento/Eav/Model/Entity/AttributeCache.php b/app/code/Magento/Eav/Model/Entity/AttributeCache.php index 865fc5ebb5b1e0f26b3b75108be0115c11a7682a..f4f52e154cdd1cb1970ff07913cd273b0a5c77b2 100644 --- a/app/code/Magento/Eav/Model/Entity/AttributeCache.php +++ b/app/code/Magento/Eav/Model/Entity/AttributeCache.php @@ -9,6 +9,7 @@ namespace Magento\Eav\Model\Entity; use Magento\Eav\Model\Entity\Attribute\AbstractAttribute; use Magento\Framework\App\CacheInterface; use Magento\Framework\App\Cache\StateInterface; +use Magento\Framework\Serialize\SerializerInterface; /** * Class AttributeCache @@ -120,7 +121,7 @@ class AttributeCache [ \Magento\Eav\Model\Cache\Type::CACHE_TAG, \Magento\Eav\Model\Entity\Attribute::CACHE_TAG, - \Magento\Framework\App\Config\ScopePool::CACHE_TAG + \Magento\Config\App\Config\Type\System::CACHE_TAG ] ); } diff --git a/app/code/Magento/Email/Model/Template/Css/Processor.php b/app/code/Magento/Email/Model/Template/Css/Processor.php index ae7d083750863d2d7dbd5869341bbee772544421..0386a9ace5ea5a7b5d9c93075224d1031017f28f 100644 --- a/app/code/Magento/Email/Model/Template/Css/Processor.php +++ b/app/code/Magento/Email/Model/Template/Css/Processor.php @@ -8,6 +8,9 @@ namespace Magento\Email\Model\Template\Css; use Magento\Framework\View\Asset\NotationResolver\Variable; use Magento\Framework\View\Asset\Repository; +/** + * Class for processing css placeholders + */ class Processor { /** diff --git a/app/code/Magento/Email/Model/Template/Filter.php b/app/code/Magento/Email/Model/Template/Filter.php index d9409d62f159cfd7c2ab1e6c32aae6d07a33b8fc..658b2977fdf738207d07ddcb5d4774c6fe9cb72c 100644 --- a/app/code/Magento/Email/Model/Template/Filter.php +++ b/app/code/Magento/Email/Model/Template/Filter.php @@ -216,31 +216,6 @@ class Filter extends \Magento\Framework\Filter\Template parent::__construct($string, $variables); } - /** - * @deprecated - * @return Css\Processor - */ - private function getCssProcessor() - { - if (!$this->cssProcessor) { - $this->cssProcessor = ObjectManager::getInstance()->get(Css\Processor::class); - } - return $this->cssProcessor; - } - - /** - * @deprecated - * @param string $dirType - * @return ReadInterface - */ - private function getPubDirectory($dirType) - { - if (!$this->pubDirectory) { - $this->pubDirectory = ObjectManager::getInstance()->get(Filesystem::class)->getDirectoryRead($dirType); - } - return $this->pubDirectory; - } - /** * Set use absolute links flag * @@ -333,6 +308,31 @@ class Filter extends \Magento\Framework\Filter\Template return $this; } + /** + * @deprecated + * @return Css\Processor + */ + private function getCssProcessor() + { + if (!$this->cssProcessor) { + $this->cssProcessor = ObjectManager::getInstance()->get(Css\Processor::class); + } + return $this->cssProcessor; + } + + /** + * @deprecated + * @param string $dirType + * @return ReadInterface + */ + private function getPubDirectory($dirType) + { + if (!$this->pubDirectory) { + $this->pubDirectory = ObjectManager::getInstance()->get(Filesystem::class)->getDirectoryRead($dirType); + } + return $this->pubDirectory; + } + /** * Get design parameters * diff --git a/app/code/Magento/Store/App/Config/Source/RuntimeConfigSource.php b/app/code/Magento/Store/App/Config/Source/RuntimeConfigSource.php new file mode 100644 index 0000000000000000000000000000000000000000..015ba1d6ef63392cf3c4ac6ec7d6f38a1777c80b --- /dev/null +++ b/app/code/Magento/Store/App/Config/Source/RuntimeConfigSource.php @@ -0,0 +1,197 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Store\App\Config\Source; + +use Magento\Framework\App\Config\ConfigSourceInterface; +use Magento\Framework\App\DeploymentConfig; +use Magento\Store\Model\ResourceModel\Website\CollectionFactory as WebsiteCollectionFactory; +use Magento\Store\Model\ResourceModel\Group\CollectionFactory as GroupCollectionFactory; +use Magento\Store\Model\ResourceModel\Store\CollectionFactory as StoreCollectionFactory; +use Magento\Store\Model\WebsiteFactory; +use Magento\Store\Model\GroupFactory; +use Magento\Store\Model\StoreFactory; + +/** + * Class RuntimeConfigSource + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ +class RuntimeConfigSource implements ConfigSourceInterface +{ + /** + * @var WebsiteCollectionFactory + */ + private $websiteCollectionFactory; + + /** + * @var GroupCollectionFactory + */ + private $groupCollectionFactory; + + /** + * @var StoreCollectionFactory + */ + private $storeCollectionFactory; + + /** + * @var DeploymentConfig + */ + private $deploymentConfig; + + /** + * @var WebsiteFactory + */ + private $websiteFactory; + + /** + * @var GroupFactory + */ + private $groupFactory; + + /** + * @var StoreFactory + */ + private $storeFactory; + + /** + * DynamicDataProvider constructor. + * + * @param WebsiteCollectionFactory $websiteCollectionFactory + * @param GroupCollectionFactory $groupCollectionFactory + * @param StoreCollectionFactory $storeCollectionFactory + * @param WebsiteFactory $websiteFactory + * @param GroupFactory $groupFactory + * @param StoreFactory $storeFactory + * @param DeploymentConfig $deploymentConfig + */ + public function __construct( + WebsiteCollectionFactory $websiteCollectionFactory, + GroupCollectionFactory $groupCollectionFactory, + StoreCollectionFactory $storeCollectionFactory, + WebsiteFactory $websiteFactory, + GroupFactory $groupFactory, + StoreFactory $storeFactory, + DeploymentConfig $deploymentConfig + ) { + $this->websiteCollectionFactory = $websiteCollectionFactory; + $this->groupCollectionFactory = $groupCollectionFactory; + $this->storeCollectionFactory = $storeCollectionFactory; + $this->deploymentConfig = $deploymentConfig; + $this->websiteFactory = $websiteFactory; + $this->groupFactory = $groupFactory; + $this->storeFactory = $storeFactory; + } + + /** + * @inheritdoc + */ + public function get($path = '') + { + if (strpos($path, '/') === false) { + $scopePool = $path; + $scopeCode = null; + } else { + list($scopePool, $scopeCode) = explode('/', $path); + } + + $data = []; + if ($this->canUseDatabase()) { + switch ($scopePool) { + case 'websites': + $data = $this->getWebsitesData($scopeCode); + break; + case 'groups': + $data = $this->getGroupsData($scopeCode); + break; + case 'stores': + $data = $this->getStoresData($scopeCode); + break; + default: + $data = [ + 'websites' => $this->getWebsitesData(), + 'groups' => $this->getGroupsData(), + 'stores' => $this->getStoresData(), + ]; + break; + } + } + + return $data; + } + + /** + * @param string|null $code + * @return array + */ + private function getWebsitesData($code = null) + { + if ($code) { + $website = $this->websiteFactory->create(); + $website->load($code); + $data = $website->getData(); + } else { + $collection = $this->websiteCollectionFactory->create(); + $collection->setLoadDefault(true); + $data = []; + foreach ($collection as $website) { + $data[$website->getCode()] = $website->getData(); + } + } + return $data; + } + + /** + * @param string|null $id + * @return array + */ + private function getGroupsData($id = null) + { + if ($id) { + $group = $this->groupFactory->create(); + $group->load($id); + $data = $group->getData(); + } else { + $collection = $this->groupCollectionFactory->create(); + $collection->setLoadDefault(true); + $data = []; + foreach ($collection as $group) { + $data[$group->getId()] = $group->getData(); + } + } + return $data; + } + + /** + * @param string|null $code + * @return array + */ + private function getStoresData($code = null) + { + if ($code) { + $store = $this->storeFactory->create(); + $store->load($code, 'code'); + $data = $store->getData(); + } else { + $collection = $this->storeCollectionFactory->create(); + $collection->setLoadDefault(true); + $data = []; + foreach ($collection as $store) { + $data[$store->getCode()] = $store->getData(); + } + return $data; + } + return $data; + } + + /** + * Check whether db connection is available and can be used + * + * @return bool + */ + private function canUseDatabase() + { + return $this->deploymentConfig->get('db'); + } +} diff --git a/app/code/Magento/Store/App/Config/Type/Scopes.php b/app/code/Magento/Store/App/Config/Type/Scopes.php new file mode 100644 index 0000000000000000000000000000000000000000..1c9ac59442163945f6aab2739807afdd74be7673 --- /dev/null +++ b/app/code/Magento/Store/App/Config/Type/Scopes.php @@ -0,0 +1,62 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Store\App\Config\Type; + +use Magento\Framework\App\Config\ConfigTypeInterface; +use Magento\Framework\App\Config\ConfigSourceInterface; +use Magento\Framework\DataObject; + +/** + * Merge and hold scopes data from different sources + * + * @package Magento\Store\App\Config\Type + */ +class Scopes implements ConfigTypeInterface +{ + const CONFIG_TYPE = 'scopes'; + + /** + * @var ConfigSourceInterface + */ + private $source; + + /** + * @var DataObject[] + */ + private $data; + + /** + * System constructor. + * @param ConfigSourceInterface $source + */ + public function __construct( + ConfigSourceInterface $source + ) { + $this->source = $source; + } + + /** + * @inheritdoc + */ + public function get($path = '') + { + if (!$this->data) { + $this->data = new DataObject($this->source->get()); + } + + return $this->data->getData($path); + } + + /** + * Clean cache + * + * @return void + */ + public function clean() + { + $this->data = null; + } +} diff --git a/app/code/Magento/Store/Model/Config/Converter.php b/app/code/Magento/Store/Model/Config/Converter.php index 9cc898e58207a890e7f8eaaf3730a01e88f83181..939544399d517f7adc73da6f8ee1ac32948721eb 100644 --- a/app/code/Magento/Store/Model/Config/Converter.php +++ b/app/code/Magento/Store/Model/Config/Converter.php @@ -7,21 +7,11 @@ */ namespace Magento\Store\Model\Config; +/** + * Class Converter. + */ class Converter extends \Magento\Framework\App\Config\Scope\Converter { - /** - * @var \Magento\Store\Model\Config\Processor\Placeholder - */ - protected $_processor; - - /** - * @param \Magento\Store\Model\Config\Processor\Placeholder $processor - */ - public function __construct(\Magento\Store\Model\Config\Processor\Placeholder $processor) - { - $this->_processor = $processor; - } - /** * Convert config data * @@ -31,7 +21,6 @@ class Converter extends \Magento\Framework\App\Config\Scope\Converter */ public function convert($source, $initialConfig = []) { - $config = array_replace_recursive($initialConfig, parent::convert($source)); - return $this->_processor->process($config); + return array_replace_recursive($initialConfig, parent::convert($source)); } } diff --git a/app/code/Magento/Store/Model/Config/Placeholder.php b/app/code/Magento/Store/Model/Config/Placeholder.php new file mode 100644 index 0000000000000000000000000000000000000000..af313c82b949aeaf177655c08d3af4003a3ae2e0 --- /dev/null +++ b/app/code/Magento/Store/Model/Config/Placeholder.php @@ -0,0 +1,165 @@ +<?php +/** + * Placeholder configuration values processor. Replace placeholders in configuration with config values + * + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Store\Model\Config; + +class Placeholder +{ + /** + * @var \Magento\Framework\App\RequestInterface + */ + protected $request; + + /** + * @var string[] + */ + protected $urlPaths; + + /** + * @var string + */ + protected $urlPlaceholder; + + /** + * @param \Magento\Framework\App\RequestInterface $request + * @param string[] $urlPaths + * @param string $urlPlaceholder + */ + public function __construct(\Magento\Framework\App\RequestInterface $request, $urlPaths, $urlPlaceholder) + { + $this->request = $request; + $this->urlPaths = $urlPaths; + $this->urlPlaceholder = $urlPlaceholder; + } + + /** + * Replace placeholders with config values + * + * @param array $data + * @return array + */ + public function process(array $data = []) + { + foreach (array_keys($data) as $key) { + $this->_processData($data, $key); + } + return $data; + } + + /** + * Process array data recursively + * + * @param array &$data + * @param string $path + * @return void + */ + protected function _processData(&$data, $path) + { + $configValue = $this->_getValue($path, $data); + if (is_array($configValue)) { + foreach (array_keys($configValue) as $key) { + $this->_processData($data, $path . '/' . $key); + } + } else { + $this->_setValue($data, $path, $this->_processPlaceholders($configValue, $data)); + } + } + + /** + * Replace placeholders with config values + * + * @param string $value + * @param array $data + * @return string + */ + protected function _processPlaceholders($value, $data) + { + $placeholder = $this->_getPlaceholder($value); + if ($placeholder) { + $url = false; + if ($placeholder == 'unsecure_base_url') { + $url = $this->_getValue($this->urlPaths['unsecureBaseUrl'], $data); + } elseif ($placeholder == 'secure_base_url') { + $url = $this->_getValue($this->urlPaths['secureBaseUrl'], $data); + } + + if ($url) { + $value = str_replace('{{' . $placeholder . '}}', $url, $value); + } elseif (strpos($value, $this->urlPlaceholder) !== false) { + $distroBaseUrl = $this->request->getDistroBaseUrl(); + $value = str_replace($this->urlPlaceholder, $distroBaseUrl, $value); + } + + if (null !== $this->_getPlaceholder($value)) { + $value = $this->_processPlaceholders($value, $data); + } + } + return $value; + } + + /** + * Get placeholder from value + * + * @param string $value + * @return string|null + */ + protected function _getPlaceholder($value) + { + if (is_string($value) && preg_match('/{{(.*)}}.*/', $value, $matches)) { + $placeholder = $matches[1]; + if ($placeholder == 'unsecure_base_url' || $placeholder == 'secure_base_url' || strpos( + $value, + $this->urlPlaceholder + ) !== false + ) { + return $placeholder; + } + } + return null; + } + + /** + * Get array value by path + * + * @param string $path + * @param array $data + * @return array|null + */ + protected function _getValue($path, array $data) + { + $keys = explode('/', $path); + foreach ($keys as $key) { + if (is_array($data) && (isset($data[$key]) || array_key_exists($key, $data))) { + $data = $data[$key]; + } else { + return null; + } + } + return $data; + } + + /** + * Set array value by path + * + * @param array &$container + * @param string $path + * @param string $value + * @return void + */ + protected function _setValue(array &$container, $path, $value) + { + $segments = explode('/', $path); + $currentPointer = & $container; + foreach ($segments as $segment) { + if (!isset($currentPointer[$segment])) { + $currentPointer[$segment] = []; + } + $currentPointer = & $currentPointer[$segment]; + } + $currentPointer = $value; + } +} diff --git a/app/code/Magento/Store/Model/Config/Processor/Fallback.php b/app/code/Magento/Store/Model/Config/Processor/Fallback.php new file mode 100644 index 0000000000000000000000000000000000000000..612f0514e77c13d9b7600478af0f1ff9fcaddf69 --- /dev/null +++ b/app/code/Magento/Store/Model/Config/Processor/Fallback.php @@ -0,0 +1,115 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Store\Model\Config\Processor; + +use Magento\Framework\App\Config\Spi\PostProcessorInterface; +use Magento\Store\App\Config\Type\Scopes; + +/** + * Fallback throguh different scopes and merge them + * + * @package Magento\Store\Model\Config\Processor + */ +class Fallback implements PostProcessorInterface +{ + /** + * @var Scopes + */ + private $scopes; + + /** + * Fallback constructor. + * @param Scopes $scopes + */ + public function __construct(Scopes $scopes) + { + $this->scopes = $scopes; + } + + /** + * @inheritdoc + */ + public function process(array $data) + { + $defaultConfig = isset($data['default']) ? $data['default'] : []; + $result = [ + 'default' => $defaultConfig, + 'websites' => [], + 'stores' => [] + ]; + + $websitesConfig = isset($data['websites']) ? $data['websites'] : []; + $result['websites'] = $this->prepareWebsitesConfig($defaultConfig, $websitesConfig); + + $storesConfig = isset($data['stores']) ? $data['stores'] : []; + $result['stores'] = $this->prepareStoresConfig($defaultConfig, $websitesConfig, $storesConfig); + + return $result; + } + + /** + * Prepare website data from Config/Type/Scopes + * + * @param array $defaultConfig + * @param array $websitesConfig + * @return array + */ + private function prepareWebsitesConfig(array $defaultConfig, array $websitesConfig) + { + $result = []; + foreach ($this->scopes->get('websites') as $websiteData) { + $code = $websiteData['code']; + $id = $websiteData['website_id']; + $websiteConfig = isset($websitesConfig[$code]) ? $websitesConfig[$code] : []; + $result[$code] = array_replace_recursive($defaultConfig, $websiteConfig); + $result[$id] = $result[$code]; + } + return $result; + } + + /** + * Prepare stores data from Config/Type/Scopes + * + * @param array $defaultConfig + * @param array $websitesConfig + * @param array $storesConfig + * @return array + */ + private function prepareStoresConfig(array $defaultConfig, array $websitesConfig, array $storesConfig) + { + $result = []; + foreach ($this->scopes->get('stores') as $storeData) { + $code = $storeData['code']; + $id = $storeData['store_id']; + $websiteConfig = []; + if (isset($storeData['website_id'])) { + $websiteConfig = $this->getWebsiteConfig($websitesConfig, $storeData['website_id']); + } + $storeConfig = isset($storesConfig[$code]) ? $storesConfig[$code] : []; + $result[$code] = array_replace_recursive($defaultConfig, $websiteConfig, $storeConfig); + $result[$id] = $result[$code]; + } + return $result; + } + + /** + * Retrieve Website Config + * + * @param array $websites + * @param int $id + * @return array + */ + private function getWebsiteConfig(array $websites, $id) + { + foreach ($this->scopes->get('websites') as $websiteData) { + if ($websiteData['website_id'] == $id) { + $code = $websiteData['code']; + return isset($websites[$code]) ? $websites[$code] : []; + } + } + return []; + } +} diff --git a/app/code/Magento/Store/Model/Config/Processor/Placeholder.php b/app/code/Magento/Store/Model/Config/Processor/Placeholder.php index ac150267053885b7c8b6e863155aa164cd17d6da..3695a9a9d66ce05de260bae5d60649a602e5a68d 100644 --- a/app/code/Magento/Store/Model/Config/Processor/Placeholder.php +++ b/app/code/Magento/Store/Model/Config/Processor/Placeholder.php @@ -7,159 +7,44 @@ */ namespace Magento\Store\Model\Config\Processor; -class Placeholder -{ - /** - * @var \Magento\Framework\App\RequestInterface - */ - protected $request; - - /** - * @var string[] - */ - protected $urlPaths; - - /** - * @var string - */ - protected $urlPlaceholder; - - /** - * @param \Magento\Framework\App\RequestInterface $request - * @param string[] $urlPaths - * @param string $urlPlaceholder - */ - public function __construct(\Magento\Framework\App\RequestInterface $request, $urlPaths, $urlPlaceholder) - { - $this->request = $request; - $this->urlPaths = $urlPaths; - $this->urlPlaceholder = $urlPlaceholder; - } - - /** - * Replace placeholders with config values - * - * @param array $data - * @return array - */ - public function process(array $data = []) - { - foreach (array_keys($data) as $key) { - $this->_processData($data, $key); - } - return $data; - } - - /** - * Process array data recursively - * - * @param array &$data - * @param string $path - * @return void - */ - protected function _processData(&$data, $path) - { - $configValue = $this->_getValue($path, $data); - if (is_array($configValue)) { - foreach (array_keys($configValue) as $key) { - $this->_processData($data, $path . '/' . $key); - } - } else { - $this->_setValue($data, $path, $this->_processPlaceholders($configValue, $data)); - } - } +use Magento\Framework\App\Config\Spi\PostProcessorInterface; +use Magento\Store\Model\Config\Placeholder as ConfigPlaceholder; +/** + * Placeholder configuration values processor. Replace placeholders in configuration with config values + * @package Magento\Store\Model\Config\Processor + */ +class Placeholder implements PostProcessorInterface +{ /** - * Replace placeholders with config values - * - * @param string $value - * @param array $data - * @return string + * @var ConfigPlaceholder */ - protected function _processPlaceholders($value, $data) - { - $placeholder = $this->_getPlaceholder($value); - if ($placeholder) { - $url = false; - if ($placeholder == 'unsecure_base_url') { - $url = $this->_getValue($this->urlPaths['unsecureBaseUrl'], $data); - } elseif ($placeholder == 'secure_base_url') { - $url = $this->_getValue($this->urlPaths['secureBaseUrl'], $data); - } - - if ($url) { - $value = str_replace('{{' . $placeholder . '}}', $url, $value); - } elseif (strpos($value, $this->urlPlaceholder) !== false) { - $distroBaseUrl = $this->request->getDistroBaseUrl(); - $value = str_replace($this->urlPlaceholder, $distroBaseUrl, $value); - } - - if (null !== $this->_getPlaceholder($value)) { - $value = $this->_processPlaceholders($value, $data); - } - } - return $value; - } + private $configPlaceholder; /** - * Get placeholder from value - * - * @param string $value - * @return string|null + * Placeholder constructor. + * @param ConfigPlaceholder $configPlaceholder */ - protected function _getPlaceholder($value) + public function __construct(ConfigPlaceholder $configPlaceholder) { - if (is_string($value) && preg_match('/{{(.*)}}.*/', $value, $matches)) { - $placeholder = $matches[1]; - if ($placeholder == 'unsecure_base_url' || $placeholder == 'secure_base_url' || strpos( - $value, - $this->urlPlaceholder - ) !== false - ) { - return $placeholder; - } - } - return null; + $this->configPlaceholder = $configPlaceholder; } /** - * Get array value by path - * - * @param string $path - * @param array $data - * @return array|null + * @inheritdoc */ - protected function _getValue($path, array $data) + public function process(array $data) { - $keys = explode('/', $path); - foreach ($keys as $key) { - if (is_array($data) && (isset($data[$key]) || array_key_exists($key, $data))) { - $data = $data[$key]; + foreach ($data as $scope => &$scopeData) { + if ($scope === 'default') { + $scopeData = $this->configPlaceholder->process($scopeData); } else { - return null; + foreach ($scopeData as &$sData) { + $sData = $this->configPlaceholder->process($sData); + } } } - return $data; - } - /** - * Set array value by path - * - * @param array &$container - * @param string $path - * @param string $value - * @return void - */ - protected function _setValue(array &$container, $path, $value) - { - $segments = explode('/', $path); - $currentPointer = & $container; - foreach ($segments as $segment) { - if (!isset($currentPointer[$segment])) { - $currentPointer[$segment] = []; - } - $currentPointer = & $currentPointer[$segment]; - } - $currentPointer = $value; + return $data; } } diff --git a/app/code/Magento/Store/Model/Config/Reader/DefaultReader.php b/app/code/Magento/Store/Model/Config/Reader/DefaultReader.php deleted file mode 100644 index 6436f1895a67525919767a0cc0025736f82d5c02..0000000000000000000000000000000000000000 --- a/app/code/Magento/Store/Model/Config/Reader/DefaultReader.php +++ /dev/null @@ -1,73 +0,0 @@ -<?php -/** - * Default configuration reader - * - * Copyright © 2016 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Store\Model\Config\Reader; - -use Magento\Framework\App\Config\ScopeConfigInterface; -use Magento\Framework\Exception\LocalizedException; - -class DefaultReader implements \Magento\Framework\App\Config\Scope\ReaderInterface -{ - /** - * @var \Magento\Framework\App\Config\Initial - */ - protected $_initialConfig; - - /** - * @var \Magento\Framework\App\Config\Scope\Converter - */ - protected $_converter; - - /** - * @var \Magento\Store\Model\ResourceModel\Config\Collection\ScopedFactory - */ - protected $_collectionFactory; - - /** - * @param \Magento\Framework\App\Config\Initial $initialConfig - * @param \Magento\Framework\App\Config\Scope\Converter $converter - * @param \Magento\Store\Model\ResourceModel\Config\Collection\ScopedFactory $collectionFactory - */ - public function __construct( - \Magento\Framework\App\Config\Initial $initialConfig, - \Magento\Framework\App\Config\Scope\Converter $converter, - \Magento\Store\Model\ResourceModel\Config\Collection\ScopedFactory $collectionFactory - ) { - $this->_initialConfig = $initialConfig; - $this->_converter = $converter; - $this->_collectionFactory = $collectionFactory; - } - - /** - * Read configuration data - * - * @param null|string $scope - * @throws LocalizedException Exception is thrown when scope other than default is given - * @return array - */ - public function read($scope = null) - { - $scope = $scope === null ? ScopeConfigInterface::SCOPE_TYPE_DEFAULT : $scope; - if ($scope !== ScopeConfigInterface::SCOPE_TYPE_DEFAULT) { - throw new \Magento\Framework\Exception\LocalizedException(__("Only default scope allowed")); - } - - $config = $this->_initialConfig->getData($scope); - - $collection = $this->_collectionFactory->create( - ['scope' => $scope] - ); - $dbDefaultConfig = []; - foreach ($collection as $item) { - $dbDefaultConfig[$item->getPath()] = $item->getValue(); - } - $dbDefaultConfig = $this->_converter->convert($dbDefaultConfig); - $config = array_replace_recursive($config, $dbDefaultConfig); - - return $config; - } -} diff --git a/app/code/Magento/Store/Model/Config/Reader/ReaderPool.php b/app/code/Magento/Store/Model/Config/Reader/ReaderPool.php deleted file mode 100644 index 55bbe33c3a93c4354d2d06304218d63c0cbece04..0000000000000000000000000000000000000000 --- a/app/code/Magento/Store/Model/Config/Reader/ReaderPool.php +++ /dev/null @@ -1,36 +0,0 @@ -<?php -/** - * Copyright © 2016 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Store\Model\Config\Reader; - -class ReaderPool implements \Magento\Framework\App\Config\Scope\ReaderPoolInterface -{ - /** - * List of readers - * - * @var array - */ - protected $_readers = []; - - /** - * @param \Magento\Framework\App\Config\Scope\ReaderInterface[] $readers - */ - public function __construct( - array $readers - ) { - $this->_readers = $readers; - } - - /** - * Retrieve reader by scope type - * - * @param string $scopeType - * @return mixed - */ - public function getReader($scopeType) - { - return $this->_readers[$scopeType]; - } -} diff --git a/app/code/Magento/Store/Model/Config/Reader/Source/Dynamic/DefaultScope.php b/app/code/Magento/Store/Model/Config/Reader/Source/Dynamic/DefaultScope.php new file mode 100644 index 0000000000000000000000000000000000000000..1f25a29856a78fbcbb3df02853bf30c9ab5fcb30 --- /dev/null +++ b/app/code/Magento/Store/Model/Config/Reader/Source/Dynamic/DefaultScope.php @@ -0,0 +1,61 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Store\Model\Config\Reader\Source\Dynamic; + +use Magento\Framework\App\Config\Scope\Converter; +use Magento\Store\Model\ResourceModel\Config\Collection\ScopedFactory; +use Magento\Framework\App\Config\Reader\Source\SourceInterface; +use Magento\Framework\App\Config\ScopeConfigInterface; + +/** + * Class for retrieving configuration from DB by default scope + */ +class DefaultScope implements SourceInterface +{ + /** + * @var ScopedFactory + */ + private $collectionFactory; + + /** + * @var Converter + */ + private $converter; + + /** + * @param ScopedFactory $collectionFactory + * @param Converter $converter + */ + public function __construct( + ScopedFactory $collectionFactory, + Converter $converter + ) { + $this->collectionFactory = $collectionFactory; + $this->converter = $converter; + } + + /** + * Retrieve config by default scope + * + * @param string|null $scopeCode + * @return array + */ + public function get($scopeCode = null) + { + try { + $collection = $this->collectionFactory->create( + ['scope' => ScopeConfigInterface::SCOPE_TYPE_DEFAULT] + ); + } catch (\DomainException $e) { + $collection = []; + } + $config = []; + foreach ($collection as $item) { + $config[$item->getPath()] = $item->getValue(); + } + return $this->converter->convert($config); + } +} diff --git a/app/code/Magento/Store/Model/Config/Reader/Source/Dynamic/Store.php b/app/code/Magento/Store/Model/Config/Reader/Source/Dynamic/Store.php new file mode 100644 index 0000000000000000000000000000000000000000..e1d0eaf51e05c27fb792e0c856073d1846bd38ba --- /dev/null +++ b/app/code/Magento/Store/Model/Config/Reader/Source/Dynamic/Store.php @@ -0,0 +1,92 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Store\Model\Config\Reader\Source\Dynamic; + +use Magento\Framework\App\Config\Scope\Converter; +use Magento\Store\Model\ResourceModel\Config\Collection\ScopedFactory; +use Magento\Framework\App\Config\Reader\Source\SourceInterface; +use Magento\Store\Model\ScopeInterface; +use Magento\Store\Model\StoreManagerInterface; +use Magento\Store\Model\WebsiteFactory; + +/** + * Class for retrieving configuration from DB by store scope + */ +class Store implements SourceInterface +{ + /** + * @var ScopedFactory + */ + private $collectionFactory; + + /** + * @var Converter + */ + private $converter; + + /** + * @var WebsiteFactory + */ + private $websiteFactory; + + /** + * @var Website + */ + private $websiteSource; + + /** + * @var StoreManagerInterface + */ + private $storeManager; + + /** + * @param ScopedFactory $collectionFactory + * @param Converter $converter + * @param WebsiteFactory $websiteFactory + * @param Website $websiteSource + * @param StoreManagerInterface $storeManager + */ + public function __construct( + ScopedFactory $collectionFactory, + Converter $converter, + WebsiteFactory $websiteFactory, + Website $websiteSource, + StoreManagerInterface $storeManager + ) { + $this->collectionFactory = $collectionFactory; + $this->converter = $converter; + $this->websiteFactory = $websiteFactory; + $this->websiteSource = $websiteSource; + $this->storeManager = $storeManager; + } + + /** + * Retrieve config by store scope + * + * @param string|null $scopeCode + * @return array + */ + public function get($scopeCode = null) + { + try { + $store = $this->storeManager->getStore($scopeCode); + $collection = $this->collectionFactory->create( + ['scope' => ScopeInterface::SCOPE_STORES, 'scopeId' => $store->getId()] + ); + + $config = []; + foreach ($collection as $item) { + $config[$item->getPath()] = $item->getValue(); + } + return $this->converter->convert(array_replace_recursive( + $this->websiteSource->get($store->getWebsiteId()), + $this->converter->convert($config) + )); + } catch (\DomainException $e) { + return []; + } + } +} diff --git a/app/code/Magento/Store/Model/Config/Reader/Source/Dynamic/Website.php b/app/code/Magento/Store/Model/Config/Reader/Source/Dynamic/Website.php new file mode 100644 index 0000000000000000000000000000000000000000..0edd12fd2809876f600244319cdc98ffa88231d3 --- /dev/null +++ b/app/code/Magento/Store/Model/Config/Reader/Source/Dynamic/Website.php @@ -0,0 +1,80 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Store\Model\Config\Reader\Source\Dynamic; + +use Magento\Framework\App\Config\Scope\Converter; +use Magento\Store\Model\ResourceModel\Config\Collection\ScopedFactory; +use Magento\Framework\App\Config\Reader\Source\SourceInterface; +use Magento\Store\Model\ScopeInterface; +use Magento\Store\Model\WebsiteFactory; + +/** + * Class for retrieving configuration from DB by website scope + */ +class Website implements SourceInterface +{ + /** + * @var ScopedFactory + */ + private $collectionFactory; + + /** + * @var Converter + */ + private $converter; + + /** + * @var WebsiteFactory + */ + private $websiteFactory; + + /** + * @var DefaultScope + */ + private $defaultScope; + + /** + * @param ScopedFactory $collectionFactory + * @param Converter $converter + * @param WebsiteFactory $websiteFactory + * @param DefaultScope $defaultScope + */ + public function __construct( + ScopedFactory $collectionFactory, + Converter $converter, + WebsiteFactory $websiteFactory, + DefaultScope $defaultScope + ) { + $this->collectionFactory = $collectionFactory; + $this->converter = $converter; + $this->websiteFactory = $websiteFactory; + $this->defaultScope = $defaultScope; + } + + /** + * Retrieve config by website scope + * + * @param string|null $scopeCode + * @return array + */ + public function get($scopeCode = null) + { + try { + $website = $this->websiteFactory->create(); + $website->load($scopeCode); + $collection = $this->collectionFactory->create( + ['scope' => ScopeInterface::SCOPE_WEBSITES, 'scopeId' => $website->getId()] + ); + $config = []; + foreach ($collection as $item) { + $config[$item->getPath()] = $item->getValue(); + } + return array_replace_recursive($this->defaultScope->get(), $this->converter->convert($config)); + } catch (\DomainException $e) { + return []; + } + } +} diff --git a/app/code/Magento/Store/Model/Config/Reader/Source/Initial/DefaultScope.php b/app/code/Magento/Store/Model/Config/Reader/Source/Initial/DefaultScope.php new file mode 100644 index 0000000000000000000000000000000000000000..071599d2df56b8b1e5b52c42777abe43eab165a0 --- /dev/null +++ b/app/code/Magento/Store/Model/Config/Reader/Source/Initial/DefaultScope.php @@ -0,0 +1,50 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Store\Model\Config\Reader\Source\Initial; + +use Magento\Framework\App\Config\Initial; +use Magento\Framework\App\Config\Reader\Source\SourceInterface; +use Magento\Framework\App\Config\Scope\Converter; +use Magento\Framework\App\Config\ScopeConfigInterface; + +/** + * Class for retrieving configuration from initial by default scope + */ +class DefaultScope implements SourceInterface +{ + /** + * @var Initial + */ + private $initialConfig; + + /** + * @var Converter + */ + private $converter; + + /** + * @param Initial $initialConfig + * @param Converter $converter + */ + public function __construct( + Initial $initialConfig, + Converter $converter + ) { + $this->initialConfig = $initialConfig; + $this->converter = $converter; + } + + /** + * Retrieve config by default scope + * + * @param string|null $scopeCode + * @return array + */ + public function get($scopeCode = null) + { + return $this->converter->convert($this->initialConfig->getData(ScopeConfigInterface::SCOPE_TYPE_DEFAULT)); + } +} diff --git a/app/code/Magento/Store/Model/Config/Reader/Source/Initial/Store.php b/app/code/Magento/Store/Model/Config/Reader/Source/Initial/Store.php new file mode 100644 index 0000000000000000000000000000000000000000..8a36fa76ed335f0e768df1a3aecad4b627b9b987 --- /dev/null +++ b/app/code/Magento/Store/Model/Config/Reader/Source/Initial/Store.php @@ -0,0 +1,75 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Store\Model\Config\Reader\Source\Initial; + +use Magento\Framework\App\Config\Initial; +use Magento\Framework\App\Config\Reader\Source\SourceInterface; +use Magento\Framework\App\Config\Scope\Converter; +use Magento\Store\Model\StoreManagerInterface; + +/** + * Class for retrieving configuration from initial config by store scope + */ +class Store implements SourceInterface +{ + /** + * @var Initial + */ + private $initialConfig; + + /** + * @var Website + */ + private $websiteSource; + + /** + * @var StoreManagerInterface + */ + private $storeManager; + + /** + * @var Converter + */ + private $converter; + + /** + * @param Initial $initialConfig + * @param Website $website + * @param StoreManagerInterface $storeManager + * @param Converter $converter + */ + public function __construct( + Initial $initialConfig, + Website $website, + StoreManagerInterface $storeManager, + Converter $converter + ) { + $this->initialConfig = $initialConfig; + $this->websiteSource = $website; + $this->storeManager = $storeManager; + $this->converter = $converter; + } + + /** + * Retrieve config by store scope + * + * @param string|null $scopeCode + * @return array + */ + public function get($scopeCode = null) + { + try { + /** @var \Magento\Store\Model\Store $store */ + $store = $this->storeManager->getStore($scopeCode); + return $this->converter->convert(array_replace_recursive( + $this->websiteSource->get($store->getData('website_code')), + $this->initialConfig->getData("stores|{$scopeCode}") + )); + } catch (\Exception $e) { + return []; + } + } +} diff --git a/app/code/Magento/Store/Model/Config/Reader/Source/Initial/Website.php b/app/code/Magento/Store/Model/Config/Reader/Source/Initial/Website.php new file mode 100644 index 0000000000000000000000000000000000000000..efd85e83a593e52b8886d903b8145903f33fe95d --- /dev/null +++ b/app/code/Magento/Store/Model/Config/Reader/Source/Initial/Website.php @@ -0,0 +1,60 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Store\Model\Config\Reader\Source\Initial; + +use Magento\Framework\App\Config\Initial; +use Magento\Framework\App\Config\Reader\Source\SourceInterface; +use Magento\Framework\App\Config\Scope\Converter; + +/** + * Class for retrieving configuration from initial config by website scope + */ +class Website implements SourceInterface +{ + /** + * @var Initial + */ + private $initialConfig; + + /** + * @var DefaultScope + */ + private $defaultScope; + + /** + * @var Converter + */ + private $converter; + + /** + * @param Initial $initialConfig + * @param DefaultScope $defaultScope + * @param Converter $converter + */ + public function __construct( + Initial $initialConfig, + DefaultScope $defaultScope, + Converter $converter + ) { + $this->initialConfig = $initialConfig; + $this->defaultScope = $defaultScope; + $this->converter = $converter; + } + + /** + * Retrieve config by website scope + * + * @param string|null $scopeCode + * @return array + */ + public function get($scopeCode = null) + { + return $this->converter->convert(array_replace_recursive( + $this->defaultScope->get(), + $this->initialConfig->getData("websites|{$scopeCode}") + )); + } +} diff --git a/app/code/Magento/Store/Model/Config/Reader/Store.php b/app/code/Magento/Store/Model/Config/Reader/Store.php deleted file mode 100644 index 8b4eb2d67365158cfc242b83eda77970f2abf999..0000000000000000000000000000000000000000 --- a/app/code/Magento/Store/Model/Config/Reader/Store.php +++ /dev/null @@ -1,84 +0,0 @@ -<?php -/** - * Copyright © 2016 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Store\Model\Config\Reader; - -use Magento\Framework\Exception\NoSuchEntityException; - -class Store implements \Magento\Framework\App\Config\Scope\ReaderInterface -{ - /** - * @var \Magento\Framework\App\Config\Initial - */ - protected $_initialConfig; - - /** - * @var \Magento\Framework\App\Config\ScopePool - */ - protected $_scopePool; - - /** - * @var \Magento\Store\Model\Config\Converter - */ - protected $_converter; - - /** - * @var \Magento\Store\Model\ResourceModel\Config\Collection\ScopedFactory - */ - protected $_collectionFactory; - - /** - * @var \Magento\Store\Model\StoreManagerInterface - */ - protected $_storeManager; - - /** - * @param \Magento\Framework\App\Config\Initial $initialConfig - * @param \Magento\Framework\App\Config\ScopePool $scopePool - * @param \Magento\Store\Model\Config\Converter $converter - * @param \Magento\Store\Model\ResourceModel\Config\Collection\ScopedFactory $collectionFactory - * @param \Magento\Store\Model\StoreManagerInterface $storeManager - */ - public function __construct( - \Magento\Framework\App\Config\Initial $initialConfig, - \Magento\Framework\App\Config\ScopePool $scopePool, - \Magento\Store\Model\Config\Converter $converter, - \Magento\Store\Model\ResourceModel\Config\Collection\ScopedFactory $collectionFactory, - \Magento\Store\Model\StoreManagerInterface $storeManager - ) { - $this->_initialConfig = $initialConfig; - $this->_scopePool = $scopePool; - $this->_converter = $converter; - $this->_collectionFactory = $collectionFactory; - $this->_storeManager = $storeManager; - } - - /** - * Read configuration by code - * - * @param null|string $code - * @return array - * @throws NoSuchEntityException - */ - public function read($code = null) - { - $store = $this->_storeManager->getStore($code); - - $websiteConfig = $this->_scopePool->getScope( - \Magento\Store\Model\ScopeInterface::SCOPE_WEBSITE, - $store->getWebsite()->getCode() - )->getSource(); - $config = array_replace_recursive($websiteConfig, $this->_initialConfig->getData("stores|{$code}")); - - $collection = $this->_collectionFactory->create( - ['scope' => \Magento\Store\Model\ScopeInterface::SCOPE_STORES, 'scopeId' => $store->getId()] - ); - $dbStoreConfig = []; - foreach ($collection as $item) { - $dbStoreConfig[$item->getPath()] = $item->getValue(); - } - return $this->_converter->convert($dbStoreConfig, $config); - } -} diff --git a/app/code/Magento/Store/Model/Config/Reader/Website.php b/app/code/Magento/Store/Model/Config/Reader/Website.php deleted file mode 100644 index 3ae30ea86a506afb22c1790d687efd2a835bd005..0000000000000000000000000000000000000000 --- a/app/code/Magento/Store/Model/Config/Reader/Website.php +++ /dev/null @@ -1,88 +0,0 @@ -<?php -/** - * Copyright © 2016 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Store\Model\Config\Reader; - -use Magento\Framework\App\Config\ScopeConfigInterface; - -class Website implements \Magento\Framework\App\Config\Scope\ReaderInterface -{ - /** - * @var \Magento\Framework\App\Config\Initial - */ - protected $_initialConfig; - - /** - * @var \Magento\Framework\App\Config\ScopePool - */ - protected $_scopePool; - - /** - * @var \Magento\Framework\App\Config\Scope\Converter - */ - protected $_converter; - - /** - * @var \Magento\Store\Model\ResourceModel\Config\Collection\ScopedFactory - */ - protected $_collectionFactory; - - /** - * @var \Magento\Store\Model\WebsiteFactory - */ - protected $_websiteFactory; - - /** - * @param \Magento\Framework\App\Config\Initial $initialConfig - * @param \Magento\Framework\App\Config\ScopePool $scopePool - * @param \Magento\Framework\App\Config\Scope\Converter $converter - * @param \Magento\Store\Model\ResourceModel\Config\Collection\ScopedFactory $collectionFactory - * @param \Magento\Store\Model\WebsiteFactory $websiteFactory - */ - public function __construct( - \Magento\Framework\App\Config\Initial $initialConfig, - \Magento\Framework\App\Config\ScopePool $scopePool, - \Magento\Framework\App\Config\Scope\Converter $converter, - \Magento\Store\Model\ResourceModel\Config\Collection\ScopedFactory $collectionFactory, - \Magento\Store\Model\WebsiteFactory $websiteFactory - ) { - $this->_initialConfig = $initialConfig; - $this->_scopePool = $scopePool; - $this->_converter = $converter; - $this->_collectionFactory = $collectionFactory; - $this->_websiteFactory = $websiteFactory; - } - - /** - * Read configuration by code - * - * @param string $code - * @return array - */ - public function read($code = null) - { - $config = array_replace_recursive( - $this->_scopePool->getScope(ScopeConfigInterface::SCOPE_TYPE_DEFAULT)->getSource(), - $this->_initialConfig->getData("websites|{$code}") - ); - - $website = $this->_websiteFactory->create(); - $website->load($code); - $collection = $this->_collectionFactory->create( - ['scope' => \Magento\Store\Model\ScopeInterface::SCOPE_WEBSITES, 'scopeId' => $website->getId()] - ); - $dbWebsiteConfig = []; - foreach ($collection as $configValue) { - $dbWebsiteConfig[$configValue->getPath()] = $configValue->getValue(); - } - $dbWebsiteConfig = $this->_converter->convert($dbWebsiteConfig); - - if (count($dbWebsiteConfig)) { - $config = array_replace_recursive($config, $dbWebsiteConfig); - } - - return $config; - } -} diff --git a/app/code/Magento/Store/Model/Group.php b/app/code/Magento/Store/Model/Group.php index cd6044dd7f78632bbcc629c91bbef11ff7d612af..f95d0aaded312e0ce0355238f23c16033a9817fc 100644 --- a/app/code/Magento/Store/Model/Group.php +++ b/app/code/Magento/Store/Model/Group.php @@ -442,7 +442,7 @@ class Group extends \Magento\Framework\Model\AbstractExtensibleModel implements */ public function getIdentities() { - return [self::CACHE_TAG . '_' . $this->getId()]; + return [self::CACHE_TAG]; } /** diff --git a/app/code/Magento/Store/Model/GroupRepository.php b/app/code/Magento/Store/Model/GroupRepository.php index 3cc833138b241386413d2563306def2f9679d4ad..dadcc6fb24e68e9e474c0a3e992f01b77f07712f 100644 --- a/app/code/Magento/Store/Model/GroupRepository.php +++ b/app/code/Magento/Store/Model/GroupRepository.php @@ -5,8 +5,15 @@ */ namespace Magento\Store\Model; +use Magento\Framework\App\ObjectManager; use Magento\Framework\Exception\NoSuchEntityException; +use Magento\Framework\App\Config; +/** + * Information Expert in store groups handling + * + * @package Magento\Store\Model + */ class GroupRepository implements \Magento\Store\Api\GroupRepositoryInterface { /** @@ -29,6 +36,11 @@ class GroupRepository implements \Magento\Store\Api\GroupRepositoryInterface */ protected $groupCollectionFactory; + /** + * @var Config + */ + private $appConfig; + /** * @param GroupFactory $groupFactory * @param \Magento\Store\Model\ResourceModel\Group\CollectionFactory $groupCollectionFactory @@ -49,8 +61,21 @@ class GroupRepository implements \Magento\Store\Api\GroupRepositoryInterface if (isset($this->entities[$id])) { return $this->entities[$id]; } - $group = $this->groupFactory->create(); - $group->load($id); + + $groupData = []; + $groups = $this->getAppConfig()->get('scopes', 'groups', []); + if ($groups) { + foreach ($groups as $data) { + if (isset($data['group_id']) && $data['group_id'] == $id) { + $groupData = $data; + break; + } + } + } + $group = $this->groupFactory->create([ + 'data' => $groupData + ]); + if (null === $group->getId()) { throw new NoSuchEntityException(); } @@ -64,14 +89,16 @@ class GroupRepository implements \Magento\Store\Api\GroupRepositoryInterface public function getList() { if (!$this->allLoaded) { - /** @var \Magento\Store\Model\ResourceModel\Group\Collection $groupCollection */ - $groupCollection = $this->groupCollectionFactory->create(); - $groupCollection->setLoadDefault(true); - foreach ($groupCollection as $item) { - $this->entities[$item->getId()] = $item; + $groups = $this->getAppConfig()->get('scopes', 'groups', []); + foreach ($groups as $data) { + $group = $this->groupFactory->create([ + 'data' => $data + ]); + $this->entities[$group->getId()] = $group; } $this->allLoaded = true; } + return $this->entities; } @@ -83,4 +110,18 @@ class GroupRepository implements \Magento\Store\Api\GroupRepositoryInterface $this->entities = []; $this->allLoaded = false; } + + /** + * Retrieve application config. + * + * @deprecated + * @return Config + */ + private function getAppConfig() + { + if (!$this->appConfig) { + $this->appConfig = ObjectManager::getInstance()->get(Config::class); + } + return $this->appConfig; + } } diff --git a/app/code/Magento/Store/Model/Store.php b/app/code/Magento/Store/Model/Store.php index 270b621407d4697c3612f54dc0059ecb16cb1903..ccd1aed947d787e37ee5126e227542856ed3d73d 100644 --- a/app/code/Magento/Store/Model/Store.php +++ b/app/code/Magento/Store/Model/Store.php @@ -1036,6 +1036,18 @@ class Store extends AbstractExtensibleModel implements return $this->_getData('website_id'); } + /** + * Reinit Stores on after save + * + * @deprecated + * @return $this + */ + public function afterSave() + { + $this->_storeManager->reinitStores(); + return parent::afterSave(); + } + /** * @inheritdoc */ @@ -1272,7 +1284,7 @@ class Store extends AbstractExtensibleModel implements */ public function getIdentities() { - return [self::CACHE_TAG . '_' . $this->getId()]; + return [self::CACHE_TAG]; } /** diff --git a/app/code/Magento/Store/Model/StoreManager.php b/app/code/Magento/Store/Model/StoreManager.php index c34f4e1bd2a58d370e92a34295ae4a60647133c1..13840b120636773dd108adcdf4a9f590e629383d 100644 --- a/app/code/Magento/Store/Model/StoreManager.php +++ b/app/code/Magento/Store/Model/StoreManager.php @@ -10,6 +10,8 @@ use Magento\Store\Api\StoreResolverInterface; use Magento\Store\Model\ResourceModel\StoreWebsiteRelation; /** + * Service contract, which manage scopes + * * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class StoreManager implements @@ -198,9 +200,12 @@ class StoreManager implements $website = $websiteId; } elseif ($websiteId === true) { $website = $this->websiteRepository->getDefault(); - } else { + } elseif (is_numeric($websiteId)) { $website = $this->websiteRepository->getById($websiteId); + } else { + $website = $this->websiteRepository->get($websiteId); } + return $website; } @@ -228,6 +233,7 @@ class StoreManager implements */ public function reinitStores() { + $this->scopeConfig->clean(); $this->currentStoreId = null; $this->storeRepository->clean(); $this->websiteRepository->clean(); diff --git a/app/code/Magento/Store/Model/StoreRepository.php b/app/code/Magento/Store/Model/StoreRepository.php index 47e185f48cc52532909d34dcb53a1ad66704765c..c9e7a0ebc9d313d0a3a0fcb8d29631105ff2371a 100644 --- a/app/code/Magento/Store/Model/StoreRepository.php +++ b/app/code/Magento/Store/Model/StoreRepository.php @@ -5,8 +5,15 @@ */ namespace Magento\Store\Model; +use Magento\Framework\App\ObjectManager; use Magento\Framework\Exception\NoSuchEntityException; +use Magento\Framework\App\Config; +/** + * Information Expert in stores handling + * + * @package Magento\Store\Model + */ class StoreRepository implements \Magento\Store\Api\StoreRepositoryInterface { /** @@ -34,6 +41,11 @@ class StoreRepository implements \Magento\Store\Api\StoreRepositoryInterface */ protected $allLoaded = false; + /** + * @var Config + */ + private $appConfig; + /** * @param StoreFactory $storeFactory * @param \Magento\Store\Model\ResourceModel\Store\CollectionFactory $storeCollectionFactory @@ -54,8 +66,12 @@ class StoreRepository implements \Magento\Store\Api\StoreRepositoryInterface if (isset($this->entities[$code])) { return $this->entities[$code]; } - $store = $this->storeFactory->create(); - $store->load($code, 'code'); + + $storeData = $this->getAppConfig()->get('scopes', "stores/$code", []); + $store = $this->storeFactory->create([ + 'data' => $storeData + ]); + if ($store->getId() === null) { throw new NoSuchEntityException(__('Requested store is not found')); } @@ -85,11 +101,23 @@ class StoreRepository implements \Magento\Store\Api\StoreRepositoryInterface if (isset($this->entitiesById[$id])) { return $this->entitiesById[$id]; } - $store = $this->storeFactory->create(); - $store->load($id); + + $storeData = []; + $stores = $this->getAppConfig()->get('scopes', "stores", []); + foreach ($stores as $data) { + if (isset($data['store_id']) && $data['store_id'] == $id) { + $storeData = $data; + break; + } + } + $store = $this->storeFactory->create([ + 'data' => $storeData + ]); + if ($store->getId() === null) { throw new NoSuchEntityException(__('Requested store is not found')); } + $this->entitiesById[$id] = $store; $this->entities[$store->getCode()] = $store; return $store; @@ -113,19 +141,35 @@ class StoreRepository implements \Magento\Store\Api\StoreRepositoryInterface */ public function getList() { - if (!$this->allLoaded) { - /** @var $storeCollection \Magento\Store\Model\ResourceModel\Store\Collection */ - $storeCollection = $this->storeCollectionFactory->create(); - $storeCollection->setLoadDefault(true); - foreach ($storeCollection as $item) { - $this->entities[$item->getCode()] = $item; - $this->entitiesById[$item->getId()] = $item; - } - $this->allLoaded = true; + if ($this->allLoaded) { + return $this->entities; } + $stores = $this->getAppConfig()->get('scopes', "stores", []); + foreach ($stores as $data) { + $store = $this->storeFactory->create([ + 'data' => $data + ]); + $this->entities[$store->getCode()] = $store; + $this->entitiesById[$store->getId()] = $store; + } + $this->allLoaded = true; return $this->entities; } + /** + * Retrieve application config. + * + * @deprecated + * @return Config + */ + private function getAppConfig() + { + if (!$this->appConfig) { + $this->appConfig = ObjectManager::getInstance()->get(Config::class); + } + return $this->appConfig; + } + /** * {@inheritdoc} */ diff --git a/app/code/Magento/Store/Model/Website.php b/app/code/Magento/Store/Model/Website.php index 1370cea5cf42bf5217938d2769820f48e9b929c9..a3a6b6dbc3f7f425fc3527e8a27ef355cca74066 100644 --- a/app/code/Magento/Store/Model/Website.php +++ b/app/code/Magento/Store/Model/Website.php @@ -652,7 +652,7 @@ class Website extends \Magento\Framework\Model\AbstractExtensibleModel implement */ public function getIdentities() { - return [self::CACHE_TAG . '_' . $this->getId()]; + return [self::CACHE_TAG]; } /** diff --git a/app/code/Magento/Store/Model/WebsiteRepository.php b/app/code/Magento/Store/Model/WebsiteRepository.php index 0aeb65f47cdb4af0c464f2a00323c83560471b1d..dffcef921bc22194cd762eea74a96e1fb2d4b22c 100644 --- a/app/code/Magento/Store/Model/WebsiteRepository.php +++ b/app/code/Magento/Store/Model/WebsiteRepository.php @@ -5,9 +5,16 @@ */ namespace Magento\Store\Model; +use Magento\Framework\App\ObjectManager; use Magento\Framework\Exception\NoSuchEntityException; use Magento\Store\Model\ResourceModel\Website\CollectionFactory; +use Magento\Framework\App\Config; +/** + * Information Expert in store websites handling + * + * @package Magento\Store\Model + */ class WebsiteRepository implements \Magento\Store\Api\WebsiteRepositoryInterface { /** @@ -40,6 +47,11 @@ class WebsiteRepository implements \Magento\Store\Api\WebsiteRepositoryInterface */ protected $default; + /** + * @var Config + */ + private $appConfig; + /** * @param WebsiteFactory $factory * @param CollectionFactory $websiteCollectionFactory @@ -60,8 +72,12 @@ class WebsiteRepository implements \Magento\Store\Api\WebsiteRepositoryInterface if (isset($this->entities[$code])) { return $this->entities[$code]; } - $website = $this->factory->create(); - $website->load($code, 'code'); + + $websiteData = $this->getAppConfig()->get('scopes', "websites/$code", []); + $website = $this->factory->create([ + 'data' => $websiteData + ]); + if ($website->getId() === null) { throw new NoSuchEntityException(); } @@ -78,14 +94,23 @@ class WebsiteRepository implements \Magento\Store\Api\WebsiteRepositoryInterface if (isset($this->entitiesById[$id])) { return $this->entitiesById[$id]; } - /** @var Website $website */ - $website = $this->factory->create(); - $website->load($id); + $websiteData = []; + $websites = $this->getAppConfig()->get('scopes', 'websites', []); + foreach ($websites as $data) { + if (isset($data['website_id']) && $data['website_id'] == $id) { + $websiteData = $data; + break; + } + } + $website = $this->factory->create([ + 'data' => $websiteData + ]); + if ($website->getId() === null) { throw new NoSuchEntityException(); } - $this->entitiesById[$id] = $website; $this->entities[$website->getCode()] = $website; + $this->entitiesById[$id] = $website; return $website; } @@ -95,10 +120,13 @@ class WebsiteRepository implements \Magento\Store\Api\WebsiteRepositoryInterface public function getList() { if (!$this->allLoaded) { - $collection = $this->websiteCollectionFactory->create(); - $collection->setLoadDefault(true); - foreach ($collection as $item) { - $this->entities[$item->getCode()] = $item; + $websites = $this->getAppConfig()->get('scopes', 'websites', []); + foreach ($websites as $data) { + $website = $this->factory->create([ + 'data' => $data + ]); + $this->entities[$website->getCode()] = $website; + $this->entitiesById[$website->getId()] = $website; } $this->allLoaded = true; } @@ -118,23 +146,13 @@ class WebsiteRepository implements \Magento\Store\Api\WebsiteRepositoryInterface } } if (!$this->allLoaded) { - /** @var \Magento\Store\Model\ResourceModel\Website\Collection $collection */ - $collection = $this->websiteCollectionFactory->create(); - $collection->addFieldToFilter('is_default', 1); - $items = $collection->getItems(); - if (count($items) > 1) { - throw new \DomainException(__('More than one default website is defined')); - } - if (count($items) === 0) { - throw new \DomainException(__('Default website is not defined')); - } - $this->default = $collection->getFirstItem(); - $this->entities[$this->default->getCode()] = $this->default; - $this->entitiesById[$this->default->getId()] = $this->default; - } else { + $this->initDefaultWebsite(); + } + if (!$this->default) { throw new \DomainException(__('Default website is not defined')); } } + return $this->default; } @@ -148,4 +166,40 @@ class WebsiteRepository implements \Magento\Store\Api\WebsiteRepositoryInterface $this->default = null; $this->allLoaded = false; } + + /** + * Retrieve application config. + * + * @deprecated + * @return Config + */ + private function getAppConfig() + { + if (!$this->appConfig) { + $this->appConfig = ObjectManager::getInstance()->get(Config::class); + } + return $this->appConfig; + } + + /** + * Initialize default website. + * @return void + */ + private function initDefaultWebsite() + { + $websites = (array)$this->getAppConfig()->get('scopes', 'websites', []); + foreach ($websites as $data) { + if (isset($data['is_default']) && $data['is_default'] == 1) { + if ($this->default) { + throw new \DomainException(__('More than one default website is defined')); + } + $website = $this->factory->create([ + 'data' => $data + ]); + $this->default = $website; + $this->entities[$this->default->getCode()] = $this->default; + $this->entitiesById[$this->default->getId()] = $this->default; + } + } + } } diff --git a/app/code/Magento/Store/Test/Unit/App/Config/Source/RuntimeConfigSourceTest.php b/app/code/Magento/Store/Test/Unit/App/Config/Source/RuntimeConfigSourceTest.php new file mode 100644 index 0000000000000000000000000000000000000000..8b3ffeafd8b2b71d26e8e2d0b4db627726925680 --- /dev/null +++ b/app/code/Magento/Store/Test/Unit/App/Config/Source/RuntimeConfigSourceTest.php @@ -0,0 +1,358 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Store\Test\Unit\App\Config\Source; + +use Magento\Framework\App\DeploymentConfig; +use Magento\Store\App\Config\Source\RuntimeConfigSource; +use Magento\Store\Model\Group; +use Magento\Store\Model\GroupFactory; +use Magento\Store\Model\ResourceModel\Website\CollectionFactory; +use Magento\Store\Model\ResourceModel\Group\CollectionFactory as GroupCollectionFactory; +use Magento\Store\Model\ResourceModel\Store\CollectionFactory as StoreCollectionFactory; +use Magento\Store\Model\ResourceModel\Website\Collection as WebsiteCollection; +use Magento\Store\Model\ResourceModel\Group\Collection as GroupCollection; +use Magento\Store\Model\ResourceModel\Store\Collection as StoreCollection; +use Magento\Store\Model\Store; +use Magento\Store\Model\StoreFactory; +use Magento\Store\Model\Website; +use Magento\Store\Model\WebsiteFactory; + +/** + * @SuppressWarnings(PHPMD.ExcessiveParameterList) + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ +class RuntimeConfigSourceTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var array + */ + private $data; + + /** + * @var CollectionFactory|\PHPUnit_Framework_MockObject_MockObject + */ + private $websiteCollectionFactory; + + /** + * @var GroupCollectionFactory|\PHPUnit_Framework_MockObject_MockObject + */ + private $groupCollectionFactory; + + /** + * @var StoreCollectionFactory|\PHPUnit_Framework_MockObject_MockObject + */ + private $storeCollectionFactory; + + /** + * @var WebsiteCollection|\PHPUnit_Framework_MockObject_MockObject + */ + private $websiteCollection; + + /** + * @var GroupCollection|\PHPUnit_Framework_MockObject_MockObject + */ + private $groupCollection; + + /** + * @var StoreCollection|\PHPUnit_Framework_MockObject_MockObject + */ + private $storeCollection; + + /** + * @var WebsiteFactory|\PHPUnit_Framework_MockObject_MockObject + */ + private $websiteFactory; + + /** + * @var GroupFactory|\PHPUnit_Framework_MockObject_MockObject + */ + private $groupFactory; + + /** + * @var StoreFactory|\PHPUnit_Framework_MockObject_MockObject + */ + private $storeFactory; + + /** + * @var Website|\PHPUnit_Framework_MockObject_MockObject + */ + private $website; + + /** + * @var Group|\PHPUnit_Framework_MockObject_MockObject + */ + private $group; + + /** + * @var Store|\PHPUnit_Framework_MockObject_MockObject + */ + private $store; + + /** + * @var DeploymentConfig|\PHPUnit_Framework_MockObject_MockObject + */ + private $deploymentConfig; + + /** + * @var RuntimeConfigSource + */ + private $configSource; + + public function setUp() + { + $this->data = [ + 'group' => [ + 'code' => 'myGroup', + 'data' => [ + 'name' => 'My Group', + 'group_id' => $this->data['group']['code'] + ] + ], + 'website' => [ + 'code' => 'myWebsite', + 'data' => [ + 'name' => 'My Website', + 'website_code' => $this->data['website']['code'] + ] + ], + 'store' => [ + 'code' => 'myStore', + 'data' => [ + 'name' => 'My Store', + 'store_code' => $this->data['store']['code'] + ] + ], + ]; + $this->websiteCollectionFactory = $this->getMockBuilder(CollectionFactory::class) + ->disableOriginalConstructor() + ->setMethods(['create']) + ->getMock(); + $this->groupCollectionFactory = $this->getMockBuilder(GroupCollectionFactory::class) + ->disableOriginalConstructor() + ->setMethods(['create']) + ->getMock(); + $this->storeCollectionFactory = $this->getMockBuilder(StoreCollectionFactory::class) + ->disableOriginalConstructor() + ->setMethods(['create']) + ->getMock(); + + $this->websiteCollection = $this->getMockBuilder(WebsiteCollection::class) + ->disableOriginalConstructor() + ->setMethods(['setLoadDefault', 'getIterator']) + ->getMock(); + $this->groupCollection = $this->getMockBuilder(GroupCollection::class) + ->disableOriginalConstructor() + ->setMethods(['setLoadDefault', 'getIterator']) + ->getMock(); + $this->storeCollection = $this->getMockBuilder(StoreCollection::class) + ->disableOriginalConstructor() + ->setMethods(['setLoadDefault', 'getIterator']) + ->getMock(); + + $this->websiteFactory = $this->getMockBuilder(WebsiteFactory::class) + ->disableOriginalConstructor() + ->setMethods(['create']) + ->getMock(); + $this->groupFactory = $this->getMockBuilder(GroupFactory::class) + ->disableOriginalConstructor() + ->setMethods(['create']) + ->getMock(); + $this->storeFactory = $this->getMockBuilder(StoreFactory::class) + ->disableOriginalConstructor() + ->setMethods(['create']) + ->getMock(); + $this->website = $this->getMockBuilder(Website::class) + ->disableOriginalConstructor() + ->getMock(); + $this->group = $this->getMockBuilder(Group::class) + ->disableOriginalConstructor() + ->getMock(); + $this->store = $this->getMockBuilder(Store::class) + ->disableOriginalConstructor() + ->getMock(); + $this->deploymentConfig = $this->getMockBuilder(DeploymentConfig::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->configSource = new RuntimeConfigSource( + $this->websiteCollectionFactory, + $this->groupCollectionFactory, + $this->storeCollectionFactory, + $this->websiteFactory, + $this->groupFactory, + $this->storeFactory, + $this->deploymentConfig + ); + } + + /** + * @param string $path + * @dataProvider getDataProvider + * @return void + */ + public function testGet($path) + { + $this->deploymentConfig->expects($this->once()) + ->method('get') + ->with('db') + ->willReturn(true); + $this->prepareWebsites($path); + $this->prepareGroups($path); + $this->prepareStores($path); + $this->assertEquals($this->getExpectedResult($path), $this->configSource->get($path)); + } + + private function getExpectedResult($path) + { + switch ($this->getScope($path)) { + case 'websites': + $result = $this->data['website']['data']; + break; + case 'groups': + $result = $this->data['group']['data']; + break; + case 'stores': + $result = $this->data['store']['data']; + break; + default: + $result = [ + 'websites' => [ + $this->data['website']['code'] => $this->data['website']['data'] + ], + 'groups' => [ + $this->data['group']['code'] => $this->data['group']['data'] + ], + 'stores' => [ + $this->data['store']['code'] => $this->data['store']['data'] + ], + ]; + break; + } + return $result; + } + + private function prepareStores($path) + { + $scope = $this->getScope($path); + if ($scope == 'stores' || $scope == 'default') { + if ($this->getScopeCode($path)) { + $this->storeFactory->expects($this->once()) + ->method('create') + ->willReturn($this->store); + $this->store->expects($this->once()) + ->method('load') + ->with($this->data['store']['code'], 'code') + ->willReturnSelf(); + } else { + $this->storeCollectionFactory->expects($this->once()) + ->method('create') + ->willReturn($this->storeCollection); + $this->storeCollection->expects($this->once()) + ->method('setLoadDefault') + ->with(true) + ->willReturnSelf(); + $this->storeCollection->expects($this->once()) + ->method('getIterator') + ->willReturn(new \ArrayIterator([$this->store])); + $this->store->expects($this->once()) + ->method('getCode') + ->willReturn($this->data['store']['code']); + } + $this->store->expects($this->once()) + ->method('getData') + ->willReturn($this->data['store']['data']); + } + } + + private function prepareGroups($path) + { + $scope = $this->getScope($path); + if ($scope == 'groups' || $scope == 'default') { + if ($this->getScopeCode($path)) { + $this->groupFactory->expects($this->once()) + ->method('create') + ->willReturn($this->group); + $this->group->expects($this->once()) + ->method('load') + ->with($this->data['group']['code']) + ->willReturnSelf(); + } else { + $this->groupCollectionFactory->expects($this->once()) + ->method('create') + ->willReturn($this->groupCollection); + $this->groupCollection->expects($this->once()) + ->method('setLoadDefault') + ->with(true) + ->willReturnSelf(); + $this->groupCollection->expects($this->once()) + ->method('getIterator') + ->willReturn(new \ArrayIterator([$this->group])); + $this->group->expects($this->once()) + ->method('getId') + ->willReturn($this->data['group']['code']); + } + $this->group->expects($this->once()) + ->method('getData') + ->willReturn($this->data['group']['data']); + } + } + + private function prepareWebsites($path) + { + $scope = $this->getScope($path); + if ($scope == 'websites' || $scope == 'default') { + if ($this->getScopeCode($path)) { + $this->websiteFactory->expects($this->once()) + ->method('create') + ->willReturn($this->website); + $this->website->expects($this->once()) + ->method('load') + ->with($this->data['website']['code']) + ->willReturnSelf(); + } else { + $this->websiteCollectionFactory->expects($this->once()) + ->method('create') + ->willReturn($this->websiteCollection); + $this->websiteCollection->expects($this->once()) + ->method('setLoadDefault') + ->with(true) + ->willReturnSelf(); + $this->websiteCollection->expects($this->once()) + ->method('getIterator') + ->willReturn(new \ArrayIterator([$this->website])); + $this->website->expects($this->once()) + ->method('getCode') + ->willReturn($this->data['website']['code']); + } + $this->website->expects($this->once()) + ->method('getData') + ->willReturn($this->data['website']['data']); + } + } + + private function getScopeCode($path) + { + return implode('/', array_slice(explode('/', $path), 1, 1)); + } + + private function getScope($path) + { + return implode('/', array_slice(explode('/', $path), 0, 1)); + } + + /** + * @return array + */ + public function getDataProvider() + { + return [ + ['websites/myWebsite'], + ['groups/myGroup'], + ['stores/myStore'], + ['default'] + ]; + } +} diff --git a/app/code/Magento/Store/Test/Unit/Model/Config/ConverterTest.php b/app/code/Magento/Store/Test/Unit/Model/Config/ConverterTest.php index 7cd9fd91aedb842e5c79551d8d91c859abc751d8..2a154bcea3431afe026f08b7cd7662f0476e804e 100644 --- a/app/code/Magento/Store/Test/Unit/Model/Config/ConverterTest.php +++ b/app/code/Magento/Store/Test/Unit/Model/Config/ConverterTest.php @@ -10,19 +10,9 @@ class ConverterTest extends \PHPUnit_Framework_TestCase /** @var \Magento\Store\Model\Config\Converter */ protected $_model; - /** @var \PHPUnit_Framework_MockObject_MockObject */ - protected $_processorMock; - protected function setUp() { - $this->_processorMock = $this->getMock( - \Magento\Store\Model\Config\Processor\Placeholder::class, - [], - [], - '', - false - ); - $this->_model = new \Magento\Store\Model\Config\Converter($this->_processorMock); + $this->_model = new \Magento\Store\Model\Config\Converter(); } public function testConvert() @@ -34,17 +24,6 @@ class ConverterTest extends \PHPUnit_Framework_TestCase 'to' => ['save' => 'saved value', 'overwrite' => 'overwritten', 'added' => 'added value'], ], ]; - $processorResult = '123Value'; - $this->_processorMock->expects( - $this->once() - )->method( - 'process' - )->with( - $mergeResult - )->will( - $this->returnValue($processorResult) - ); - - $this->assertEquals($processorResult, $this->_model->convert($source, $initial)); + $this->assertEquals($mergeResult, $this->_model->convert($source, $initial)); } } diff --git a/app/code/Magento/Store/Test/Unit/Model/Config/PlaceholderTest.php b/app/code/Magento/Store/Test/Unit/Model/Config/PlaceholderTest.php new file mode 100644 index 0000000000000000000000000000000000000000..7b952dd84fb38d7f577716a40c9111c37b217ced --- /dev/null +++ b/app/code/Magento/Store/Test/Unit/Model/Config/PlaceholderTest.php @@ -0,0 +1,64 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Store\Test\Unit\Model\Config; + +use Magento\Store\Model\Store; + +class PlaceholderTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var \Magento\Store\Model\Config\Processor\Placeholder + */ + protected $_model; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $_requestMock; + + protected function setUp() + { + $this->_requestMock = $this->getMock(\Magento\Framework\App\Request\Http::class, [], [], '', false); + $this->_requestMock->expects( + $this->any() + )->method( + 'getDistroBaseUrl' + )->will( + $this->returnValue('http://localhost/') + ); + $this->_model = new \Magento\Store\Model\Config\Placeholder( + $this->_requestMock, + [ + 'unsecureBaseUrl' => Store::XML_PATH_UNSECURE_BASE_URL, + 'secureBaseUrl' => Store::XML_PATH_SECURE_BASE_URL + ], + \Magento\Store\Model\Store::BASE_URL_PLACEHOLDER + ); + } + + public function testProcess() + { + $data = [ + 'web' => [ + 'unsecure' => [ + 'base_url' => 'http://localhost/', + 'base_link_url' => '{{unsecure_base_url}}website/de', + ], + 'secure' => [ + 'base_url' => 'https://localhost/', + 'base_link_url' => '{{secure_base_url}}website/de', + ], + ], + 'path' => 'value', + 'some_url' => '{{base_url}}some', + ]; + $expectedResult = $data; + $expectedResult['web']['unsecure']['base_link_url'] = 'http://localhost/website/de'; + $expectedResult['web']['secure']['base_link_url'] = 'https://localhost/website/de'; + $expectedResult['some_url'] = 'http://localhost/some'; + $this->assertEquals($expectedResult, $this->_model->process($data)); + } +} diff --git a/app/code/Magento/Store/Test/Unit/Model/Config/Processor/PlaceholderTest.php b/app/code/Magento/Store/Test/Unit/Model/Config/Processor/PlaceholderTest.php index 493895ddabe74c12c81d7d3b90a3228b2a633f64..7a258fe41a51d351b653b78d87fe2ab17842a926 100644 --- a/app/code/Magento/Store/Test/Unit/Model/Config/Processor/PlaceholderTest.php +++ b/app/code/Magento/Store/Test/Unit/Model/Config/Processor/PlaceholderTest.php @@ -5,60 +5,61 @@ */ namespace Magento\Store\Test\Unit\Model\Config\Processor; -use Magento\Store\Model\Store; - +/** + * Class PlaceholderTest + */ class PlaceholderTest extends \PHPUnit_Framework_TestCase { /** * @var \Magento\Store\Model\Config\Processor\Placeholder */ - protected $_model; + private $model; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Store\Model\Config\Placeholder|\PHPUnit_Framework_MockObject_MockObject */ - protected $_requestMock; + private $configPlaceholderMock; protected function setUp() { - $this->_requestMock = $this->getMock(\Magento\Framework\App\Request\Http::class, [], [], '', false); - $this->_requestMock->expects( + $this->configPlaceholderMock = $this->getMock( + \Magento\Store\Model\Config\Placeholder::class, + [], + [], + '', + false + ); + + $this->configPlaceholderMock->expects( $this->any() )->method( - 'getDistroBaseUrl' - )->will( - $this->returnValue('http://localhost/') - ); - $this->_model = new \Magento\Store\Model\Config\Processor\Placeholder( - $this->_requestMock, - [ - 'unsecureBaseUrl' => Store::XML_PATH_UNSECURE_BASE_URL, - 'secureBaseUrl' => Store::XML_PATH_SECURE_BASE_URL - ], - \Magento\Store\Model\Store::BASE_URL_PLACEHOLDER + 'process' + )->withConsecutive( + [['key1' => 'value1']], + [['key2' => 'value2']] + )->willReturnOnConsecutiveCalls( + ['key1' => 'value1-processed'], + ['key2' => 'value2-processed'] ); + + $this->model = new \Magento\Store\Model\Config\Processor\Placeholder($this->configPlaceholderMock); } public function testProcess() { $data = [ - 'web' => [ - 'unsecure' => [ - 'base_url' => 'http://localhost/', - 'base_link_url' => '{{unsecure_base_url}}website/de', - ], - 'secure' => [ - 'base_url' => 'https://localhost/', - 'base_link_url' => '{{secure_base_url}}website/de', - ], - ], - 'path' => 'value', - 'some_url' => '{{base_url}}some', + 'default' => ['key1' => 'value1'], + 'websites' => [ + 'code' => ['key2' => 'value2'] + ] ]; - $expectedResult = $data; - $expectedResult['web']['unsecure']['base_link_url'] = 'http://localhost/website/de'; - $expectedResult['web']['secure']['base_link_url'] = 'https://localhost/website/de'; - $expectedResult['some_url'] = 'http://localhost/some'; - $this->assertEquals($expectedResult, $this->_model->process($data)); + $expected = [ + 'default' => ['key1' => 'value1-processed'], + 'websites' => [ + 'code' => ['key2' => 'value2-processed'] + ] + ]; + + $this->assertEquals($expected, $this->model->process($data)); } } diff --git a/app/code/Magento/Store/Test/Unit/Model/Config/Reader/DefaultReaderTest.php b/app/code/Magento/Store/Test/Unit/Model/Config/Reader/DefaultReaderTest.php deleted file mode 100644 index dccabb9048dd387fc1b6863877e3d4fc95ce4de6..0000000000000000000000000000000000000000 --- a/app/code/Magento/Store/Test/Unit/Model/Config/Reader/DefaultReaderTest.php +++ /dev/null @@ -1,74 +0,0 @@ -<?php -/** - * Copyright © 2016 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Store\Test\Unit\Model\Config\Reader; - -use Magento\Framework\App\Config\ScopeConfigInterface; - -class DefaultReaderTest extends \PHPUnit_Framework_TestCase -{ - /** - * @var \Magento\Store\Model\Config\Reader\DefaultReader - */ - protected $_model; - - /** - * @var \PHPUnit_Framework_MockObject_MockObject - */ - protected $_initialConfigMock; - - /** - * @var \PHPUnit_Framework_MockObject_MockObject - */ - protected $_collectionFactory; - - protected function setUp() - { - $this->_initialConfigMock = $this->getMock(\Magento\Framework\App\Config\Initial::class, [], [], '', false); - $this->_collectionFactory = $this->getMock( - \Magento\Store\Model\ResourceModel\Config\Collection\ScopedFactory::class, - ['create'], - [], - '', - false - ); - $this->_model = new \Magento\Store\Model\Config\Reader\DefaultReader( - $this->_initialConfigMock, - new \Magento\Framework\App\Config\Scope\Converter(), - $this->_collectionFactory - ); - } - - public function testRead() - { - $this->_initialConfigMock->expects( - $this->any() - )->method( - 'getData' - )->with( - ScopeConfigInterface::SCOPE_TYPE_DEFAULT - )->will( - $this->returnValue(['config' => ['key1' => 'default_value1', 'key2' => 'default_value2']]) - ); - $this->_collectionFactory->expects( - $this->once() - )->method( - 'create' - )->with( - ['scope' => 'default'] - )->will( - $this->returnValue( - [ - new \Magento\Framework\DataObject(['path' => 'config/key1', 'value' => 'default_db_value1']), - new \Magento\Framework\DataObject(['path' => 'config/key3', 'value' => 'default_db_value3']), - ] - ) - ); - $expectedData = [ - 'config' => ['key1' => 'default_db_value1', 'key2' => 'default_value2', 'key3' => 'default_db_value3'], - ]; - $this->assertEquals($expectedData, $this->_model->read()); - } -} diff --git a/app/code/Magento/Store/Test/Unit/Model/Config/Reader/ReaderPoolTest.php b/app/code/Magento/Store/Test/Unit/Model/Config/Reader/ReaderPoolTest.php deleted file mode 100644 index fb814415fd2dd34cc2a6028880ac0f0417519e9c..0000000000000000000000000000000000000000 --- a/app/code/Magento/Store/Test/Unit/Model/Config/Reader/ReaderPoolTest.php +++ /dev/null @@ -1,83 +0,0 @@ -<?php -/** - * Copyright © 2016 Magento. All rights reserved. - * See COPYING.txt for license details. - */ - -// @codingStandardsIgnoreFile - -namespace Magento\Store\Test\Unit\Model\Config\Reader; - -class ReaderPoolTest extends \PHPUnit_Framework_TestCase -{ - /** - * @var \Magento\Store\Model\Config\Reader\ReaderPool - */ - protected $_model; - - /** - * @var \Magento\Store\Model\Config\Reader\DefaultReader - */ - protected $_defaultReaderMock; - - /** - * @var \Magento\Store\Model\Config\Reader\Website - */ - protected $_websiteReaderMock; - - /** - * @var \Magento\Store\Model\Config\Reader\Store - */ - protected $_storeReaderMock; - - protected function setUp() - { - $this->_defaultReaderMock = $this->getMock( - \Magento\Store\Model\Config\Reader\DefaultReader::class, [], [], '', false - ); - $this->_websiteReaderMock = $this->getMock( - \Magento\Store\Model\Config\Reader\Website::class, [], [], '', false - ); - $this->_storeReaderMock = $this->getMock( - \Magento\Store\Model\Config\Reader\Store::class, [], [], '', false - ); - - $this->_model = new \Magento\Store\Model\Config\Reader\ReaderPool([ - 'default' => $this->_defaultReaderMock, - 'website' => $this->_websiteReaderMock, - 'store' => $this->_storeReaderMock, - ]); - } - - /** - * @covers \Magento\Store\Model\Config\Reader\ReaderPool::getReader - * @dataProvider getReaderDataProvider - * @param string $scope - * @param string $instanceType - */ - public function testGetReader($scope, $instanceType) - { - $this->assertInstanceOf($instanceType, $this->_model->getReader($scope)); - } - - /** - * @return array - */ - public function getReaderDataProvider() - { - return [ - [ - 'scope' => 'default', - 'expectedResult' => \Magento\Store\Model\Config\Reader\DefaultReader::class, - ], - [ - 'scope' => 'website', - 'expectedResult' => \Magento\Store\Model\Config\Reader\Website::class - ], - [ - 'scope' => 'store', - 'expectedResult' => \Magento\Store\Model\Config\Reader\Store::class - ], - ]; - } -} diff --git a/app/code/Magento/Store/Test/Unit/Model/Config/Reader/Source/Dynamic/DefaultScopeTest.php b/app/code/Magento/Store/Test/Unit/Model/Config/Reader/Source/Dynamic/DefaultScopeTest.php new file mode 100644 index 0000000000000000000000000000000000000000..2680bde4c00dcfa53a8c1ac63ebb8c4dd9fca340 --- /dev/null +++ b/app/code/Magento/Store/Test/Unit/Model/Config/Reader/Source/Dynamic/DefaultScopeTest.php @@ -0,0 +1,46 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Store\Test\Unit\Model\Config\Reader\Source\Dynamic; + +use Magento\Framework\App\Config\Scope\Converter; +use Magento\Framework\App\Config\ScopeConfigInterface; +use Magento\Framework\DataObject; +use Magento\Store\Model\Config\Reader\Source\Dynamic\DefaultScope; +use Magento\Store\Model\ResourceModel\Config\Collection\ScopedFactory; + +class DefaultScopeTest extends \PHPUnit_Framework_TestCase +{ + public function testGet() + { + $expectedResult = [ + 'config/key1' => 'default_db_value1', + 'config/key3' => 'default_db_value3', + ]; + $collectionFactory = $this->getMockBuilder(ScopedFactory::class) + ->disableOriginalConstructor() + ->setMethods(['create']) + ->getMock(); + $collectionFactory->expects($this->once()) + ->method('create') + ->with(['scope' => ScopeConfigInterface::SCOPE_TYPE_DEFAULT]) + ->willReturn([ + new DataObject(['path' => 'config/key1', 'value' => 'default_db_value1']), + new DataObject(['path' => 'config/key3', 'value' => 'default_db_value3']), + ]); + $converter = $this->getMockBuilder(Converter::class) + ->disableOriginalConstructor() + ->getMock(); + $converter->expects($this->once()) + ->method('convert') + ->with($expectedResult) + ->willReturnArgument(0); + $source = new DefaultScope( + $collectionFactory, + $converter + ); + $this->assertEquals($expectedResult, $source->get()); + } +} diff --git a/app/code/Magento/Store/Test/Unit/Model/Config/Reader/Source/Dynamic/StoreTest.php b/app/code/Magento/Store/Test/Unit/Model/Config/Reader/Source/Dynamic/StoreTest.php new file mode 100644 index 0000000000000000000000000000000000000000..3fef89f4c22d4d258750b30847715160478a8fc5 --- /dev/null +++ b/app/code/Magento/Store/Test/Unit/Model/Config/Reader/Source/Dynamic/StoreTest.php @@ -0,0 +1,144 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Store\Test\Unit\Model\Config\Reader\Source\Dynamic; + +use Magento\Framework\App\Config\Scope\Converter; +use Magento\Store\Model\Config\Reader\Source\Dynamic\Store as StoreSource; +use Magento\Store\Model\ResourceModel\Config\Collection\ScopedFactory; +use Magento\Store\Model\ScopeInterface; +use Magento\Store\Model\WebsiteFactory; +use Magento\Store\Model\Website; +use Magento\Store\Model\Config\Reader\Source\Dynamic\Website as WebsiteSource; +use Magento\Store\Model\StoreManagerInterface; +use Magento\Store\Api\Data\StoreInterface; +use Magento\Framework\DataObject; + +/** + * Class StoreTest + * + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ +class StoreTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var ScopedFactory|\PHPUnit_Framework_MockObject_MockObject + */ + private $collectionFactory; + + /** + * @var Converter|\PHPUnit_Framework_MockObject_MockObject + */ + private $converter; + + /** + * @var WebsiteFactory|\PHPUnit_Framework_MockObject_MockObject + */ + private $websiteFactory; + + /** + * @var Website|\PHPUnit_Framework_MockObject_MockObject + */ + private $website; + + /** + * @var WebsiteSource|\PHPUnit_Framework_MockObject_MockObject + */ + private $websiteSource; + + /** + * @var StoreManagerInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $storeManager; + + /** + * @var StoreInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $store; + + /** + * @var StoreSource + */ + private $storeSource; + + public function setUp() + { + $this->collectionFactory = $this->getMockBuilder(ScopedFactory::class) + ->disableOriginalConstructor() + ->setMethods(['create']) + ->getMockForAbstractClass(); + $this->converter = $this->getMockBuilder(Converter::class) + ->disableOriginalConstructor() + ->getMock(); + $this->websiteFactory = $this->getMockBuilder(\Magento\Store\Model\WebsiteFactory::class) + ->disableOriginalConstructor() + ->setMethods(['create']) + ->getMockForAbstractClass(); + $this->website = $this->getMockBuilder(\Magento\Store\Model\Website::class) + ->disableOriginalConstructor() + ->getMock(); + $this->websiteSource = $this->getMockBuilder(WebsiteSource::class) + ->disableOriginalConstructor() + ->getMock(); + $this->storeManager = $this->getMockBuilder(StoreManagerInterface::class) + ->disableOriginalConstructor() + ->getMock(); + $this->store = $this->getMockBuilder(StoreInterface::class) + ->disableOriginalConstructor() + ->getMock(); + $this->storeSource = new StoreSource( + $this->collectionFactory, + $this->converter, + $this->websiteFactory, + $this->websiteSource, + $this->storeManager + ); + } + + public function testGet() + { + $scopeCode = 'myStore'; + $expectedResult = [ + 'config/key1' => 'default_db_value1', + 'config/key3' => 'default_db_value3', + ]; + $this->storeManager->expects($this->once()) + ->method('getStore') + ->with($scopeCode) + ->willReturn($this->store); + $this->store->expects($this->once()) + ->method('getId') + ->willReturn(1); + $this->store->expects($this->once()) + ->method('getWebsiteId') + ->willReturn(1); + $this->collectionFactory->expects($this->once()) + ->method('create') + ->with(['scope' => ScopeInterface::SCOPE_STORES, 'scopeId' => 1]) + ->willReturn([ + new DataObject(['path' => 'config/key1', 'value' => 'default_db_value1']), + new DataObject(['path' => 'config/key3', 'value' => 'default_db_value3']), + ]); + $this->websiteSource->expects($this->once()) + ->method('get') + ->with(1) + ->willReturn([]); + + $this->converter->expects($this->at(0)) + ->method('convert') + ->with([ + 'config/key1' => 'default_db_value1', + 'config/key3' => 'default_db_value3' + ]) + ->willReturnArgument(0); + + $this->converter->expects($this->at(1)) + ->method('convert') + ->with($expectedResult) + ->willReturnArgument(0); + + $this->assertEquals($expectedResult, $this->storeSource->get($scopeCode)); + } +} diff --git a/app/code/Magento/Store/Test/Unit/Model/Config/Reader/Source/Dynamic/WebsiteTest.php b/app/code/Magento/Store/Test/Unit/Model/Config/Reader/Source/Dynamic/WebsiteTest.php new file mode 100644 index 0000000000000000000000000000000000000000..b07dafd2fe67b52b9bae650a4ecf1ba198ead47c --- /dev/null +++ b/app/code/Magento/Store/Test/Unit/Model/Config/Reader/Source/Dynamic/WebsiteTest.php @@ -0,0 +1,113 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Store\Test\Unit\Model\Config\Reader\Source\Dynamic; + +use Magento\Framework\DataObject; +use Magento\Store\Model\Config\Reader\Source\Dynamic\Website as WebsiteSource; +use Magento\Framework\App\Config\Scope\Converter; +use Magento\Store\Model\ResourceModel\Config\Collection\ScopedFactory; +use Magento\Store\Model\ScopeInterface; +use Magento\Store\Model\WebsiteFactory; +use Magento\Store\Model\Website; +use Magento\Store\Model\Config\Reader\Source\Dynamic\DefaultScope; + +/** + * Class WebsiteTest + * + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ +class WebsiteTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var ScopedFactory|\PHPUnit_Framework_MockObject_MockObject + */ + private $collectionFactory; + + /** + * @var Converter|\PHPUnit_Framework_MockObject_MockObject + */ + private $converter; + + /** + * @var WebsiteFactory|\PHPUnit_Framework_MockObject_MockObject + */ + private $websiteFactory; + + /** + * @var Website|\PHPUnit_Framework_MockObject_MockObject + */ + private $website; + + /** + * @var DefaultScope|\PHPUnit_Framework_MockObject_MockObject + */ + private $defaultScopeReader; + + /** + * @var WebsiteSource + */ + private $websiteSource; + + public function setUp() + { + $this->collectionFactory = $this->getMockBuilder(ScopedFactory::class) + ->disableOriginalConstructor() + ->setMethods(['create']) + ->getMockForAbstractClass(); + $this->converter = $this->getMockBuilder(Converter::class) + ->disableOriginalConstructor() + ->getMock(); + $this->websiteFactory = $this->getMockBuilder(\Magento\Store\Model\WebsiteFactory::class) + ->disableOriginalConstructor() + ->setMethods(['create']) + ->getMockForAbstractClass(); + $this->website = $this->getMockBuilder(\Magento\Store\Model\Website::class) + ->disableOriginalConstructor() + ->getMock(); + $this->defaultScopeReader = $this->getMockBuilder(DefaultScope::class) + ->disableOriginalConstructor() + ->getMock(); + $this->websiteSource = new WebsiteSource( + $this->collectionFactory, + $this->converter, + $this->websiteFactory, + $this->defaultScopeReader + ); + } + + public function testGet() + { + $scopeCode = 'myWebsite'; + $expectedResult = [ + 'config/key1' => 'default_db_value1', + 'config/key3' => 'default_db_value3', + ]; + $this->websiteFactory->expects($this->once()) + ->method('create') + ->willReturn($this->website); + $this->website->expects($this->once()) + ->method('load') + ->with($scopeCode); + $this->website->expects($this->once()) + ->method('getId') + ->willReturn(1); + $this->collectionFactory->expects($this->once()) + ->method('create') + ->with(['scope' => ScopeInterface::SCOPE_WEBSITES, 'scopeId' => 1]) + ->willReturn([ + new DataObject(['path' => 'config/key1', 'value' => 'default_db_value1']), + new DataObject(['path' => 'config/key3', 'value' => 'default_db_value3']), + ]); + $this->defaultScopeReader->expects($this->once()) + ->method('get') + ->willReturn([]); + $this->converter->expects($this->once()) + ->method('convert') + ->with($expectedResult) + ->willReturnArgument(0); + $this->assertEquals($expectedResult, $this->websiteSource->get($scopeCode)); + } +} diff --git a/app/code/Magento/Store/Test/Unit/Model/Config/Reader/Source/Initial/DefaultScopeTest.php b/app/code/Magento/Store/Test/Unit/Model/Config/Reader/Source/Initial/DefaultScopeTest.php new file mode 100644 index 0000000000000000000000000000000000000000..d0b68c59749f89b3bd2bf2e182678d39185750e9 --- /dev/null +++ b/app/code/Magento/Store/Test/Unit/Model/Config/Reader/Source/Initial/DefaultScopeTest.php @@ -0,0 +1,34 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Store\Test\Unit\Model\Config\Reader\Source\Initial; + +use Magento\Framework\App\Config\ScopeConfigInterface; +use Magento\Store\Model\Config\Reader\Source\Initial\DefaultScope; +use Magento\Framework\App\Config\Scope\Converter; + +class DefaultScopeTest extends \PHPUnit_Framework_TestCase +{ + public function testGet() + { + $initialConfig = $this->getMockBuilder(\Magento\Framework\App\Config\Initial::class) + ->disableOriginalConstructor() + ->getMock(); + $initialConfig->expects($this->once()) + ->method('getData') + ->with(ScopeConfigInterface::SCOPE_TYPE_DEFAULT) + ->willReturn([]); + $converter = $this->getMockBuilder(Converter::class) + ->disableOriginalConstructor() + ->getMock(); + $converter->expects($this->once()) + ->method('convert') + ->with([]) + ->willReturnArgument(0); + + $defaultSource = new DefaultScope($initialConfig, $converter); + $this->assertEquals([], $defaultSource->get()); + } +} diff --git a/app/code/Magento/Store/Test/Unit/Model/Config/Reader/Source/Initial/StoreTest.php b/app/code/Magento/Store/Test/Unit/Model/Config/Reader/Source/Initial/StoreTest.php new file mode 100644 index 0000000000000000000000000000000000000000..14531490cf4d072eab19e00a138f995f1497f9df --- /dev/null +++ b/app/code/Magento/Store/Test/Unit/Model/Config/Reader/Source/Initial/StoreTest.php @@ -0,0 +1,81 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Store\Test\Unit\Model\Config\Reader\Source\Initial; + +use Magento\Store\Model\Config\Reader\Source\Initial\Store; +use Magento\Framework\App\Config\Initial; +use Magento\Store\Model\Config\Reader\Source\Initial\Website; +use Magento\Store\Model\StoreManagerInterface; +use Magento\Framework\App\Config\Scope\Converter; + +class StoreTest extends \PHPUnit_Framework_TestCase +{ + public function testGet() + { + $scopeCode = 'myStore'; + $websiteCode = 'myWebsite'; + $initialConfig = $this->getMockBuilder(Initial::class) + ->disableOriginalConstructor() + ->getMock(); + $initialConfig->expects($this->once()) + ->method('getData') + ->with("stores|$scopeCode") + ->willReturn([ + 'general' => [ + 'locale' => [ + 'code'=> 'en_US' + ] + ] + ]); + $websiteSource = $this->getMockBuilder(Website::class) + ->disableOriginalConstructor() + ->getMock(); + $websiteSource->expects($this->once()) + ->method('get') + ->with($websiteCode) + ->willReturn([ + 'general' => [ + 'locale' => [ + 'code'=> 'ru_RU' + ] + ] + ]); + $storeManager = $this->getMockBuilder(StoreManagerInterface::class) + ->disableOriginalConstructor() + ->getMock(); + $store = $this->getMockBuilder(\Magento\Store\Model\Store::class) + ->disableOriginalConstructor() + ->getMock(); + $store->expects($this->once()) + ->method('getData') + ->with('website_code') + ->willReturn('myWebsite'); + + $storeManager->expects($this->once()) + ->method('getStore') + ->with($scopeCode) + ->willReturn($store); + + $converter = $this->getMockBuilder(Converter::class) + ->disableOriginalConstructor() + ->getMock(); + $converter->expects($this->once()) + ->method('convert') + ->willReturnArgument(0); + + $storeSource = new Store($initialConfig, $websiteSource, $storeManager, $converter); + $this->assertEquals( + [ + 'general' => [ + 'locale' => [ + 'code'=> 'en_US' + ] + ] + ], + $storeSource->get($scopeCode) + ); + } +} diff --git a/app/code/Magento/Store/Test/Unit/Model/Config/Reader/Source/Initial/WebsiteTest.php b/app/code/Magento/Store/Test/Unit/Model/Config/Reader/Source/Initial/WebsiteTest.php new file mode 100644 index 0000000000000000000000000000000000000000..6a4f3dd189eacf14f98b2d365da48b59b105063b --- /dev/null +++ b/app/code/Magento/Store/Test/Unit/Model/Config/Reader/Source/Initial/WebsiteTest.php @@ -0,0 +1,62 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Store\Test\Unit\Model\Config\Reader\Source\Initial; + +use Magento\Framework\App\Config\Initial; +use Magento\Store\Model\Config\Reader\Source\Initial\DefaultScope; +use Magento\Store\Model\Config\Reader\Source\Initial\Website; +use Magento\Framework\App\Config\Scope\Converter; + +class WebsiteTest extends \PHPUnit_Framework_TestCase +{ + public function testGet() + { + $scopeCode = 'myWebsite'; + $initialConfig = $this->getMockBuilder(Initial::class) + ->disableOriginalConstructor() + ->getMock(); + $initialConfig->expects($this->once()) + ->method('getData') + ->with("websites|$scopeCode") + ->willReturn([ + 'general' => [ + 'locale' => [ + 'code'=> 'en_US' + ] + ] + ]); + $defaultScopeReader = $this->getMockBuilder(DefaultScope::class) + ->disableOriginalConstructor() + ->getMock(); + $defaultScopeReader->expects($this->once()) + ->method('get') + ->willReturn([ + 'general' => [ + 'locale' => [ + 'code'=> 'ru_RU' + ] + ] + ]); + $converter = $this->getMockBuilder(Converter::class) + ->disableOriginalConstructor() + ->getMock(); + $converter->expects($this->once()) + ->method('convert') + ->willReturnArgument(0); + + $websiteSource = new Website($initialConfig, $defaultScopeReader, $converter); + $this->assertEquals( + [ + 'general' => [ + 'locale' => [ + 'code'=> 'en_US' + ] + ] + ], + $websiteSource->get($scopeCode) + ); + } +} diff --git a/app/code/Magento/Store/Test/Unit/Model/Config/Reader/StoreTest.php b/app/code/Magento/Store/Test/Unit/Model/Config/Reader/StoreTest.php deleted file mode 100644 index a3db4f89c1b876d660805343302e72f4e333bdab..0000000000000000000000000000000000000000 --- a/app/code/Magento/Store/Test/Unit/Model/Config/Reader/StoreTest.php +++ /dev/null @@ -1,159 +0,0 @@ -<?php -/** - * Copyright © 2016 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Store\Test\Unit\Model\Config\Reader; - -class StoreTest extends \PHPUnit_Framework_TestCase -{ - /** - * @var \Magento\Store\Model\Config\Reader\Store - */ - protected $_model; - - /** - * @var \Magento\Framework\App\Config\ScopePool|\PHPUnit_Framework_MockObject_MockObject - */ - protected $_scopePullMock; - - /** - * @var \PHPUnit_Framework_MockObject_MockObject - */ - protected $_initialConfigMock; - - /** - * @var \PHPUnit_Framework_MockObject_MockObject - */ - protected $_collectionFactory; - - /** - * @var \PHPUnit_Framework_MockObject_MockObject - */ - protected $_storeMock; - - /** - * @var \Magento\Store\Model\StoreManagerInterface|\PHPUnit_Framework_MockObject_MockObject - */ - protected $_storeManagerMock; - - protected function setUp() - { - $this->_scopePullMock = $this->getMock(\Magento\Framework\App\Config\ScopePool::class, [], [], '', false); - $this->_storeManagerMock = $this->getMock(\Magento\Store\Model\StoreManagerInterface::class); - $this->_initialConfigMock = $this->getMock(\Magento\Framework\App\Config\Initial::class, [], [], '', false); - $this->_collectionFactory = $this->getMock( - \Magento\Store\Model\ResourceModel\Config\Collection\ScopedFactory::class, - ['create'], - [], - '', - false - ); - $this->_storeMock = $this->getMock(\Magento\Store\Model\Store::class, [], [], '', false); - $placeholderProcessor = $this->getMock( - \Magento\Store\Model\Config\Processor\Placeholder::class, - [], - [], - '', - false - ); - $placeholderProcessor->expects($this->any())->method('process')->will($this->returnArgument(0)); - $this->_model = new \Magento\Store\Model\Config\Reader\Store( - $this->_initialConfigMock, - $this->_scopePullMock, - new \Magento\Store\Model\Config\Converter($placeholderProcessor), - $this->_collectionFactory, - $this->_storeManagerMock - ); - } - - /** - * @dataProvider readDataProvider - * @param string|null $storeCode - */ - public function testRead($storeCode) - { - $websiteCode = 'default'; - $storeId = 1; - $websiteMock = $this->getMock(\Magento\Store\Model\Website::class, [], [], '', false); - $websiteMock->expects($this->any())->method('getCode')->will($this->returnValue($websiteCode)); - $this->_storeMock->expects($this->any())->method('getWebsite')->will($this->returnValue($websiteMock)); - $this->_storeMock->expects($this->any())->method('getId')->will($this->returnValue($storeId)); - $this->_storeMock->expects($this->any())->method('getCode')->will($this->returnValue($websiteCode)); - - $dataMock = $this->getMock(\Magento\Framework\App\Config\Data::class, [], [], '', false); - $dataMock->expects( - $this->any() - )->method( - 'getValue' - )->will( - $this->returnValue(['config' => ['key0' => 'website_value0', 'key1' => 'website_value1']]) - ); - - $dataMock->expects( - $this->once() - )->method( - 'getSource' - )->will( - $this->returnValue(['config' => ['key0' => 'website_value0', 'key1' => 'website_value1']]) - ); - $this->_scopePullMock->expects( - $this->once() - )->method( - 'getScope' - )->with( - 'website', - $websiteCode - )->will( - $this->returnValue($dataMock) - ); - - $this->_initialConfigMock->expects( - $this->once() - )->method( - 'getData' - )->with( - "stores|{$storeCode}" - )->will( - $this->returnValue(['config' => ['key1' => 'store_value1', 'key2' => 'store_value2']]) - ); - $this->_collectionFactory->expects( - $this->once() - )->method( - 'create' - )->with( - ['scope' => 'stores', 'scopeId' => $storeId] - )->will( - $this->returnValue( - [ - new \Magento\Framework\DataObject(['path' => 'config/key1', 'value' => 'store_db_value1']), - new \Magento\Framework\DataObject(['path' => 'config/key3', 'value' => 'store_db_value3']), - ] - ) - ); - - $this->_storeManagerMock - ->expects($this->any()) - ->method('getStore') - ->with($storeCode) - ->will($this->returnValue($this->_storeMock)); - $expectedData = [ - 'config' => [ - 'key0' => 'website_value0', - 'key1' => 'store_db_value1', - 'key2' => 'store_value2', - 'key3' => 'store_db_value3', - ], - ]; - $this->assertEquals($expectedData, $this->_model->read($storeCode)); - } - - public function readDataProvider() - { - return [ - ['default'], - [null], - ['code', ''] - ]; - } -} diff --git a/app/code/Magento/Store/Test/Unit/Model/Config/Reader/WebsiteTest.php b/app/code/Magento/Store/Test/Unit/Model/Config/Reader/WebsiteTest.php deleted file mode 100644 index 8aed6de6dd235bbcbc86bd7b996562eb3a42017d..0000000000000000000000000000000000000000 --- a/app/code/Magento/Store/Test/Unit/Model/Config/Reader/WebsiteTest.php +++ /dev/null @@ -1,131 +0,0 @@ -<?php -/** - * Copyright © 2016 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Store\Test\Unit\Model\Config\Reader; - -class WebsiteTest extends \PHPUnit_Framework_TestCase -{ - /** - * @var \Magento\Store\Model\Config\Reader\Website - */ - protected $_model; - - /** - * @var \PHPUnit_Framework_MockObject_MockObject - */ - protected $_initialConfigMock; - - /** - * @var \Magento\Framework\App\Config\ScopePool|\PHPUnit_Framework_MockObject_MockObject - */ - protected $_scopePullMock; - - /** - * @var \PHPUnit_Framework_MockObject_MockObject - */ - protected $_collectionFactory; - - /** - * @var \PHPUnit_Framework_MockObject_MockObject - */ - protected $_websiteMock; - - protected function setUp() - { - $this->_initialConfigMock = $this->getMock(\Magento\Framework\App\Config\Initial::class, [], [], '', false); - $this->_scopePullMock = $this->getMock(\Magento\Framework\App\Config\ScopePool::class, [], [], '', false); - $this->_collectionFactory = $this->getMock( - \Magento\Store\Model\ResourceModel\Config\Collection\ScopedFactory::class, - ['create'], - [], - '', - false - ); - $websiteFactoryMock = $this->getMock( - \Magento\Store\Model\WebsiteFactory::class, - ['create'], - [], - '', - false - ); - $this->_websiteMock = $this->getMock(\Magento\Store\Model\Website::class, [], [], '', false); - $websiteFactoryMock->expects($this->any())->method('create')->will($this->returnValue($this->_websiteMock)); - - $this->_model = new \Magento\Store\Model\Config\Reader\Website( - $this->_initialConfigMock, - $this->_scopePullMock, - new \Magento\Framework\App\Config\Scope\Converter(), - $this->_collectionFactory, - $websiteFactoryMock - ); - } - - public function testRead() - { - $websiteCode = 'default'; - $websiteId = 1; - - $dataMock = $this->getMock(\Magento\Framework\App\Config\Data::class, [], [], '', false); - $dataMock->expects( - $this->any() - )->method( - 'getValue' - )->will( - $this->returnValue(['config' => ['key0' => 'default_value0', 'key1' => 'default_value1']]) - ); - $dataMock->expects( - $this->once() - )->method( - 'getSource' - )->will( - $this->returnValue(['config' => ['key0' => 'default_value0', 'key1' => 'default_value1']]) - ); - $this->_scopePullMock->expects( - $this->once() - )->method( - 'getScope' - )->with( - 'default', - null - )->will( - $this->returnValue($dataMock) - ); - - $this->_initialConfigMock->expects( - $this->any() - )->method( - 'getData' - )->with( - "websites|{$websiteCode}" - )->will( - $this->returnValue(['config' => ['key1' => 'website_value1', 'key2' => 'website_value2']]) - ); - $this->_websiteMock->expects($this->once())->method('load')->with($websiteCode); - $this->_websiteMock->expects($this->any())->method('getId')->will($this->returnValue($websiteId)); - $this->_collectionFactory->expects( - $this->once() - )->method( - 'create' - )->with( - ['scope' => 'websites', 'scopeId' => $websiteId] - )->will( - $this->returnValue( - [ - new \Magento\Framework\DataObject(['path' => 'config/key1', 'value' => 'website_db_value1']), - new \Magento\Framework\DataObject(['path' => 'config/key3', 'value' => 'website_db_value3']), - ] - ) - ); - $expectedData = [ - 'config' => [ - 'key0' => 'default_value0', - 'key1' => 'website_db_value1', - 'key2' => 'website_value2', - 'key3' => 'website_db_value3', - ], - ]; - $this->assertEquals($expectedData, $this->_model->read($websiteCode)); - } -} diff --git a/app/code/Magento/Store/Test/Unit/Model/StoreManagerTest.php b/app/code/Magento/Store/Test/Unit/Model/StoreManagerTest.php index 8e32ba2f989a90e4055d5186f2f11490b09dbfeb..f9d110359895ecd73c8c06f3cd0a438c98c5d090 100644 --- a/app/code/Magento/Store/Test/Unit/Model/StoreManagerTest.php +++ b/app/code/Magento/Store/Test/Unit/Model/StoreManagerTest.php @@ -6,6 +6,8 @@ namespace Magento\Store\Test\Unit\Model; +use Magento\Framework\App\DeploymentConfig; + class StoreManagerTest extends \PHPUnit_Framework_TestCase { /** diff --git a/app/code/Magento/Store/Test/Unit/Model/StoreRepositoryTest.php b/app/code/Magento/Store/Test/Unit/Model/StoreRepositoryTest.php new file mode 100644 index 0000000000000000000000000000000000000000..43bb331c017b218bce651515b6933c3e917aafcd --- /dev/null +++ b/app/code/Magento/Store/Test/Unit/Model/StoreRepositoryTest.php @@ -0,0 +1,185 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Store\Test\Unit\Model; + +use Magento\Framework\Exception\NoSuchEntityException; +use Magento\Store\Api\Data\StoreInterface; +use Magento\Store\Api\StoreRepositoryInterface; +use Magento\Store\Model\ResourceModel\Store\Collection; +use Magento\Store\Model\ResourceModel\Store\CollectionFactory; +use Magento\Store\Model\Store; +use Magento\Store\Model\StoreFactory; +use Magento\Store\Model\StoreRepository; +use Magento\Framework\App\Config; + +/** + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ +class StoreRepositoryTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var StoreFactory | \PHPUnit_Framework_MockObject_MockObject + */ + protected $storeFactory; + + /** + * @var CollectionFactory | \PHPUnit_Framework_MockObject_MockObject + */ + protected $storeCollectionFactory; + + /** + * @var bool + */ + protected $allLoaded = false; + + /** + * @var StoreRepositoryInterface + */ + private $storeRepository; + + /** + * @var Config | \PHPUnit_Framework_MockObject_MockObject + */ + private $appConfigMock; + + public function setUp() + { + $this->storeFactory = $this->getMockBuilder(StoreFactory::class) + ->setMethods(['create']) + ->disableOriginalConstructor() + ->getMock(); + $this->storeCollectionFactory = $this->getMockBuilder(CollectionFactory::class) + ->setMethods(['create']) + ->disableOriginalConstructor() + ->getMock(); + $this->storeRepository = new StoreRepository( + $this->storeFactory, + $this->storeCollectionFactory + ); + $this->appConfigMock = $this->getMockBuilder(Config::class) + ->disableOriginalConstructor() + ->getMock(); + $this->initDistroList(); + } + + private function initDistroList() + { + $repositoryReflection = new \ReflectionClass($this->storeRepository); + $deploymentProperty = $repositoryReflection->getProperty('appConfig'); + $deploymentProperty->setAccessible(true); + $deploymentProperty->setValue($this->storeRepository, $this->appConfigMock); + } + + /** + * @expectedException \Magento\Framework\Exception\NoSuchEntityException + * @expectedExceptionMessage Requested store is not found + */ + public function testGetWithException() + { + $storeMock = $this->getMockBuilder(Store::class) + ->disableOriginalConstructor() + ->getMock(); + $this->storeFactory->expects($this->once()) + ->method('create') + ->willReturn($storeMock); + + $this->storeRepository->get('some_code'); + } + + public function testGetWithAvailableStoreFromScope() + { + $storeMock = $this->getMockBuilder(Store::class) + ->disableOriginalConstructor() + ->getMock(); + $storeMock->expects($this->exactly(2)) + ->method('getId') + ->willReturn(1); + $this->storeFactory->expects($this->once()) + ->method('create') + ->willReturn($storeMock); + + $this->assertEquals($storeMock, $this->storeRepository->get('some_code')); + } + + public function testGetByIdWithAvailableStoreFromScope() + { + $storeMock = $this->getMockBuilder(Store::class) + ->disableOriginalConstructor() + ->getMock(); + $storeMock->expects($this->once()) + ->method('getId') + ->willReturn(1); + $storeMock->expects($this->once()) + ->method('getCode') + ->willReturn('some_code'); + $this->storeFactory->expects($this->once()) + ->method('create') + ->willReturn($storeMock); + $this->appConfigMock->expects($this->once()) + ->method('get') + ->willReturn([]); + + $this->assertEquals($storeMock, $this->storeRepository->getById(1)); + } + + /** + * @expectedException \Magento\Framework\Exception\NoSuchEntityException + * @expectedExceptionMessage Requested store is not found + */ + public function testGetByIdWithException() + { + $storeMock = $this->getMockBuilder(Store::class) + ->disableOriginalConstructor() + ->getMock(); + $this->storeFactory->expects($this->once()) + ->method('create') + ->willReturn($storeMock); + $this->appConfigMock->expects($this->once()) + ->method('get') + ->willReturn([]); + $this->storeRepository->getById(1); + } + + public function testGetList() + { + $storeMock1 = $this->getMock(StoreInterface::class); + $storeMock1->expects($this->once()) + ->method('getCode') + ->willReturn('some_code'); + $storeMock1->expects($this->once()) + ->method('getId') + ->willReturn(1); + $storeMock2 = $this->getMock(StoreInterface::class); + $storeMock2->expects($this->once()) + ->method('getCode') + ->willReturn('some_code_2'); + $storeMock2->expects($this->once()) + ->method('getId') + ->willReturn(2); + $this->appConfigMock->expects($this->once()) + ->method('get') + ->willReturn([ + [ + 'code' => 'some_code' + ], + [ + 'code' => 'some_code_2' + ] + ]); + $this->storeFactory->expects($this->at(0)) + ->method('create') + ->willReturn($storeMock1); + $this->storeFactory->expects($this->at(1)) + ->method('create') + ->willReturn($storeMock2); + + $this->assertEquals( + ['some_code' => $storeMock1, 'some_code_2' => $storeMock2], + $this->storeRepository->getList() + ); + } +} diff --git a/app/code/Magento/Store/Test/Unit/Model/WebsiteRepositoryTest.php b/app/code/Magento/Store/Test/Unit/Model/WebsiteRepositoryTest.php index 3cc8b646f75d438cda892bb7c228b64a70514778..fdb2e4530bfdb096563bb8a02b8ef9554df26a2a 100644 --- a/app/code/Magento/Store/Test/Unit/Model/WebsiteRepositoryTest.php +++ b/app/code/Magento/Store/Test/Unit/Model/WebsiteRepositoryTest.php @@ -6,6 +6,8 @@ namespace Magento\Store\Test\Unit\Model; +use Magento\Framework\App\Config; + class WebsiteRepositoryTest extends \PHPUnit_Framework_TestCase { /** @@ -13,14 +15,29 @@ class WebsiteRepositoryTest extends \PHPUnit_Framework_TestCase */ protected $model; + /** + * @var \Magento\Store\Model\WebsiteFactory|\PHPUnit_Framework_MockObject_MockObject + */ + protected $websiteFactoryMock; + /** * @var \Magento\Store\Model\ResourceModel\Website\CollectionFactory|\PHPUnit_Framework_MockObject_MockObject */ protected $websiteCollectionFactoryMock; + /** + * @var Config | \PHPUnit_Framework_MockObject_MockObject + */ + private $appConfigMock; + protected function setUp() { $objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); + $this->websiteFactoryMock = + $this->getMockBuilder('Magento\Store\Model\WebsiteFactory') + ->disableOriginalConstructor() + ->setMethods(['create']) + ->getMock(); $this->websiteCollectionFactoryMock = $this->getMockBuilder(\Magento\Store\Model\ResourceModel\Website\CollectionFactory::class) ->disableOriginalConstructor() @@ -29,26 +46,46 @@ class WebsiteRepositoryTest extends \PHPUnit_Framework_TestCase $this->model = $objectManager->getObject( \Magento\Store\Model\WebsiteRepository::class, [ + 'factory' => $this->websiteFactoryMock, 'websiteCollectionFactory' => $this->websiteCollectionFactoryMock ] ); + $this->appConfigMock = $this->getMockBuilder(Config::class) + ->disableOriginalConstructor() + ->getMock(); + $this->initDistroList(); + } + private function initDistroList() + { + $repositoryReflection = new \ReflectionClass($this->model); + $deploymentProperty = $repositoryReflection->getProperty('appConfig'); + $deploymentProperty->setAccessible(true); + $deploymentProperty->setValue($this->model, $this->appConfigMock); } public function testGetDefault() { - $collectionMock = $this->getMockBuilder(\Magento\Store\Model\ResourceModel\Website\Collection::class) - ->disableOriginalConstructor() - ->setMethods([]) - ->getMock(); $websiteMock = $this->getMockBuilder(\Magento\Store\Api\Data\WebsiteInterface::class) ->disableOriginalConstructor() ->setMethods([]) ->getMock(); - $this->websiteCollectionFactoryMock->expects($this->any())->method('create')->willReturn($collectionMock); - $collectionMock->expects($this->any())->method('addFieldToFilter'); - $collectionMock->expects($this->any())->method('getItems')->willReturn([1]); - $collectionMock->expects($this->any())->method('getFirstItem')->willReturn($websiteMock); + $this->appConfigMock->expects($this->once()) + ->method('get') + ->with('scopes', 'websites') + ->willReturn([ + 'some_code' => [ + 'code' => 'some_code', + 'is_default' => 1 + ], + 'some_code_2' => [ + 'code' => 'some_code_2', + 'is_default' => 0 + ] + ]); + $this->websiteFactoryMock->expects($this->at(0)) + ->method('create') + ->willReturn($websiteMock); $website = $this->model->getDefault(); $this->assertInstanceOf(\Magento\Store\Api\Data\WebsiteInterface::class, $website); @@ -61,13 +98,24 @@ class WebsiteRepositoryTest extends \PHPUnit_Framework_TestCase */ public function testGetDefaultIsSeveral() { - $collectionMock = $this->getMockBuilder(\Magento\Store\Model\ResourceModel\Website\Collection::class) + $websiteMock = $this->getMockBuilder(\Magento\Store\Api\Data\WebsiteInterface::class) ->disableOriginalConstructor() ->setMethods([]) ->getMock(); - $this->websiteCollectionFactoryMock->expects($this->any())->method('create')->willReturn($collectionMock); - $collectionMock->expects($this->any())->method('addFieldToFilter'); - $collectionMock->expects($this->any())->method('getItems')->willReturn([1, 2]); + $this->appConfigMock->expects($this->once()) + ->method('get') + ->with('scopes', 'websites') + ->willReturn([ + 'some_code' => [ + 'code' => 'some_code', + 'is_default' => 1 + ], + 'some_code_2' => [ + 'code' => 'some_code_2', + 'is_default' => 1 + ] + ]); + $this->websiteFactoryMock->expects($this->any())->method('create')->willReturn($websiteMock); $this->model->getDefault(); } @@ -78,13 +126,24 @@ class WebsiteRepositoryTest extends \PHPUnit_Framework_TestCase */ public function testGetDefaultIsZero() { - $collectionMock = $this->getMockBuilder(\Magento\Store\Model\ResourceModel\Website\Collection::class) + $websiteMock = $this->getMockBuilder(\Magento\Store\Api\Data\WebsiteInterface::class) ->disableOriginalConstructor() ->setMethods([]) ->getMock(); - $this->websiteCollectionFactoryMock->expects($this->any())->method('create')->willReturn($collectionMock); - $collectionMock->expects($this->any())->method('addFieldToFilter'); - $collectionMock->expects($this->any())->method('getItems')->willReturn([]); + $this->appConfigMock->expects($this->once()) + ->method('get') + ->with('scopes', 'websites') + ->willReturn([ + 'some_code' => [ + 'code' => 'some_code', + 'is_default' => 0 + ], + 'some_code_2' => [ + 'code' => 'some_code_2', + 'is_default' => 0 + ] + ]); + $this->websiteFactoryMock->expects($this->any())->method('create')->willReturn($websiteMock); $this->model->getDefault(); } diff --git a/app/code/Magento/Store/composer.json b/app/code/Magento/Store/composer.json index d5b8a2b4b980b58648c04cfed916b5bd390db048..1c74c46cdf89f3aaa0bf5efc3143556d610e518b 100644 --- a/app/code/Magento/Store/composer.json +++ b/app/code/Magento/Store/composer.json @@ -10,6 +10,9 @@ "magento/module-media-storage": "100.2.*", "magento/framework": "100.2.*" }, + "suggest": { + "magento/module-deploy": "100.2.*" + }, "type": "magento2-module", "version": "100.2.0-dev", "license": [ diff --git a/app/code/Magento/Store/etc/di.xml b/app/code/Magento/Store/etc/di.xml index 57bf057af2724c220d3e7d1bda152351a8b9de88..7307493cefb4cca65eb81eacaec265e9a381f6f1 100644 --- a/app/code/Magento/Store/etc/di.xml +++ b/app/code/Magento/Store/etc/di.xml @@ -33,28 +33,11 @@ <argument name="xFrameOpt" xsi:type="init_parameter">Magento\Framework\App\Response\HeaderProvider\XFrameOptions::DEPLOYMENT_CONFIG_X_FRAME_OPT</argument> </arguments> </type> - <type name="Magento\Framework\App\Config\ScopePool"> - <arguments> - <argument name="readerPool" xsi:type="object">Magento\Store\Model\Config\Reader\ReaderPool\Proxy</argument> - <argument name="cache" xsi:type="object">Magento\Framework\App\Cache\Type\Config</argument> - </arguments> - </type> <type name="Magento\Framework\View\Element\Template\File\Validator"> <arguments> <argument name="scope" xsi:type="string">store</argument> </arguments> </type> - <type name="Magento\Store\Model\Config\Reader\Website"> - <arguments> - <argument name="scopePool" xsi:type="object">Magento\Framework\App\Config\ScopePool\Proxy</argument> - </arguments> - </type> - <type name="Magento\Store\Model\Config\Reader\Store"> - <arguments> - <argument name="scopePool" xsi:type="object">Magento\Framework\App\Config\ScopePool\Proxy</argument> - <argument name="storeManager" xsi:type="object">Magento\Store\Model\StoreManagerInterface\Proxy</argument> - </arguments> - </type> <type name="Magento\Store\Model\Resolver\Store"> <arguments> <argument name="storeManager" xsi:type="object">Magento\Store\Model\StoreManagerInterface\Proxy</argument> @@ -70,18 +53,6 @@ <argument name="storeManager" xsi:type="object">Magento\Store\Model\StoreManagerInterface\Proxy</argument> </arguments> </type> - <type name="Magento\Store\Model\Config\Reader\ReaderPool"> - <arguments> - <argument name="readers" xsi:type="array"> - <item name="default" xsi:type="object">Magento\Store\Model\Config\Reader\DefaultReader</item> - <item name="website" xsi:type="object">Magento\Store\Model\Config\Reader\Website</item> - <item name="websites" xsi:type="object">Magento\Store\Model\Config\Reader\Website</item> - <item name="store" xsi:type="object">Magento\Store\Model\Config\Reader\Store</item> - <item name="stores" xsi:type="object">Magento\Store\Model\Config\Reader\Store</item> - </argument> - </arguments> - </type> - <preference for="Magento\Framework\App\Config\Scope\ReaderPoolInterface" type="Magento\Store\Model\Config\Reader\ReaderPool"/> <preference for="Magento\Framework\App\ScopeResolverInterface" type="Magento\Store\Model\Resolver\Store" /> <preference for="Magento\Framework\App\Router\PathConfigInterface" type="Magento\Store\Model\PathConfig" /> <type name="\Magento\Framework\App\Action\AbstractAction"> @@ -164,7 +135,7 @@ <argument name="cacheLifetime" xsi:type="boolean">false</argument> </arguments> </virtualType> - <type name="Magento\Store\Model\Config\Processor\Placeholder"> + <type name="Magento\Store\Model\Config\Placeholder"> <arguments> <argument name="request" xsi:type="object">Magento\Framework\App\Request\Http\Proxy</argument> <argument name="urlPaths" xsi:type="array"> @@ -344,4 +315,59 @@ </argument> </arguments> </type> + <virtualType name="systemConfigPostProcessorComposite" type="Magento\Framework\App\Config\PostProcessorComposite"> + <arguments> + <argument name="processors" xsi:type="array"> + <item name="placeholder" xsi:type="object">Magento\Store\Model\Config\Processor\Placeholder</item> + </argument> + </arguments> + </virtualType> + <type name="Magento\Framework\App\Config"> + <arguments> + <argument name="types" xsi:type="array"> + <item name="scopes" xsi:type="object">Magento\Store\App\Config\Type\Scopes</item> + </argument> + </arguments> + </type> + <type name="Magento\Store\App\Config\Type\Scopes"> + <arguments> + <argument name="source" xsi:type="object">scopesConfigSourceAggregatedProxy</argument> + </arguments> + </type> + <virtualType name="scopesConfigSourceAggregatedProxy" type="Magento\Framework\App\Config\ConfigSourceAggregated\Proxy"> + <arguments> + <argument name="instanceName" xsi:type="string">scopesConfigSourceAggregated</argument> + </arguments> + </virtualType> + <virtualType name="scopesConfigSourceAggregated" type="Magento\Framework\App\Config\ConfigSourceAggregated"> + <arguments> + <argument name="sources" xsi:type="array"> + <item name="initial" xsi:type="array"> + <item name="source" xsi:type="object">scopesConfigInitialDataProvider</item> + <item name="sortOrder" xsi:type="string">10</item> + </item> + <item name="runtime" xsi:type="array"> + <item name="source" xsi:type="object">Magento\Store\App\Config\Source\RuntimeConfigSource</item> + <item name="sortOrder" xsi:type="string">10</item> + </item> + </argument> + </arguments> + </virtualType> + <virtualType name="scopesConfigInitialDataProvider" type="Magento\Framework\App\Config\InitialConfigSource"> + <arguments> + <argument name="reader" xsi:type="object">Magento\Framework\App\DeploymentConfig\Reader</argument> + <argument name="configType" xsi:type="const">Magento\Store\App\Config\Type\Scopes::CONFIG_TYPE</argument> + <argument name="fileKey" xsi:type="const">Magento\Framework\Config\File\ConfigFilePool::APP_CONFIG</argument> + </arguments> + </virtualType> + <type name="Magento\Deploy\Console\Command\App\ApplicationDumpCommand"> + <arguments> + <argument name="sources" xsi:type="array"> + <item name="scopes" xsi:type="array"> + <item name="source" xsi:type="object">scopesConfigSourceAggregated</item> + <item name="namespace" xsi:type="const">Magento\Store\App\Config\Type\Scopes::CONFIG_TYPE</item> + </item> + </argument> + </arguments> + </type> </config> diff --git a/app/code/Magento/Theme/Model/Theme/ThemeProvider.php b/app/code/Magento/Theme/Model/Theme/ThemeProvider.php index 9fd3ce94dac45888687cbe6bff26f86a2ac9d2e7..89d7bfc18d30c27026777f7864b562354277dfee 100644 --- a/app/code/Magento/Theme/Model/Theme/ThemeProvider.php +++ b/app/code/Magento/Theme/Model/Theme/ThemeProvider.php @@ -5,6 +5,13 @@ */ namespace Magento\Theme\Model\Theme; +use Magento\Framework\App\ObjectManager; +use Magento\Framework\View\Design\Theme\ListInterface; +use Magento\Framework\App\DeploymentConfig; + +/** + * Provide data for theme grid and for theme edit page + */ class ThemeProvider implements \Magento\Framework\View\Design\Theme\ThemeProviderInterface { /** @@ -27,6 +34,16 @@ class ThemeProvider implements \Magento\Framework\View\Design\Theme\ThemeProvide */ private $themes; + /** + * @var ListInterface + */ + private $themeList; + + /** + * @var DeploymentConfig + */ + private $deploymentConfig; + /** * ThemeProvider constructor. * @@ -52,6 +69,11 @@ class ThemeProvider implements \Magento\Framework\View\Design\Theme\ThemeProvide if (isset($this->themes[$fullPath])) { return $this->themes[$fullPath]; } + + if (! $this->getDeploymentConfig()->isDbAvailable()) { + return $this->getThemeList()->getThemeByFullPath($fullPath); + } + /** @var $themeCollection \Magento\Theme\Model\ResourceModel\Theme\Collection */ $theme = $this->cache->load('theme'. $fullPath); if ($theme) { @@ -105,4 +127,28 @@ class ThemeProvider implements \Magento\Framework\View\Design\Theme\ThemeProvide } return $themeModel; } + + /** + * @deprecated + * @return ListInterface + */ + private function getThemeList() + { + if ($this->themeList === null) { + $this->themeList = ObjectManager::getInstance()->get(ListInterface::class); + } + return $this->themeList; + } + + /** + * @deprecated + * @return DeploymentConfig + */ + private function getDeploymentConfig() + { + if ($this->deploymentConfig === null) { + $this->deploymentConfig = ObjectManager::getInstance()->get(DeploymentConfig::class); + } + return $this->deploymentConfig; + } } diff --git a/app/code/Magento/Theme/Test/Unit/Model/Theme/ThemeProviderTest.php b/app/code/Magento/Theme/Test/Unit/Model/Theme/ThemeProviderTest.php index 54120d23699835954283b2768403e07d63dcc66c..fb0e1f9897587ad706301f91f621d31991fca838 100644 --- a/app/code/Magento/Theme/Test/Unit/Model/Theme/ThemeProviderTest.php +++ b/app/code/Magento/Theme/Test/Unit/Model/Theme/ThemeProviderTest.php @@ -10,6 +10,10 @@ use Magento\Framework\View\Design\ThemeInterface; use Magento\Theme\Model\Theme\ThemeProvider; use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper; +/** + * Class ThemeProviderTest + * @covers \Magento\Theme\Model\Theme\ThemeProvider + */ class ThemeProviderTest extends \PHPUnit_Framework_TestCase { /** @var \Magento\Framework\TestFramework\Unit\Helper\ObjectManager */ @@ -52,6 +56,21 @@ class ThemeProviderTest extends \PHPUnit_Framework_TestCase ] ); + $deploymentConfig = $this->getMockBuilder(\Magento\Framework\App\DeploymentConfig::class) + ->disableOriginalConstructor() + ->getMock(); + $deploymentConfig->expects($this->once()) + ->method('isDbAvailable') + ->willReturn(true); + + $objectManagerMock = $this->getMock(\Magento\Framework\ObjectManagerInterface::class); + $objectManagerMock->expects($this->any()) + ->method('get') + ->willReturnMap([ + [\Magento\Framework\App\DeploymentConfig::class, $deploymentConfig], + ]); + \Magento\Framework\App\ObjectManager::setInstance($objectManagerMock); + $this->assertSame($theme, $themeProvider->getThemeByFullPath($path)); } @@ -66,6 +85,9 @@ class ThemeProviderTest extends \PHPUnit_Framework_TestCase false ); $theme = $this->getMock(\Magento\Theme\Model\Theme::class, [], [], '', false); + $theme->expects($this->once()) + ->method('getId') + ->willReturn(1); $theme->expects($this->once())->method('load')->with($themeId)->will($this->returnSelf()); $theme->expects($this->once())->method('getId')->will($this->returnValue(1)); $theme->expects($this->once())->method('__sleep')->will($this->returnValue([])); diff --git a/app/code/Magento/Translation/App/Config/Type/Translation.php b/app/code/Magento/Translation/App/Config/Type/Translation.php new file mode 100644 index 0000000000000000000000000000000000000000..9a5090f3f5486d3b082ed82279487d27db7748bf --- /dev/null +++ b/app/code/Magento/Translation/App/Config/Type/Translation.php @@ -0,0 +1,62 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Translation\App\Config\Type; + +use Magento\Framework\App\Config\ConfigSourceInterface; +use Magento\Framework\App\Config\ConfigTypeInterface; +use Magento\Framework\DataObject; + +/** + * Class which hold all translation sources and merge them + * + * @package Magento\Translation\App\Config\Type + */ +class Translation implements ConfigTypeInterface +{ + const CONFIG_TYPE = "i18n"; + + /** + * @var DataObject[] + */ + private $data; + + /** + * @var ConfigSourceInterface + */ + private $source; + + /** + * Translation constructor. + * @param ConfigSourceInterface $source + */ + public function __construct( + ConfigSourceInterface $source + ) { + $this->source = $source; + } + + /** + * @inheritDoc + */ + public function get($path = '') + { + if (!$this->data) { + $this->data = new DataObject($this->source->get()); + } + + return $this->data->getData($path); + } + + /** + * Clean cache + * + * @return void + */ + public function clean() + { + $this->data = null; + } +} diff --git a/app/code/Magento/Translation/Model/ResourceModel/Translate.php b/app/code/Magento/Translation/Model/ResourceModel/Translate.php index 0d40a7254eba1e1840e6c1ac7209a09263f9249f..49a8bcdbb43a862700d0e6da11a7f179935d4d67 100644 --- a/app/code/Magento/Translation/Model/ResourceModel/Translate.php +++ b/app/code/Magento/Translation/Model/ResourceModel/Translate.php @@ -5,6 +5,11 @@ */ namespace Magento\Translation\Model\ResourceModel; +use Magento\Framework\App\ObjectManager; +use Magento\Framework\App\DeploymentConfig; +use Magento\Framework\App\Config; +use Magento\Translation\App\Config\Type\Translation; + class Translate extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb implements \Magento\Framework\Translate\ResourceInterface { @@ -18,6 +23,16 @@ class Translate extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb imp */ protected $scope; + /** + * @var Config + */ + private $appConfig; + + /** + * @var DeploymentConfig + */ + private $deployedConfig; + /** * @param \Magento\Framework\Model\ResourceModel\Db\Context $context * @param \Magento\Framework\App\ScopeResolverInterface $scopeResolver @@ -57,21 +72,25 @@ class Translate extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb imp if ($storeId === null) { $storeId = $this->getStoreId(); } + $locale = (string) $locale; + $data = $this->getAppConfig()->get( + Translation::CONFIG_TYPE, + $locale . '/' . $this->getStoreCode($storeId), + [] + ); $connection = $this->getConnection(); - if (!$connection) { - return []; + if ($connection) { + $select = $connection->select() + ->from($this->getMainTable(), ['string', 'translate']) + ->where('store_id IN (0 , :store_id)') + ->where('locale = :locale') + ->order('store_id'); + $bind = [':locale' => $locale, ':store_id' => $storeId]; + $dbData = $connection->fetchPairs($select, $bind); + $data = array_replace($data, $dbData); } - - $select = $connection->select() - ->from($this->getMainTable(), ['string', 'translate']) - ->where('store_id IN (0 , :store_id)') - ->where('locale = :locale') - ->order('store_id'); - - $bind = [':locale' => (string)$locale, ':store_id' => $storeId]; - - return $connection->fetchPairs($select, $bind); + return $data; } /** @@ -115,6 +134,19 @@ class Translate extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb imp return $this->getChecksum($this->getMainTable()); } + /** + * Get connection + * + * @return \Magento\Framework\DB\Adapter\AdapterInterface|false + */ + public function getConnection() + { + if (!$this->getDeployedConfig()->isDbAvailable()) { + return false; + } + return parent::getConnection(); + } + /** * Retrieve current store identifier * @@ -124,4 +156,39 @@ class Translate extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb imp { return $this->scopeResolver->getScope($this->scope)->getId(); } + + /** + * Retrieve store code by store id + * + * @param int $storeId + * @return string + */ + private function getStoreCode($storeId) + { + return $this->scopeResolver->getScope($storeId)->getCode(); + } + + /** + * @deprecated + * @return DeploymentConfig + */ + private function getDeployedConfig() + { + if ($this->deployedConfig === null) { + $this->deployedConfig = ObjectManager::getInstance()->get(DeploymentConfig::class); + } + return $this->deployedConfig; + } + + /** + * @deprecated + * @return Config + */ + private function getAppConfig() + { + if ($this->appConfig === null) { + $this->appConfig = ObjectManager::getInstance()->get(Config::class); + } + return $this->appConfig; + } } diff --git a/app/code/Magento/Translation/Model/Source/InitialTranslationSource.php b/app/code/Magento/Translation/Model/Source/InitialTranslationSource.php new file mode 100644 index 0000000000000000000000000000000000000000..22828cfb1be05eb8609eb9ebdcb1d99667d06391 --- /dev/null +++ b/app/code/Magento/Translation/Model/Source/InitialTranslationSource.php @@ -0,0 +1,82 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Translation\Model\Source; + +use Magento\Framework\App\DeploymentConfig; +use Magento\Store\Model\StoreManager; +use Magento\Translation\Model\ResourceModel\TranslateFactory; +use Magento\Translation\Model\ResourceModel\Translate; +use Magento\Framework\App\Config\ConfigSourceInterface; +use Magento\Framework\DataObject; + +/** + * Class for reading translations from DB + */ +class InitialTranslationSource implements ConfigSourceInterface +{ + /** + * @var TranslateFactory + */ + private $translateFactory; + + /** + * @var StoreManager + */ + private $storeManager; + + /** + * @var array + */ + private $data; + + /** + * @var DeploymentConfig + */ + private $deploymentConfig; + + /** + * @param TranslateFactory $translateFactory + * @param StoreManager $storeManager + * @param DeploymentConfig $deploymentConfig + */ + public function __construct( + TranslateFactory $translateFactory, + StoreManager $storeManager, + DeploymentConfig $deploymentConfig + ) { + $this->translateFactory = $translateFactory; + $this->storeManager = $storeManager; + $this->deploymentConfig = $deploymentConfig; + } + + /** + * Read translations for the given 'path' from application initial configuration. + * + * @param string $path + * @return mixed + */ + public function get($path = '') + { + if (!$this->deploymentConfig->isDbAvailable()) { + return []; + } + + if (!$this->data) { + /** @var Translate $translate */ + $translate = $this->translateFactory->create(); + $select = $translate->getConnection()->select() + ->from($translate->getMainTable(), ['string', 'translate', 'store_id', 'locale']) + ->order('store_id'); + $translations = []; + foreach ($translate->getConnection()->fetchAll($select) as $item) { + $store = $this->storeManager->getStore($item['store_id']); + $translations[$item['locale']][$store->getCode()][$item['string']] = $item['translate']; + } + $this->data = new DataObject($translations); + } + return $this->data->getData($path) ?: []; + } +} diff --git a/app/code/Magento/Translation/Test/Unit/App/Config/Type/TranslationTest.php b/app/code/Magento/Translation/Test/Unit/App/Config/Type/TranslationTest.php new file mode 100644 index 0000000000000000000000000000000000000000..8f2c1efdf515b51bf6985318cfc7f11c0fa0ca65 --- /dev/null +++ b/app/code/Magento/Translation/Test/Unit/App/Config/Type/TranslationTest.php @@ -0,0 +1,55 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Translation\Test\Unit\App\Config\Type; + +use Magento\Authorizenet\Helper\Backend\Data; +use Magento\Framework\App\Cache\Type\Translate; +use Magento\Framework\App\Config\ConfigSourceInterface; +use Magento\Framework\Cache\FrontendInterface; +use Magento\Translation\App\Config\Type\Translation; +use Magento\Framework\DataObject; + +/** + * @covers \Magento\Translation\App\Config\Type\Translation + */ +class TranslationTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var ConfigSourceInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $source; + + /** + * @var Translation + */ + private $configType; + + public function setUp() + { + $this->source = $this->getMockBuilder(ConfigSourceInterface::class) + ->getMockForAbstractClass(); + $this->configType = new Translation($this->source); + } + + public function testGet() + { + $path = 'en_US/default'; + $data = [ + 'en_US' => [ + 'default' => [ + 'hello' => 'bonjour' + ] + ] + ]; + + $this->source->expects($this->once()) + ->method('get') + ->with() + ->willReturn($data); + + $this->assertEquals(['hello' => 'bonjour'], $this->configType->get($path)); + } +} diff --git a/app/code/Magento/Translation/Test/Unit/Model/Source/InitialTranslationSourceTest.php b/app/code/Magento/Translation/Test/Unit/Model/Source/InitialTranslationSourceTest.php new file mode 100644 index 0000000000000000000000000000000000000000..f6b3a39dcbf424131a0bef5012e62f8e3356bad6 --- /dev/null +++ b/app/code/Magento/Translation/Test/Unit/Model/Source/InitialTranslationSourceTest.php @@ -0,0 +1,159 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Translation\Test\Unit\Model\Source; + +use Magento\Framework\App\DeploymentConfig; +use Magento\Framework\DB\Adapter\AdapterInterface; +use Magento\Framework\DB\Select; +use Magento\Store\Model\Store; +use Magento\Store\Model\StoreManager; +use Magento\Translation\Model\ResourceModel\Translate; +use Magento\Translation\Model\ResourceModel\TranslateFactory; +use Magento\Translation\Model\Source\InitialTranslationSource; + +/** + * @covers \Magento\Translation\Model\Source\InitialTranslationSource + * @package Magento\Translation\Test\Unit\Model\Source + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ +class InitialTranslationSourceTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var TranslateFactory|\PHPUnit_Framework_MockObject_MockObject + */ + private $translationFactory; + + /** + * @var Translate|\PHPUnit_Framework_MockObject_MockObject + */ + private $translation; + + /** + * @var StoreManager|\PHPUnit_Framework_MockObject_MockObject + */ + private $storeManager; + + /** + * @var Store|\PHPUnit_Framework_MockObject_MockObject + */ + private $store; + + /** + * @var AdapterInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $connection; + + /** + * @var Select|\PHPUnit_Framework_MockObject_MockObject + */ + private $select; + + /** + * @var DeploymentConfig | \PHPUnit_Framework_MockObject_MockObject + */ + private $deploymentConfigMock; + + /** + * @var InitialTranslationSource + */ + private $source; + + public function setUp() + { + $this->translationFactory = $this->getMockBuilder(TranslateFactory::class) + ->disableOriginalConstructor() + ->setMethods(['create']) + ->getMock(); + $this->translation = $this->getMockBuilder(Translate::class) + ->disableOriginalConstructor() + ->getMock(); + $this->storeManager = $this->getMockBuilder(StoreManager::class) + ->disableOriginalConstructor() + ->getMock(); + $this->store = $this->getMockBuilder(Store::class) + ->disableOriginalConstructor() + ->getMock(); + $this->connection = $this->getMockBuilder(AdapterInterface::class) + ->disableOriginalConstructor() + ->getMock(); + $this->select = $this->getMockBuilder(Select::class) + ->disableOriginalConstructor() + ->getMock(); + $this->deploymentConfigMock = $this->getMockBuilder(DeploymentConfig::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->source = new InitialTranslationSource( + $this->translationFactory, + $this->storeManager, + $this->deploymentConfigMock + ); + } + + public function testGet() + { + $this->deploymentConfigMock->expects($this->once()) + ->method('isDbAvailable') + ->willReturn(true); + $this->translationFactory->expects($this->once()) + ->method('create') + ->willReturn($this->translation); + $this->translation->expects($this->atLeastOnce()) + ->method('getConnection') + ->willReturn($this->connection); + $this->connection->expects($this->once()) + ->method('select') + ->willReturn($this->select); + $this->translation->expects($this->once()) + ->method('getMainTable') + ->willReturn('main_table.translate'); + $this->select->expects($this->once()) + ->method('from') + ->with('main_table.translate', ['string', 'translate', 'store_id', 'locale']) + ->willReturnSelf(); + $this->select->expects($this->once()) + ->method('order') + ->with('store_id') + ->willReturnSelf(); + $this->connection->expects($this->once()) + ->method('fetchAll') + ->with($this->select) + ->willReturn([ + [ + 'store_id' => 2, + 'locale' => 'en_US', + 'string' => 'hello', + 'translate' => 'bonjour' + ] + ]); + $this->storeManager->expects($this->once()) + ->method('getStore') + ->with(2) + ->willReturn($this->store); + $this->store->expects($this->once()) + ->method('getCode') + ->willReturn('myStore'); + + $this->assertEquals( + [ + 'en_US' => [ + 'myStore' => [ + 'hello' => 'bonjour' + ] + ] + ], + $this->source->get() + ); + } + + public function testGetWithoutAvailableDb() + { + $this->deploymentConfigMock->expects($this->once()) + ->method('isDbAvailable') + ->willReturn(false); + $this->assertEquals([], $this->source->get()); + } +} diff --git a/app/code/Magento/Translation/composer.json b/app/code/Magento/Translation/composer.json index b9ed830c9053ea492d76a2402ec8f523fb03a46a..6c6c5fad3e7b9abcab6211e1c2326f9a31054088 100644 --- a/app/code/Magento/Translation/composer.json +++ b/app/code/Magento/Translation/composer.json @@ -9,6 +9,9 @@ "magento/module-theme": "100.2.*", "magento/framework": "100.2.*" }, + "suggest": { + "magento/module-deploy": "100.2.*" + }, "type": "magento2-module", "version": "100.2.0-dev", "license": [ diff --git a/app/code/Magento/Translation/etc/di.xml b/app/code/Magento/Translation/etc/di.xml index 8e29e941499129a546ded22c3532c198f00d9838..3e76f80fff261299484704e3b66a294839cfff42 100644 --- a/app/code/Magento/Translation/etc/di.xml +++ b/app/code/Magento/Translation/etc/di.xml @@ -70,7 +70,6 @@ </argument> </arguments> </type> - <virtualType name="AssetPreProcessorPool"> <arguments> <argument name="preprocessors" xsi:type="array"> @@ -87,7 +86,6 @@ </argument> </arguments> </virtualType> - <type name="Magento\Framework\Console\CommandListInterface"> <arguments> <argument name="commands" xsi:type="array"> @@ -95,4 +93,47 @@ </argument> </arguments> </type> + <virtualType name="translationConfigInitialDataProvider" type="Magento\Framework\App\Config\InitialConfigSource"> + <arguments> + <argument name="reader" xsi:type="object">Magento\Framework\App\DeploymentConfig\Reader</argument> + <argument name="configType" xsi:type="const">Magento\Translation\App\Config\Type\Translation::CONFIG_TYPE</argument> + <argument name="fileKey" xsi:type="const">Magento\Framework\Config\File\ConfigFilePool::APP_CONFIG</argument> + </arguments> + </virtualType> + <virtualType name="translationConfigSourceAggregated" type="Magento\Framework\App\Config\ConfigSourceAggregated"> + <arguments> + <argument name="sources" xsi:type="array"> + <item name="dynamic" xsi:type="array"> + <item name="source" xsi:type="object">Magento\Translation\Model\Source\InitialTranslationSource\Proxy</item> + <item name="sortOrder" xsi:type="string">100</item> + </item> + <item name="initial" xsi:type="array"> + <item name="source" xsi:type="object">translationConfigInitialDataProvider</item> + <item name="sortOrder" xsi:type="string">1000</item> + </item> + </argument> + </arguments> + </virtualType> + <type name="Magento\Translation\App\Config\Type\Translation"> + <arguments> + <argument name="source" xsi:type="object">translationConfigSourceAggregated</argument> + </arguments> + </type> + <type name="Magento\Framework\App\Config"> + <arguments> + <argument name="types" xsi:type="array"> + <item name="i18n" xsi:type="object">Magento\Translation\App\Config\Type\Translation</item> + </argument> + </arguments> + </type> + <type name="Magento\Deploy\Console\Command\App\ApplicationDumpCommand"> + <arguments> + <argument name="sources" xsi:type="array"> + <item name="i18n" xsi:type="array"> + <item name="source" xsi:type="object">Magento\Translation\Model\Source\InitialTranslationSource</item> + <item name="namespace" xsi:type="const">Magento\Translation\App\Config\Type\Translation::CONFIG_TYPE</item> + </item> + </argument> + </arguments> + </type> </config> diff --git a/app/code/Magento/User/Model/ResourceModel/User.php b/app/code/Magento/User/Model/ResourceModel/User.php index b35deb6c5c6f147dfba617705c3877a771494f10..d3e228d44358136c748258c47da3f7f2b2bba76b 100644 --- a/app/code/Magento/User/Model/ResourceModel/User.php +++ b/app/code/Magento/User/Model/ResourceModel/User.php @@ -34,13 +34,6 @@ class User extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb */ protected $dateTime; - /** - * Users table - * - * @var string - */ - protected $_usersTable; - /** * Construct * @@ -61,7 +54,6 @@ class User extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb $this->_aclCache = $aclCache; $this->_roleFactory = $roleFactory; $this->dateTime = $dateTime; - $this->_usersTable = $this->getTable('admin_user'); } /** @@ -473,7 +465,7 @@ class User extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb if (sizeof($users) > 0) { $bind = ['reload_acl_flag' => 1]; $where = ['user_id IN(?)' => $users]; - $rowsCount = $connection->update($this->_usersTable, $bind, $where); + $rowsCount = $connection->update($this->getTable('admin_user'), $bind, $where); } return $rowsCount > 0; diff --git a/app/etc/di.xml b/app/etc/di.xml index e430c15729d3d0cced20bf2b326d40f152b174e6..e9767eccb28114ffa66bc8bc84829d92b1620e99 100755 --- a/app/etc/di.xml +++ b/app/etc/di.xml @@ -956,11 +956,6 @@ <argument name="uploader" xsi:type="object">Magento\Framework\View\Design\Theme\Image\Uploader\Proxy</argument> </arguments> </type> - <type name="Magento\Framework\App\Config\ScopePool"> - <arguments> - <argument name="cache" xsi:type="object">Magento\Framework\App\Cache\Type\Config</argument> - </arguments> - </type> <type name="Magento\Framework\App\Config\Initial"> <arguments> <argument name="reader" xsi:type="object">Magento\Framework\App\Config\Initial\Reader\Proxy</argument> diff --git a/dev/tests/api-functional/testsuite/Magento/Quote/Api/CartManagementTest.php b/dev/tests/api-functional/testsuite/Magento/Quote/Api/CartManagementTest.php index 43134e838c9c7845ddc1648210b1d5e956b64c56..2cb9aa3bbc9a13ef08244eef48686c88de3fe417 100644 --- a/dev/tests/api-functional/testsuite/Magento/Quote/Api/CartManagementTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Quote/Api/CartManagementTest.php @@ -6,8 +6,14 @@ namespace Magento\Quote\Api; +use Magento\Framework\App\Config; use Magento\TestFramework\TestCase\WebapiAbstract; +/** + * Class CartManagementTest + * @package Magento\Quote\Api + * @magentoAppIsolation enabled + */ class CartManagementTest extends WebapiAbstract { const SERVICE_VERSION = 'V1'; @@ -25,6 +31,8 @@ class CartManagementTest extends WebapiAbstract protected function setUp() { $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); + $appConfig = $this->objectManager->get(Config::class); + $appConfig->clean(); } public function tearDown() diff --git a/dev/tests/integration/etc/di/preferences/ce.php b/dev/tests/integration/etc/di/preferences/ce.php index cec08b1d91da7ec77ce81d00dcdf8fd09addfd9c..f1654cba97d74faedd12797d19a967afb410d500 100644 --- a/dev/tests/integration/etc/di/preferences/ce.php +++ b/dev/tests/integration/etc/di/preferences/ce.php @@ -1,5 +1,7 @@ <?php /** + * Preferences for classes like in di.xml (for integration tests) + * * Copyright © 2016 Magento. All rights reserved. * See COPYING.txt for license details. */ @@ -19,5 +21,6 @@ return [ \Magento\Framework\View\LayoutInterface::class => \Magento\TestFramework\View\Layout::class, \Magento\Framework\App\ResourceConnection\ConnectionAdapterInterface::class => \Magento\TestFramework\Db\ConnectionAdapter::class, - \Magento\Framework\Filesystem\DriverInterface::class => \Magento\Framework\Filesystem\Driver\File::class + \Magento\Framework\Filesystem\DriverInterface::class => \Magento\Framework\Filesystem\Driver\File::class, + \Magento\Framework\App\Config\ScopeConfigInterface::class => \Magento\TestFramework\App\Config::class, ]; diff --git a/dev/tests/integration/framework/Magento/TestFramework/Annotation/AdminConfigFixture.php b/dev/tests/integration/framework/Magento/TestFramework/Annotation/AdminConfigFixture.php index 780beaef7cc44715cebb722d02382cd602ab1f75..5b687d4d5a4660cecfe276f59fe4ed92a30441e6 100644 --- a/dev/tests/integration/framework/Magento/TestFramework/Annotation/AdminConfigFixture.php +++ b/dev/tests/integration/framework/Magento/TestFramework/Annotation/AdminConfigFixture.php @@ -9,6 +9,11 @@ */ namespace Magento\TestFramework\Annotation; +/** + * Handler for applying magentoAdminConfig annotation + * + * @package Magento\TestFramework\Annotation + */ class AdminConfigFixture { /** @@ -34,7 +39,7 @@ class AdminConfigFixture protected function _getConfigValue($configPath) { return \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get( - \Magento\Backend\App\ConfigInterface::class + \Magento\Framework\App\Config\MutableScopeConfigInterface::class )->getValue( $configPath ); @@ -49,7 +54,7 @@ class AdminConfigFixture protected function _setConfigValue($configPath, $value) { \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get( - \Magento\Backend\App\ConfigInterface::class + \Magento\Framework\App\Config\MutableScopeConfigInterface::class )->setValue( $configPath, $value diff --git a/dev/tests/integration/framework/Magento/TestFramework/Annotation/ConfigFixture.php b/dev/tests/integration/framework/Magento/TestFramework/Annotation/ConfigFixture.php index 25863089bd6308d2c990c249ba427723d1ccdf1b..d9df69b7b76e5aed096d74e727f6c4ae9de0022d 100644 --- a/dev/tests/integration/framework/Magento/TestFramework/Annotation/ConfigFixture.php +++ b/dev/tests/integration/framework/Magento/TestFramework/Annotation/ConfigFixture.php @@ -11,6 +11,11 @@ namespace Magento\TestFramework\Annotation; use Magento\Framework\App\Config\ScopeConfigInterface; +/** + * Handler which works with magentoConfigFixture annotations + * + * @package Magento\TestFramework\Annotation + */ class ConfigFixture { /** diff --git a/dev/tests/integration/framework/Magento/TestFramework/App/Config.php b/dev/tests/integration/framework/Magento/TestFramework/App/Config.php new file mode 100644 index 0000000000000000000000000000000000000000..43a47debf9064abacd7ca1ddf7c081561c4e6ec9 --- /dev/null +++ b/dev/tests/integration/framework/Magento/TestFramework/App/Config.php @@ -0,0 +1,137 @@ +<?php +/** + * Application configuration object. Used to access configuration when application is initialized and installed. + * + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\TestFramework\App; + +use Magento\Framework\App\Config\ScopeCodeResolver; +use Magento\Framework\App\Config\ScopeConfigInterface; +use Magento\Framework\DataObject; +use Magento\TestFramework\ObjectManager; + +/** + * @inheritdoc + */ +class Config extends \Magento\Framework\App\Config +{ + /** + * @var DataObject[] + */ + private $data; + + /** + * @var ScopeCodeResolver + */ + private $scopeCodeResolver; + + /** + * Initialize data object with all settings data + * + * @param array $data + * @param string $configType + * @return void + */ + private function setData(array $data, $configType) + { + $this->data[$configType] = new DataObject($data); + } + + /** + * Retrieve Scope Code Resolver + * + * @return ScopeCodeResolver + */ + private function getScopeCodeResolver() + { + if (!$this->scopeCodeResolver) { + $this->scopeCodeResolver = ObjectManager::getInstance()->get(ScopeCodeResolver::class); + } + + return $this->scopeCodeResolver; + } + + /** + * Set config value in the corresponding config scope + * + * @param string $path + * @param mixed $value + * @param string $scope + * @param null|string $scopeCode + * @return void + */ + public function setValue( + $path, + $value, + $scope = ScopeConfigInterface::SCOPE_TYPE_DEFAULT, + $scopeCode = null + ) { + $result = $this->get('system'); + + if ($scope === 'store') { + $scope = 'stores'; + } elseif ($scope === 'website') { + $scope = 'websites'; + } + + if (empty($scopeCode)) { + $scopeCode = $this->getScopeCodeResolver()->resolve($scope, $scopeCode); + } + + $keys = explode('/', $path); + if ($scope !== ScopeConfigInterface::SCOPE_TYPE_DEFAULT) { + $searchKeys = array_merge([$scope, $scopeCode], $keys); + } else { + $searchKeys = array_merge([$scope], $keys); + } + + $this->updateResult($searchKeys, $result, $value); + $this->setData($result, 'system'); + } + + /** + * Recursively update results in global variable, which hold configs + * + * @param array $keys + * @param array $result + * @param mixed $value + * @return void + */ + private function updateResult(array $keys, & $result, $value) + { + $key = array_shift($keys); + + if (empty($keys)) { + $result[$key] = $value; + } else { + $this->updateResult($keys, $result[$key], $value); + } + } + + /** + * Flush all muted settings + * + * @return void + */ + public function clean() + { + $this->data = null; + $this->scopeCodeResolver = null; + parent::clean(); + } + + /** + * @inheritdoc + */ + public function get($configType, $path = null, $default = null) + { + $path = $path === null ? '' : $path; + if (!isset($this->data[$configType]) || $this->data[$configType]->getData($path) === null) { + return parent::get($configType, $path, $default); + } + + return $this->data[$configType]->getData($path); + } +} diff --git a/dev/tests/integration/framework/Magento/TestFramework/App/MutableScopeConfig.php b/dev/tests/integration/framework/Magento/TestFramework/App/MutableScopeConfig.php new file mode 100644 index 0000000000000000000000000000000000000000..3af325bab0ec18e674ada29ab6d236d4970fe274 --- /dev/null +++ b/dev/tests/integration/framework/Magento/TestFramework/App/MutableScopeConfig.php @@ -0,0 +1,80 @@ +<?php +/** + * Application configuration object. Used to access configuration when application is installed. + * + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\TestFramework\App; + +use Magento\Framework\App\Config\MutableScopeConfigInterface; +use Magento\Framework\App\Config\ScopeConfigInterface; +use Magento\TestFramework\ObjectManager; + +/** + * @inheritdoc + */ +class MutableScopeConfig implements MutableScopeConfigInterface +{ + /** + * @var Config + */ + private $testAppConfig; + + /** + * @param string $path + * @param string $scopeType + * @param null $scopeCode + * @return bool + */ + public function isSetFlag($path, $scopeType = ScopeConfigInterface::SCOPE_TYPE_DEFAULT, $scopeCode = null) + { + return $this->getTestAppConfig()->isSetFlag($path, $scopeType, $scopeCode); + } + + /** + * @inheritdoc + */ + public function getValue($path, $scopeType = ScopeConfigInterface::SCOPE_TYPE_DEFAULT, $scopeCode = null) + { + return $this->getTestAppConfig()->getValue($path, $scopeType, $scopeCode); + } + + /** + * @inheritdoc + */ + public function setValue( + $path, + $value, + $scopeType = \Magento\Framework\App\Config\ScopeConfigInterface::SCOPE_TYPE_DEFAULT, + $scopeCode = null + ) { + return $this->getTestAppConfig()->setValue($path, $value, $scopeType, $scopeCode); + } + + /** + * Clean app config cache + * + * @param string|null $type + * @return void + */ + public function clean() + { + $this->getTestAppConfig()->clean(); + } + + /** + * Retrieve test app config instance + * + * @return \Magento\TestFramework\App\Config + */ + private function getTestAppConfig() + { + if (!$this->testAppConfig) { + $this->testAppConfig = ObjectManager::getInstance()->get(ScopeConfigInterface::class); + } + + return $this->testAppConfig; + } +} diff --git a/dev/tests/integration/framework/Magento/TestFramework/App/ReinitableConfig.php b/dev/tests/integration/framework/Magento/TestFramework/App/ReinitableConfig.php new file mode 100644 index 0000000000000000000000000000000000000000..6d0b52555a395e398823e9d5ec1dd1d7aba59042 --- /dev/null +++ b/dev/tests/integration/framework/Magento/TestFramework/App/ReinitableConfig.php @@ -0,0 +1,43 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\TestFramework\App; + +use Magento\Framework\App\Config\ReinitableConfigInterface; +use Magento\TestFramework\ObjectManager; + +/** + * @inheritdoc + */ +class ReinitableConfig extends MutableScopeConfig implements ReinitableConfigInterface +{ + /** + * @var Config + */ + private $testAppConfig; + + /** + * {@inheritdoc} + */ + public function reinit() + { + $this->getTestScopeConfig()->clean(); + return $this; + } + + /** + * Retrieve Test Scope Config + * + * @return Config + */ + public function getTestScopeConfig() + { + if (!$this->testAppConfig) { + $this->testAppConfig = ObjectManager::getInstance()->get(Config::class); + } + + return $this->testAppConfig; + } +} diff --git a/dev/tests/integration/framework/Magento/TestFramework/Application.php b/dev/tests/integration/framework/Magento/TestFramework/Application.php index 3ae2c994511c7ed64038826399dc00cd9af62817..15407f2cd572f32b143d82bad9b59e6e382dc9fe 100644 --- a/dev/tests/integration/framework/Magento/TestFramework/Application.php +++ b/dev/tests/integration/framework/Magento/TestFramework/Application.php @@ -6,8 +6,6 @@ namespace Magento\TestFramework; use Magento\Framework\Autoload\AutoloaderInterface; -use Magento\Framework\Filesystem; -use Magento\Framework\Filesystem\DriverInterface; use Magento\Framework\App\Filesystem\DirectoryList; use Magento\Framework\App\DeploymentConfig; use Magento\Framework\Config\ConfigOptionsListConstants; @@ -561,7 +559,6 @@ class Application /** @var $objectManager \Magento\TestFramework\ObjectManager */ $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); $objectManager->clearCache(); - \Magento\Framework\Data\Form::setElementRenderer(null); \Magento\Framework\Data\Form::setFieldsetRenderer(null); \Magento\Framework\Data\Form::setFieldsetElementRenderer(null); diff --git a/dev/tests/integration/framework/Magento/TestFramework/Backend/App/Config.php b/dev/tests/integration/framework/Magento/TestFramework/Backend/App/Config.php new file mode 100644 index 0000000000000000000000000000000000000000..7907cf5a82d2e01d1814497879a49fcbccd3d229 --- /dev/null +++ b/dev/tests/integration/framework/Magento/TestFramework/Backend/App/Config.php @@ -0,0 +1,46 @@ +<?php +/** + * Default application path for backend area + * + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +// @codingStandardsIgnoreFile + +namespace Magento\TestFramework\Backend\App; +use Magento\Framework\App\Config\ScopeConfigInterface; + +/** + * Backend config accessor. + */ +class Config extends \Magento\Backend\App\Config +{ + /** + * @var \Magento\TestFramework\App\MutableScopeConfig + */ + private $mutableScopeConfig; + + /** + * Config constructor. + * @param \Magento\TestFramework\App\Config $appConfig + * @param \Magento\TestFramework\App\MutableScopeConfig $mutableScopeConfig + */ + public function __construct(\Magento\TestFramework\App\Config $appConfig, \Magento\TestFramework\App\MutableScopeConfig $mutableScopeConfig) + { + parent::__construct($appConfig); + $this->mutableScopeConfig = $mutableScopeConfig; + } + + /** + * @inheritdoc + */ + public function setValue( + $path, + $value, + $scope = ScopeConfigInterface::SCOPE_TYPE_DEFAULT, + $scopeCode = null + ) { + $this->mutableScopeConfig->setValue($path, $value, $scope, $scopeCode); + } +} diff --git a/dev/tests/integration/framework/Magento/TestFramework/Bootstrap/DocBlock.php b/dev/tests/integration/framework/Magento/TestFramework/Bootstrap/DocBlock.php index 2349ae949876eff6cdbe29c47ac44c846fb8ba4b..bf890b2448e23f7a134574b9fb2fb2d7eca1151e 100644 --- a/dev/tests/integration/framework/Magento/TestFramework/Bootstrap/DocBlock.php +++ b/dev/tests/integration/framework/Magento/TestFramework/Bootstrap/DocBlock.php @@ -53,6 +53,7 @@ class DocBlock new \Magento\TestFramework\Isolation\WorkingDirectory(), new \Magento\TestFramework\Isolation\DeploymentConfig(), new \Magento\TestFramework\Annotation\AppIsolation($application), + new \Magento\TestFramework\Isolation\AppConfig(), new \Magento\TestFramework\Annotation\ConfigFixture(), new \Magento\TestFramework\Annotation\DataFixtureBeforeTransaction($this->_fixturesBaseDir), new \Magento\TestFramework\Event\Transaction( @@ -66,7 +67,7 @@ class DocBlock new \Magento\TestFramework\Annotation\ComponentRegistrarFixture($this->_fixturesBaseDir), new \Magento\TestFramework\Annotation\AppArea($application), new \Magento\TestFramework\Annotation\Cache($application), - new \Magento\TestFramework\Annotation\AdminConfigFixture() + new \Magento\TestFramework\Annotation\AdminConfigFixture(), ]; } } diff --git a/dev/tests/integration/framework/Magento/TestFramework/Isolation/AppConfig.php b/dev/tests/integration/framework/Magento/TestFramework/Isolation/AppConfig.php new file mode 100644 index 0000000000000000000000000000000000000000..514b074d23366b25f6427f2d1e50da35e7641e0b --- /dev/null +++ b/dev/tests/integration/framework/Magento/TestFramework/Isolation/AppConfig.php @@ -0,0 +1,50 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\TestFramework\Isolation; + +use Magento\TestFramework\App\Config; +use Magento\TestFramework\ObjectManager; + +/** + * A listener that watches for integrity of app configuration + */ +class AppConfig +{ + /** + * @var Config + */ + private $testAppConfig; + + /** + * Clean memorized and cached setting values + * + * Assumption: this is done once right before executing very first test suite. + * It is assumed that deployment configuration is valid at this point + * + * @param \PHPUnit_Framework_TestCase $test + * @return void + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + */ + public function startTest(\PHPUnit_Framework_TestCase $test) + { + $this->getTestAppConfig()->clean(); + } + + /** + * Retrieve Test App Config + * + * @return Config + */ + private function getTestAppConfig() + { + if (!$this->testAppConfig) { + $this->testAppConfig = ObjectManager::getInstance()->get(Config::class); + } + + return $this->testAppConfig; + } +} diff --git a/dev/tests/integration/framework/Magento/TestFramework/ObjectManager.php b/dev/tests/integration/framework/Magento/TestFramework/ObjectManager.php index c65ce0907912834027f929432be7f62dc01330a4..ad685845cde004bd54c8499671e9e22faa72d0e5 100644 --- a/dev/tests/integration/framework/Magento/TestFramework/ObjectManager.php +++ b/dev/tests/integration/framework/Magento/TestFramework/ObjectManager.php @@ -5,6 +5,7 @@ * Copyright © 2016 Magento. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\TestFramework; class ObjectManager extends \Magento\Framework\App\ObjectManager @@ -23,6 +24,8 @@ class ObjectManager extends \Magento\Framework\App\ObjectManager * @var array */ protected $persistedInstances = [ + \Magento\TestFramework\App\Config::class, + \Magento\Framework\App\Config\ScopeConfigInterface::class, \Magento\Framework\App\ResourceConnection::class, \Magento\Framework\Config\Scope::class, \Magento\Framework\ObjectManager\RelationsInterface::class, diff --git a/dev/tests/integration/framework/Magento/TestFramework/ObjectManager/Configurator.php b/dev/tests/integration/framework/Magento/TestFramework/ObjectManager/Configurator.php index b4a9819228e5fc653530a8ab3d28351e2538f2f6..afab0eca6edf051ff710b229ac114845f160e998 100644 --- a/dev/tests/integration/framework/Magento/TestFramework/ObjectManager/Configurator.php +++ b/dev/tests/integration/framework/Magento/TestFramework/ObjectManager/Configurator.php @@ -5,10 +5,23 @@ */ namespace Magento\TestFramework\ObjectManager; +use Magento\Framework\App\Config\ScopeConfigInterface; +use Magento\Framework\Stdlib\CookieManagerInterface; +use Magento\Store\Model\StoreManagerInterface; +use Magento\Framework\App\MutableScopeConfig; +use Magento\Framework\App\ReinitableConfig; +use Magento\Framework\App\Config as AppConfig; +use Magento\Backend\App\Config as BackendConfig; + +/** + * Class which hold configurations (preferences, etc...) of integration test framework + * + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ class Configurator implements \Magento\Framework\ObjectManager\DynamicConfigInterface { /** - * Map application initialization params to Object Manager configuration format + * Map application initialization params to Object Manager configuration format. * * @return array */ @@ -16,8 +29,13 @@ class Configurator implements \Magento\Framework\ObjectManager\DynamicConfigInte { return [ 'preferences' => [ - \Magento\Framework\Stdlib\CookieManagerInterface::class => \Magento\TestFramework\CookieManager::class, - \Magento\Store\Model\StoreManagerInterface::class => \Magento\TestFramework\Store\StoreManager::class, + CookieManagerInterface::class => \Magento\TestFramework\CookieManager::class, + StoreManagerInterface::class => \Magento\TestFramework\Store\StoreManager::class, + ScopeConfigInterface::class => \Magento\TestFramework\App\Config::class, + \Magento\Framework\App\Config::class => \Magento\TestFramework\App\Config::class, + BackendConfig::class => \Magento\TestFramework\Backend\App\Config::class, + ReinitableConfig::class => \Magento\TestFramework\App\ReinitableConfig::class, + MutableScopeConfig::class => \Magento\TestFramework\App\MutableScopeConfig::class, ] ]; } diff --git a/dev/tests/integration/framework/Magento/TestFramework/Store/StoreManager.php b/dev/tests/integration/framework/Magento/TestFramework/Store/StoreManager.php index 9f0124593ac1eff7892dabbb3e4b94a69150f831..5b2546765a132d35cd451fff449c80d06f31c06f 100644 --- a/dev/tests/integration/framework/Magento/TestFramework/Store/StoreManager.php +++ b/dev/tests/integration/framework/Magento/TestFramework/Store/StoreManager.php @@ -5,6 +5,14 @@ */ namespace Magento\TestFramework\Store; +use Magento\TestFramework\App\Config; +use Magento\TestFramework\ObjectManager; + +/** + * Integration tests decoration of store manager + * + * @package Magento\TestFramework\Store + */ class StoreManager implements \Magento\Store\Model\StoreManagerInterface { /** @@ -117,7 +125,16 @@ class StoreManager implements \Magento\Store\Model\StoreManagerInterface */ public function reinitStores() { + //In order to restore configFixture values + $testAppConfig = ObjectManager::getInstance()->get(Config::class); + $reflection = new \ReflectionClass($testAppConfig); + $dataProperty = $reflection->getProperty('data'); + $dataProperty->setAccessible(true); + $savedConfig = $dataProperty->getValue($testAppConfig); + $this->decoratedStoreManager->reinitStores(); + + $dataProperty->setValue($testAppConfig, $savedConfig); $this->dispatchInitCurrentStoreAfterEvent(); } diff --git a/dev/tests/integration/framework/tests/unit/testsuite/Magento/Test/App/ConfigTest.php b/dev/tests/integration/framework/tests/unit/testsuite/Magento/Test/App/ConfigTest.php new file mode 100644 index 0000000000000000000000000000000000000000..508550fc1385ac47e75c7e63be982f6e9f1b57ca --- /dev/null +++ b/dev/tests/integration/framework/tests/unit/testsuite/Magento/Test/App/ConfigTest.php @@ -0,0 +1,50 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +/** + * Test class for \Magento\TestFramework\App\Config. + */ +namespace Magento\Test\App; + +use Magento\Framework\App\Config\ScopeCodeResolver; +use Magento\TestFramework\App\Config; + +class ConfigTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var Config + */ + private $model; + + public function setUp() + { + $scopeCodeResolver = $this->getMockBuilder(ScopeCodeResolver::class) + ->disableOriginalConstructor() + ->getMock(); + $this->model = new Config($scopeCodeResolver); + } + + public function testGet() + { + $configType = "system"; + $path = "stores/one"; + $value = 1; + $this->model->setValue($path, $value, 'default', 'one'); + + $this->assertEquals($value, $this->model->get($configType, 'default/stores/one')); + } + + public function testClean() + { + $configType = "system"; + $path = "stores/one"; + $value = 1; + $this->model->setValue($path, $value, 'default', 'one'); + $this->assertEquals($value, $this->model->get($configType, 'default/stores/one')); + $this->model->clean(); + $this->assertNull($this->model->get($configType, 'default/stores/one')); + } +} diff --git a/dev/tests/integration/framework/tests/unit/testsuite/Magento/Test/Isolation/AppConfigTest.php b/dev/tests/integration/framework/tests/unit/testsuite/Magento/Test/Isolation/AppConfigTest.php new file mode 100644 index 0000000000000000000000000000000000000000..34cf654dcf5c0669cd16532d8960215565a92dde --- /dev/null +++ b/dev/tests/integration/framework/tests/unit/testsuite/Magento/Test/Isolation/AppConfigTest.php @@ -0,0 +1,48 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +/** + * Test class for \Magento\TestFramework\Isolation\WorkingDirectory. + */ +namespace Magento\Test\Isolation; + +use Magento\Framework\ObjectManagerInterface; +use Magento\TestFramework\ObjectManager; + +class AppConfigTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var \Magento\TestFramework\Isolation\WorkingDirectory + */ + private $model; + + protected function setUp() + { + $this->model = new \Magento\TestFramework\Isolation\AppConfig(); + } + + protected function tearDown() + { + $this->model = null; + } + + public function testStartTestEndTest() + { + $test = $this->getMockBuilder(\PHPUnit_Framework_TestCase::class) + ->disableOriginalConstructor() + ->getMock(); + $modelReflection = new \ReflectionClass($this->model); + $testAppConfigProperty = $modelReflection->getProperty('testAppConfig'); + $testAppConfigProperty->setAccessible(true); + $testAppConfigMock = $this->getMockBuilder(\Magento\TestFramework\App\Config::class) + ->disableOriginalConstructor() + ->getMock(); + $testAppConfigProperty->setValue($this->model, $testAppConfigMock); + $testAppConfigMock->expects($this->once()) + ->method('clean'); + $this->model->startTest($test); + } +} diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Helper/DataTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Helper/DataTest.php index 650c84f17a36624b39df6ccd6bef5094ec021123..071c2499bb33262f1f1df9a6bcbd1f37340516ed 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/Helper/DataTest.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/Helper/DataTest.php @@ -397,7 +397,7 @@ class DataTest extends \PHPUnit_Framework_TestCase ], 'price include tax, display excluding tax, high rate product tax class, round' => [ (new \Magento\Framework\DataObject())->setPrice(3.256)->setRoundPrice(true), - '2.67', + '2.97', [ [ 'path' => Config::CONFIG_XML_PATH_PRICE_INCLUDES_TAX, diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Helper/Product/FlatTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Helper/Product/FlatTest.php index 0d6f18dbacbc837485b20751d9f840ee252db284..9252f87079fa501960e274789d394bd577137ceb 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/Helper/Product/FlatTest.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/Helper/Product/FlatTest.php @@ -27,11 +27,6 @@ class FlatTest extends \PHPUnit_Framework_TestCase ); } - public function testIsEnabledDefault() - { - $this->assertFalse($this->_state->isFlatEnabled()); - } - /** * @magentoConfigFixture current_store catalog/frontend/flat_catalog_product 1 */ diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Model/ResourceModel/Product/Indexer/Eav/SourceTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Model/ResourceModel/Product/Indexer/Eav/SourceTest.php index ed8f12020a977192d94c866e81110a167d7a3587..2d811ea59bfa95eedb56f48635ed4dd0d95a0c87 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/Model/ResourceModel/Product/Indexer/Eav/SourceTest.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/Model/ResourceModel/Product/Indexer/Eav/SourceTest.php @@ -11,6 +11,7 @@ use Magento\TestFramework\Helper\Bootstrap; /** * Class SourceTest + * @magentoAppIsolation enabled */ class SourceTest extends \PHPUnit_Framework_TestCase { diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/multiselect_attribute.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/multiselect_attribute.php index 963de3e46fea69c821902b8d4266681adc0d5ea8..6b1e53242cb3dcf412525eb1334e398c55a58d8b 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/_files/multiselect_attribute.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/multiselect_attribute.php @@ -3,7 +3,6 @@ * Copyright © 2016 Magento. All rights reserved. * See COPYING.txt for license details. */ - /* Create attribute */ /** @var $installer \Magento\Catalog\Setup\CategorySetup */ $installer = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create( diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/multiselect_attribute_rollback.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/multiselect_attribute_rollback.php new file mode 100644 index 0000000000000000000000000000000000000000..6fe9f0d2b4898fd3cf3a09208272ae87133036f5 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/multiselect_attribute_rollback.php @@ -0,0 +1,18 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +/* Delete attribute with multiselect_attribute code */ +$registry = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get('Magento\Framework\Registry'); +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', true); +/** @var $attribute \Magento\Catalog\Model\ResourceModel\Eav\Attribute */ +$attribute = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create( + 'Magento\Catalog\Model\ResourceModel\Eav\Attribute' +); +$attribute->load('multiselect_attribute', 'attribute_code'); +$attribute->delete(); + +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', false); diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/products_with_multiselect_attribute.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/products_with_multiselect_attribute.php index f252447a1586d363be145a74e4e7c9fab00d63a6..259b7a9166c32b6a19071ab9a6358fe2494d84c3 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/_files/products_with_multiselect_attribute.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/products_with_multiselect_attribute.php @@ -3,8 +3,14 @@ * Copyright © 2016 Magento. All rights reserved. * See COPYING.txt for license details. */ + +/** + * Create multiselect attribute + */ require __DIR__ . '/multiselect_attribute.php'; +/** Create product with options and multiselect attribute */ + /** @var $installer \Magento\Catalog\Setup\CategorySetup */ $installer = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create( \Magento\Catalog\Setup\CategorySetup::class diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/products_with_multiselect_attribute_rollback.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/products_with_multiselect_attribute_rollback.php new file mode 100644 index 0000000000000000000000000000000000000000..97937bc3509ea10220c013118449be0e869d47c7 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/products_with_multiselect_attribute_rollback.php @@ -0,0 +1,23 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +/** + * Remove all products as strategy of isolation process + */ +$registry = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get('Magento\Framework\Registry'); +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', true); + +/** @var $productCollection \Magento\Catalog\Model\ResourceModel\Product */ +$productCollection = \Magento\TestFramework\Helper\Bootstrap::getObjectManager() + ->create('Magento\Catalog\Model\Product') + ->getCollection(); + +foreach ($productCollection as $product) { + $product->delete(); +} + +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', false); diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/text_attribute_rollback.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/text_attribute_rollback.php new file mode 100644 index 0000000000000000000000000000000000000000..c81afcaf95d2ea6dbd712229bce891a2cd17d50f --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/text_attribute_rollback.php @@ -0,0 +1,18 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +/* Delete attribute with text_attribute code */ +$registry = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get('Magento\Framework\Registry'); +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', true); +/** @var $attribute \Magento\Catalog\Model\ResourceModel\Eav\Attribute */ +$attribute = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create( + 'Magento\Catalog\Model\ResourceModel\Eav\Attribute' +); +$attribute->load('text_attribute', 'attribute_code'); +$attribute->delete(); + +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', false); diff --git a/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/AbstractProductExportImportTestCase.php b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/AbstractProductExportImportTestCase.php index 3f566bda2d3525d4375ec58477e9a7cb20d50e7f..c5ebf80c6a060681947e920a686997c48c07b3d2 100644 --- a/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/AbstractProductExportImportTestCase.php +++ b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/AbstractProductExportImportTestCase.php @@ -6,9 +6,12 @@ namespace Magento\CatalogImportExport\Model; use Magento\Framework\App\Bootstrap; +use Magento\Framework\App\Config; use Magento\Framework\App\Filesystem\DirectoryList; /** + * Abstract class for testing product export and import scenarios + * * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ abstract class AbstractProductExportImportTestCase extends \PHPUnit_Framework_TestCase @@ -64,6 +67,7 @@ abstract class AbstractProductExportImportTestCase extends \PHPUnit_Framework_Te $this->productResource = $this->objectManager->create( \Magento\Catalog\Model\ResourceModel\Product::class ); + \Magento\CatalogImportExport\Model\Import\Product\Type\AbstractType::$commonAttributesCache = []; } protected function tearDown() diff --git a/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Export/ProductTest.php b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Export/ProductTest.php index dc9e440b045f86ad2e85de45124ac01881d3892c..9087aefa11e8320b7b1113770109904ffc3dcb6a 100644 --- a/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Export/ProductTest.php +++ b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Export/ProductTest.php @@ -7,6 +7,8 @@ namespace Magento\CatalogImportExport\Model\Export; /** * @magentoDataFixtureBeforeTransaction Magento/Catalog/_files/enable_reindex_schedule.php + * @magentoAppIsolation enabled + * @magentoDbIsolation enabled */ class ProductTest extends \PHPUnit_Framework_TestCase { @@ -66,6 +68,7 @@ class ProductTest extends \PHPUnit_Framework_TestCase /** * @magentoDataFixture Magento/CatalogImportExport/_files/product_export_data.php + * @magentoDbIsolationEnabled */ public function testExport() { @@ -88,6 +91,7 @@ class ProductTest extends \PHPUnit_Framework_TestCase /** * @magentoDataFixture Magento/CatalogImportExport/_files/product_export_with_product_links_data.php + * @magentoDbIsolationEnabled */ public function testExportWithProductLinks() { @@ -101,7 +105,9 @@ class ProductTest extends \PHPUnit_Framework_TestCase /** * Verify that all stock item attribute values are exported (aren't equal to empty string) - * + * + * @magentoAppIsolation enabled + * @magentoDbIsolation enabled * @covers \Magento\CatalogImportExport\Model\Export\Product::export * @magentoDataFixture Magento/CatalogImportExport/_files/product_export_data.php */ @@ -163,7 +169,7 @@ class ProductTest extends \PHPUnit_Framework_TestCase /** * Verifies if exception processing works properly - * + * @magentoDbIsolation enabled * @magentoDataFixture Magento/CatalogImportExport/_files/product_export_data.php */ public function testExceptionInGetExportData() diff --git a/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/ProductTest.php b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/ProductTest.php index c0e45410952717c783686e05b75d54eabdc6a295..ff21749ccf372d3dae8d07d64406b21e87465b49 100644 --- a/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/ProductTest.php +++ b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/ProductTest.php @@ -24,7 +24,8 @@ use Magento\CatalogImportExport\Model\Import\Product\RowValidatorInterface; /** * Class ProductTest - * + * @magentoAppIsolation enabled + * @magentoDbIsolation enabled * @magentoDataFixtureBeforeTransaction Magento/Catalog/_files/enable_reindex_schedule.php * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ diff --git a/dev/tests/integration/testsuite/Magento/CatalogImportExport/_files/product_export_data.php b/dev/tests/integration/testsuite/Magento/CatalogImportExport/_files/product_export_data.php index ffee568b0622fa8ef3f5af185e24805367ee9203..f7fd7cec31996908d0a6ed5b76ad5d6ada302381 100644 --- a/dev/tests/integration/testsuite/Magento/CatalogImportExport/_files/product_export_data.php +++ b/dev/tests/integration/testsuite/Magento/CatalogImportExport/_files/product_export_data.php @@ -3,12 +3,13 @@ * Copyright © 2016 Magento. All rights reserved. * See COPYING.txt for license details. */ - -\Magento\TestFramework\Helper\Bootstrap::getInstance()->reinitialize(); - +/** Create category */ require dirname(dirname(__DIR__)) . '/Catalog/_files/category.php'; +/** Create fixture store */ require dirname(dirname(__DIR__)) . '/Store/_files/second_store.php'; +/** Create product with multiselect attribute and values */ require dirname(dirname(__DIR__)) . '/Catalog/_files/products_with_multiselect_attribute.php'; +/** Create dummy text attribute */ require dirname(dirname(__DIR__)) . '/Catalog/_files/product_text_attribute.php'; $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); diff --git a/dev/tests/integration/testsuite/Magento/CatalogImportExport/_files/product_export_data_rollback.php b/dev/tests/integration/testsuite/Magento/CatalogImportExport/_files/product_export_data_rollback.php new file mode 100644 index 0000000000000000000000000000000000000000..fdb65e731f8255aba9c26c750f1d74760ea6fc59 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/CatalogImportExport/_files/product_export_data_rollback.php @@ -0,0 +1,10 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +/** Delete all products */ +require dirname(dirname(__DIR__)) . '/Catalog/_files/products_with_multiselect_attribute_rollback.php'; +/** Delete text attribute */ +require dirname(dirname(__DIR__)) . '/Catalog/_files/text_attribute_rollback.php'; diff --git a/dev/tests/integration/testsuite/Magento/CatalogImportExport/_files/product_export_with_product_links_data.php b/dev/tests/integration/testsuite/Magento/CatalogImportExport/_files/product_export_with_product_links_data.php index fcbf58a44e569aa80f2cfe94251ca7e1859a8483..bf5f4f96eed0221a6f1579508bfce5636caf7cf4 100644 --- a/dev/tests/integration/testsuite/Magento/CatalogImportExport/_files/product_export_with_product_links_data.php +++ b/dev/tests/integration/testsuite/Magento/CatalogImportExport/_files/product_export_with_product_links_data.php @@ -3,9 +3,11 @@ * Copyright © 2016 Magento. All rights reserved. * See COPYING.txt for license details. */ - +/** Create category */ require dirname(dirname(__DIR__)) . '/Catalog/_files/category.php'; +/** Create fixture store */ require dirname(dirname(__DIR__)) . '/Store/_files/second_store.php'; +/** Create product with mulselect attribute */ require dirname(dirname(__DIR__)) . '/Catalog/_files/products_with_multiselect_attribute.php'; $productModel = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create( diff --git a/dev/tests/integration/testsuite/Magento/CatalogImportExport/_files/product_export_with_product_links_data_rollback.php b/dev/tests/integration/testsuite/Magento/CatalogImportExport/_files/product_export_with_product_links_data_rollback.php new file mode 100644 index 0000000000000000000000000000000000000000..519568103b9dabb3bd6abf42b386ce6ebd5cc32d --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/CatalogImportExport/_files/product_export_with_product_links_data_rollback.php @@ -0,0 +1,12 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +/** Remove fixture category */ +require dirname(dirname(__DIR__)) . '/Catalog/_files/category_rollback.php'; +/** Remove fixture store */ +require dirname(dirname(__DIR__)) . '/Store/_files/second_store_rollback.php'; +/** Delete all products */ +require dirname(dirname(__DIR__)) . '/Catalog/_files/products_with_multiselect_attribute_rollback.php'; diff --git a/dev/tests/integration/testsuite/Magento/ConfigurableProduct/Model/Product/Type/Configurable/PriceTest.php b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/Model/Product/Type/Configurable/PriceTest.php index 6322a60cef8a5fda1b50e220b10de7c5385956d4..783baba407da5a3365a5c08e65ae78c35afef2e4 100644 --- a/dev/tests/integration/testsuite/Magento/ConfigurableProduct/Model/Product/Type/Configurable/PriceTest.php +++ b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/Model/Product/Type/Configurable/PriceTest.php @@ -80,6 +80,7 @@ class PriceTest extends \PHPUnit_Framework_TestCase } /** + * @magentoConfigFixture current_store tax/display/type 1 * @magentoDataFixture Magento/ConfigurableProduct/_files/tax_rule.php * @magentoDataFixture Magento/ConfigurableProduct/_files/product_configurable.php */ diff --git a/dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/configurable_attribute.php b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/configurable_attribute.php index 2ef7beb59838f0d052056d2a01932d9d60e1d473..b6fe9d7097e1648196b3b4260c443d019563c7f9 100644 --- a/dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/configurable_attribute.php +++ b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/configurable_attribute.php @@ -54,8 +54,9 @@ if (!$attribute->getId()) { ); $attributeRepository->save($attribute); + + /* Assign attribute to attribute set */ + $installer->addAttributeToGroup('catalog_product', 'Default', 'General', $attribute->getId()); } -/* Assign attribute to attribute set */ -$installer->addAttributeToGroup('catalog_product', 'Default', 'General', $attribute->getId()); $eavConfig->clear(); diff --git a/dev/tests/integration/testsuite/Magento/Customer/_files/customer_non_default_website_id.php b/dev/tests/integration/testsuite/Magento/Customer/_files/customer_non_default_website_id.php index 305a6e699125fae655dcf67b36b6ba8772f2a71e..79a2ff32eed54a8a9b3693732536074505b8458f 100644 --- a/dev/tests/integration/testsuite/Magento/Customer/_files/customer_non_default_website_id.php +++ b/dev/tests/integration/testsuite/Magento/Customer/_files/customer_non_default_website_id.php @@ -1,5 +1,7 @@ <?php /** + * Create customer and attach it to custom website with code newwebsite + * * Copyright © 2016 Magento. All rights reserved. * See COPYING.txt for license details. */ @@ -13,8 +15,10 @@ $website = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create(\ $website->setName('new Website')->setCode('newwebsite')->save(); $websiteId = $website->getId(); - -$customer = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create( +$storeManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager() + ->get(\Magento\Store\Model\StoreManager::class); +$storeManager->reinitStores(); +$customer = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create( \Magento\Customer\Model\Customer::class); /** @var Magento\Customer\Model\Customer $customer */ $customer->setWebsiteId( @@ -47,7 +51,7 @@ $customer->setWebsiteId( $customer->isObjectNew(true); /** @var \Magento\Customer\Model\Address $addressOne */ -$addressOne = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create( +$addressOne = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create( \Magento\Customer\Model\Address::class); $addressOneData = [ 'firstname' => 'Firstname', @@ -63,7 +67,7 @@ $addressOne->setData($addressOneData); $customer->addAddress($addressOne); /** @var \Magento\Customer\Model\Address $addressTwo */ -$addressTwo = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create( +$addressTwo = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create( \Magento\Customer\Model\Address::class); $addressTwoData = [ 'firstname' => 'test firstname', @@ -79,7 +83,7 @@ $addressTwo->setData($addressTwoData); $customer->addAddress($addressTwo); /** @var \Magento\Customer\Model\Address $addressThree */ -$addressThree = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create( +$addressThree = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create( \Magento\Customer\Model\Address::class); $addressThreeData = [ 'firstname' => 'removed firstname', diff --git a/dev/tests/integration/testsuite/Magento/Deploy/Console/Command/App/ApplicationDumpCommandTest.php b/dev/tests/integration/testsuite/Magento/Deploy/Console/Command/App/ApplicationDumpCommandTest.php new file mode 100644 index 0000000000000000000000000000000000000000..a229b64bb7dd10ef29acd5e824dfb5a9b28bfcc8 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Deploy/Console/Command/App/ApplicationDumpCommandTest.php @@ -0,0 +1,64 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Deploy\Console\Command\App; + +use Magento\Framework\App\DeploymentConfig; +use Magento\Framework\App\Filesystem\DirectoryList; +use Magento\Framework\App\ObjectManager; +use Magento\Framework\Config\File\ConfigFilePool; +use Magento\Framework\Filesystem\DriverPool; +use Magento\Framework\ObjectManagerInterface; +use Magento\TestFramework\Helper\Bootstrap; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; + +class ApplicationDumpCommandTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var ApplicationDumpCommand + */ + private $command; + + /** + * @var ObjectManagerInterface + */ + private $objectManager; + + public function setUp() + { + $this->command = Bootstrap::getObjectManager()->get(ApplicationDumpCommand::class); + $this->objectManager = Bootstrap::getObjectManager(); + } + + public function testExecute() + { + $inputMock = $this->getMock(InputInterface::class); + $outputMock = $this->getMock(OutputInterface::class); + $outputMock->expects($this->once()) + ->method('writeln') + ->with('<info>Done.</info>'); + $this->assertEquals(0, $this->command->run($inputMock, $outputMock)); + } + + public function tearDown() + { + /** @var ConfigFilePool $configFilePool */ + $configFilePool = $this->objectManager->get(ConfigFilePool::class); + $filePool = $configFilePool->getInitialFilePools(); + $file = $filePool[ConfigFilePool::LOCAL][ConfigFilePool::APP_CONFIG]; + /** @var DirectoryList $dirList */ + $dirList = $this->objectManager->get(DirectoryList::class); + $path = $dirList->getPath(DirectoryList::CONFIG); + $driverPool = $this->objectManager->get(DriverPool::class); + $fileDriver = $driverPool->getDriver(DriverPool::FILE); + if ($fileDriver->isExists($path . '/' . $file)) { + unlink($path . '/' . $file); + } + /** @var DeploymentConfig $deploymentConfig */ + $deploymentConfig = $this->objectManager->get(DeploymentConfig::class); + $deploymentConfig->resetData(); + } +} diff --git a/dev/tests/integration/testsuite/Magento/Email/Model/Template/FilterTest.php b/dev/tests/integration/testsuite/Magento/Email/Model/Template/FilterTest.php index be9c2afe32f42cc0da7ebc591fc144cae8ad39e2..5144c31bfd1486ffb0f0be013cdc98d992e57900 100644 --- a/dev/tests/integration/testsuite/Magento/Email/Model/Template/FilterTest.php +++ b/dev/tests/integration/testsuite/Magento/Email/Model/Template/FilterTest.php @@ -12,6 +12,7 @@ use Magento\Framework\Phrase; use Magento\Setup\Module\I18n\Locale; /** + * @magentoAppIsolation enabled * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class FilterTest extends \PHPUnit_Framework_TestCase diff --git a/dev/tests/integration/testsuite/Magento/Framework/App/Config/DataTest.php b/dev/tests/integration/testsuite/Magento/Framework/App/Config/DataTest.php index 25187acef3950ead32082e338c9bdf06f402ece7..5a5a6fa0cf99c345c92dc28bed32d84d79d342af 100644 --- a/dev/tests/integration/testsuite/Magento/Framework/App/Config/DataTest.php +++ b/dev/tests/integration/testsuite/Magento/Framework/App/Config/DataTest.php @@ -5,6 +5,9 @@ */ namespace Magento\Framework\App\Config; +use Magento\Framework\App\Config; +use Magento\Framework\App\ObjectManager; + class DataTest extends \PHPUnit_Framework_TestCase { const SAMPLE_CONFIG_PATH = 'web/unsecure/base_url'; @@ -45,6 +48,8 @@ class DataTest extends \PHPUnit_Framework_TestCase \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get(\Magento\Framework\App\CacheInterface::class) ->clean([\Magento\Framework\App\Config::CACHE_TAG]); \Magento\TestFramework\Helper\Bootstrap::getInstance()->reinitialize(); + $appConfig = ObjectManager::getInstance()->get(Config::class); + $appConfig->clean(); } protected function setUp() diff --git a/dev/tests/integration/testsuite/Magento/Framework/Search/_files/filterable_attribute_rollback.php b/dev/tests/integration/testsuite/Magento/Framework/Search/_files/filterable_attribute_rollback.php index 9498a4251be1274d6e92313a32c90825398ac053..214f2b1dda5de0ee5c0be976664ef76730f6e189 100644 --- a/dev/tests/integration/testsuite/Magento/Framework/Search/_files/filterable_attribute_rollback.php +++ b/dev/tests/integration/testsuite/Magento/Framework/Search/_files/filterable_attribute_rollback.php @@ -3,7 +3,6 @@ * Copyright © 2016 Magento. All rights reserved. * See COPYING.txt for license details. */ - /* Create attribute */ /** @var $installer \Magento\Catalog\Setup\CategorySetup */ $installer = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create( diff --git a/dev/tests/integration/testsuite/Magento/Framework/TranslateCachingTest.php b/dev/tests/integration/testsuite/Magento/Framework/TranslateCachingTest.php index fbbc2ffc7bd1bdeee03e9f612e6bc2a3ee6fc3a2..e2b1982ba534c9c6ac84e18fc25f50ec4c6cd661 100644 --- a/dev/tests/integration/testsuite/Magento/Framework/TranslateCachingTest.php +++ b/dev/tests/integration/testsuite/Magento/Framework/TranslateCachingTest.php @@ -6,8 +6,12 @@ namespace Magento\Framework; use Magento\TestFramework\Helper\Bootstrap; -use Magento\Framework\Phrase; +/** + * Class TranslateCachingTest + * @package Magento\Framework + * @magentoAppIsolation enabled + */ class TranslateCachingTest extends \PHPUnit_Framework_TestCase { /** diff --git a/dev/tests/integration/testsuite/Magento/Framework/TranslateTest.php b/dev/tests/integration/testsuite/Magento/Framework/TranslateTest.php index 2af602ff91850720845b73f04cd74b6c610714a0..0b3566a129b7f3064c1b4b86b22328ef1ee51204 100644 --- a/dev/tests/integration/testsuite/Magento/Framework/TranslateTest.php +++ b/dev/tests/integration/testsuite/Magento/Framework/TranslateTest.php @@ -8,6 +8,7 @@ namespace Magento\Framework; use Magento\TestFramework\Helper\Bootstrap; /** + * @magentoAppIsolation enabled * @magentoCache all disabled * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ diff --git a/dev/tests/integration/testsuite/Magento/Sales/Model/Order/ShipmentTest.php b/dev/tests/integration/testsuite/Magento/Sales/Model/Order/ShipmentTest.php index 13d7636b0cbac8721a8c3e0757137f86f1533bd0..fe12480e25879014edd75f47b90876c4e53fddeb 100644 --- a/dev/tests/integration/testsuite/Magento/Sales/Model/Order/ShipmentTest.php +++ b/dev/tests/integration/testsuite/Magento/Sales/Model/Order/ShipmentTest.php @@ -5,6 +5,11 @@ */ namespace Magento\Sales\Model\Order; +/** + * Class ShipmentTest + * @magentoAppIsolation enabled + * @package Magento\Sales\Model\Order + */ class ShipmentTest extends \PHPUnit_Framework_TestCase { /** diff --git a/dev/tests/integration/testsuite/Magento/Store/Controller/Store/SwitchActionTest.php b/dev/tests/integration/testsuite/Magento/Store/Controller/Store/SwitchActionTest.php index cdf0a38d249150a9454d580353c938b26637103e..155431ba67f1e2cba89b1cb973e17776aed666ef 100644 --- a/dev/tests/integration/testsuite/Magento/Store/Controller/Store/SwitchActionTest.php +++ b/dev/tests/integration/testsuite/Magento/Store/Controller/Store/SwitchActionTest.php @@ -21,7 +21,7 @@ class SwitchActionTest extends \Magento\TestFramework\TestCase\AbstractControlle */ public function testExecuteWithCustomDefaultStore() { - + \Magento\TestFramework\Helper\Bootstrap::getInstance()->reinitialize(); $defaultStoreCode = 'default'; $modifiedDefaultCode = 'modified_default_code'; $this->changeStoreCode($defaultStoreCode, $modifiedDefaultCode); diff --git a/dev/tests/integration/testsuite/Magento/Store/_files/scope.config.fixture.php b/dev/tests/integration/testsuite/Magento/Store/_files/scope.config.fixture.php new file mode 100644 index 0000000000000000000000000000000000000000..1bf8fa811183391f3450c185bee4f25579dfbf21 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Store/_files/scope.config.fixture.php @@ -0,0 +1,11 @@ +<?php +/** + * Fixture which retrieve dummy scopes + * + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +return [ + +]; diff --git a/dev/tests/integration/testsuite/Magento/Store/_files/second_store.php b/dev/tests/integration/testsuite/Magento/Store/_files/second_store.php index b75c491b36a0e9c013707aec4155f7454eb5a8ba..91b30888194f44a007528ddc557784e58cab5fd6 100644 --- a/dev/tests/integration/testsuite/Magento/Store/_files/second_store.php +++ b/dev/tests/integration/testsuite/Magento/Store/_files/second_store.php @@ -1,5 +1,7 @@ <?php /** + * Create fixture store + * * Copyright © 2016 Magento. All rights reserved. * See COPYING.txt for license details. */ @@ -26,9 +28,9 @@ if (!$store->load('fixture_second_store', 'code')->getId()) { 1 ); $store->save(); - - /* Refresh stores memory cache */ - \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get( - \Magento\Store\Model\StoreManagerInterface::class - )->reinitStores(); } + +/* Refresh stores memory cache */ +\Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get( + \Magento\Store\Model\StoreManagerInterface::class +)->reinitStores(); diff --git a/dev/tests/integration/testsuite/Magento/Store/_files/store.php b/dev/tests/integration/testsuite/Magento/Store/_files/store.php index 9bb761f0b6a136c5b01c50ba2c5a1942716db18e..35ade6fe3a4358c865196157e041d5cd465f6388 100644 --- a/dev/tests/integration/testsuite/Magento/Store/_files/store.php +++ b/dev/tests/integration/testsuite/Magento/Store/_files/store.php @@ -1,5 +1,7 @@ <?php /** + * Create fixture store with code test + * * Copyright © 2016 Magento. All rights reserved. * See COPYING.txt for license details. */ @@ -19,3 +21,6 @@ if (!$store->load('test', 'code')->getId()) { ); $store->save(); } +$objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); +/* Refresh stores memory cache */ +$objectManager->get('Magento\Store\Model\StoreManagerInterface')->reinitStores(); diff --git a/dev/tests/integration/testsuite/Magento/Store/_files/website.php b/dev/tests/integration/testsuite/Magento/Store/_files/website.php index 4e1f03fcadb58acea0d69fb9cb195437f9355030..dfe04879548ccbb88a7db58e762f8aab1e05b969 100644 --- a/dev/tests/integration/testsuite/Magento/Store/_files/website.php +++ b/dev/tests/integration/testsuite/Magento/Store/_files/website.php @@ -8,3 +8,7 @@ $website = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create(\Magento\Store\Model\Website::class); $website->setData(['code' => 'test', 'name' => 'Test Website', 'default_group_id' => '1', 'is_default' => '0']); $website->save(); + +$objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); +/* Refresh stores memory cache */ +$objectManager->get('Magento\Store\Model\StoreManagerInterface')->reinitStores(); diff --git a/dev/tests/integration/testsuite/Magento/UrlRewrite/Block/Edit/FormTest.php b/dev/tests/integration/testsuite/Magento/UrlRewrite/Block/Edit/FormTest.php index 54f4a030992803ff60cdd9cdffacc5879056069b..8e820c1d22c10a6c055cbe45f950465ba40cfe1f 100644 --- a/dev/tests/integration/testsuite/Magento/UrlRewrite/Block/Edit/FormTest.php +++ b/dev/tests/integration/testsuite/Magento/UrlRewrite/Block/Edit/FormTest.php @@ -146,6 +146,7 @@ class FormTest extends \PHPUnit_Framework_TestCase * Test fields disabled status * @dataProvider fieldsStateDataProvider * @magentoAppIsolation enabled + * @magentoConfigFixture current_store general/single_store_mode/enabled 0 */ public function testReadonlyFields($urlRewrite, $fields) { diff --git a/dev/tests/integration/testsuite/Magento/User/Helper/DataTest.php b/dev/tests/integration/testsuite/Magento/User/Helper/DataTest.php index 4c0a81b41efd42f05c1fe5b83cbbb36ede2cedee..c197f3f86d22f1dbe4aa5d57051f945b5668045c 100644 --- a/dev/tests/integration/testsuite/Magento/User/Helper/DataTest.php +++ b/dev/tests/integration/testsuite/Magento/User/Helper/DataTest.php @@ -42,7 +42,7 @@ class DataTest extends \PHPUnit_Framework_TestCase { /** @var $configModel \Magento\Backend\App\ConfigInterface */ $configModel = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get( - \Magento\Backend\App\ConfigInterface::class + \Magento\Framework\App\Config\MutableScopeConfigInterface::class ); $this->assertEquals( 2, diff --git a/dev/tests/static/testsuite/Magento/Test/Legacy/ModuleDBChangeTest.php b/dev/tests/static/testsuite/Magento/Test/Legacy/ModuleDBChangeTest.php index 2f3d312fb41ffba1287bafd324a64ac751316d5c..5c8c2fdf0501699768457b3b888c217a1301f6c3 100644 --- a/dev/tests/static/testsuite/Magento/Test/Legacy/ModuleDBChangeTest.php +++ b/dev/tests/static/testsuite/Magento/Test/Legacy/ModuleDBChangeTest.php @@ -15,12 +15,7 @@ class ModuleDBChangeTest extends \PHPUnit_Framework_TestCase /** * @var string */ - private static $branchesFilesPattern = __DIR__ . '/../_files/branches*'; - - /** - * @var string - */ - private static $changedFilesPattern = __DIR__ . '/../_files/changed_files*'; + protected static $changedFilesPattern = __DIR__ . '/../_files/changed_files*'; /** * @var string @@ -37,24 +32,6 @@ class ModuleDBChangeTest extends \PHPUnit_Framework_TestCase */ public static function setUpBeforeClass() { - foreach (glob(self::$branchesFilesPattern) as $branchesFile) { - //get the current branchname from the first line - $branchName = trim(file($branchesFile)[0]); - if ($branchName === 'develop') { - self::$actualBranch = true; - } else { - //get current minor branch name - preg_match('|^(\d+\.\d+)|', $branchName, $minorBranch); - $branchName = $minorBranch[0]; - - //get all version branches - preg_match_all('|^(\d+\.\d+)|m', file_get_contents($branchesFile), $matches); - - //check is this a latest release branch - self::$actualBranch = ($branchName == max($matches[0])); - } - } - foreach (glob(self::$changedFilesPattern) as $changedFile) { self::$changedFileList .= file_get_contents($changedFile) . PHP_EOL; } diff --git a/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_classes.php b/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_classes.php index f5ae2f2dfd67b5628326149d6d28f055c9d2485f..2a0c4f23bf3793978b06c3cb26e8706554d0ad51 100755 --- a/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_classes.php +++ b/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_classes.php @@ -3826,8 +3826,8 @@ return [ ], ['Magento\Setup\Model\Deployer', 'Magento\Deploy\Model\Deployer'], [ - 'Magento\Setup\Console\Command\DeployStaticContentCommand', - 'Magento\Deploy\Console\Command\DeployStaticContentCommand' + 'Magento\Deploy\Console\Command\DeployStaticContentCommand', + 'Magento\Setup\Console\Command\DeployStaticContentCommand' ], [ 'Magento\Setup\Test\Unit\Console\Command\DeployStaticContentCommandTest', diff --git a/lib/internal/Magento/Framework/App/Config.php b/lib/internal/Magento/Framework/App/Config.php index e8aaaa0bbe57094d088e0df9cf81711d251b8cd6..d25739c5d1bf3238745d5016d28f5cae95459bfd 100644 --- a/lib/internal/Magento/Framework/App/Config.php +++ b/lib/internal/Magento/Framework/App/Config.php @@ -7,9 +7,14 @@ */ namespace Magento\Framework\App; +use Magento\Framework\App\Config\ScopeCodeResolver; use Magento\Framework\App\Config\ScopeConfigInterface; +use Magento\Framework\App\Config\ConfigTypeInterface; -class Config implements \Magento\Framework\App\Config\ScopeConfigInterface +/** + * Class Config + */ +class Config implements ScopeConfigInterface { /** * Config cache tag @@ -17,16 +22,27 @@ class Config implements \Magento\Framework\App\Config\ScopeConfigInterface const CACHE_TAG = 'CONFIG'; /** - * @var \Magento\Framework\App\Config\ScopePool + * @var ScopeCodeResolver */ - protected $_scopePool; + private $scopeCodeResolver; /** - * @param \Magento\Framework\App\Config\ScopePool $scopePool + * @var ConfigTypeInterface[] */ - public function __construct(\Magento\Framework\App\Config\ScopePool $scopePool) - { - $this->_scopePool = $scopePool; + private $types; + + /** + * Config constructor. + * + * @param ScopeCodeResolver $scopeCodeResolver + * @param array $types + */ + public function __construct( + ScopeCodeResolver $scopeCodeResolver, + array $types = [] + ) { + $this->scopeCodeResolver = $scopeCodeResolver; + $this->types = $types; } /** @@ -42,7 +58,26 @@ class Config implements \Magento\Framework\App\Config\ScopeConfigInterface $scope = ScopeConfigInterface::SCOPE_TYPE_DEFAULT, $scopeCode = null ) { - return $this->_scopePool->getScope($scope, $scopeCode)->getValue($path); + if ($scope === 'store') { + $scope = 'stores'; + } elseif ($scope === 'website') { + $scope = 'websites'; + } + $configPath = $scope; + if ($scope !== 'default') { + if (is_numeric($scopeCode) || $scopeCode === null) { + $scopeCode = $this->scopeCodeResolver->resolve($scope, $scopeCode); + } else if ($scopeCode instanceof \Magento\Framework\App\ScopeInterface) { + $scopeCode = $scopeCode->getCode(); + } + if ($scopeCode) { + $configPath .= '/' . $scopeCode; + } + } + if ($path) { + $configPath .= '/' . $path; + } + return $this->get('system', $configPath); } /** @@ -55,6 +90,45 @@ class Config implements \Magento\Framework\App\Config\ScopeConfigInterface */ public function isSetFlag($path, $scope = ScopeConfigInterface::SCOPE_TYPE_DEFAULT, $scopeCode = null) { - return (bool) $this->getValue($path, $scope, $scopeCode); + return !!$this->getValue($path, $scope, $scopeCode); + } + + /** + * Invalidate cache by type + * + * @return void + */ + public function clean() + { + foreach ($this->types as $type) { + $type->clean(); + } + } + + /** + * Retrieve configuration. + * + * ('modules') - modules status configuration data + * ('scopes', 'websites/base') - base website data + * ('scopes', 'stores/default') - default store data + * + * ('system', 'default/web/seo/use_rewrites') - default system configuration data + * ('system', 'websites/base/web/seo/use_rewrites') - 'base' website system configuration data + * + * ('i18n', 'default/en_US') - translations for default store and 'en_US' locale + * + * @param string $configType + * @param string|null $path + * @param mixed|null $default + * @return array + */ + public function get($configType, $path = '', $default = null) + { + $result = null; + if (isset($this->types[$configType])) { + $result = $this->types[$configType]->get($path); + } + + return $result !== null ? $result : $default; } } diff --git a/lib/internal/Magento/Framework/App/Config/ConfigSourceAggregated.php b/lib/internal/Magento/Framework/App/Config/ConfigSourceAggregated.php new file mode 100644 index 0000000000000000000000000000000000000000..c1a9259a4329b4ce2998b53f293ed7bf0301deb5 --- /dev/null +++ b/lib/internal/Magento/Framework/App/Config/ConfigSourceAggregated.php @@ -0,0 +1,56 @@ +<?php +/** + * Application configuration object. Used to access configuration when application is initialized and installed. + * + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Framework\App\Config; + +class ConfigSourceAggregated implements ConfigSourceInterface +{ + /** + * @var ConfigSourceInterface[] + */ + private $sources; + + /** + * ConfigSourceAggregated constructor. + * + * @param array $sources + */ + public function __construct(array $sources = []) + { + $this->sources = $sources; + } + + /** + * Retrieve aggregated configuration from all available sources. + * + * @param string $path + * @return array + */ + public function get($path = '') + { + $this->sortSources(); + $data = []; + foreach ($this->sources as $sourceConfig) { + /** @var ConfigSourceInterface $source */ + $source = $sourceConfig['source']; + $data = array_replace_recursive($data, $source->get($path)); + } + return $data; + } + + /** + * Sort sources + * + * @return void + */ + private function sortSources() + { + uasort($this->sources, function ($firstItem, $secondItem) { + return $firstItem['sortOrder'] > $secondItem['sortOrder']; + }); + } +} diff --git a/lib/internal/Magento/Framework/App/Config/ConfigSourceInterface.php b/lib/internal/Magento/Framework/App/Config/ConfigSourceInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..c070125de9f35d5119b9d4df5ddf250ed09a4ca4 --- /dev/null +++ b/lib/internal/Magento/Framework/App/Config/ConfigSourceInterface.php @@ -0,0 +1,22 @@ +<?php +/** + * Provide access to data. Each Source can be responsible for each storage, where config data can be placed + * + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Framework\App\Config; + +/** + * Interface ConfigSourceInterface + */ +interface ConfigSourceInterface +{ + /** + * Retrieve configuration raw data array. + * + * @param string $path + * @return array + */ + public function get($path = ''); +} diff --git a/lib/internal/Magento/Framework/App/Config/ConfigTypeInterface.php b/lib/internal/Magento/Framework/App/Config/ConfigTypeInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..81dce57e314786144fa53a8b9bc31bb79ebbc9bb --- /dev/null +++ b/lib/internal/Magento/Framework/App/Config/ConfigTypeInterface.php @@ -0,0 +1,27 @@ +<?php +/** + * Application configuration object. Used to access configuration when application is initialized and installed. + * + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Framework\App\Config; + +/** + * Interface ConfigTypeInterface + */ +interface ConfigTypeInterface +{ + /** + * Retrieve configuration raw data array. + * + * @param string $path + * @return array + */ + public function get($path = ''); + + /** + * @return void + */ + public function clean(); +} diff --git a/lib/internal/Magento/Framework/App/Config/InitialConfigSource.php b/lib/internal/Magento/Framework/App/Config/InitialConfigSource.php new file mode 100644 index 0000000000000000000000000000000000000000..1f75bef92914a348e28317bf6b81739eae5c145d --- /dev/null +++ b/lib/internal/Magento/Framework/App/Config/InitialConfigSource.php @@ -0,0 +1,56 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Framework\App\Config; + +use Magento\Framework\App\DeploymentConfig\Reader; +use Magento\Framework\DataObject; + +/** + * Responsible for reading sources from files: config.dist.php, config.local.php, config.php + */ +class InitialConfigSource implements ConfigSourceInterface +{ + /** + * @var Reader + */ + private $reader; + + /** + * @var string + */ + private $configType; + + /** + * @var string + */ + private $fileKey; + + /** + * DataProvider constructor. + * + * @param Reader $reader + * @param string $configType + * @param string $fileKey + */ + public function __construct(Reader $reader, $configType, $fileKey) + { + $this->reader = $reader; + $this->configType = $configType; + $this->fileKey = $fileKey; + } + + /** + * @inheritdoc + */ + public function get($path = '') + { + $data = new DataObject($this->reader->load($this->fileKey)); + if ($path !== '' && $path !== null) { + $path = '/' . $path; + } + return $data->getData($this->configType . $path) ?: []; + } +} diff --git a/lib/internal/Magento/Framework/App/Config/MetadataConfigTypeProcessor.php b/lib/internal/Magento/Framework/App/Config/MetadataConfigTypeProcessor.php new file mode 100644 index 0000000000000000000000000000000000000000..04acde7950c136f070b413c198b192a5417744b7 --- /dev/null +++ b/lib/internal/Magento/Framework/App/Config/MetadataConfigTypeProcessor.php @@ -0,0 +1,116 @@ +<?php +/** + * Configuration metadata processor + * + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Framework\App\Config; + +use Magento\Framework\App\Config\Spi\PostProcessorInterface; + +class MetadataConfigTypeProcessor implements PostProcessorInterface +{ + /** + * @var \Magento\Framework\App\Config\Data\ProcessorFactory + */ + protected $_processorFactory; + + /** + * @var array + */ + protected $_metadata = []; + + /** + * @param \Magento\Framework\App\Config\Data\ProcessorFactory $processorFactory + * @param Initial $initialConfig + */ + public function __construct( + \Magento\Framework\App\Config\Data\ProcessorFactory $processorFactory, + Initial $initialConfig + ) { + $this->_processorFactory = $processorFactory; + $this->_metadata = $initialConfig->getMetadata(); + } + + /** + * Retrieve array value by path + * + * @param array $data + * @param string $path + * @return string|null + */ + protected function _getValue(array $data, $path) + { + $keys = explode('/', $path); + foreach ($keys as $key) { + if (is_array($data) && array_key_exists($key, $data)) { + $data = $data[$key]; + } else { + return null; + } + } + return $data; + } + + /** + * Set array value by path + * + * @param array &$container + * @param string $path + * @param string $value + * @return void + */ + protected function _setValue(array &$container, $path, $value) + { + $segments = explode('/', $path); + $currentPointer = & $container; + foreach ($segments as $segment) { + if (!isset($currentPointer[$segment])) { + $currentPointer[$segment] = []; + } + $currentPointer = & $currentPointer[$segment]; + } + $currentPointer = $value; + } + + /** + * Process data by sections: stores, default, websites and by scope codes + * + * @param array $data + * @return array + */ + private function processScopeData(array $data) + { + foreach ($this->_metadata as $path => $metadata) { + /** @var \Magento\Framework\App\Config\Data\ProcessorInterface $processor */ + $processor = $this->_processorFactory->get($metadata['backendModel']); + $value = $processor->processValue($this->_getValue($data, $path)); + $this->_setValue($data, $path, $value); + } + + return $data; + } + + /** + * Process config data + * + * @param array $data + * @return array + */ + public function process(array $rawData) + { + $processedData = []; + foreach ($rawData as $scope => $scopeData) { + if ($scope == ScopeConfigInterface::SCOPE_TYPE_DEFAULT) { + $processedData[ScopeConfigInterface::SCOPE_TYPE_DEFAULT] = $this->processScopeData($scopeData); + } else { + foreach ($scopeData as $scopeCode => $data) { + $processedData[$scope][$scopeCode] = $this->processScopeData($data); + } + } + } + + return $processedData; + } +} diff --git a/lib/internal/Magento/Framework/App/Config/PostProcessorComposite.php b/lib/internal/Magento/Framework/App/Config/PostProcessorComposite.php new file mode 100644 index 0000000000000000000000000000000000000000..a008b1abd0595bf163c20563c822484d9076d3b5 --- /dev/null +++ b/lib/internal/Magento/Framework/App/Config/PostProcessorComposite.php @@ -0,0 +1,39 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Framework\App\Config; + +use Magento\Framework\App\Config\Spi\PostProcessorInterface; + +/** + * @inheritdoc + * @package Magento\Framework\App\Config + */ +class PostProcessorComposite implements PostProcessorInterface +{ + /** @var PostProcessorInterface[] */ + private $processors; + + /** + * @param array $processors + */ + public function __construct(array $processors = []) + { + $this->processors = $processors; + } + + /** + * @param array $config + * @return array + */ + public function process(array $config) + { + foreach ($this->processors as $processor) { + $config = $processor->process($config); + } + + return $config; + } +} diff --git a/lib/internal/Magento/Framework/App/Config/Reader/Source/SourceInterface.php b/lib/internal/Magento/Framework/App/Config/Reader/Source/SourceInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..2f1061fb7b6bdb5533929a9ac477ab695491de29 --- /dev/null +++ b/lib/internal/Magento/Framework/App/Config/Reader/Source/SourceInterface.php @@ -0,0 +1,22 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Framework\App\Config\Reader\Source; + +/** + * Provide access to data. Each Source can be responsible for each storage, where config data can be placed + * + * @package Magento\Framework\App\Config\Reader\Source + */ +interface SourceInterface +{ + /** + * Retrieve config by scope + * + * @param string|null $scopeCode + * @return array + */ + public function get($scopeCode = null); +} diff --git a/lib/internal/Magento/Framework/App/Config/Scope/ReaderPoolInterface.php b/lib/internal/Magento/Framework/App/Config/Scope/ReaderPoolInterface.php deleted file mode 100644 index 9c2b66dad2860156393bfe5f02f5512850f067c8..0000000000000000000000000000000000000000 --- a/lib/internal/Magento/Framework/App/Config/Scope/ReaderPoolInterface.php +++ /dev/null @@ -1,17 +0,0 @@ -<?php -/** - * Copyright © 2016 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Framework\App\Config\Scope; - -interface ReaderPoolInterface -{ - /** - * Retrieve reader by scope - * - * @param string $scopeType - * @return ReaderInterface|null - */ - public function getReader($scopeType); -} diff --git a/lib/internal/Magento/Framework/App/Config/ScopeCodeResolver.php b/lib/internal/Magento/Framework/App/Config/ScopeCodeResolver.php new file mode 100644 index 0000000000000000000000000000000000000000..ef7da5c94c1e25e061909fffa692ecfb0c728fd6 --- /dev/null +++ b/lib/internal/Magento/Framework/App/Config/ScopeCodeResolver.php @@ -0,0 +1,61 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Framework\App\Config; + +use Magento\Framework\App\ScopeResolverPool; + +/** + * Class for resolving scope code + */ +class ScopeCodeResolver +{ + /** + * @var ScopeResolverPool + */ + private $scopeResolverPool; + + /** + * @var array + */ + private $resolvedScopeCodes = []; + + /** + * @param ScopeResolverPool $scopeResolverPool + */ + public function __construct(ScopeResolverPool $scopeResolverPool) + { + $this->scopeResolverPool = $scopeResolverPool; + } + + /** + * Resolve scope code + * + * @param string $scopeType + * @param string $scopeCode + * @return string + */ + public function resolve($scopeType, $scopeCode) + { + if (isset($this->resolvedScopeCodes[$scopeType][$scopeCode])) { + return $this->resolvedScopeCodes[$scopeType][$scopeCode]; + } + if (($scopeCode === null || is_numeric($scopeCode)) + && $scopeType !== ScopeConfigInterface::SCOPE_TYPE_DEFAULT + ) { + $scopeResolver = $this->scopeResolverPool->get($scopeType); + $resolverScopeCode = $scopeResolver->getScope($scopeCode); + } else { + $resolverScopeCode = $scopeCode; + } + + if ($resolverScopeCode instanceof \Magento\Framework\App\ScopeInterface) { + $resolverScopeCode = $resolverScopeCode->getCode(); + } + + $this->resolvedScopeCodes[$scopeType][$scopeCode] = $resolverScopeCode; + return $resolverScopeCode; + } +} diff --git a/lib/internal/Magento/Framework/App/Config/ScopePool.php b/lib/internal/Magento/Framework/App/Config/ScopePool.php deleted file mode 100644 index 9e6a47d918f7602cd2e2b1d50286eb82f3f5cca6..0000000000000000000000000000000000000000 --- a/lib/internal/Magento/Framework/App/Config/ScopePool.php +++ /dev/null @@ -1,156 +0,0 @@ -<?php -/** - * Copyright © 2016 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Framework\App\Config; - -use Magento\Framework\App\RequestInterface; - -/** - * @SuppressWarnings(PHPMD.CouplingBetweenObjects) - */ -class ScopePool -{ - const CACHE_TAG = 'config_scopes'; - - /** - * @var \Magento\Framework\App\Config\Scope\ReaderPoolInterface - */ - protected $_readerPool; - - /** - * @var DataFactory - */ - protected $_dataFactory; - - /** - * @var \Magento\Framework\Cache\FrontendInterface - */ - protected $_cache; - - /** - * @var string - */ - protected $_cacheId; - - /** - * @var DataInterface[] - */ - protected $_scopes = []; - - /** - * @var \Magento\Framework\App\ScopeResolverPool - */ - protected $_scopeResolverPool; - - /** - * @var RequestInterface - */ - private $request; - - /** - * @param \Magento\Framework\App\Config\Scope\ReaderPoolInterface $readerPool - * @param DataFactory $dataFactory - * @param \Magento\Framework\Cache\FrontendInterface $cache - * @param \Magento\Framework\App\ScopeResolverPool $scopeResolverPool - * @param string $cacheId - */ - public function __construct( - \Magento\Framework\App\Config\Scope\ReaderPoolInterface $readerPool, - DataFactory $dataFactory, - \Magento\Framework\Cache\FrontendInterface $cache, - \Magento\Framework\App\ScopeResolverPool $scopeResolverPool, - $cacheId = 'default_config_cache' - ) { - $this->_readerPool = $readerPool; - $this->_dataFactory = $dataFactory; - $this->_cache = $cache; - $this->_cacheId = $cacheId; - $this->_scopeResolverPool = $scopeResolverPool; - } - - /** - * @return RequestInterface - */ - private function getRequest() - { - if ($this->request === null) { - $this->request = \Magento\Framework\App\ObjectManager::getInstance()->get(RequestInterface::class); - } - return $this->request; - } - - /** - * Retrieve config section - * - * @param string $scopeType - * @param string|\Magento\Framework\DataObject|null $scopeCode - * @return \Magento\Framework\App\Config\DataInterface - */ - public function getScope($scopeType, $scopeCode = null) - { - $scopeCode = $this->_getScopeCode($scopeType, $scopeCode); - - $code = $scopeType . '|' . $scopeCode; - - if (!isset($this->_scopes[$code])) { - // Key by url to support dynamic {{base_url}} and port assignments - $host = $this->getRequest()->getHttpHost(); - $port = $this->getRequest()->getServer('SERVER_PORT'); - $path = $this->getRequest()->getBasePath(); - - $urlInfo = $host . $port . trim($path, '/'); - $cacheKey = $this->_cacheId . '|' . $code . '|' . $urlInfo; - $data = $this->_cache->load($cacheKey); - - if ($data) { - $data = unserialize($data); - } else { - $reader = $this->_readerPool->getReader($scopeType); - if ($scopeType === ScopeConfigInterface::SCOPE_TYPE_DEFAULT) { - $data = $reader->read(); - } else { - $data = $reader->read($scopeCode); - } - $this->_cache->save(serialize($data), $cacheKey, [self::CACHE_TAG]); - } - $this->_scopes[$code] = $this->_dataFactory->create(['data' => $data]); - } - return $this->_scopes[$code]; - } - - /** - * Clear cache of all scopes - * - * @return void - */ - public function clean() - { - $this->_scopes = []; - $this->_cache->clean(\Zend_Cache::CLEANING_MODE_MATCHING_TAG, [self::CACHE_TAG]); - } - - /** - * Retrieve scope code value - * - * @param string $scopeType - * @param string|\Magento\Framework\DataObject|null $scopeCode - * @return string - */ - protected function _getScopeCode($scopeType, $scopeCode) - { - if (($scopeCode === null || is_numeric($scopeCode)) - && $scopeType !== ScopeConfigInterface::SCOPE_TYPE_DEFAULT - ) { - $scopeResolver = $this->_scopeResolverPool->get($scopeType); - $scopeCode = $scopeResolver->getScope($scopeCode); - } - - if ($scopeCode instanceof \Magento\Framework\App\ScopeInterface) { - $scopeCode = $scopeCode->getCode(); - } - - return $scopeCode; - } -} diff --git a/lib/internal/Magento/Framework/App/Config/Spi/PostProcessorInterface.php b/lib/internal/Magento/Framework/App/Config/Spi/PostProcessorInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..53c348170761f448914a01447a028c766ec89f4b --- /dev/null +++ b/lib/internal/Magento/Framework/App/Config/Spi/PostProcessorInterface.php @@ -0,0 +1,27 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Framework\App\Config\Spi; + +use Magento\Framework\App\Config\ConfigTypeInterface; +use Magento\Framework\App\Config\Reader\Source\SourceInterface; + +/** + * Allows to use custom callbacks and functions after collecting config from all sources + * + * @see SourceInterface + * @see ConfigTypeInterface + * @package Magento\Framework\App\Config\Spi + */ +interface PostProcessorInterface +{ + /** + * Process config after reading and converting to appropriate format + * + * @param array $config + * @return array + */ + public function process(array $config); +} diff --git a/lib/internal/Magento/Framework/App/DeploymentConfig.php b/lib/internal/Magento/Framework/App/DeploymentConfig.php index d1a8b9018d55deb6b2d4d32031c168efec1d5f23..fa81b0fd8bc71f502bc1c0798a4698e33f667569 100644 --- a/lib/internal/Magento/Framework/App/DeploymentConfig.php +++ b/lib/internal/Magento/Framework/App/DeploymentConfig.php @@ -114,6 +114,17 @@ class DeploymentConfig $this->data = null; } + /** + * Check if data from deploy files is avaiable + * + * @return bool + */ + public function isDbAvailable() + { + $this->load(); + return isset($this->data['db']); + } + /** * Loads the configuration data * diff --git a/lib/internal/Magento/Framework/App/DeploymentConfig/Reader.php b/lib/internal/Magento/Framework/App/DeploymentConfig/Reader.php index 6a4af75512d4d993f99ac374b33c1b5dca7bc812..a1635fc4b2670d3749adbc8ac7bb88bab31904cf 100644 --- a/lib/internal/Magento/Framework/App/DeploymentConfig/Reader.php +++ b/lib/internal/Magento/Framework/App/DeploymentConfig/Reader.php @@ -11,7 +11,7 @@ use Magento\Framework\Config\File\ConfigFilePool; use Magento\Framework\Filesystem\DriverPool; /** - * Deployment configuration reader + * Deployment configuration reader from files: env.php, config.php (config.local.php, config.dist.php) */ class Reader { @@ -72,7 +72,26 @@ class Reader */ public function getFiles() { - return $this->files; + $path = $this->dirList->getPath(DirectoryList::CONFIG); + $fileDriver = $this->driverPool->getDriver(DriverPool::FILE); + $initialFilePools = $this->configFilePool->getInitialFilePools(); + + $files = []; + foreach ($this->files as $fileKey => $filePath) { + $files[$fileKey] = $filePath; + if (!$fileDriver->isExists($path . "/" . $filePath)) { + foreach ($initialFilePools as $initialFiles) { + if ( + isset($initialFiles[$fileKey]) + && $fileDriver->isExists($path . '/' . $initialFiles[$fileKey]) + ) { + $files[$fileKey] = $initialFiles[$fileKey]; + } + } + } + } + + return $files; } /** @@ -84,26 +103,19 @@ class Reader */ public function load($fileKey = null) { - $path = $this->dirList->getPath(DirectoryList::CONFIG); - $fileDriver = $this->driverPool->getDriver(DriverPool::FILE); - $result = []; if ($fileKey) { - $filePath = $path . '/' . $this->configFilePool->getPath($fileKey); - if ($fileDriver->isExists($filePath)) { - $result = include $filePath; - } + $pathConfig = $this->configFilePool->getPath($fileKey); + return $this->loadConfigFile($fileKey, $pathConfig); } else { $configFiles = $this->configFilePool->getPaths(); $allFilesData = []; $result = []; - foreach (array_keys($configFiles) as $fileKey) { - $configFile = $path . '/' . $this->configFilePool->getPath($fileKey); - if ($fileDriver->isExists($configFile)) { - $fileData = include $configFile; - } else { + foreach ($configFiles as $fileKey => $pathConfig) { + $fileData = $this->loadConfigFile($fileKey, $pathConfig); + if (!$fileData) { continue; } - $allFilesData[$configFile] = $fileData; + $allFilesData[$fileKey] = $fileData; if (!empty($fileData)) { $intersection = array_intersect_key($result, $fileData); if (!empty($intersection)) { @@ -116,8 +128,38 @@ class Reader $result = array_merge($result, $fileData); } } + return $result; } - return $result ?: []; + } + + /** + * @param string $fileKey + * @param string $pathConfig + * @param bool $ignoreInitialConfigFiles + * @return array + */ + public function loadConfigFile($fileKey, $pathConfig, $ignoreInitialConfigFiles = false) + { + $result = []; + $initialFilePools = $this->configFilePool->getInitialFilePools(); + $path = $this->dirList->getPath(DirectoryList::CONFIG); + $fileDriver = $this->driverPool->getDriver(DriverPool::FILE); + + if (!$ignoreInitialConfigFiles) { + foreach ($initialFilePools as $initialFiles) { + if (isset($initialFiles[$fileKey]) && $fileDriver->isExists($path . '/' . $initialFiles[$fileKey])) { + $fileBuffer = include $path . '/' . $initialFiles[$fileKey]; + $result = array_replace_recursive($result, $fileBuffer); + } + } + } + + if ($fileDriver->isExists($path . '/' . $pathConfig)) { + $fileBuffer = include $path . '/' . $pathConfig; + $result = array_replace_recursive($result, $fileBuffer); + } + + return $result; } /** diff --git a/lib/internal/Magento/Framework/App/DeploymentConfig/Writer.php b/lib/internal/Magento/Framework/App/DeploymentConfig/Writer.php index ac1e5f6ecf897c4769af5b3dbe97cfde4a9e9ee8..6cead0305a6c6ada899060a2a7debdbfe71f6f1a 100644 --- a/lib/internal/Magento/Framework/App/DeploymentConfig/Writer.php +++ b/lib/internal/Magento/Framework/App/DeploymentConfig/Writer.php @@ -14,7 +14,7 @@ use Magento\Framework\Config\File\ConfigFilePool; use Magento\Framework\Phrase; /** - * Deployment configuration writer + * Deployment configuration writer to files: env.php, config.php (config.local.php, config.dist.php) */ class Writer { @@ -93,17 +93,18 @@ class Writer * * @param array $data * @param bool $override + * @param string $pool * @return void + * @throws FileSystemException */ - public function saveConfig(array $data, $override = false) + public function saveConfig(array $data, $override = false, $pool = null) { - $paths = $this->configFilePool->getPaths(); - foreach ($data as $fileKey => $config) { - if (isset($paths[$fileKey])) { + $paths = $pool ? $this->configFilePool->getPathsByPool($pool) : $this->configFilePool->getPaths(); - if ($this->filesystem->getDirectoryWrite(DirectoryList::CONFIG)->isExist($paths[$fileKey])) { - $currentData = $this->reader->load($fileKey); + if (isset($paths[$fileKey])) { + $currentData = $this->reader->loadConfigFile($fileKey, $paths[$fileKey], true); + if ($currentData) { if ($override) { $config = array_merge($currentData, $config); } else { @@ -113,7 +114,8 @@ class Writer $contents = $this->formatter->format($config); try { - $this->filesystem->getDirectoryWrite(DirectoryList::CONFIG)->writeFile($paths[$fileKey], $contents); + $writeFilePath = $paths[$fileKey]; + $this->filesystem->getDirectoryWrite(DirectoryList::CONFIG)->writeFile($writeFilePath, $contents); } catch (FileSystemException $e) { throw new FileSystemException( new Phrase('Deployment config file %1 is not writable.', [$paths[$fileKey]]) diff --git a/lib/internal/Magento/Framework/App/MutableScopeConfig.php b/lib/internal/Magento/Framework/App/MutableScopeConfig.php index 5cbf108bc20317e27be0e13be4d4f3b2e2fc547a..010504d993bfcf7f54268994b03294289348956f 100644 --- a/lib/internal/Magento/Framework/App/MutableScopeConfig.php +++ b/lib/internal/Magento/Framework/App/MutableScopeConfig.php @@ -11,8 +11,31 @@ namespace Magento\Framework\App; use Magento\Framework\App\Config\MutableScopeConfigInterface; use Magento\Framework\App\Config\ScopeConfigInterface; +/** + * @inheritdoc + */ class MutableScopeConfig extends Config implements MutableScopeConfigInterface { + /** + * @var array + */ + private $data; + + /** + * @inheritdoc + */ + public function getValue( + $path = null, + $scope = ScopeConfigInterface::SCOPE_TYPE_DEFAULT, + $scopeCode = null + ) { + if (isset($this->data[$scope][$scopeCode][$path])) { + return $this->data[$scope][$scopeCode][$path]; + } + + return parent::getValue($path, $scope, $scopeCode); + } + /** * Set config value in the corresponding config scope * @@ -28,9 +51,15 @@ class MutableScopeConfig extends Config implements MutableScopeConfigInterface $scope = ScopeConfigInterface::SCOPE_TYPE_DEFAULT, $scopeCode = null ) { - if (empty($scopeCode)) { - $scopeCode = null; - } - $this->_scopePool->getScope($scope, $scopeCode)->setValue($path, $value); + $this->data[$scope][$scopeCode][$path] = $value; + } + + /** + * @inheritdoc + */ + public function clean() + { + $this->data = null; + parent::clean(); } } diff --git a/lib/internal/Magento/Framework/App/ReinitableConfig.php b/lib/internal/Magento/Framework/App/ReinitableConfig.php index 9944978785f54445eb0da3cd8007ec7b27712ed4..2d50bbadabbfefd81ef59a9be7a8ee7e193169fb 100644 --- a/lib/internal/Magento/Framework/App/ReinitableConfig.php +++ b/lib/internal/Magento/Framework/App/ReinitableConfig.php @@ -7,6 +7,10 @@ namespace Magento\Framework\App; use Magento\Framework\App\Config\ReinitableConfigInterface; +/** + * @inheritdoc + * @deprecated + */ class ReinitableConfig extends MutableScopeConfig implements ReinitableConfigInterface { /** @@ -14,7 +18,7 @@ class ReinitableConfig extends MutableScopeConfig implements ReinitableConfigInt */ public function reinit() { - $this->_scopePool->clean(); + $this->clean(); return $this; } } diff --git a/lib/internal/Magento/Framework/App/ResourceConnection/Config.php b/lib/internal/Magento/Framework/App/ResourceConnection/Config.php index 9cd03c8372e1753c1268e4a523a1407151cefa52..d9410bc9f7dd8b44b3cb94cceacd61cf45cff954 100644 --- a/lib/internal/Magento/Framework/App/ResourceConnection/Config.php +++ b/lib/internal/Magento/Framework/App/ResourceConnection/Config.php @@ -18,6 +18,16 @@ class Config extends \Magento\Framework\Config\Data\Scoped implements ConfigInte */ protected $_connectionNames = []; + /** + * @var \Magento\Framework\App\DeploymentConfig + */ + private $deploymentConfig; + + /** + * @var bool + */ + private $initialized = false; + /** * @param Config\Reader $reader * @param \Magento\Framework\Config\ScopeInterface $configScope @@ -34,14 +44,7 @@ class Config extends \Magento\Framework\Config\Data\Scoped implements ConfigInte $cacheId = 'resourcesCache' ) { parent::__construct($reader, $configScope, $cache, $cacheId); - - $resource = $deploymentConfig->getConfigData(ConfigOptionsListConstants::KEY_RESOURCE); - foreach ($resource as $resourceName => $resourceData) { - if (!isset($resourceData['connection'])) { - throw new \InvalidArgumentException('Invalid initial resource configuration'); - } - $this->_connectionNames[$resourceName] = $resourceData['connection']; - } + $this->deploymentConfig = $deploymentConfig; } /** @@ -52,6 +55,7 @@ class Config extends \Magento\Framework\Config\Data\Scoped implements ConfigInte */ public function getConnectionName($resourceName) { + $this->initConnections(); $connectionName = \Magento\Framework\App\ResourceConnection::DEFAULT_CONNECTION; $resourceName = preg_replace("/_setup$/", '', $resourceName); @@ -80,4 +84,23 @@ class Config extends \Magento\Framework\Config\Data\Scoped implements ConfigInte return $connectionName; } + + /** + * Initialise connections + * + * @return void + */ + private function initConnections() + { + if (!$this->initialized) { + $this->initialized = true; + $resource = $this->deploymentConfig->getConfigData(ConfigOptionsListConstants::KEY_RESOURCE) ?: []; + foreach ($resource as $resourceName => $resourceData) { + if (!isset($resourceData['connection'])) { + throw new \InvalidArgumentException('Invalid initial resource configuration'); + } + $this->_connectionNames[$resourceName] = $resourceData['connection']; + } + } + } } diff --git a/lib/internal/Magento/Framework/App/Test/Unit/Config/ConfigSourceAggregatedTest.php b/lib/internal/Magento/Framework/App/Test/Unit/Config/ConfigSourceAggregatedTest.php new file mode 100644 index 0000000000000000000000000000000000000000..9ddd8e325671afa3199270522811027308c222e6 --- /dev/null +++ b/lib/internal/Magento/Framework/App/Test/Unit/Config/ConfigSourceAggregatedTest.php @@ -0,0 +1,69 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Framework\App\Test\Unit\Config; + +use Magento\Framework\App\Config\ConfigSourceAggregated; +use Magento\Framework\App\Config\ConfigSourceInterface; + +class ConfigSourceAggregatedTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var ConfigSourceInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $sourceMock; + + /** + * @var ConfigSourceInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $sourceMockTwo; + + /** + * @var ConfigSourceAggregated + */ + private $source; + + public function setUp() + { + $this->sourceMock = $this->getMockBuilder(ConfigSourceInterface::class) + ->getMockForAbstractClass(); + $this->sourceMockTwo = $this->getMockBuilder(ConfigSourceInterface::class) + ->getMockForAbstractClass(); + + $sources = [ + [ + 'source' => $this->sourceMockTwo, + 'sortOrder' => 100 + ], + [ + 'source' => $this->sourceMock, + 'sortOrder' => 10 + ], + + ]; + + $this->source = new ConfigSourceAggregated($sources); + } + + public function testGet() + { + $path = 'path'; + $this->sourceMock->expects($this->once()) + ->method('get') + ->with($path) + ->willReturn(['key' => 'value1', 'test' => false]); + $this->sourceMockTwo->expects($this->once()) + ->method('get') + ->with($path) + ->willReturn(['key' => 'value2']); + $this->assertEquals( + [ + 'test' => false, + 'key' => 'value2' + ], + $this->source->get($path) + ); + } +} diff --git a/lib/internal/Magento/Framework/App/Test/Unit/Config/InitialConfigSourceTest.php b/lib/internal/Magento/Framework/App/Test/Unit/Config/InitialConfigSourceTest.php new file mode 100644 index 0000000000000000000000000000000000000000..e1b8d1e465141c4a724c891f5fae1d09eaa87299 --- /dev/null +++ b/lib/internal/Magento/Framework/App/Test/Unit/Config/InitialConfigSourceTest.php @@ -0,0 +1,54 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Framework\App\Test\Unit\Config; + + +use Magento\Framework\App\Config\InitialConfigSource; +use Magento\Framework\App\DeploymentConfig\Reader; + +class InitialConfigSourceTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var Reader|\PHPUnit_Framework_MockObject_MockObject + */ + private $reader; + + /** + * @var string + */ + private $configType; + + /** + * @var string + */ + private $fileKey; + + /** + * @var InitialConfigSource + */ + private $source; + + public function setUp() + { + $this->reader = $this->getMockBuilder(Reader::class) + ->disableOriginalConstructor() + ->getMock(); + $this->configType = 'configType'; + $this->fileKey = 'file.php'; + $this->source = new InitialConfigSource($this->reader, $this->configType, $this->fileKey); + } + + public function testGet() + { + $path = 'path'; + $this->reader->expects($this->once()) + ->method('load') + ->with($this->fileKey) + ->willReturn([$this->configType => [$path => 'value']]); + $this->assertEquals('value', $this->source->get($path)); + } +} diff --git a/lib/internal/Magento/Framework/App/Test/Unit/Config/MetadataConfigTypeProcessorTest.php b/lib/internal/Magento/Framework/App/Test/Unit/Config/MetadataConfigTypeProcessorTest.php new file mode 100644 index 0000000000000000000000000000000000000000..f1bedf1c3276b338075f83694fe0b1e8917192a0 --- /dev/null +++ b/lib/internal/Magento/Framework/App/Test/Unit/Config/MetadataConfigTypeProcessorTest.php @@ -0,0 +1,79 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Framework\App\Test\Unit\Config; + +class MetadataConfigTypeProcessorTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var \Magento\Framework\App\Config\MetadataProcessor + */ + protected $_model; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $_initialConfigMock; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $_modelPoolMock; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $_backendModelMock; + + protected function setUp() + { + $this->_modelPoolMock = $this->getMock( + \Magento\Framework\App\Config\Data\ProcessorFactory::class, + [], + [], + '', + false + ); + $this->_initialConfigMock = $this->getMock(\Magento\Framework\App\Config\Initial::class, [], [], '', false); + $this->_backendModelMock = $this->getMock(\Magento\Framework\App\Config\Data\ProcessorInterface::class); + $this->_initialConfigMock->expects( + $this->any() + )->method( + 'getMetadata' + )->will( + $this->returnValue(['some/config/path' => ['backendModel' => 'Custom_Backend_Model']]) + ); + $this->_model = new \Magento\Framework\App\Config\MetadataConfigTypeProcessor( + $this->_modelPoolMock, + $this->_initialConfigMock + ); + } + + public function testProcess() + { + $this->_modelPoolMock->expects( + $this->once() + )->method( + 'get' + )->with( + 'Custom_Backend_Model' + )->will( + $this->returnValue($this->_backendModelMock) + ); + $this->_backendModelMock->expects( + $this->once() + )->method( + 'processValue' + )->with( + 'value' + )->will( + $this->returnValue('processed_value') + ); + $data = ['default' => [ 'some' => ['config' => ['path' => 'value']], 'active' => 1]]; + $expectedResult = $data; + $expectedResult['default']['some']['config']['path'] = 'processed_value'; + $this->assertEquals($expectedResult, $this->_model->process($data)); + } +} diff --git a/lib/internal/Magento/Framework/App/Test/Unit/Config/ScopeCodeResolverTest.php b/lib/internal/Magento/Framework/App/Test/Unit/Config/ScopeCodeResolverTest.php new file mode 100644 index 0000000000000000000000000000000000000000..cbf671479877bedc1f6bb55f682f60b329e105bf --- /dev/null +++ b/lib/internal/Magento/Framework/App/Test/Unit/Config/ScopeCodeResolverTest.php @@ -0,0 +1,68 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Framework\App\Test\Unit\Config; + +use Magento\Framework\App\Config\ScopeCodeResolver; +use Magento\Framework\App\ScopeInterface; +use Magento\Framework\App\ScopeResolverInterface; +use Magento\Framework\App\ScopeResolverPool; + +class ScopeCodeResolverTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var ScopeResolverPool|\PHPUnit_Framework_MockObject_MockObject + */ + private $scopeResolverPool; + + /** + * @var ScopeResolverInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $scopeResolver; + + /** + * @var ScopeInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $scope; + + /** + * @var ScopeCodeResolver + */ + private $scopeCodeResolver; + + public function setUp() + { + $this->scopeResolverPool = $this->getMockBuilder(ScopeResolverPool::class) + ->disableOriginalConstructor() + ->getMock(); + $this->scopeResolver = $this->getMockBuilder(ScopeResolverInterface::class) + ->disableOriginalConstructor() + ->getMockForAbstractClass(); + $this->scope = $this->getMockBuilder(ScopeInterface::class) + ->disableOriginalConstructor() + ->getMockForAbstractClass(); + + $this->scopeCodeResolver = new ScopeCodeResolver($this->scopeResolverPool); + } + + public function testResolve() + { + $scopeType = 'website'; + $scopeCode = 'myWebsite'; + $scopeId = 4; + $this->scopeResolverPool->expects($this->once()) + ->method('get') + ->with($scopeType) + ->willReturn($this->scopeResolver); + $this->scopeResolver->expects($this->once()) + ->method('getScope') + ->with($scopeId) + ->willReturn($this->scope); + $this->scope->expects($this->once()) + ->method('getCode') + ->willReturn($scopeCode); + $this->assertEquals($scopeCode, $this->scopeCodeResolver->resolve($scopeType, $scopeId)); + } +} diff --git a/lib/internal/Magento/Framework/App/Test/Unit/Config/ScopePoolTest.php b/lib/internal/Magento/Framework/App/Test/Unit/Config/ScopePoolTest.php deleted file mode 100644 index 6c9ae8a09a77de9481e80de94c1b2faa1a19bf42..0000000000000000000000000000000000000000 --- a/lib/internal/Magento/Framework/App/Test/Unit/Config/ScopePoolTest.php +++ /dev/null @@ -1,168 +0,0 @@ -<?php -/** - * Copyright © 2016 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Framework\App\Test\Unit\Config; - -use Magento\Framework\App\Config\Scope\ReaderInterface; -use Magento\Framework\App\Config\Scope\ReaderPoolInterface; - -class ScopePoolTest extends \PHPUnit_Framework_TestCase -{ - /** - * @var ReaderInterface|\PHPUnit_Framework_MockObject_MockObject - */ - protected $_reader; - - /** - * @var ReaderPoolInterface|\PHPUnit_Framework_MockObject_MockObject - */ - protected $_readerPool; - - /** - * @var \Magento\Framework\App\Config\DataFactory|\PHPUnit_Framework_MockObject_MockObject - */ - protected $_dataFactory; - - /** - * @var \Magento\Framework\Cache\FrontendInterface|\PHPUnit_Framework_MockObject_MockObject - */ - protected $_cache; - - /** - * @var \Magento\Framework\App\Config\ScopePool - */ - protected $_object; - - protected function setUp() - { - $helper = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); - $this->_readerPool = $this->getMockForAbstractClass(ReaderPoolInterface::class); - $this->_reader = $this->getMockForAbstractClass(ReaderInterface::class); - $this->_dataFactory = $this->getMockBuilder( - \Magento\Framework\App\Config\DataFactory::class - )->disableOriginalConstructor()->getMock(); - $this->_cache = $this->getMock(\Magento\Framework\Cache\FrontendInterface::class); - $this->_object = $helper->getObject( - \Magento\Framework\App\Config\ScopePool::class, - [ - 'readerPool' => $this->_readerPool, - 'dataFactory' => $this->_dataFactory, - 'cache' => $this->_cache, - 'cacheId' => 'test_cache_id' - ] - ); - - $requestMock = $this->getMockBuilder(\Magento\Framework\App\RequestInterface::class) - ->disableOriginalConstructor() - ->setMethods( - [ - 'getBasePath', - 'getModuleName', - 'setModuleName', - 'getActionName', - 'setActionName', - 'getParam', - 'getParams', - 'setParams', - 'getCookie', - 'isSecure', - 'getServer', - 'getHttpHost' - ] - )->getMock(); - $reflection = new \ReflectionClass(get_class($this->_object)); - $reflectionProperty = $reflection->getProperty('request'); - $reflectionProperty->setAccessible(true); - $reflectionProperty->setValue($this->_object, $requestMock); - $requestMock->expects($this->any()) - ->method('getBasePath') - ->willReturn('baseUrl'); - } - - /** - * @dataProvider getScopeDataProvider - * - * @param string $scopeType - * @param string $scope - * @param array $data - * @param string|null $cachedData - */ - public function testGetScope($scopeType, $scope, array $data, $cachedData) - { - $scopeCode = $scope instanceof \Magento\Framework\App\ScopeInterface ? $scope->getCode() : $scope; - $cacheKey = "test_cache_id|{$scopeType}|{$scopeCode}|baseUrl"; - - $this->_readerPool->expects( - $this->any() - )->method( - 'getReader' - )->with( - $scopeType - )->will( - $this->returnValue($this->_reader) - ); - $this->_cache->expects($this->once())->method('load')->with($cacheKey)->will($this->returnValue($cachedData)); - - if (!$cachedData) { - $this->_reader->expects($this->once())->method('read')->with('testScope')->will($this->returnValue($data)); - $this->_cache->expects( - $this->once() - )->method( - 'save' - )->with( - serialize($data), - $cacheKey, - [\Magento\Framework\App\Config\ScopePool::CACHE_TAG] - ); - } - - $configData = $this->getMockBuilder(\Magento\Framework\App\Config\Data::class) - ->disableOriginalConstructor() - ->getMock(); - $this->_dataFactory->expects( - $this->once() - )->method( - 'create' - )->with( - ['data' => $data] - )->will( - $this->returnValue($configData) - ); - $this->assertInstanceOf( - \Magento\Framework\App\Config\DataInterface::class, - $this->_object->getScope($scopeType, $scope) - ); - - // second call to check caching - $this->assertInstanceOf( - \Magento\Framework\App\Config\DataInterface::class, - $this->_object->getScope($scopeType, $scope) - ); - } - - public function getScopeDataProvider() - { - $baseScope = $this->getMockForAbstractClass(\Magento\Framework\App\ScopeInterface::class); - $baseScope->expects($this->any())->method('getCode')->will($this->returnValue('testScope')); - return [ - ['scopeType1', 'testScope', ['key' => 'value'], null], - ['scopeType2', 'testScope', ['key' => 'value'], serialize(['key' => 'value'])], - ['scopeType1', $baseScope, ['key' => 'value'], null] - ]; - } - - public function testClean() - { - $this->_cache->expects( - $this->once() - )->method( - 'clean' - )->with( - \Zend_Cache::CLEANING_MODE_MATCHING_TAG, - [\Magento\Framework\App\Config\ScopePool::CACHE_TAG] - ); - $this->_object->clean('testScope'); - } -} diff --git a/lib/internal/Magento/Framework/App/Test/Unit/ConfigTest.php b/lib/internal/Magento/Framework/App/Test/Unit/ConfigTest.php new file mode 100644 index 0000000000000000000000000000000000000000..d2474829693e40a16890041c25791f05525defe3 --- /dev/null +++ b/lib/internal/Magento/Framework/App/Test/Unit/ConfigTest.php @@ -0,0 +1,83 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Framework\App\Test\Unit; + +use Magento\Framework\App\Config; +use Magento\Framework\App\Config\ConfigTypeInterface; +use Magento\Framework\App\Config\ScopeCodeResolver; +use Magento\Framework\App\ScopeInterface; + +class ConfigTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var ScopeCodeResolver|\PHPUnit_Framework_MockObject_MockObject + */ + private $scopeCodeResolver; + + /** + * @var ConfigTypeInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $configType; + + /** + * @var ScopeInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $scope; + + /** + * @var Config + */ + private $appConfig; + + public function setUp() + { + $this->scopeCodeResolver = $this->getMockBuilder(ScopeCodeResolver::class) + ->disableOriginalConstructor() + ->getMock(); + $this->configType = $this->getMockBuilder(ConfigTypeInterface::class) + ->getMockForAbstractClass(); + $this->scope = $this->getMockBuilder(ScopeInterface::class) + ->getMockForAbstractClass(); + + $this->appConfig = new Config($this->scopeCodeResolver, ['system' => $this->configType]); + } + + /** + * @param string $scope + * @param string|null $scopeCode + * + * @dataProvider getValueDataProvider + * @return void + */ + public function testGetValue($scope, $scopeCode = null) + { + $path = 'path'; + if (!is_string($scope)) { + $this->scopeCodeResolver->expects($this->once()) + ->method('resolve') + ->with('stores', $scopeCode) + ->willReturn('myStore'); + } elseif (!$scopeCode) { + $this->scope->expects($this->once()) + ->method('getCode') + ->willReturn('myWebsite'); + } + $this->configType->expects($this->once()) + ->method('get') + ->with($scope =='store' ? 'stores/path' : 'websites/myWebsite/path') + ->willReturn(true); + + $this->assertTrue($this->appConfig->getValue($path, $scope, $scopeCode ?: $this->scope)); + } + + public function getValueDataProvider() + { + return [ + ['store', 1], + ['website'], + ]; + } +} diff --git a/lib/internal/Magento/Framework/App/Test/Unit/DeploymentConfig/ReaderTest.php b/lib/internal/Magento/Framework/App/Test/Unit/DeploymentConfig/ReaderTest.php index b78e5a536ac9d3757f537822851a3e450788aa9b..a321775883e09abb951aa3179a24d2ec82ce6370 100644 --- a/lib/internal/Magento/Framework/App/Test/Unit/DeploymentConfig/ReaderTest.php +++ b/lib/internal/Magento/Framework/App/Test/Unit/DeploymentConfig/ReaderTest.php @@ -61,6 +61,10 @@ class ReaderTest extends \PHPUnit_Framework_TestCase ->expects($this->any()) ->method('getPaths') ->willReturn(['configKeyOne' => 'config.php', 'configKeyTwo' => 'env.php']); + $this->configFilePool + ->expects($this->any()) + ->method('getInitialFilePools') + ->willReturn([]); } public function testGetFile() @@ -103,6 +107,7 @@ class ReaderTest extends \PHPUnit_Framework_TestCase $configFilePool = $this->getMock(\Magento\Framework\Config\File\ConfigFilePool::class, [], [], '', false); $configFilePool->expects($this->any())->method('getPaths')->willReturn([$file]); $configFilePool->expects($this->any())->method('getPath')->willReturn($file); + $configFilePool->expects($this->any())->method('getInitialFilePools')->willReturn([]); $object = new Reader($this->dirList, $this->driverPool, $configFilePool, $file); $this->assertSame($expected, $object->load($file)); } @@ -130,6 +135,9 @@ class ReaderTest extends \PHPUnit_Framework_TestCase ->expects($this->any()) ->method('getPath') ->will($this->returnValueMap($files)); + $configFilePool->expects($this->any()) + ->method('getInitialFilePools') + ->willReturn([]); $configFilePool ->expects($this->any()) ->method('getPaths') @@ -150,6 +158,9 @@ class ReaderTest extends \PHPUnit_Framework_TestCase ->expects($this->any()) ->method('getPath') ->will($this->returnValueMap($files)); + $configFilePool->expects($this->any()) + ->method('getInitialFilePools') + ->willReturn([]); $configFilePool ->expects($this->any()) ->method('getPaths') diff --git a/lib/internal/Magento/Framework/App/Test/Unit/DeploymentConfig/WriterTest.php b/lib/internal/Magento/Framework/App/Test/Unit/DeploymentConfig/WriterTest.php index de06f6f18a5909093a0b5d45e8c2b34c2f1940b9..02d3ade243b8319f458b28a24977bd7893240ad8 100644 --- a/lib/internal/Magento/Framework/App/Test/Unit/DeploymentConfig/WriterTest.php +++ b/lib/internal/Magento/Framework/App/Test/Unit/DeploymentConfig/WriterTest.php @@ -18,6 +18,11 @@ use Magento\Framework\Filesystem\Directory\ReadInterface; use Magento\Framework\Filesystem\Directory\WriteInterface; use Magento\Framework\Phrase; +/** + * @covers \Magento\Framework\App\DeploymentConfig\Writer + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + * @package Magento\Framework\App\Test\Unit\DeploymentConfig + */ class WriterTest extends \PHPUnit_Framework_TestCase { /** @var Writer */ @@ -76,8 +81,7 @@ class WriterTest extends \PHPUnit_Framework_TestCase public function testSaveConfig() { $configFiles = [ - ConfigFilePool::APP_CONFIG => 'test_conf.php', - 'test_key' => 'test2_conf.php' + ConfigFilePool::APP_CONFIG => 'config.php' ]; $testSetExisting = [ @@ -113,13 +117,14 @@ class WriterTest extends \PHPUnit_Framework_TestCase $this->deploymentConfig->expects($this->once())->method('resetData'); $this->configFilePool->expects($this->once())->method('getPaths')->willReturn($configFiles); $this->dirWrite->expects($this->any())->method('isExist')->willReturn(true); - $this->reader->expects($this->once())->method('load')->willReturn($testSetExisting[ConfigFilePool::APP_CONFIG]); + $this->reader->expects($this->once())->method('loadConfigFile') + ->willReturn($testSetExisting[ConfigFilePool::APP_CONFIG]); $this->formatter ->expects($this->once()) ->method('format') ->with($testSetExpected[ConfigFilePool::APP_CONFIG]) ->willReturn([]); - $this->dirWrite->expects($this->once())->method('writeFile')->with('test_conf.php', []); + $this->dirWrite->expects($this->once())->method('writeFile')->with('config.php', []); $this->object->saveConfig($testSetUpdate); } @@ -127,19 +132,7 @@ class WriterTest extends \PHPUnit_Framework_TestCase public function testSaveConfigOverride() { $configFiles = [ - ConfigFilePool::APP_CONFIG => 'test_conf.php', - 'test_key' => 'test2_conf.php' - ]; - - $testSetExisting = [ - ConfigFilePool::APP_CONFIG => [ - 'foo' => 'bar', - 'key' => 'value', - 'baz' => [ - 'test' => 'value', - 'test1' => 'value1' - ] - ], + ConfigFilePool::APP_CONFIG => 'config.php' ]; $testSetUpdate = [ @@ -152,8 +145,6 @@ class WriterTest extends \PHPUnit_Framework_TestCase $testSetExpected = [ ConfigFilePool::APP_CONFIG => [ - 'foo' => 'bar', - 'key' => 'value', 'baz' => [ 'test' => 'value2', ] @@ -163,13 +154,12 @@ class WriterTest extends \PHPUnit_Framework_TestCase $this->deploymentConfig->expects($this->once())->method('resetData'); $this->configFilePool->expects($this->once())->method('getPaths')->willReturn($configFiles); $this->dirWrite->expects($this->any())->method('isExist')->willReturn(true); - $this->reader->expects($this->once())->method('load')->willReturn($testSetExisting[ConfigFilePool::APP_CONFIG]); $this->formatter ->expects($this->once()) ->method('format') ->with($testSetExpected[ConfigFilePool::APP_CONFIG]) ->willReturn([]); - $this->dirWrite->expects($this->once())->method('writeFile')->with('test_conf.php', []); + $this->dirWrite->expects($this->once())->method('writeFile')->with('config.php', []); $this->object->saveConfig($testSetUpdate, true); } diff --git a/lib/internal/Magento/Framework/App/Test/Unit/ReinitableConfigTest.php b/lib/internal/Magento/Framework/App/Test/Unit/ReinitableConfigTest.php deleted file mode 100644 index 9a35aa9104e80e3eae34c928130fd32add5f0d2e..0000000000000000000000000000000000000000 --- a/lib/internal/Magento/Framework/App/Test/Unit/ReinitableConfigTest.php +++ /dev/null @@ -1,22 +0,0 @@ -<?php -/** - * Copyright © 2016 Magento. All rights reserved. - * See COPYING.txt for license details. - */ - -// @codingStandardsIgnoreFile - -namespace Magento\Framework\App\Test\Unit; - -class ReinitableConfigTest extends \PHPUnit_Framework_TestCase -{ - public function testReinit() - { - $helper = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); - $scopePool = $this->getMock(\Magento\Framework\App\Config\ScopePool::class, ['clean'], [], '', false); - $scopePool->expects($this->once())->method('clean'); - /** @var \Magento\Framework\App\ReinitableConfig $config */ - $config = $helper->getObject(\Magento\Framework\App\ReinitableConfig::class, ['scopePool' => $scopePool]); - $this->assertInstanceOf(\Magento\Framework\App\Config\ReinitableConfigInterface::class, $config->reinit()); - } -} diff --git a/lib/internal/Magento/Framework/App/Test/Unit/ResourceConnection/ConfigTest.php b/lib/internal/Magento/Framework/App/Test/Unit/ResourceConnection/ConfigTest.php index 936a806432419a43a33207d51cfd751e71bee814..dead64911174ae3fa5f4f98edf748d7d49cb8e0c 100644 --- a/lib/internal/Magento/Framework/App/Test/Unit/ResourceConnection/ConfigTest.php +++ b/lib/internal/Magento/Framework/App/Test/Unit/ResourceConnection/ConfigTest.php @@ -5,10 +5,12 @@ */ namespace Magento\Framework\App\Test\Unit\ResourceConnection; +use Magento\Framework\Config\ConfigOptionsListConstants; + class ConfigTest extends \PHPUnit_Framework_TestCase { /** - * @var \Magento\Framework\App\\Config + * @var \Magento\Framework\App\ResourceConnection\Config */ protected $_model; @@ -33,9 +35,9 @@ class ConfigTest extends \PHPUnit_Framework_TestCase protected $_resourcesConfig; /** - * @var array + * @var \Magento\Framework\App\DeploymentConfig|\PHPUnit_Framework_MockObject_MockObject */ - protected $_initialResources; + private $deploymentConfig; protected function setUp() { @@ -53,10 +55,6 @@ class ConfigTest extends \PHPUnit_Framework_TestCase 'extendedResourceName' => ['name' => 'extendedResourceName', 'extends' => 'validResource'], ]; - $this->_initialResources = [ - 'validResource' => ['connection' => 'validConnectionName'], - ]; - $this->_cacheMock->expects( $this->any() )->method( @@ -65,17 +63,12 @@ class ConfigTest extends \PHPUnit_Framework_TestCase $this->returnValue(serialize($this->_resourcesConfig)) ); - $deploymentConfig = $this->getMock(\Magento\Framework\App\DeploymentConfig::class, [], [], '', false); - $deploymentConfig->expects($this->once()) - ->method('getConfigData') - ->with('resource') - ->willReturn($this->_initialResources); - + $this->deploymentConfig = $this->getMock(\Magento\Framework\App\DeploymentConfig::class, [], [], '', false); $this->_model = new \Magento\Framework\App\ResourceConnection\Config( $this->_readerMock, $this->_scopeMock, $this->_cacheMock, - $deploymentConfig, + $this->deploymentConfig, 'cacheId' ); } @@ -87,27 +80,34 @@ class ConfigTest extends \PHPUnit_Framework_TestCase */ public function testGetConnectionName($resourceName, $connectionName) { + $this->deploymentConfig->expects($this->once()) + ->method('getConfigData') + ->with(ConfigOptionsListConstants::KEY_RESOURCE) + ->willReturn([ + 'validResource' => ['connection' => 'validConnectionName'], + ]); $this->assertEquals($connectionName, $this->_model->getConnectionName($resourceName)); } /** * @expectedException \InvalidArgumentException */ - public function testExceptionConstructor() + public function testGetConnectionNameWithException() { $deploymentConfig = $this->getMock(\Magento\Framework\App\DeploymentConfig::class, [], [], '', false); $deploymentConfig->expects($this->once()) ->method('getConfigData') - ->with('resource') + ->with(ConfigOptionsListConstants::KEY_RESOURCE) ->willReturn(['validResource' => ['somekey' => 'validConnectionName']]); - new \Magento\Framework\App\ResourceConnection\Config( + $model = new \Magento\Framework\App\ResourceConnection\Config( $this->_readerMock, $this->_scopeMock, $this->_cacheMock, $deploymentConfig, 'cacheId' ); + $model->getConnectionName('default'); } /** diff --git a/lib/internal/Magento/Framework/Code/GeneratedFiles.php b/lib/internal/Magento/Framework/Code/GeneratedFiles.php index 75d5ff4b4b73bce4e7d82ba65b107611b0208344..f3d3c2bd611d5c0bb1795aaacc24c4701009d573 100644 --- a/lib/internal/Magento/Framework/Code/GeneratedFiles.php +++ b/lib/internal/Magento/Framework/Code/GeneratedFiles.php @@ -133,7 +133,6 @@ class GeneratedFiles return $enabledCacheTypes; } - /** * Returns path to env.php file * @@ -183,8 +182,7 @@ class GeneratedFiles * Enables apppropriate cache types in app/etc/env.php based on the passed in $cacheTypes array * TODO: to be removed in scope of MAGETWO-53476 * - * @param string[] - * + * @param string[] $cacheTypes * @return void */ private function enableCacheTypes($cacheTypes) diff --git a/lib/internal/Magento/Framework/Code/Test/Unit/GeneratedFilesTest.php b/lib/internal/Magento/Framework/Code/Test/Unit/GeneratedFilesTest.php index facf71854c575da7d093d865e8bd919c443ec7a8..ab5e0a594e14ae849ac3e6a442a93a8c62b98e64 100644 --- a/lib/internal/Magento/Framework/Code/Test/Unit/GeneratedFilesTest.php +++ b/lib/internal/Magento/Framework/Code/Test/Unit/GeneratedFilesTest.php @@ -12,12 +12,12 @@ use Magento\Framework\Code\GeneratedFiles; class GeneratedFilesTest extends \PHPUnit_Framework_TestCase { /** - * @var Magento\Framework\App\Filesystem\DirectoryList | \PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\App\Filesystem\DirectoryList | \PHPUnit_Framework_MockObject_MockObject */ private $directoryList; /** - * @var Magento\Framework\Filesystem\Directory\WriteInterface | \PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\Filesystem\Directory\WriteInterface | \PHPUnit_Framework_MockObject_MockObject */ private $writeInterface; diff --git a/lib/internal/Magento/Framework/Config/Converter.php b/lib/internal/Magento/Framework/Config/Converter.php index 5ea535bac5f29ccff3d8ac8c1f4675d317eb6083..b22d4d61a68673e158ed973de3d271422d0706fa 100644 --- a/lib/internal/Magento/Framework/Config/Converter.php +++ b/lib/internal/Magento/Framework/Config/Converter.php @@ -7,6 +7,11 @@ namespace Magento\Framework\Config; use Magento\Framework\View\Xsd\Media\TypeDataExtractorPool; +/** + * Class Converter convert xml to appropriate array + * + * @package Magento\Framework\Config + */ class Converter implements \Magento\Framework\Config\ConverterInterface { /** diff --git a/lib/internal/Magento/Framework/Config/File/ConfigFilePool.php b/lib/internal/Magento/Framework/Config/File/ConfigFilePool.php index c9439d0a45e8fd064dc6db4a2dc69c075c0ba38c..e84f61383c7cc86d2c5c5fda7abacc42611366d7 100644 --- a/lib/internal/Magento/Framework/Config/File/ConfigFilePool.php +++ b/lib/internal/Magento/Framework/Config/File/ConfigFilePool.php @@ -14,6 +14,9 @@ class ConfigFilePool const APP_CONFIG = 'app_config'; const APP_ENV = 'app_env'; + const LOCAL = 'local'; + const DIST = 'dist'; + /** * Default files for configuration * @@ -24,6 +27,22 @@ class ConfigFilePool self::APP_ENV => 'env.php', ]; + /** + * Initial files for configuration + * + * @var array + */ + private $initialConfigFiles = [ + self::DIST => [ + self::APP_CONFIG => 'config.dist.php', + self::APP_ENV => 'env.dist.php', + ], + self::LOCAL => [ + self::APP_CONFIG => 'config.local.php', + self::APP_ENV => 'env.local.php', + ] + ]; + /** * Constructor * @@ -35,7 +54,7 @@ class ConfigFilePool } /** - * Returns application config files + * Returns application config files. * * @return array */ @@ -58,4 +77,25 @@ class ConfigFilePool } return $this->applicationConfigFiles[$fileKey]; } + + /** + * Returns application initial config files. + * + * @return array + */ + public function getInitialFilePools() + { + return $this->initialConfigFiles; + } + + /** + * Retrieve all config file pools. + * + * @param string $pool + * @return array + */ + public function getPathsByPool($pool) + { + return $this->initialConfigFiles[$pool]; + } } diff --git a/lib/internal/Magento/Framework/Config/FileResolver.php b/lib/internal/Magento/Framework/Config/FileResolver.php index 1455eb355df7ac5e0307405fbe6560c03108f5bc..a6726b95526b34c73d232094c3bb06cd431ee533 100644 --- a/lib/internal/Magento/Framework/Config/FileResolver.php +++ b/lib/internal/Magento/Framework/Config/FileResolver.php @@ -7,7 +7,7 @@ */ namespace Magento\Framework\Config; -use Magento\Framework\Module\Dir\Reader; +use Magento\Framework\Module\Dir\Reader as DirReader; use Magento\Framework\Filesystem; use Magento\Framework\View\Design\ThemeInterface; use Magento\Framework\View\DesignInterface; @@ -24,7 +24,7 @@ class FileResolver implements \Magento\Framework\Config\FileResolverInterface, D /** * Module configuration file reader * - * @var \Magento\Framework\Module\Dir\Reader + * @var DirReader */ protected $moduleReader; @@ -54,7 +54,7 @@ class FileResolver implements \Magento\Framework\Config\FileResolverInterface, D protected $resolver; /** - * @param Reader $moduleReader + * @param DirReader $moduleReader * @param FileIteratorFactory $iteratorFactory * @param DesignInterface $designInterface * @param DirectoryList $directoryList @@ -62,7 +62,7 @@ class FileResolver implements \Magento\Framework\Config\FileResolverInterface, D * @param ResolverInterface $resolver */ public function __construct( - Reader $moduleReader, + DirReader $moduleReader, FileIteratorFactory $iteratorFactory, DesignInterface $designInterface, DirectoryList $directoryList, diff --git a/lib/internal/Magento/Framework/Config/Reader.php b/lib/internal/Magento/Framework/Config/Reader.php new file mode 100644 index 0000000000000000000000000000000000000000..f99e4e3341860d4acf33402c2623889fe523a484 --- /dev/null +++ b/lib/internal/Magento/Framework/Config/Reader.php @@ -0,0 +1,75 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Framework\Config; + +use Magento\Framework\Exception\LocalizedException; + +/** + * Read config from different sources and aggregate them + * + * @package Magento\Framework\Config + */ +class Reader implements \Magento\Framework\App\Config\Scope\ReaderInterface +{ + /** + * @var array + */ + private $sources; + + /** + * @param array $sources + */ + public function __construct(array $sources) + { + $this->sources = $this->prepareSources($sources); + } + + /** + * Read configuration data + * + * @param null|string $scope + * @throws LocalizedException Exception is thrown when scope other than default is given + * @return array + */ + public function read($scope = null) + { + $config = []; + foreach ($this->sources as $sourceData) { + /** @var \Magento\Framework\App\Config\Reader\Source\SourceInterface $source */ + $source = $sourceData['class']; + $config = array_replace_recursive($config, $source->get($scope)); + } + + return $config; + } + + /** + * Prepare source for usage + * + * @param array $array + * @return array + */ + private function prepareSources(array $array) + { + $array = array_filter( + $array, + function ($item) { + return (!isset($item['disable']) || !$item['disable']) && $item['class']; + } + ); + uasort( + $array, + function ($firstItem, $nexItem) { + if ((int)$firstItem['sortOrder'] == (int)$nexItem['sortOrder']) { + return 0; + } + return (int)$firstItem['sortOrder'] < (int)$nexItem['sortOrder'] ? -1 : 1; + } + ); + + return $array; + } +} diff --git a/lib/internal/Magento/Framework/Config/Test/Unit/ReaderTest.php b/lib/internal/Magento/Framework/Config/Test/Unit/ReaderTest.php new file mode 100644 index 0000000000000000000000000000000000000000..b51fbd3598e11b8c021d25405ffbe19dd41a0355 --- /dev/null +++ b/lib/internal/Magento/Framework/Config/Test/Unit/ReaderTest.php @@ -0,0 +1,46 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Framework\Config\Test\Unit; + +use Magento\Framework\App\Config\Reader\Source\SourceInterface; +use Magento\Framework\App\Config\Scope\Converter; +use Magento\Framework\Config\Reader; +use Magento\Framework\Stdlib\ArrayUtils; + +class ReaderTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var SourceInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $source; + + /** + * @var Reader + */ + private $reader; + + public function setUp() + { + $this->source = $this->getMockBuilder(SourceInterface::class) + ->getMockForAbstractClass(); + $this->reader = new Reader([['class' => $this->source]]); + } + + public function testRead() + { + $config = [ + 'default' => [ + 'general/locale/code'=> 'ru_RU', + 'general/locale/timezone'=> 'America/Chicago', + ] + ]; + $this->source->expects($this->once()) + ->method('get') + ->with(null) + ->willReturn($config); + $this->assertEquals($config, $this->reader->read()); + } +} diff --git a/app/code/Magento/Deploy/Console/Command/DeployStaticContentCommand.php b/setup/src/Magento/Setup/Console/Command/DeployStaticContentCommand.php similarity index 96% rename from app/code/Magento/Deploy/Console/Command/DeployStaticContentCommand.php rename to setup/src/Magento/Setup/Console/Command/DeployStaticContentCommand.php index 8a006c8154b4b97eb6d39c1d41f8363b3e4df761..e7badbf908b1015c5a47034e2aae99397451a1a3 100644 --- a/app/code/Magento/Deploy/Console/Command/DeployStaticContentCommand.php +++ b/setup/src/Magento/Setup/Console/Command/DeployStaticContentCommand.php @@ -3,15 +3,15 @@ * Copyright © 2016 Magento. All rights reserved. * See COPYING.txt for license details. */ -namespace Magento\Deploy\Console\Command; +namespace Magento\Setup\Console\Command; use Magento\Framework\App\Utility\Files; +use Magento\Setup\Model\ObjectManagerProvider; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Input\InputArgument; -use Magento\Framework\App\ObjectManagerFactory; use Magento\Framework\ObjectManagerInterface; use Magento\Framework\Validator\Locale; use Magento\Framework\Exception\LocalizedException; @@ -64,13 +64,6 @@ class DeployStaticContentCommand extends Command */ private $validator; - /** - * Factory to get object manager - * - * @var ObjectManagerFactory - */ - private $objectManagerFactory; - /** * object manager to create various objects * @@ -85,19 +78,16 @@ class DeployStaticContentCommand extends Command /** * Inject dependencies * - * @param ObjectManagerFactory $objectManagerFactory * @param Locale $validator - * @param ObjectManagerInterface $objectManager + * @param ObjectManagerProvider $objectManagerProvider * @throws \LogicException When the command name is empty */ public function __construct( - ObjectManagerFactory $objectManagerFactory, Locale $validator, - ObjectManagerInterface $objectManager + ObjectManagerProvider $objectManagerProvider ) { - $this->objectManagerFactory = $objectManagerFactory; $this->validator = $validator; - $this->objectManager = $objectManager; + $this->objectManager = $objectManagerProvider->get(); parent::__construct(); } diff --git a/setup/src/Magento/Setup/Console/CommandList.php b/setup/src/Magento/Setup/Console/CommandList.php index 4bb5ac0181a794b575b420499908d1cb3871b383..e025de44602503c004bcdcd009111a31a6624a7e 100644 --- a/setup/src/Magento/Setup/Console/CommandList.php +++ b/setup/src/Magento/Setup/Console/CommandList.php @@ -72,6 +72,7 @@ class CommandList \Magento\Setup\Console\Command\RollbackCommand::class, \Magento\Setup\Console\Command\UpgradeCommand::class, \Magento\Setup\Console\Command\UninstallCommand::class, + \Magento\Setup\Console\Command\DeployStaticContentCommand::class ]; } diff --git a/app/code/Magento/Deploy/Test/Unit/Console/Command/DeployStaticContentCommandTest.php b/setup/src/Magento/Setup/Test/Unit/Console/Command/DeployStaticContentCommandTest.php similarity index 98% rename from app/code/Magento/Deploy/Test/Unit/Console/Command/DeployStaticContentCommandTest.php rename to setup/src/Magento/Setup/Test/Unit/Console/Command/DeployStaticContentCommandTest.php index c8fa2138e7c81fb69d562fb5ec55e049cb5deabc..82777bb6b7aee697ba5a77df1a9dfcc95d93dedc 100644 --- a/app/code/Magento/Deploy/Test/Unit/Console/Command/DeployStaticContentCommandTest.php +++ b/setup/src/Magento/Setup/Test/Unit/Console/Command/DeployStaticContentCommandTest.php @@ -3,9 +3,9 @@ * Copyright © 2016 Magento. All rights reserved. * See COPYING.txt for license details. */ -namespace Magento\Deploy\Test\Unit\Console\Command; +namespace Magento\Setup\Test\Unit\Console\Command; -use Magento\Deploy\Console\Command\DeployStaticContentCommand; +use Magento\Setup\Console\Command\DeployStaticContentCommand; use Symfony\Component\Console\Tester\CommandTester; use Magento\Framework\Validator\Locale; use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; diff --git a/app/code/Magento/Deploy/Test/Unit/Console/Command/FunctionExistMock.php b/setup/src/Magento/Setup/Test/Unit/Console/Command/FunctionExistMock.php similarity index 100% rename from app/code/Magento/Deploy/Test/Unit/Console/Command/FunctionExistMock.php rename to setup/src/Magento/Setup/Test/Unit/Console/Command/FunctionExistMock.php