diff --git a/app/code/Magento/Authorizenet/Model/Authorizenet.php b/app/code/Magento/Authorizenet/Model/Authorizenet.php index 9ab3317a43bb97d950ab32196ce1f9596ba8f7e4..4408c68436707cbfae7332f32cf7d3c902b531f0 100644 --- a/app/code/Magento/Authorizenet/Model/Authorizenet.php +++ b/app/code/Magento/Authorizenet/Model/Authorizenet.php @@ -332,7 +332,7 @@ abstract class Authorizenet extends \Magento\Payment\Model\Method\Cc ->setXCity($billing->getCity()) ->setXState($billing->getRegion()) ->setXZip($billing->getPostcode()) - ->setXCountry($billing->getCountry()) + ->setXCountry($billing->getCountryId()) ->setXPhone($billing->getTelephone()) ->setXFax($billing->getFax()) ->setXCustId($order->getCustomerId()) @@ -352,7 +352,7 @@ abstract class Authorizenet extends \Magento\Payment\Model\Method\Cc ->setXShipToCity($shipping->getCity()) ->setXShipToState($shipping->getRegion()) ->setXShipToZip($shipping->getPostcode()) - ->setXShipToCountry($shipping->getCountry()); + ->setXShipToCountry($shipping->getCountryId()); } $request->setXPoNum($payment->getPoNumber()) diff --git a/app/code/Magento/Authorizenet/Model/Directpost/Request.php b/app/code/Magento/Authorizenet/Model/Directpost/Request.php index 8be7ed5da15ac1dd627ce691ef1cd6eaf9455824..4d5da3e76dc1c3eb4ff204e9ec388f9cece87865 100644 --- a/app/code/Magento/Authorizenet/Model/Directpost/Request.php +++ b/app/code/Magento/Authorizenet/Model/Directpost/Request.php @@ -123,7 +123,7 @@ class Request extends AuthorizenetRequest ->setXCity(strval($billing->getCity())) ->setXState(strval($billing->getRegion())) ->setXZip(strval($billing->getPostcode())) - ->setXCountry(strval($billing->getCountry())) + ->setXCountry(strval($billing->getCountryId())) ->setXPhone(strval($billing->getTelephone())) ->setXFax(strval($billing->getFax())) ->setXCustId(strval($billing->getCustomerId())) @@ -151,7 +151,7 @@ class Request extends AuthorizenetRequest )->setXShipToZip( strval($shipping->getPostcode()) )->setXShipToCountry( - strval($shipping->getCountry()) + strval($shipping->getCountryId()) ); } diff --git a/app/code/Magento/Authorizenet/composer.json b/app/code/Magento/Authorizenet/composer.json index b93cb6688f56d826a8d981518612897aae6f1ac8..f4acc4504604d0625543812ecec21b1d90286e59 100644 --- a/app/code/Magento/Authorizenet/composer.json +++ b/app/code/Magento/Authorizenet/composer.json @@ -12,6 +12,9 @@ "magento/module-catalog": "101.1.*", "magento/framework": "100.2.*" }, + "suggest": { + "magento/module-config": "100.2.*" + }, "type": "magento2-module", "version": "100.2.0-dev", "license": [ diff --git a/app/code/Magento/Authorizenet/etc/di.xml b/app/code/Magento/Authorizenet/etc/di.xml index f5e595fb450e83a60a4ce9b45196018cad335f3d..287cdec6fa0f7f62d68e20bfb49254209ef16ca9 100644 --- a/app/code/Magento/Authorizenet/etc/di.xml +++ b/app/code/Magento/Authorizenet/etc/di.xml @@ -16,4 +16,14 @@ <argument name="storage" xsi:type="object">Magento\Authorizenet\Model\Directpost\Session\Storage</argument> </arguments> </type> + <type name="Magento\Config\Model\Config\Export\ExcludeList"> + <arguments> + <argument name="configs" xsi:type="array"> + <item name="payment/authorizenet_directpost/login" xsi:type="string">1</item> + <item name="payment/authorizenet_directpost/trans_key" xsi:type="string">1</item> + <item name="payment/authorizenet_directpost/trans_md5" xsi:type="string">1</item> + <item name="payment/authorizenet_directpost/merchant_email" xsi:type="string">1</item> + </argument> + </arguments> + </type> </config> 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/Block/Cache/Grid/Massaction/ProductionModeVisibilityChecker.php b/app/code/Magento/Backend/Block/Cache/Grid/Massaction/ProductionModeVisibilityChecker.php new file mode 100644 index 0000000000000000000000000000000000000000..70a125e399ab3034669c011ee24c3877154469e9 --- /dev/null +++ b/app/code/Magento/Backend/Block/Cache/Grid/Massaction/ProductionModeVisibilityChecker.php @@ -0,0 +1,36 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Backend\Block\Cache\Grid\Massaction; + +use Magento\Backend\Block\Widget\Grid\Massaction\VisibilityCheckerInterface; +use Magento\Framework\App\State; + +/** + * Class checks that action can be displayed on massaction list + */ +class ProductionModeVisibilityChecker implements VisibilityCheckerInterface +{ + /** + * @var State + */ + private $state; + + /** + * @param State $state + */ + public function __construct(State $state) + { + $this->state = $state; + } + + /** + * {@inheritdoc} + */ + public function isVisible() + { + return $this->state->getMode() !== State::MODE_PRODUCTION; + } +} diff --git a/app/code/Magento/Backend/Block/Widget/Grid/Column/Renderer/Text.php b/app/code/Magento/Backend/Block/Widget/Grid/Column/Renderer/Text.php index 1427cec7604e88935f53d6c108d77bb58357bdfa..11aa6bf86257cad79ea7698e6c9fdf893ba7082b 100644 --- a/app/code/Magento/Backend/Block/Widget/Grid/Column/Renderer/Text.php +++ b/app/code/Magento/Backend/Block/Widget/Grid/Column/Renderer/Text.php @@ -3,14 +3,13 @@ * Copyright © 2016 Magento. All rights reserved. * See COPYING.txt for license details. */ +namespace Magento\Backend\Block\Widget\Grid\Column\Renderer; + +use Magento\Framework\DataObject; /** * Backend grid item renderer - * - * @author Magento Core Team <core@magentocommerce.com> */ -namespace Magento\Backend\Block\Widget\Grid\Column\Renderer; - class Text extends \Magento\Backend\Block\Widget\Grid\Column\Renderer\AbstractRenderer { /** @@ -21,30 +20,53 @@ class Text extends \Magento\Backend\Block\Widget\Grid\Column\Renderer\AbstractRe protected $_variablePattern = '/\\$([a-z0-9_]+)/i'; /** - * Renders grid column + * Get value for the cel * - * @param \Magento\Framework\DataObject $row - * @return mixed + * @param DataObject $row + * @return string */ - public function _getValue(\Magento\Framework\DataObject $row) + public function _getValue(DataObject $row) { - $format = $this->getColumn()->getFormat() ? $this->getColumn()->getFormat() : null; - $defaultValue = $this->getColumn()->getDefault(); - if ($format === null) { - // If no format and it column not filtered specified return data as is. - $data = parent::_getValue($row); - $string = $data === null ? $defaultValue : $data; - return $this->escapeHtml($string); - } elseif (preg_match_all($this->_variablePattern, $format, $matches)) { - // Parsing of format string - $formattedString = $format; - foreach ($matches[0] as $matchIndex => $match) { - $value = $row->getData($matches[1][$matchIndex]); - $formattedString = str_replace($match, $value, $formattedString); + if (null === $this->getColumn()->getFormat()) { + return $this->getSimpleValue($row); + } + return $this->getFormattedValue($row); + } + + /** + * Get simple value + * + * @param DataObject $row + * @return string + */ + private function getSimpleValue(DataObject $row) + { + $data = parent::_getValue($row); + $value = null === $data ? $this->getColumn()->getDefault() : $data; + if (true === $this->getColumn()->getTranslate()) { + $value = __($value); + } + return $this->escapeHtml($value); + } + + /** + * Replace placeholders in the string with values + * + * @param DataObject $row + * @return string + */ + private function getFormattedValue(DataObject $row) + { + $value = $this->getColumn()->getFormat() ?: null; + if (true === $this->getColumn()->getTranslate()) { + $value = __($value); + } + if (preg_match_all($this->_variablePattern, $value, $matches)) { + foreach ($matches[0] as $index => $match) { + $replacement = $row->getData($matches[1][$index]); + $value = str_replace($match, $replacement, $value); } - return $formattedString; - } else { - return $this->escapeHtml($format); } + return $this->escapeHtml($value); } } diff --git a/app/code/Magento/Backend/Block/Widget/Grid/Massaction.php b/app/code/Magento/Backend/Block/Widget/Grid/Massaction.php index ffe12c6cff46ee17442f7a69293172c02e206d30..c86907cc98042b30f6bac68ea0b0d2977ae87591 100644 --- a/app/code/Magento/Backend/Block/Widget/Grid/Massaction.php +++ b/app/code/Magento/Backend/Block/Widget/Grid/Massaction.php @@ -3,14 +3,11 @@ * Copyright © 2016 Magento. All rights reserved. * See COPYING.txt for license details. */ +namespace Magento\Backend\Block\Widget\Grid; /** * Grid widget massaction default block - * - * @author Magento Core Team <core@magentocommerce.com> */ -namespace Magento\Backend\Block\Widget\Grid; - class Massaction extends \Magento\Backend\Block\Widget\Grid\Massaction\AbstractMassaction { } diff --git a/app/code/Magento/Backend/Block/Widget/Grid/Massaction/AbstractMassaction.php b/app/code/Magento/Backend/Block/Widget/Grid/Massaction/AbstractMassaction.php index 2f3df1377b395de426cc573f4d48016de82d7229..7f697599c7003583d08bc6c2f40ff138971bd4c0 100644 --- a/app/code/Magento/Backend/Block/Widget/Grid/Massaction/AbstractMassaction.php +++ b/app/code/Magento/Backend/Block/Widget/Grid/Massaction/AbstractMassaction.php @@ -5,14 +5,14 @@ */ namespace Magento\Backend\Block\Widget\Grid\Massaction; -use Magento\Framework\View\Element\Template; +use Magento\Backend\Block\Widget\Grid\Massaction\VisibilityCheckerInterface as VisibilityChecker; +use Magento\Framework\DataObject; /** * Grid widget massaction block * * @method \Magento\Quote\Model\Quote setHideFormElement(boolean $value) Hide Form element to prevent IE errors * @method boolean getHideFormElement() - * @author Magento Core Team <core@magentocommerce.com> */ abstract class AbstractMassaction extends \Magento\Backend\Block\Widget { @@ -73,20 +73,21 @@ abstract class AbstractMassaction extends \Magento\Backend\Block\Widget * 'complete' => string, // Only for ajax enabled grid (optional) * 'url' => string, * 'confirm' => string, // text of confirmation of this action (optional) - * 'additional' => string // (optional) + * 'additional' => string, // (optional) + * 'visible' => object // instance of VisibilityCheckerInterface (optional) * ); * * @param string $itemId - * @param array|\Magento\Framework\DataObject $item + * @param array|DataObject $item * @return $this */ public function addItem($itemId, $item) { if (is_array($item)) { - $item = new \Magento\Framework\DataObject($item); + $item = new DataObject($item); } - if ($item instanceof \Magento\Framework\DataObject) { + if ($item instanceof DataObject && $this->isVisible($item)) { $item->setId($itemId); $item->setUrl($this->getUrl($item->getUrl())); $this->_items[$itemId] = $item; @@ -95,6 +96,19 @@ abstract class AbstractMassaction extends \Magento\Backend\Block\Widget return $this; } + /** + * Check that item can be added to list + * + * @param DataObject $item + * @return bool + */ + private function isVisible(DataObject $item) + { + /** @var VisibilityChecker $checker */ + $checker = $item->getData('visible'); + return (!$checker instanceof VisibilityChecker) || $checker->isVisible(); + } + /** * Retrieve massaction item with id $itemId * diff --git a/app/code/Magento/Backend/Block/Widget/Grid/Massaction/VisibilityCheckerInterface.php b/app/code/Magento/Backend/Block/Widget/Grid/Massaction/VisibilityCheckerInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..934c4a84d145f349e028fc5497b9db62b2cdac54 --- /dev/null +++ b/app/code/Magento/Backend/Block/Widget/Grid/Massaction/VisibilityCheckerInterface.php @@ -0,0 +1,18 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Backend\Block\Widget\Grid\Massaction; + +use Magento\Framework\View\Element\Block\ArgumentInterface; + +interface VisibilityCheckerInterface extends ArgumentInterface +{ + /** + * Check that action can be displayed on massaction list + * + * @return bool + */ + public function isVisible(); +} diff --git a/app/code/Magento/Backend/Controller/Adminhtml/Cache/MassDisable.php b/app/code/Magento/Backend/Controller/Adminhtml/Cache/MassDisable.php index 7266775959fc348796fabbb150f9e49b2ae9f7ad..42cbe229815aef16e13005ebdc802ec9b9bbd5c5 100644 --- a/app/code/Magento/Backend/Controller/Adminhtml/Cache/MassDisable.php +++ b/app/code/Magento/Backend/Controller/Adminhtml/Cache/MassDisable.php @@ -8,15 +8,41 @@ namespace Magento\Backend\Controller\Adminhtml\Cache; use Magento\Framework\Exception\LocalizedException; use Magento\Framework\Controller\ResultFactory; +use Magento\Framework\App\State; +use Magento\Framework\App\ObjectManager; +/** + * Controller disables some types of cache + */ class MassDisable extends \Magento\Backend\Controller\Adminhtml\Cache { + /** + * @var State + */ + private $state; + /** * Mass action for cache disabling * * @return \Magento\Backend\Model\View\Result\Redirect */ public function execute() + { + if ($this->getState()->getMode() === State::MODE_PRODUCTION) { + $this->messageManager->addErrorMessage(__('You can\'t change status of cache type(s) in production mode')); + } else { + $this->disableCache(); + } + + return $this->resultFactory->create(ResultFactory::TYPE_REDIRECT)->setPath('adminhtml/*'); + } + + /** + * Disable cache + * + * @return void + */ + private function disableCache() { try { $types = $this->getRequest()->getParam('types'); @@ -41,9 +67,20 @@ class MassDisable extends \Magento\Backend\Controller\Adminhtml\Cache } catch (\Exception $e) { $this->messageManager->addException($e, __('An error occurred while disabling cache.')); } + } + + /** + * Get State Instance + * + * @return State + * @deprecated + */ + private function getState() + { + if ($this->state === null) { + $this->state = ObjectManager::getInstance()->get(State::class); + } - /** @var \Magento\Backend\Model\View\Result\Redirect $resultRedirect */ - $resultRedirect = $this->resultFactory->create(ResultFactory::TYPE_REDIRECT); - return $resultRedirect->setPath('adminhtml/*'); + return $this->state; } } diff --git a/app/code/Magento/Backend/Controller/Adminhtml/Cache/MassEnable.php b/app/code/Magento/Backend/Controller/Adminhtml/Cache/MassEnable.php index 6c8bccfee166a5f746fd138c1b4e043ac1834542..8c4117831e8c8d7463b3112ac495cdede04f13d5 100644 --- a/app/code/Magento/Backend/Controller/Adminhtml/Cache/MassEnable.php +++ b/app/code/Magento/Backend/Controller/Adminhtml/Cache/MassEnable.php @@ -8,15 +8,41 @@ namespace Magento\Backend\Controller\Adminhtml\Cache; use Magento\Framework\Exception\LocalizedException; use Magento\Framework\Controller\ResultFactory; +use Magento\Framework\App\State; +use Magento\Framework\App\ObjectManager; +/** + * Controller enables some types of cache + */ class MassEnable extends \Magento\Backend\Controller\Adminhtml\Cache { + /** + * @var State + */ + private $state; + /** * Mass action for cache enabling * * @return \Magento\Backend\Model\View\Result\Redirect */ public function execute() + { + if ($this->getState()->getMode() === State::MODE_PRODUCTION) { + $this->messageManager->addErrorMessage(__('You can\'t change status of cache type(s) in production mode')); + } else { + $this->enableCache(); + } + + return $this->resultFactory->create(ResultFactory::TYPE_REDIRECT)->setPath('adminhtml/*'); + } + + /** + * Enable cache + * + * @return void + */ + private function enableCache() { try { $types = $this->getRequest()->getParam('types'); @@ -40,9 +66,20 @@ class MassEnable extends \Magento\Backend\Controller\Adminhtml\Cache } catch (\Exception $e) { $this->messageManager->addException($e, __('An error occurred while enabling cache.')); } + } + + /** + * Get State Instance + * + * @return State + * @deprecated + */ + private function getState() + { + if ($this->state === null) { + $this->state = ObjectManager::getInstance()->get(State::class); + } - /** @var \Magento\Backend\Model\View\Result\Redirect $resultRedirect */ - $resultRedirect = $this->resultFactory->create(ResultFactory::TYPE_REDIRECT); - return $resultRedirect->setPath('adminhtml/*'); + return $this->state; } } diff --git a/app/code/Magento/Backend/Model/Session/Quote.php b/app/code/Magento/Backend/Model/Session/Quote.php index 12a4d4d138f5323f420dc56f5ba466e6efda0a46..6ca269488294a7d5036eedd9bacae42266ae8ea0 100644 --- a/app/code/Magento/Backend/Model/Session/Quote.php +++ b/app/code/Magento/Backend/Model/Session/Quote.php @@ -7,8 +7,6 @@ namespace Magento\Backend\Model\Session; use Magento\Customer\Api\CustomerRepositoryInterface; use Magento\Customer\Api\GroupManagementInterface; -use Magento\Framework\App\ObjectManager; -use Magento\Quote\Api\CartManagementInterface; /** * Adminhtml quote session @@ -81,11 +79,6 @@ class Quote extends \Magento\Framework\Session\SessionManager */ protected $quoteFactory; - /** - * @var \Magento\Quote\Api\CartManagementInterface; - */ - private $cartManagement; - /** * @param \Magento\Framework\App\Request\Http $request * @param \Magento\Framework\Session\SidResolverInterface $sidResolver diff --git a/app/code/Magento/Backend/Model/Url.php b/app/code/Magento/Backend/Model/Url.php index c1aa03a457cac21032566c9b0540f7b5972ab563..f09c9c04ee6bb942eb774b60837dbbe598a1426b 100644 --- a/app/code/Magento/Backend/Model/Url.php +++ b/app/code/Magento/Backend/Model/Url.php @@ -5,6 +5,8 @@ */ namespace Magento\Backend\Model; +use Magento\Framework\Url\HostChecker; +use Magento\Framework\App\ObjectManager; /** * Class \Magento\Backend\Model\UrlInterface @@ -77,6 +79,8 @@ class Url extends \Magento\Framework\Url implements \Magento\Backend\Model\UrlIn protected $_scope; /** + * Constructor + * * @param \Magento\Framework\App\Route\ConfigInterface $routeConfig * @param \Magento\Framework\App\RequestInterface $request * @param \Magento\Framework\Url\SecurityInfoInterface $urlSecurityInfo @@ -96,7 +100,7 @@ class Url extends \Magento\Framework\Url implements \Magento\Backend\Model\UrlIn * @param \Magento\Store\Model\StoreFactory $storeFactory * @param \Magento\Framework\Data\Form\FormKey $formKey * @param array $data - * + * @param HostChecker|null $hostChecker * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( @@ -118,9 +122,11 @@ class Url extends \Magento\Framework\Url implements \Magento\Backend\Model\UrlIn \Magento\Framework\Encryption\EncryptorInterface $encryptor, \Magento\Store\Model\StoreFactory $storeFactory, \Magento\Framework\Data\Form\FormKey $formKey, - array $data = [] + array $data = [], + HostChecker $hostChecker = null ) { $this->_encryptor = $encryptor; + $hostChecker = $hostChecker ?: ObjectManager::getInstance()->get(HostChecker::class); parent::__construct( $routeConfig, $request, @@ -133,7 +139,8 @@ class Url extends \Magento\Framework\Url implements \Magento\Backend\Model\UrlIn $scopeConfig, $routeParamsPreprocessor, $scopeType, - $data + $data, + $hostChecker ); $this->_backendHelper = $backendHelper; $this->_menuConfig = $menuConfig; 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/Backend/Test/Unit/Block/Widget/Grid/MassactionTest.php b/app/code/Magento/Backend/Test/Unit/Block/Widget/Grid/MassactionTest.php index 234e9d857549e073cb2fdba1bc39b3e4c7248349..79ecb388873eba21ed9fbfd166a651987194aa52 100644 --- a/app/code/Magento/Backend/Test/Unit/Block/Widget/Grid/MassactionTest.php +++ b/app/code/Magento/Backend/Test/Unit/Block/Widget/Grid/MassactionTest.php @@ -9,6 +9,8 @@ */ namespace Magento\Backend\Test\Unit\Block\Widget\Grid; +use Magento\Backend\Block\Widget\Grid\Massaction\VisibilityCheckerInterface as VisibilityChecker; + class MassactionTest extends \PHPUnit_Framework_TestCase { /** @@ -17,12 +19,12 @@ class MassactionTest extends \PHPUnit_Framework_TestCase protected $_block; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\View\Layout|\PHPUnit_Framework_MockObject_MockObject */ protected $_layoutMock; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Backend\Block\Widget\Grid|\PHPUnit_Framework_MockObject_MockObject */ protected $_gridMock; @@ -32,63 +34,63 @@ class MassactionTest extends \PHPUnit_Framework_TestCase protected $_eventManagerMock; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Backend\Model\Url|\PHPUnit_Framework_MockObject_MockObject */ protected $_urlModelMock; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\App\Request\Http|\PHPUnit_Framework_MockObject_MockObject */ protected $_requestMock; + /** + * @var VisibilityChecker|\PHPUnit_Framework_MockObject_MockObject + */ + private $visibilityCheckerMock; + protected function setUp() { - $this->_gridMock = $this->getMock( - \Magento\Backend\Block\Widget\Grid::class, - ['getId', 'getCollection'], - [], - '', - false - ); - $this->_gridMock->expects($this->any())->method('getId')->will($this->returnValue('test_grid')); - - $this->_layoutMock = $this->getMock( - \Magento\Framework\View\Layout::class, - ['getParentName', 'getBlock', 'helper'], - [], - '', - false, - false - ); + $this->_gridMock = $this->getMockBuilder(\Magento\Backend\Block\Widget\Grid::class) + ->disableOriginalConstructor() + ->disableOriginalClone() + ->setMethods(['getId', 'getCollection']) + ->getMock(); + $this->_gridMock->expects($this->any()) + ->method('getId') + ->willReturn('test_grid'); - $this->_layoutMock->expects( - $this->any() - )->method( - 'getParentName' - )->with( - 'test_grid_massaction' - )->will( - $this->returnValue('test_grid') - ); - $this->_layoutMock->expects( - $this->any() - )->method( - 'getBlock' - )->with( - 'test_grid' - )->will( - $this->returnValue($this->_gridMock) - ); + $this->_layoutMock = $this->getMockBuilder(\Magento\Framework\View\Layout::class) + ->disableOriginalConstructor() + ->disableOriginalClone() + ->setMethods(['getParentName', 'getBlock', 'helper']) + ->getMock(); + $this->_layoutMock->expects($this->any()) + ->method('getParentName') + ->with('test_grid_massaction') + ->willReturn('test_grid'); + $this->_layoutMock->expects($this->any()) + ->method('getBlock') + ->with('test_grid') + ->willReturn($this->_gridMock); + + $this->_requestMock = $this->getMockBuilder(\Magento\Framework\App\Request\Http::class) + ->disableOriginalConstructor() + ->disableOriginalClone() + ->getMock(); - $this->_requestMock = $this->getMock(\Magento\Framework\App\Request\Http::class, [], [], '', false); + $this->_urlModelMock = $this->getMockBuilder(\Magento\Backend\Model\Url::class) + ->disableOriginalConstructor() + ->disableOriginalClone() + ->getMock(); - $this->_urlModelMock = $this->getMock(\Magento\Backend\Model\Url::class, [], [], '', false); + $this->visibilityCheckerMock = $this->getMockBuilder(VisibilityChecker::class) + ->getMockForAbstractClass(); $arguments = [ 'layout' => $this->_layoutMock, 'request' => $this->_requestMock, 'urlBuilder' => $this->_urlModelMock, - 'data' => ['massaction_id_field' => 'test_id', 'massaction_id_filter' => 'test_id'], + 'data' => ['massaction_id_field' => 'test_id', 'massaction_id_filter' => 'test_id'] ]; $objectManagerHelper = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); @@ -124,26 +126,24 @@ class MassactionTest extends \PHPUnit_Framework_TestCase } /** - * @param $itemId - * @param $item + * @param string $itemId + * @param \Magento\Framework\DataObject $item * @param $expectedItem \Magento\Framework\DataObject - * @dataProvider itemsDataProvider + * @dataProvider itemsProcessingDataProvider */ public function testItemsProcessing($itemId, $item, $expectedItem) { - $this->_urlModelMock->expects( - $this->any() - )->method( - 'getBaseUrl' - )->will( - $this->returnValue('http://localhost/index.php') - ); + $this->_urlModelMock->expects($this->any()) + ->method('getBaseUrl') + ->willReturn('http://localhost/index.php'); $urlReturnValueMap = [ ['*/*/test1', [], 'http://localhost/index.php/backend/admin/test/test1'], ['*/*/test2', [], 'http://localhost/index.php/backend/admin/test/test2'], ]; - $this->_urlModelMock->expects($this->any())->method('getUrl')->will($this->returnValueMap($urlReturnValueMap)); + $this->_urlModelMock->expects($this->any()) + ->method('getUrl') + ->willReturnMap($urlReturnValueMap); $this->_block->addItem($itemId, $item); $this->assertEquals(1, $this->_block->getCount()); @@ -157,7 +157,10 @@ class MassactionTest extends \PHPUnit_Framework_TestCase $this->assertNull($this->_block->getItem($itemId)); } - public function itemsDataProvider() + /** + * @return array + */ + public function itemsProcessingDataProvider() { return [ [ @@ -186,22 +189,17 @@ class MassactionTest extends \PHPUnit_Framework_TestCase } /** - * @param $param - * @param $expectedJson - * @param $expected + * @param string $param + * @param string $expectedJson + * @param array $expected * @dataProvider selectedDataProvider */ public function testSelected($param, $expectedJson, $expected) { - $this->_requestMock->expects( - $this->any() - )->method( - 'getParam' - )->with( - $this->_block->getFormFieldNameInternal() - )->will( - $this->returnValue($param) - ); + $this->_requestMock->expects($this->any()) + ->method('getParam') + ->with($this->_block->getFormFieldNameInternal()) + ->willReturn($param); $this->assertEquals($expectedJson, $this->_block->getSelectedJson()); $this->assertEquals($expected, $this->_block->getSelected()); @@ -262,6 +260,9 @@ class MassactionTest extends \PHPUnit_Framework_TestCase $this->assertEquals($result, $this->_block->getGridIdsJson()); } + /** + * @return array + */ public function dataProviderGetGridIdsJsonWithUseSelectAll() { return [ @@ -279,4 +280,71 @@ class MassactionTest extends \PHPUnit_Framework_TestCase ], ]; } + + /** + * @param string $itemId + * @param array|\Magento\Framework\DataObject $item + * @param int $count + * @param bool $withVisibilityChecker + * @param bool $isVisible + * @dataProvider addItemDataProvider + */ + public function testAddItem($itemId, $item, $count, $withVisibilityChecker, $isVisible) + { + $this->visibilityCheckerMock->expects($this->any()) + ->method('isVisible') + ->willReturn($isVisible); + + if ($withVisibilityChecker) { + $item['visible'] = $this->visibilityCheckerMock; + } + + $urlReturnValueMap = [ + ['*/*/test1', [], 'http://localhost/index.php/backend/admin/test/test1'], + ['*/*/test2', [], 'http://localhost/index.php/backend/admin/test/test2'], + ]; + $this->_urlModelMock->expects($this->any()) + ->method('getUrl') + ->willReturnMap($urlReturnValueMap); + + $this->_block->addItem($itemId, $item); + $this->assertEquals($count, $this->_block->getCount()); + } + + /** + * @return array + */ + public function addItemDataProvider() + { + return [ + [ + 'itemId' => 'test1', + 'item' => ['label' => 'Test 1', 'url' => '*/*/test1'], + 'count' => 1, + 'withVisibilityChecker' => false, + '$isVisible' => false, + ], + [ + 'itemId' => 'test2', + 'item' => ['label' => 'Test 2', 'url' => '*/*/test2'], + 'count' => 1, + 'withVisibilityChecker' => false, + 'isVisible' => true, + ], + [ + 'itemId' => 'test1', + 'item' => ['label' => 'Test 1. Hide', 'url' => '*/*/test1'], + 'count' => 0, + 'withVisibilityChecker' => true, + 'isVisible' => false, + ], + [ + 'itemId' => 'test2', + 'item' => ['label' => 'Test 2. Does not hide', 'url' => '*/*/test2'], + 'count' => 1, + 'withVisibilityChecker' => true, + 'isVisible' => true, + ] + ]; + } } diff --git a/app/code/Magento/Backend/Test/Unit/Controller/Adminhtml/Cache/MassDisableTest.php b/app/code/Magento/Backend/Test/Unit/Controller/Adminhtml/Cache/MassDisableTest.php new file mode 100644 index 0000000000000000000000000000000000000000..b2fc808b0e237b8bbeb5b323fb173ecff67d8071 --- /dev/null +++ b/app/code/Magento/Backend/Test/Unit/Controller/Adminhtml/Cache/MassDisableTest.php @@ -0,0 +1,224 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Backend\Test\Unit\Controller\Adminhtml\Cache; + +use PHPUnit_Framework_MockObject_MockObject as MockObject; +use Magento\Backend\Controller\Adminhtml\Cache\MassDisable; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper; +use Magento\Framework\App\State; +use Magento\Backend\App\Action\Context; +use Magento\Framework\Message\ManagerInterface as MessageManager; +use Magento\Framework\Controller\ResultFactory; +use Magento\Backend\Model\View\Result\Redirect; +use Magento\Framework\App\RequestInterface as Request; +use Magento\Framework\App\Cache\TypeListInterface as CacheTypeList; +use Magento\Framework\App\Cache\StateInterface as CacheState; + +/** + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ +class MassDisableTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var MassDisable + */ + private $controller; + + /** + * @var State|MockObject + */ + private $stateMock; + + /** + * @var MessageManager|MockObject + */ + private $messageManagerMock; + + /** + * @var Redirect|MockObject + */ + private $redirectMock; + + /** + * @var Request|MockObject + */ + private $requestMock; + + /** + * @var CacheTypeList|MockObject + */ + private $cacheTypeListMock; + + /** + * @var CacheState|MockObject + */ + private $cacheStateMock; + + protected function setUp() + { + $objectManagerHelper = new ObjectManagerHelper($this); + + $this->stateMock = $this->getMockBuilder(State::class) + ->disableOriginalConstructor() + ->disableOriginalClone() + ->getMock(); + + $this->messageManagerMock = $this->getMockBuilder(MessageManager::class) + ->getMockForAbstractClass(); + + $this->requestMock = $this->getMockBuilder(Request::class) + ->getMockForAbstractClass(); + + $this->cacheTypeListMock = $this->getMockBuilder(CacheTypeList::class) + ->getMockForAbstractClass(); + + $this->cacheStateMock = $this->getMockBuilder(CacheState::class) + ->getMockForAbstractClass(); + + $this->redirectMock = $this->getMockBuilder(Redirect::class) + ->disableOriginalConstructor() + ->disableOriginalClone() + ->getMock(); + $this->redirectMock->expects($this->once()) + ->method('setPath') + ->with('adminhtml/*') + ->willReturnSelf(); + $resultFactoryMock = $this->getMockBuilder(ResultFactory::class) + ->disableOriginalConstructor() + ->disableOriginalClone() + ->getMock(); + $resultFactoryMock->expects($this->once()) + ->method('create') + ->with(ResultFactory::TYPE_REDIRECT) + ->willReturn($this->redirectMock); + + $contextMock = $this->getMockBuilder(Context::class) + ->disableOriginalConstructor() + ->disableOriginalClone() + ->getMock(); + $contextMock->expects($this->once()) + ->method('getMessageManager') + ->willReturn($this->messageManagerMock); + $contextMock->expects($this->once()) + ->method('getResultFactory') + ->willReturn($resultFactoryMock); + $contextMock->expects($this->once()) + ->method('getRequest') + ->willReturn($this->requestMock); + + $this->controller = $objectManagerHelper->getObject( + MassDisable::class, + [ + 'context' => $contextMock, + 'cacheTypeList' => $this->cacheTypeListMock, + 'cacheState' => $this->cacheStateMock + ] + ); + $objectManagerHelper->setBackwardCompatibleProperty($this->controller, 'state', $this->stateMock); + } + + public function testExecuteInProductionMode() + { + $this->stateMock->expects($this->once()) + ->method('getMode') + ->willReturn(State::MODE_PRODUCTION); + + $this->messageManagerMock->expects($this->once()) + ->method('addErrorMessage') + ->with('You can\'t change status of cache type(s) in production mode', null) + ->willReturnSelf(); + + $this->assertSame($this->redirectMock, $this->controller->execute()); + } + + public function testExecuteInvalidTypeCache() + { + $this->stateMock->expects($this->once()) + ->method('getMode') + ->willReturn(State::MODE_DEVELOPER); + + $this->cacheTypeListMock->expects($this->once()) + ->method('getTypes') + ->willReturn([ + 'pageCache' => [ + 'id' => 'pageCache', + 'label' => 'Cache of Page' + ] + ]); + + $this->requestMock->expects($this->once()) + ->method('getParam') + ->with('types') + ->willReturn(['someCache']); + + $this->messageManagerMock->expects($this->once()) + ->method('addError') + ->with('Specified cache type(s) don\'t exist: someCache') + ->willReturnSelf(); + + $this->assertSame($this->redirectMock, $this->controller->execute()); + } + + public function testExecuteWithException() + { + $exception = new \Exception(); + + $this->stateMock->expects($this->once()) + ->method('getMode') + ->willReturn(State::MODE_DEVELOPER); + + $this->requestMock->expects($this->once()) + ->method('getParam') + ->willThrowException($exception); + + $this->messageManagerMock->expects($this->once()) + ->method('addException') + ->with($exception, 'An error occurred while disabling cache.') + ->willReturnSelf(); + + $this->assertSame($this->redirectMock, $this->controller->execute()); + } + + public function testExecuteSuccess() + { + $cacheType = 'pageCache'; + + $this->stateMock->expects($this->once()) + ->method('getMode') + ->willReturn(State::MODE_DEVELOPER); + + $this->cacheTypeListMock->expects($this->once()) + ->method('getTypes') + ->willReturn([ + 'pageCache' => [ + 'id' => 'pageCache', + 'label' => 'Cache of Page' + ] + ]); + + $this->requestMock->expects($this->once()) + ->method('getParam') + ->with('types') + ->willReturn([$cacheType]); + + $this->cacheStateMock->expects($this->once()) + ->method('isEnabled') + ->with($cacheType) + ->willReturn(true); + $this->cacheStateMock->expects($this->once()) + ->method('setEnabled') + ->with($cacheType, false); + $this->cacheStateMock->expects($this->once()) + ->method('persist'); + + $this->messageManagerMock->expects($this->once()) + ->method('addSuccess') + ->with('1 cache type(s) disabled.') + ->willReturnSelf(); + + $this->assertSame($this->redirectMock, $this->controller->execute()); + } +} diff --git a/app/code/Magento/Backend/Test/Unit/Controller/Adminhtml/Cache/MassEnableTest.php b/app/code/Magento/Backend/Test/Unit/Controller/Adminhtml/Cache/MassEnableTest.php new file mode 100644 index 0000000000000000000000000000000000000000..8c1b9f1718ab924379cf3e5440a942c0be5502d7 --- /dev/null +++ b/app/code/Magento/Backend/Test/Unit/Controller/Adminhtml/Cache/MassEnableTest.php @@ -0,0 +1,224 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Backend\Test\Unit\Controller\Adminhtml\Cache; + +use PHPUnit_Framework_MockObject_MockObject as MockObject; +use Magento\Backend\Controller\Adminhtml\Cache\MassEnable; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper; +use Magento\Framework\App\State; +use Magento\Backend\App\Action\Context; +use Magento\Framework\Message\ManagerInterface as MessageManager; +use Magento\Framework\Controller\ResultFactory; +use Magento\Backend\Model\View\Result\Redirect; +use Magento\Framework\App\RequestInterface as Request; +use Magento\Framework\App\Cache\TypeListInterface as CacheTypeList; +use Magento\Framework\App\Cache\StateInterface as CacheState; + +/** + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ +class MassEnableTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var MassEnable + */ + private $controller; + + /** + * @var State|MockObject + */ + private $stateMock; + + /** + * @var MessageManager|MockObject + */ + private $messageManagerMock; + + /** + * @var Redirect|MockObject + */ + private $redirectMock; + + /** + * @var Request|MockObject + */ + private $requestMock; + + /** + * @var CacheTypeList|MockObject + */ + private $cacheTypeListMock; + + /** + * @var CacheState|MockObject + */ + private $cacheStateMock; + + protected function setUp() + { + $objectManagerHelper = new ObjectManagerHelper($this); + + $this->stateMock = $this->getMockBuilder(State::class) + ->disableOriginalConstructor() + ->disableOriginalClone() + ->getMock(); + + $this->messageManagerMock = $this->getMockBuilder(MessageManager::class) + ->getMockForAbstractClass(); + + $this->requestMock = $this->getMockBuilder(Request::class) + ->getMockForAbstractClass(); + + $this->cacheTypeListMock = $this->getMockBuilder(CacheTypeList::class) + ->getMockForAbstractClass(); + + $this->cacheStateMock = $this->getMockBuilder(CacheState::class) + ->getMockForAbstractClass(); + + $this->redirectMock = $this->getMockBuilder(Redirect::class) + ->disableOriginalConstructor() + ->disableOriginalClone() + ->getMock(); + $this->redirectMock->expects($this->once()) + ->method('setPath') + ->with('adminhtml/*') + ->willReturnSelf(); + $resultFactoryMock = $this->getMockBuilder(ResultFactory::class) + ->disableOriginalConstructor() + ->disableOriginalClone() + ->getMock(); + $resultFactoryMock->expects($this->once()) + ->method('create') + ->with(ResultFactory::TYPE_REDIRECT) + ->willReturn($this->redirectMock); + + $contextMock = $this->getMockBuilder(Context::class) + ->disableOriginalConstructor() + ->disableOriginalClone() + ->getMock(); + $contextMock->expects($this->once()) + ->method('getMessageManager') + ->willReturn($this->messageManagerMock); + $contextMock->expects($this->once()) + ->method('getResultFactory') + ->willReturn($resultFactoryMock); + $contextMock->expects($this->once()) + ->method('getRequest') + ->willReturn($this->requestMock); + + $this->controller = $objectManagerHelper->getObject( + MassEnable::class, + [ + 'context' => $contextMock, + 'cacheTypeList' => $this->cacheTypeListMock, + 'cacheState' => $this->cacheStateMock + ] + ); + $objectManagerHelper->setBackwardCompatibleProperty($this->controller, 'state', $this->stateMock); + } + + public function testExecuteInProductionMode() + { + $this->stateMock->expects($this->once()) + ->method('getMode') + ->willReturn(State::MODE_PRODUCTION); + + $this->messageManagerMock->expects($this->once()) + ->method('addErrorMessage') + ->with('You can\'t change status of cache type(s) in production mode', null) + ->willReturnSelf(); + + $this->assertSame($this->redirectMock, $this->controller->execute()); + } + + public function testExecuteInvalidTypeCache() + { + $this->stateMock->expects($this->once()) + ->method('getMode') + ->willReturn(State::MODE_DEVELOPER); + + $this->cacheTypeListMock->expects($this->once()) + ->method('getTypes') + ->willReturn([ + 'pageCache' => [ + 'id' => 'pageCache', + 'label' => 'Cache of Page' + ] + ]); + + $this->requestMock->expects($this->once()) + ->method('getParam') + ->with('types') + ->willReturn(['someCache']); + + $this->messageManagerMock->expects($this->once()) + ->method('addError') + ->with('Specified cache type(s) don\'t exist: someCache') + ->willReturnSelf(); + + $this->assertSame($this->redirectMock, $this->controller->execute()); + } + + public function testExecuteWithException() + { + $exception = new \Exception(); + + $this->stateMock->expects($this->once()) + ->method('getMode') + ->willReturn(State::MODE_DEVELOPER); + + $this->requestMock->expects($this->once()) + ->method('getParam') + ->willThrowException($exception); + + $this->messageManagerMock->expects($this->once()) + ->method('addException') + ->with($exception, 'An error occurred while enabling cache.') + ->willReturnSelf(); + + $this->assertSame($this->redirectMock, $this->controller->execute()); + } + + public function testExecuteSuccess() + { + $cacheType = 'pageCache'; + + $this->stateMock->expects($this->once()) + ->method('getMode') + ->willReturn(State::MODE_DEVELOPER); + + $this->cacheTypeListMock->expects($this->once()) + ->method('getTypes') + ->willReturn([ + 'pageCache' => [ + 'id' => 'pageCache', + 'label' => 'Cache of Page' + ] + ]); + + $this->requestMock->expects($this->once()) + ->method('getParam') + ->with('types') + ->willReturn([$cacheType]); + + $this->cacheStateMock->expects($this->once()) + ->method('isEnabled') + ->with($cacheType) + ->willReturn(false); + $this->cacheStateMock->expects($this->once()) + ->method('setEnabled') + ->with($cacheType, true); + $this->cacheStateMock->expects($this->once()) + ->method('persist'); + + $this->messageManagerMock->expects($this->once()) + ->method('addSuccess') + ->with('1 cache type(s) enabled.') + ->willReturnSelf(); + + $this->assertSame($this->redirectMock, $this->controller->execute()); + } +} diff --git a/app/code/Magento/Backend/Test/Unit/Model/Session/QuoteTest.php b/app/code/Magento/Backend/Test/Unit/Model/Session/QuoteTest.php index 5db3c2e41c04adf9bf5f2105df266167c5a77364..99d7fdfab21dedc37a5bc1b144b36f2acb073fbb 100644 --- a/app/code/Magento/Backend/Test/Unit/Model/Session/QuoteTest.php +++ b/app/code/Magento/Backend/Test/Unit/Model/Session/QuoteTest.php @@ -12,6 +12,11 @@ namespace Magento\Backend\Test\Unit\Model\Session; */ class QuoteTest extends \PHPUnit_Framework_TestCase { + /** + * @var \Magento\Framework\TestFramework\Unit\Helper\ObjectManager + */ + private $objectManager; + /** * @var \Magento\Store\Model\StoreManagerInterface|\PHPUnit_Framework_MockObject_MockObject */ @@ -92,11 +97,6 @@ class QuoteTest extends \PHPUnit_Framework_TestCase */ protected $quoteFactoryMock; - /** - * @var \PHPUnit_Framework_MockObject_MockObject - */ - protected $cartManagementMock; - /** * Set up * @@ -105,6 +105,7 @@ class QuoteTest extends \PHPUnit_Framework_TestCase */ protected function setUp() { + $this->objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); $this->customerRepositoryMock = $this->getMockForAbstractClass( \Magento\Customer\Api\CustomerRepositoryInterface::class, [], @@ -197,13 +198,6 @@ class QuoteTest extends \PHPUnit_Framework_TestCase ); $this->quoteFactoryMock = $this->getMock(\Magento\Quote\Model\QuoteFactory::class, ['create'], [], '', false); - $this->cartManagementMock = $this->getMock( - \Magento\Quote\Api\CartManagementInterface::class, - [], - [], - '', - false - ); $this->quote = $this->getMock( \Magento\Backend\Model\Session\Quote::class, @@ -226,10 +220,6 @@ class QuoteTest extends \PHPUnit_Framework_TestCase 'quoteFactory' => $this->quoteFactoryMock ] ); - - $this->prepareObjectManager([ - [\Magento\Quote\Api\CartManagementInterface::class, $this->cartManagementMock] - ]); } /** @@ -416,19 +406,4 @@ class QuoteTest extends \PHPUnit_Framework_TestCase 'customer ids same' => [66, 66, 'never'], ]; } - - /** - * @param array $map - * @deprecated - */ - private function prepareObjectManager($map) - { - $objectManagerMock = $this->getMock(\Magento\Framework\ObjectManagerInterface::class); - $objectManagerMock->expects($this->any())->method('getInstance')->willReturnSelf(); - $objectManagerMock->expects($this->any())->method('get')->will($this->returnValueMap($map)); - $reflectionClass = new \ReflectionClass(\Magento\Framework\App\ObjectManager::class); - $reflectionProperty = $reflectionClass->getProperty('_instance'); - $reflectionProperty->setAccessible(true); - $reflectionProperty->setValue($objectManagerMock); - } } diff --git a/app/code/Magento/Backend/Test/Unit/Model/UrlTest.php b/app/code/Magento/Backend/Test/Unit/Model/UrlTest.php index 2bc3d86e74d697cd64be58742ab2a5e3204e8b01..4eda145156c6dbf881eadf3d88981ffb9318d32c 100644 --- a/app/code/Magento/Backend/Test/Unit/Model/UrlTest.php +++ b/app/code/Magento/Backend/Test/Unit/Model/UrlTest.php @@ -3,16 +3,13 @@ * Copyright © 2016 Magento. All rights reserved. * See COPYING.txt for license details. */ - -// @codingStandardsIgnoreFile - -/** - * Test class for \Magento\Backend\Model\Url - */ namespace Magento\Backend\Test\Unit\Model; +use Magento\Framework\Url\HostChecker; + /** * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + * @codingStandardsIgnoreFile */ class UrlTest extends \PHPUnit_Framework_TestCase { @@ -21,10 +18,12 @@ class UrlTest extends \PHPUnit_Framework_TestCase */ protected $_model; + /** + * @var string + */ protected $_areaFrontName = 'backendArea'; /** - * Mock menu model * @var \PHPUnit_Framework_MockObject_MockObject */ protected $_menuMock; @@ -62,7 +61,7 @@ class UrlTest extends \PHPUnit_Framework_TestCase /** * @var \PHPUnit_Framework_MockObject_MockObject */ - protected $_paramsResolverMock; + protected $routeParamsResolverFactoryMock; /** * @var \Magento\Framework\Encryption\EncryptorInterface @@ -75,6 +74,7 @@ class UrlTest extends \PHPUnit_Framework_TestCase */ protected function setUp() { + $objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); $this->_menuMock = $this->getMock( \Magento\Backend\Model\Menu::class, [], @@ -141,25 +141,21 @@ class UrlTest extends \PHPUnit_Framework_TestCase false, false ); - $helper = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); $this->_encryptor = $this->getMock(\Magento\Framework\Encryption\Encryptor::class, null, [], '', false); - $this->_paramsResolverMock = $this->getMock( + $routeParamsResolver = $this->getMock(\Magento\Framework\Url\RouteParamsResolver::class, [], [], '', false); + $this->routeParamsResolverFactoryMock = $this->getMock( \Magento\Framework\Url\RouteParamsResolverFactory::class, [], [], '', false ); - $this->_paramsResolverMock->expects( - $this->any() - )->method( - 'create' - )->will( - $this->returnValue( - $this->getMock(\Magento\Framework\Url\RouteParamsResolver::class, [], [], '', false) - ) - ); - $this->_model = $helper->getObject( + $this->routeParamsResolverFactoryMock->expects($this->any()) + ->method('create') + ->willReturn($routeParamsResolver); + /** @var HostChecker|\PHPUnit_Framework_MockObject_MockObject $hostCheckerMock */ + $hostCheckerMock = $this->getMock(HostChecker::class, [], [], '', false); + $this->_model = $objectManager->getObject( \Magento\Backend\Model\Url::class, [ 'scopeConfig' => $this->_scopeConfigMock, @@ -168,31 +164,10 @@ class UrlTest extends \PHPUnit_Framework_TestCase 'menuConfig' => $this->_menuConfigMock, 'authSession' => $this->_authSessionMock, 'encryptor' => $this->_encryptor, - 'routeParamsResolverFactory' => $this->_paramsResolverMock + 'routeParamsResolverFactory' => $this->routeParamsResolverFactoryMock, + 'hostChecker' => $hostCheckerMock ] ); - $this->_paramsResolverMock->expects( - $this->any() - )->method( - 'create' - )->will( - $this->returnValue( - $this->getMock(\Magento\Framework\Url\RouteParamsResolver::class, [], [], '', false) - ) - ); - $this->_model = $helper->getObject( - \Magento\Backend\Model\Url::class, - [ - 'scopeConfig' => $this->_scopeConfigMock, - 'backendHelper' => $helperMock, - 'formKey' => $this->_formKey, - 'menuConfig' => $this->_menuConfigMock, - 'authSession' => $this->_authSessionMock, - 'encryptor' => $this->_encryptor, - 'routeParamsResolverFactory' => $this->_paramsResolverMock - ] - ); - $this->_requestMock = $this->getMock(\Magento\Framework\App\Request\Http::class, [], [], '', false); $this->_model->setRequest($this->_requestMock); } @@ -262,7 +237,7 @@ class UrlTest extends \PHPUnit_Framework_TestCase [ 'backendHelper' => $helperMock, 'authSession' => $this->_authSessionMock, - 'routeParamsResolverFactory' => $this->_paramsResolverMock + 'routeParamsResolverFactory' => $this->routeParamsResolverFactoryMock ] ); $urlModel->getAreaFrontName(); diff --git a/app/code/Magento/Backend/etc/di.xml b/app/code/Magento/Backend/etc/di.xml index 8b52d08da48fbbd8fd1cf450bb8a2db66ca75b62..c0c5a0ec5b8a7ff217fcf0bb1772cb932f14bc55 100644 --- a/app/code/Magento/Backend/etc/di.xml +++ b/app/code/Magento/Backend/etc/di.xml @@ -213,4 +213,22 @@ </argument> </arguments> </type> + <type name="Magento\Config\Model\Config\Export\ExcludeList"> + <arguments> + <argument name="configs" xsi:type="array"> + <item name="trans_email/ident_general/name" xsi:type="string">1</item> + <item name="trans_email/ident_general/email" xsi:type="string">1</item> + <item name="trans_email/ident_sales/name" xsi:type="string">1</item> + <item name="trans_email/ident_sales/email" xsi:type="string">1</item> + <item name="trans_email/ident_support/name" xsi:type="string">1</item> + <item name="trans_email/ident_support/email" xsi:type="string">1</item> + <item name="trans_email/ident_custom1/name" xsi:type="string">1</item> + <item name="trans_email/ident_custom1/email" xsi:type="string">1</item> + <item name="trans_email/ident_custom2/name" xsi:type="string">1</item> + <item name="trans_email/ident_custom2/email" xsi:type="string">1</item> + <item name="admin/url/custom" xsi:type="string">1</item> + <item name="admin/url/custom_path" xsi:type="string">1</item> + </argument> + </arguments> + </type> </config> diff --git a/app/code/Magento/Backend/view/adminhtml/layout/adminhtml_cache_block.xml b/app/code/Magento/Backend/view/adminhtml/layout/adminhtml_cache_block.xml index 3e61fec077c6e3fcfccfb62b5ecad98248e9b41d..98f9ca89ba18accc9013c7b0851e39abafa517b2 100644 --- a/app/code/Magento/Backend/view/adminhtml/layout/adminhtml_cache_block.xml +++ b/app/code/Magento/Backend/view/adminhtml/layout/adminhtml_cache_block.xml @@ -23,10 +23,12 @@ <item name="enable" xsi:type="array"> <item name="label" xsi:type="string" translate="true">Enable</item> <item name="url" xsi:type="string">adminhtml/*/massEnable</item> + <item name="visible" xsi:type="object">Magento\Backend\Block\Cache\Grid\Massaction\ProductionModeVisibilityChecker</item> </item> <item name="disable" xsi:type="array"> <item name="label" xsi:type="string" translate="true">Disable</item> <item name="url" xsi:type="string">adminhtml/*/massDisable</item> + <item name="visible" xsi:type="object">Magento\Backend\Block\Cache\Grid\Massaction\ProductionModeVisibilityChecker</item> </item> <item name="refresh" xsi:type="array"> <item name="label" xsi:type="string" translate="true">Refresh</item> @@ -48,6 +50,7 @@ <argument name="width" xsi:type="string">180</argument> <argument name="align" xsi:type="string">left</argument> <argument name="sortable" xsi:type="string">0</argument> + <argument name="translate" xsi:type="boolean">true</argument> </arguments> </block> <block class="Magento\Backend\Block\Widget\Grid\Column" as="description"> @@ -57,6 +60,7 @@ <argument name="type" xsi:type="string">text</argument> <argument name="align" xsi:type="string">left</argument> <argument name="sortable" xsi:type="string">0</argument> + <argument name="translate" xsi:type="boolean">true</argument> </arguments> </block> <block class="Magento\Backend\Block\Widget\Grid\Column" as="tags"> diff --git a/app/code/Magento/Braintree/etc/di.xml b/app/code/Magento/Braintree/etc/di.xml index d051ef78cfcd22424fa359e47be3efc0ee8dcc2b..5417c96ba677204a0c3c3ffc69cefdc27f148ee3 100644 --- a/app/code/Magento/Braintree/etc/di.xml +++ b/app/code/Magento/Braintree/etc/di.xml @@ -365,7 +365,7 @@ </arguments> </virtualType> <!-- END PayPal commands --> - + <!-- Value handlers infrastructure --> <type name="Magento\Braintree\Gateway\Response\VaultDetailsHandler"> <arguments> @@ -452,7 +452,7 @@ </arguments> </virtualType> <!-- END PayPal value handlers infrastructure --> - + <!-- Void Command --> <virtualType name="BraintreeVoidCommand" type="Magento\Payment\Gateway\Command\GatewayCommand"> <arguments> @@ -544,4 +544,16 @@ </arguments> </type> <!-- END Settlement Report Section --> + <type name="Magento\Config\Model\Config\Export\ExcludeList"> + <arguments> + <argument name="configs" xsi:type="array"> + <item name="payment/braintree/merchant_id" xsi:type="string">1</item> + <item name="payment/braintree/public_key" xsi:type="string">1</item> + <item name="payment/braintree/private_key" xsi:type="string">1</item> + <item name="payment/braintree/merchant_account_id" xsi:type="string">1</item> + <item name="payment/braintree/kount_id" xsi:type="string">1</item> + <item name="payment/braintree_paypal/merchant_name_override" xsi:type="string">1</item> + </argument> + </arguments> + </type> </config> diff --git a/app/code/Magento/Braintree/view/adminhtml/web/js/vault.js b/app/code/Magento/Braintree/view/adminhtml/web/js/vault.js index ea832acb537e0051e34f976c050c9b8bd7d289b7..14729714b4e608f8c422da8c220b9ea1ed115ffb 100644 --- a/app/code/Magento/Braintree/view/adminhtml/web/js/vault.js +++ b/app/code/Magento/Braintree/view/adminhtml/web/js/vault.js @@ -28,7 +28,7 @@ define([ self.$selector = $('#' + self.selector); self.$container = $('#' + self.container); self.$selector.on( - 'setVaultNotActive', + 'setVaultNotActive.' + self.getCode(), function () { self.$selector.off('submitOrder.' + self.getCode()); } diff --git a/app/code/Magento/Bundle/Model/Product/Price.php b/app/code/Magento/Bundle/Model/Product/Price.php index 83bfcbbabc2536ab0ee2f84525dcb4cca12aa883..d0aee24945f9d21df7c3d73350093206065b0429 100644 --- a/app/code/Magento/Bundle/Model/Product/Price.php +++ b/app/code/Magento/Bundle/Model/Product/Price.php @@ -533,6 +533,10 @@ class Price extends \Magento\Catalog\Model\Product\Type\Price $prevGroup = $allCustomersGroupId; foreach ($prices as $price) { + if (empty($price['percentage_value'])) { + // can use only percentage tier price + continue; + } if ($price['cust_group'] != $custGroup && $price['cust_group'] != $allCustomersGroupId) { // tier not for current customer group nor is for all groups continue; @@ -553,8 +557,8 @@ class Price extends \Magento\Catalog\Model\Product\Type\Price continue; } - if ($price['website_price'] > $prevPrice) { - $prevPrice = $price['website_price']; + if ($price['percentage_value'] > $prevPrice) { + $prevPrice = $price['percentage_value']; $prevQty = $price['price_qty']; $prevGroup = $price['cust_group']; } diff --git a/app/code/Magento/Bundle/Model/ResourceModel/Indexer/Price.php b/app/code/Magento/Bundle/Model/ResourceModel/Indexer/Price.php index 7789f79d907f85d2402a82899af1de3f63db29de..4059f06bccded2f5dbaec98de627a0dc90407eb9 100644 --- a/app/code/Magento/Bundle/Model/ResourceModel/Indexer/Price.php +++ b/app/code/Magento/Bundle/Model/ResourceModel/Indexer/Price.php @@ -491,7 +491,7 @@ class Price extends \Magento\Catalog\Model\ResourceModel\Product\Indexer\Price\D null )->join( ['e' => $this->getTable('catalog_product_entity')], - "i.entity_id=e.$linkField", + "i.entity_id=e.entity_id", [] )->where( 'e.type_id=?', @@ -502,7 +502,7 @@ class Price extends \Magento\Catalog\Model\ResourceModel\Product\Indexer\Price\D $select = $connection->select()->from( ['tp' => $this->getTable('catalog_product_entity_tier_price')], - [$linkField] + ['e.entity_id'] )->join( ['e' => $this->getTable('catalog_product_entity')], "tp.{$linkField} = e.{$linkField}", @@ -523,11 +523,11 @@ class Price extends \Magento\Catalog\Model\ResourceModel\Product\Indexer\Price\D )->columns( new \Zend_Db_Expr('MIN(tp.value)') )->group( - ["tp.{$linkField}", 'cg.customer_group_id', 'cw.website_id'] + ['e.entity_id', 'cg.customer_group_id', 'cw.website_id'] ); if (!empty($entityIds)) { - $select->where("tp.{$linkField} IN(?)", $entityIds); + $select->where('e.entity_id IN(?)', $entityIds); } $query = $select->insertFromSelect($this->_getTierPriceIndexTable()); diff --git a/app/code/Magento/Bundle/Pricing/Price/TierPrice.php b/app/code/Magento/Bundle/Pricing/Price/TierPrice.php index cbbf45e2dbb5f01187760b73f96c251fae49c1c5..fab49292d9bdea9f2ee02e1762385b979e15bdb0 100644 --- a/app/code/Magento/Bundle/Pricing/Price/TierPrice.php +++ b/app/code/Magento/Bundle/Pricing/Price/TierPrice.php @@ -8,6 +8,7 @@ namespace Magento\Bundle\Pricing\Price; use Magento\Catalog\Pricing\Price\RegularPrice; use Magento\Framework\Pricing\Amount\AmountInterface; +use Magento\Framework\Pricing\PriceInfoInterface; /** * Bundle tier prices model @@ -32,8 +33,25 @@ class TierPrice extends \Magento\Catalog\Pricing\Price\TierPrice implements Disc public function getDiscountPercent() { if ($this->percent === null) { - $percent = parent::getValue(); - $this->percent = ($percent) ? max(0, min(100, 100 - $percent)) : null; + $prices = $this->getStoredTierPrices(); + $prevQty = PriceInfoInterface::PRODUCT_QUANTITY_DEFAULT; + $this->value = $prevPrice = false; + $priceGroup = $this->groupManagement->getAllCustomersGroup()->getId(); + + foreach ($prices as $price) { + if (!$this->canApplyTierPrice($price, $priceGroup, $prevQty) + || !isset($price['percentage_value']) + || !is_numeric($price['percentage_value']) + ) { + continue; + } + if (false === $prevPrice || $this->isFirstPriceBetter($price['website_price'], $prevPrice)) { + $prevPrice = $price['website_price']; + $prevQty = $price['price_qty']; + $priceGroup = $price['cust_group']; + $this->percent = max(0, min(100, 100 - $price['percentage_value'])); + } + } } return $this->percent; } @@ -90,13 +108,4 @@ class TierPrice extends \Magento\Catalog\Pricing\Price\TierPrice implements Disc { return true; } - - /** - * @param AmountInterface $amount - * @return float - */ - public function getSavePercent(AmountInterface $amount) - { - return round($amount->getBaseAmount()); - } } diff --git a/app/code/Magento/Bundle/Test/Unit/Model/Product/PriceTest.php b/app/code/Magento/Bundle/Test/Unit/Model/Product/PriceTest.php index e97f0bbc1558dc3c63e02ef2c894b0d4423a61b2..9f7952e7ae8c882a5b747f9fd24855feea7c380e 100644 --- a/app/code/Magento/Bundle/Test/Unit/Model/Product/PriceTest.php +++ b/app/code/Magento/Bundle/Test/Unit/Model/Product/PriceTest.php @@ -90,7 +90,6 @@ class PriceTest extends \PHPUnit_Framework_TestCase false ); $scopeConfig = $this->getMock(\Magento\Framework\App\Config\ScopeConfigInterface::class); - $objectManagerHelper = new ObjectManagerHelper($this); $this->model = $objectManagerHelper->getObject( \Magento\Bundle\Model\Product\Price::class, @@ -191,7 +190,6 @@ class PriceTest extends \PHPUnit_Framework_TestCase $dataObjectMock->expects($this->once()) ->method('getValue') ->willReturn($value); - $this->assertEquals(0, $this->model->getTotalBundleItemsPrice($productMock)); } @@ -245,7 +243,6 @@ class PriceTest extends \PHPUnit_Framework_TestCase $dataObjectMock->expects($this->once()) ->method('getValue') ->willReturn('a:1:{i:0;s:1:"1";}'); - $productTypeMock->expects($this->once()) ->method('getSelectionsByIds') ->with([1], $productMock) diff --git a/app/code/Magento/Bundle/Test/Unit/Pricing/Price/TierPriceTest.php b/app/code/Magento/Bundle/Test/Unit/Pricing/Price/TierPriceTest.php index 7b1f6181bb6f8ddc5951ce69e7564b7e2d1b1536..15bc06c2c6437d450ca480479b08a2cf1900d0de 100644 --- a/app/code/Magento/Bundle/Test/Unit/Pricing/Price/TierPriceTest.php +++ b/app/code/Magento/Bundle/Test/Unit/Pricing/Price/TierPriceTest.php @@ -188,9 +188,17 @@ class TierPriceTest extends \PHPUnit_Framework_TestCase */ public function testGetSavePercent($baseAmount, $savePercent) { + $basePrice = 10.; $amount = $this->getMockForAbstractClass(\Magento\Framework\Pricing\Amount\AmountInterface::class); $amount->expects($this->once())->method('getBaseAmount')->willReturn($baseAmount); + $price = $this->getMock(\Magento\Framework\Pricing\Price\PriceInterface::class); + $price->expects($this->any()) + ->method('getValue') + ->will($this->returnValue($basePrice)); + $this->priceInfo->expects($this->any()) + ->method('getPrice') + ->will($this->returnValue($price)); $this->assertEquals($savePercent, $this->model->getSavePercent($amount)); } @@ -200,10 +208,8 @@ class TierPriceTest extends \PHPUnit_Framework_TestCase public function providerForTestGetSavePercent() { return [ - 'no fraction' => [10.0000, 10], - 'lower half' => [10.1234, 10], - 'half way' => [10.5000, 11], - 'upper half' => [10.6789, 11], + 'no fraction' => [9.0000, 10], + 'lower half' => [9.1234, 9], ]; } } diff --git a/app/code/Magento/Bundle/Ui/DataProvider/Product/Form/Modifier/BundlePanel.php b/app/code/Magento/Bundle/Ui/DataProvider/Product/Form/Modifier/BundlePanel.php index 538c80d9b1cf27af4ba14c911b0d0a6913c403c7..4012af357e2c50e31c1052adae15ee1b1a4931bf 100644 --- a/app/code/Magento/Bundle/Ui/DataProvider/Product/Form/Modifier/BundlePanel.php +++ b/app/code/Magento/Bundle/Ui/DataProvider/Product/Form/Modifier/BundlePanel.php @@ -14,6 +14,8 @@ use Magento\Ui\Component\Container; use Magento\Ui\Component\DynamicRows; use Magento\Ui\Component\Form; use Magento\Ui\Component\Modal; +use Magento\Catalog\Api\Data\ProductAttributeInterface; +use Magento\Catalog\Model\Config\Source\ProductPriceOptionsInterface; /** * Create Ship Bundle Items and Affect Bundle Product Selections fields @@ -73,6 +75,7 @@ class BundlePanel extends AbstractModifier */ public function modifyMeta(array $meta) { + $meta = $this->removeFixedTierPrice($meta); $path = $this->arrayManager->findPath(static::CODE_BUNDLE_DATA, $meta, null, 'children'); $meta = $this->arrayManager->merge( @@ -178,6 +181,43 @@ class BundlePanel extends AbstractModifier return $meta; } + /** + * Remove option with fixed tier price from config. + * + * @param array $meta + * @return array + */ + private function removeFixedTierPrice(array $meta) + { + $tierPricePath = $this->arrayManager->findPath( + ProductAttributeInterface::CODE_TIER_PRICE, + $meta, + null, + 'children' + ); + $pricePath = $this->arrayManager->findPath( + ProductAttributeInterface::CODE_TIER_PRICE_FIELD_PRICE, + $meta, + $tierPricePath + ); + $pricePath = $this->arrayManager->slicePath($pricePath, 0, -1) . '/value_type/arguments/data/options'; + + $price = $this->arrayManager->get($pricePath, $meta); + $meta = $this->arrayManager->remove($pricePath, $meta); + foreach ($price as $key => $item) { + if ($item['value'] == ProductPriceOptionsInterface::VALUE_FIXED) { + unset($price[$key]); + } + } + $meta = $this->arrayManager->merge( + $this->arrayManager->slicePath($pricePath, 0, -1), + $meta, + ['options' => $price] + ); + + return $meta; + } + /** * {@inheritdoc} */ diff --git a/app/code/Magento/Bundle/etc/adminhtml/di.xml b/app/code/Magento/Bundle/etc/adminhtml/di.xml index ca93dd5365160fd84372425a11fd5aff32972851..19b683027dfa14062883d4d80430f68a7c6ce49e 100644 --- a/app/code/Magento/Bundle/etc/adminhtml/di.xml +++ b/app/code/Magento/Bundle/etc/adminhtml/di.xml @@ -27,11 +27,11 @@ <argument name="modifiers" xsi:type="array"> <item name="bundle" xsi:type="array"> <item name="class" xsi:type="string">Magento\Bundle\Ui\DataProvider\Product\Form\Modifier\Composite</item> - <item name="sortOrder" xsi:type="number">125</item> + <item name="sortOrder" xsi:type="number">180</item> </item> <item name="bundle_stock_data" xsi:type="array"> <item name="class" xsi:type="string">Magento\Bundle\Ui\DataProvider\Product\Form\Modifier\StockData</item> - <item name="sortOrder" xsi:type="number">126</item> + <item name="sortOrder" xsi:type="number">190</item> </item> </argument> </arguments> diff --git a/app/code/Magento/Bundle/etc/di.xml b/app/code/Magento/Bundle/etc/di.xml index 2d3913d72e579302ac9cd1f0e23d6b235f9c6b23..3425b9323ed4d4e18fd8be5342a4139be87291f3 100644 --- a/app/code/Magento/Bundle/etc/di.xml +++ b/app/code/Magento/Bundle/etc/di.xml @@ -130,4 +130,5 @@ </argument> </arguments> </type> + </config> diff --git a/app/code/Magento/Bundle/view/base/templates/product/price/tier_prices.phtml b/app/code/Magento/Bundle/view/base/templates/product/price/tier_prices.phtml index 3285603c431a219f76698b9e5e8d41571b285c11..63f090acf34dfb477521f992b2ee0f8d1eb6ff17 100644 --- a/app/code/Magento/Bundle/view/base/templates/product/price/tier_prices.phtml +++ b/app/code/Magento/Bundle/view/base/templates/product/price/tier_prices.phtml @@ -22,7 +22,7 @@ $tierPrices = $tierPriceModel->getTierPriceList(); <?php /* @escapeNotVerified */ echo __( 'Buy %1 with %2 discount each', $price['price_qty'], - '<strong class="benefit">' . $tierPriceModel->getSavePercent($price['price']) . '%</strong>' + '<strong class="benefit">' . round($price['percentage_value']) . '%</strong>' ); ?> </li> <?php endforeach; ?> diff --git a/app/code/Magento/BundleImportExport/Model/Import/Product/Type/Bundle.php b/app/code/Magento/BundleImportExport/Model/Import/Product/Type/Bundle.php index 2d0f1264b6b8a6fc6ad041b81812c942f739468c..6a99c02af9da63f9126b57c1349eb17d8df360be 100644 --- a/app/code/Magento/BundleImportExport/Model/Import/Product/Type/Bundle.php +++ b/app/code/Magento/BundleImportExport/Model/Import/Product/Type/Bundle.php @@ -9,7 +9,6 @@ namespace Magento\BundleImportExport\Model\Import\Product\Type; use \Magento\Bundle\Model\Product\Price as BundlePrice; -use \Magento\BundleImportExport\Model\Export\RowCustomizer; use \Magento\Catalog\Model\Product\Type\AbstractType; /** @@ -55,20 +54,6 @@ class Bundle extends \Magento\CatalogImportExport\Model\Import\Product\Type\Abst */ const SELECTION_PRICE_TYPE_PERCENT = 1; - /** - * Instance of database adapter. - * - * @var \Magento\Framework\DB\Adapter\AdapterInterface - */ - protected $connection; - - /** - * Instance of application resource. - * - * @var \Magento\Framework\App\ResourceConnection - */ - protected $_resource; - /** * Array of cached options. * @@ -144,23 +129,6 @@ class Bundle extends \Magento\CatalogImportExport\Model\Import\Product\Type\Abst 'multiselect' => 'multi', ]; - /** - * @param \Magento\Eav\Model\ResourceModel\Entity\Attribute\Set\CollectionFactory $attrSetColFac - * @param \Magento\Catalog\Model\ResourceModel\Product\Attribute\CollectionFactory $prodAttrColFac - * @param \Magento\Framework\App\ResourceConnection $resource - * @param array $params - */ - public function __construct( - \Magento\Eav\Model\ResourceModel\Entity\Attribute\Set\CollectionFactory $attrSetColFac, - \Magento\Catalog\Model\ResourceModel\Product\Attribute\CollectionFactory $prodAttrColFac, - \Magento\Framework\App\ResourceConnection $resource, - array $params - ) { - parent::__construct($attrSetColFac, $prodAttrColFac, $resource, $params); - $this->_resource = $resource; - $this->connection = $resource->getConnection(\Magento\Framework\App\ResourceConnection::DEFAULT_CONNECTION); - } - /** * Parse selections. * diff --git a/app/code/Magento/BundleImportExport/composer.json b/app/code/Magento/BundleImportExport/composer.json index 2f5e3afdbff86ded9c88161ebea832c29b37f229..ad849b6f31182ab49fb3acaa64fd7ae1c92e40c5 100644 --- a/app/code/Magento/BundleImportExport/composer.json +++ b/app/code/Magento/BundleImportExport/composer.json @@ -7,7 +7,6 @@ "magento/module-import-export": "100.2.*", "magento/module-catalog-import-export": "100.2.*", "magento/module-bundle": "100.2.*", - "magento/module-eav": "100.2.*", "magento/framework": "100.2.*" }, "type": "magento2-module", diff --git a/app/code/Magento/Catalog/Block/Product/View/Gallery.php b/app/code/Magento/Catalog/Block/Product/View/Gallery.php index 0edeba7d807ac8e4c1be154d236bbff7c93a87b5..97909ffaa889f283d8a07c3f87be508f0c855c0a 100644 --- a/app/code/Magento/Catalog/Block/Product/View/Gallery.php +++ b/app/code/Magento/Catalog/Block/Product/View/Gallery.php @@ -63,15 +63,13 @@ class Gallery extends \Magento\Catalog\Block\Product\View\AbstractView ); $image->setData( 'medium_image_url', - $this->_imageHelper->init($product, 'product_page_image_medium') - ->constrainOnly(true)->keepAspectRatio(true)->keepFrame(false) + $this->_imageHelper->init($product, 'product_page_image_medium_no_frame') ->setImageFile($image->getFile()) ->getUrl() ); $image->setData( 'large_image_url', - $this->_imageHelper->init($product, 'product_page_image_large') - ->constrainOnly(true)->keepAspectRatio(true)->keepFrame(false) + $this->_imageHelper->init($product, 'product_page_image_large_no_frame') ->setImageFile($image->getFile()) ->getUrl() ); diff --git a/app/code/Magento/Catalog/Helper/Image.php b/app/code/Magento/Catalog/Helper/Image.php index eb5e7142d3094f5457fde615bc4987a8df912ab1..6f13e9077f4732af3714ae2af50ca804a22f0aa2 100644 --- a/app/code/Magento/Catalog/Helper/Image.php +++ b/app/code/Magento/Catalog/Helper/Image.php @@ -195,7 +195,6 @@ class Image extends AbstractHelper protected function setImageProperties() { $this->_getModel()->setDestinationSubdir($this->getType()); - $this->_getModel()->setWidth($this->getWidth()); $this->_getModel()->setHeight($this->getHeight()); @@ -241,25 +240,25 @@ class Image extends AbstractHelper { $this->setWatermark( $this->scopeConfig->getValue( - "design/watermark/{$this->_getModel()->getDestinationSubdir()}_image", + "design/watermark/{$this->getType()}_image", \Magento\Store\Model\ScopeInterface::SCOPE_STORE ) ); $this->setWatermarkImageOpacity( $this->scopeConfig->getValue( - "design/watermark/{$this->_getModel()->getDestinationSubdir()}_imageOpacity", + "design/watermark/{$this->getType()}_imageOpacity", \Magento\Store\Model\ScopeInterface::SCOPE_STORE ) ); $this->setWatermarkPosition( $this->scopeConfig->getValue( - "design/watermark/{$this->_getModel()->getDestinationSubdir()}_position", + "design/watermark/{$this->getType()}_position", \Magento\Store\Model\ScopeInterface::SCOPE_STORE ) ); $this->setWatermarkSize( $this->scopeConfig->getValue( - "design/watermark/{$this->_getModel()->getDestinationSubdir()}_size", + "design/watermark/{$this->getType()}_size", \Magento\Store\Model\ScopeInterface::SCOPE_STORE ) ); @@ -500,10 +499,7 @@ class Image extends AbstractHelper protected function isScheduledActionsAllowed() { $model = $this->_getModel(); - if ($model->isBaseFilePlaceholder() - && $model->getNewFile() === true - || $model->isCached() - ) { + if ($model->isBaseFilePlaceholder() || $model->isCached()) { return false; } return true; diff --git a/app/code/Magento/Catalog/Model/Attribute/Config/Data.php b/app/code/Magento/Catalog/Model/Attribute/Config/Data.php index 032970a7461b60f8c3c2f900024c587fb1d22f63..1fac4e58c75c97fcc404cd0ca345e3ed1085f501 100644 --- a/app/code/Magento/Catalog/Model/Attribute/Config/Data.php +++ b/app/code/Magento/Catalog/Model/Attribute/Config/Data.php @@ -1,22 +1,31 @@ <?php /** - * Catalog attributes configuration data container. Provides catalog attributes configuration data. - * * Copyright © 2016 Magento. All rights reserved. * See COPYING.txt for license details. */ namespace Magento\Catalog\Model\Attribute\Config; +use Magento\Framework\Serialize\SerializerInterface; + +/** + * Provides catalog attributes configuration + */ class Data extends \Magento\Framework\Config\Data { /** + * Constructor + * * @param \Magento\Catalog\Model\Attribute\Config\Reader $reader * @param \Magento\Framework\Config\CacheInterface $cache + * @param string|null $cacheId + * @param SerializerInterface|null $serializer */ public function __construct( \Magento\Catalog\Model\Attribute\Config\Reader $reader, - \Magento\Framework\Config\CacheInterface $cache + \Magento\Framework\Config\CacheInterface $cache, + $cacheId = 'catalog_attributes', + SerializerInterface $serializer = null ) { - parent::__construct($reader, $cache, 'catalog_attributes'); + parent::__construct($reader, $cache, $cacheId, $serializer); } } diff --git a/app/code/Magento/Catalog/Model/Category/DataProvider.php b/app/code/Magento/Catalog/Model/Category/DataProvider.php index 8aa7216a6b63928ba9dcdd415b1745ed404321f1..6ce2dd98f89c6c707782ee1338e248a1f01abb77 100644 --- a/app/code/Magento/Catalog/Model/Category/DataProvider.php +++ b/app/code/Magento/Catalog/Model/Category/DataProvider.php @@ -15,6 +15,8 @@ use Magento\Eav\Model\Config; use Magento\Eav\Model\Entity\Type; use Magento\Catalog\Model\ResourceModel\Category\CollectionFactory as CategoryCollectionFactory; use Magento\Framework\Stdlib\ArrayManager; +use Magento\Framework\App\ObjectManager; +use Magento\Framework\Filesystem; use Magento\Store\Model\Store; use Magento\Store\Model\StoreManagerInterface; use Magento\Ui\Component\Form\Field; @@ -126,6 +128,11 @@ class DataProvider extends \Magento\Ui\DataProvider\AbstractDataProvider */ private $arrayManager; + /** + * @var Filesystem + */ + private $fileInfo; + /** * DataProvider constructor * @@ -483,8 +490,16 @@ class DataProvider extends \Magento\Ui\DataProvider\AbstractDataProvider if ($attribute->getBackend() instanceof ImageBackendModel) { unset($categoryData[$attributeCode]); - $categoryData[$attributeCode][0]['name'] = $category->getData($attributeCode); - $categoryData[$attributeCode][0]['url'] = $category->getImageUrl($attributeCode); + $fileName = $category->getData($attributeCode); + if ($this->getFileInfo()->isExist($fileName)) { + $stat = $this->getFileInfo()->getStat($fileName); + $mime = $this->getFileInfo()->getMimeType($fileName); + + $categoryData[$attributeCode][0]['name'] = $fileName; + $categoryData[$attributeCode][0]['url'] = $category->getImageUrl($attributeCode); + $categoryData['image'][0]['size'] = isset($stat) ? $stat['size'] : 0; + $categoryData['image'][0]['type'] = $mime; + } } } @@ -605,4 +620,19 @@ class DataProvider extends \Magento\Ui\DataProvider\AbstractDataProvider return $this->arrayManager; } + + /** + * Get FileInfo instance + * + * @return FileInfo + * + * @deprecated + */ + private function getFileInfo() + { + if ($this->fileInfo === null) { + $this->fileInfo = ObjectManager::getInstance()->get(FileInfo::class); + } + return $this->fileInfo; + } } diff --git a/app/code/Magento/Catalog/Model/Category/FileInfo.php b/app/code/Magento/Catalog/Model/Category/FileInfo.php new file mode 100644 index 0000000000000000000000000000000000000000..3e4d852e579afb66ac071b530494bfdad23f36e2 --- /dev/null +++ b/app/code/Magento/Catalog/Model/Category/FileInfo.php @@ -0,0 +1,107 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Catalog\Model\Category; + +use Magento\Framework\App\Filesystem\DirectoryList; +use Magento\Framework\File\Mime; +use Magento\Framework\Filesystem; +use Magento\Framework\Filesystem\Directory\WriteInterface; + +/** + * Class FileInfo + * + * Provides information about requested file + */ +class FileInfo +{ + /** + * Path in /pub/media directory + */ + const ENTITY_MEDIA_PATH = '/catalog/category'; + + /** + * @var Filesystem + */ + private $filesystem; + + /** + * @var Mime + */ + private $mime; + + /** + * @var WriteInterface + */ + private $mediaDirectory; + + /** + * @param Filesystem $filesystem + * @param Mime $mime + */ + public function __construct( + Filesystem $filesystem, + Mime $mime + ) { + $this->filesystem = $filesystem; + $this->mime = $mime; + } + + /** + * Get WriteInterface instance + * + * @return WriteInterface + */ + private function getMediaDirectory() + { + if ($this->mediaDirectory === null) { + $this->mediaDirectory = $this->filesystem->getDirectoryWrite(DirectoryList::MEDIA); + } + return $this->mediaDirectory; + } + + /** + * Retrieve MIME type of requested file + * + * @param string $fileName + * @return string + */ + public function getMimeType($fileName) + { + $filePath = self::ENTITY_MEDIA_PATH . '/' . ltrim($fileName, '/'); + $absoluteFilePath = $this->getMediaDirectory()->getAbsolutePath($filePath); + + $result = $this->mime->getMimeType($absoluteFilePath); + return $result; + } + + /** + * Get file statistics data + * + * @param string $fileName + * @return array + */ + public function getStat($fileName) + { + $filePath = self::ENTITY_MEDIA_PATH . '/' . ltrim($fileName, '/'); + + $result = $this->getMediaDirectory()->stat($filePath); + return $result; + } + + /** + * Check if the file exists + * + * @param string $fileName + * @return bool + */ + public function isExist($fileName) + { + $filePath = self::ENTITY_MEDIA_PATH . '/' . ltrim($fileName, '/'); + + $result = $this->getMediaDirectory()->isExist($filePath); + return $result; + } +} diff --git a/app/code/Magento/Catalog/Model/Config.php b/app/code/Magento/Catalog/Model/Config.php index dec29a925cc4d491ddbaab53f249ce354c7df56c..70d11f2e282b4a4268bab2c56547668badf1735a 100644 --- a/app/code/Magento/Catalog/Model/Config.php +++ b/app/code/Magento/Catalog/Model/Config.php @@ -7,6 +7,7 @@ // @codingStandardsIgnoreFile namespace Magento\Catalog\Model; +use Magento\Framework\Serialize\SerializerInterface; /** * @SuppressWarnings(PHPMD.LongVariable) @@ -132,6 +133,7 @@ class Config extends \Magento\Eav\Model\Config * @param \Magento\Eav\Model\ResourceModel\Entity\Attribute\Set\CollectionFactory $setCollectionFactory * @param \Magento\Store\Model\StoreManagerInterface $storeManager * @param \Magento\Eav\Model\Config $eavConfig + * @param SerializerInterface $serializer * * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ @@ -147,7 +149,8 @@ class Config extends \Magento\Eav\Model\Config \Magento\Eav\Model\ResourceModel\Entity\Attribute\Group\CollectionFactory $groupCollectionFactory, \Magento\Eav\Model\ResourceModel\Entity\Attribute\Set\CollectionFactory $setCollectionFactory, \Magento\Store\Model\StoreManagerInterface $storeManager, - \Magento\Eav\Model\Config $eavConfig + \Magento\Eav\Model\Config $eavConfig, + SerializerInterface $serializer = null ) { $this->_scopeConfig = $scopeConfig; $this->_configFactory = $configFactory; @@ -157,7 +160,14 @@ class Config extends \Magento\Eav\Model\Config $this->_storeManager = $storeManager; $this->_eavConfig = $eavConfig; - parent::__construct($cache, $entityTypeFactory, $entityTypeCollectionFactory, $cacheState, $universalFactory); + parent::__construct( + $cache, + $entityTypeFactory, + $entityTypeCollectionFactory, + $cacheState, + $universalFactory, + $serializer + ); } /** diff --git a/app/code/Magento/Catalog/Model/Config/Source/Product/Options/Price.php b/app/code/Magento/Catalog/Model/Config/Source/Product/Options/Price.php index b994c787bee7aa76f8a4baa3648bcbb2c0e4ee27..5e518df37db1a574f25fe008510e75742cdffa9c 100644 --- a/app/code/Magento/Catalog/Model/Config/Source/Product/Options/Price.php +++ b/app/code/Magento/Catalog/Model/Config/Source/Product/Options/Price.php @@ -23,7 +23,7 @@ class Price implements ProductPriceOptionsInterface { return [ ['value' => self::VALUE_FIXED, 'label' => __('Fixed')], - ['value' => self::VALUE_PERCENT, 'label' => __('Percent')], + ['value' => self::VALUE_PERCENT, 'label' => __('Discount')], ]; } } diff --git a/app/code/Magento/Catalog/Model/Product/Attribute/Backend/Tierprice.php b/app/code/Magento/Catalog/Model/Product/Attribute/Backend/Tierprice.php index 480f8e8942e87f200ce3829641ea026d351b1967..460204a478d9d75ac86dbaa4e8d3684ea26b8812 100644 --- a/app/code/Magento/Catalog/Model/Product/Attribute/Backend/Tierprice.php +++ b/app/code/Magento/Catalog/Model/Product/Attribute/Backend/Tierprice.php @@ -157,6 +157,7 @@ class Tierprice extends \Magento\Catalog\Model\Product\Attribute\Backend\GroupPr $data = parent::modifyPriceData($object, $data); foreach ($data as $key => $tierPrice) { if ($this->getPercentage($tierPrice)) { + $data[$key]['price'] = $object->getPrice() * (1 - $this->getPercentage($tierPrice) / 100); $data[$key]['website_price'] = $object->getPrice() * (1 - $this->getPercentage($tierPrice) / 100); } } diff --git a/app/code/Magento/Catalog/Model/Product/Attribute/Source/Countryofmanufacture.php b/app/code/Magento/Catalog/Model/Product/Attribute/Source/Countryofmanufacture.php index 7b45d162b5e98bf06251a8a6e55794b8626b25ef..8bcf01ba3db3867bb0babe3c5119097f1c860d5d 100644 --- a/app/code/Magento/Catalog/Model/Product/Attribute/Source/Countryofmanufacture.php +++ b/app/code/Magento/Catalog/Model/Product/Attribute/Source/Countryofmanufacture.php @@ -35,6 +35,11 @@ class Countryofmanufacture extends AbstractSource implements OptionSourceInterfa */ protected $_countryFactory; + /** + * @var \Magento\Framework\Serialize\SerializerInterface + */ + private $serializer; + /** * Construct * @@ -61,15 +66,30 @@ class Countryofmanufacture extends AbstractSource implements OptionSourceInterfa { $cacheKey = 'COUNTRYOFMANUFACTURE_SELECT_STORE_' . $this->_storeManager->getStore()->getCode(); if ($cache = $this->_configCacheType->load($cacheKey)) { - $options = unserialize($cache); + $options = $this->getSerializer()->unserialize($cache); } else { /** @var \Magento\Directory\Model\Country $country */ $country = $this->_countryFactory->create(); /** @var \Magento\Directory\Model\ResourceModel\Country\Collection $collection */ $collection = $country->getResourceCollection(); $options = $collection->load()->toOptionArray(); - $this->_configCacheType->save(serialize($options), $cacheKey); + $this->_configCacheType->save($this->getSerializer()->serialize($options), $cacheKey); } return $options; } + + /** + * Get serializer + * + * @return \Magento\Framework\Serialize\SerializerInterface + * @deprecated + */ + private function getSerializer() + { + if ($this->serializer === null) { + $this->serializer = \Magento\Framework\App\ObjectManager::getInstance() + ->get(\Magento\Framework\Serialize\SerializerInterface::class); + } + return $this->serializer; + } } diff --git a/app/code/Magento/Catalog/Model/Product/Gallery/GalleryManagement.php b/app/code/Magento/Catalog/Model/Product/Gallery/GalleryManagement.php index 950e2253a95dc21218ee666bb5d747b3991d3118..d2a3196868543db0fb9832aca40529df2c32f965 100644 --- a/app/code/Magento/Catalog/Model/Product/Gallery/GalleryManagement.php +++ b/app/code/Magento/Catalog/Model/Product/Gallery/GalleryManagement.php @@ -94,13 +94,16 @@ class GalleryManagement implements \Magento\Catalog\Api\ProductAttributeMediaGal } $found = false; foreach ($existingMediaGalleryEntries as $key => $existingEntry) { + $entryTypes = (array)$entry->getTypes(); + $existingEntryTypes = (array)$existingMediaGalleryEntries[$key]->getTypes(); + $existingMediaGalleryEntries[$key]->setTypes(array_diff($existingEntryTypes, $entryTypes)); + if ($existingEntry->getId() == $entry->getId()) { $found = true; if ($entry->getFile()) { $entry->setId(null); } $existingMediaGalleryEntries[$key] = $entry; - break; } } if (!$found) { diff --git a/app/code/Magento/Catalog/Model/Product/Gallery/Processor.php b/app/code/Magento/Catalog/Model/Product/Gallery/Processor.php index 3c757f8a05a2daf0ab30c9efb2031c15cefa1d4f..ec2521350d14d991e9c8deff2a74f5ff4865fbfc 100644 --- a/app/code/Magento/Catalog/Model/Product/Gallery/Processor.php +++ b/app/code/Magento/Catalog/Model/Product/Gallery/Processor.php @@ -298,11 +298,11 @@ class Processor if (is_array($mediaAttribute)) { foreach ($mediaAttribute as $attribute) { if (in_array($attribute, $mediaAttributeCodes)) { - $product->setData($attribute, null); + $product->setData($attribute, 'no_selection'); } } } elseif (in_array($mediaAttribute, $mediaAttributeCodes)) { - $product->setData($mediaAttribute, null); + $product->setData($mediaAttribute, 'no_selection'); } return $this; diff --git a/app/code/Magento/Catalog/Model/Product/Image.php b/app/code/Magento/Catalog/Model/Product/Image.php index 34e1ad30ad434add33508bb63c7b8b1a78ddc9fb..769faa682f422b569dd6673df819f05d7371aeb8 100644 --- a/app/code/Magento/Catalog/Model/Product/Image.php +++ b/app/code/Magento/Catalog/Model/Product/Image.php @@ -12,8 +12,8 @@ namespace Magento\Catalog\Model\Product; use Magento\Framework\App\Filesystem\DirectoryList; +use Magento\Framework\App\ObjectManager; use Magento\Framework\Image as MagentoImage; -use Magento\Store\Model\Store; /** * @SuppressWarnings(PHPMD.TooManyFields) @@ -170,6 +170,21 @@ class Image extends \Magento\Framework\Model\AbstractModel */ protected $_storeManager; + /** + * @var \Magento\Catalog\Model\View\Asset\ImageFactory + */ + private $viewAssetImageFactory; + + /** + * @var \Magento\Catalog\Model\View\Asset\PlaceholderFactory + */ + private $viewAssetPlaceholderFactory; + + /** + * @var \Magento\Framework\View\Asset\LocalInterface + */ + private $imageAsset; + /** * @param \Magento\Framework\Model\Context $context * @param \Magento\Framework\Registry $registry @@ -207,7 +222,6 @@ class Image extends \Magento\Framework\Model\AbstractModel $this->_coreFileStorageDatabase = $coreFileStorageDatabase; parent::__construct($context, $registry, $resource, $resourceCollection, $data); $this->_mediaDirectory = $filesystem->getDirectoryWrite(DirectoryList::MEDIA); - $result = $this->_mediaDirectory->create($this->_catalogProductMediaConfig->getBaseMediaPath()); $this->_imageFactory = $imageFactory; $this->_assetRepo = $assetRepo; $this->_viewFileSystem = $viewFileSystem; @@ -450,85 +464,29 @@ class Image extends \Magento\Framework\Model\AbstractModel * @param string $file * @return $this * @throws \Exception - * @SuppressWarnings(PHPMD.CyclomaticComplexity) - * @SuppressWarnings(PHPMD.NPathComplexity) */ public function setBaseFile($file) { $this->_isBaseFilePlaceholder = false; - if ($file && 0 !== strpos($file, '/', 0)) { - $file = '/' . $file; - } - $baseDir = $this->_catalogProductMediaConfig->getBaseMediaPath(); - - if ('/no_selection' == $file) { - $file = null; - } - if ($file) { - if (!$this->_fileExists($baseDir . $file) || !$this->_checkMemory($baseDir . $file)) { - $file = null; - } - } - if (!$file) { + $this->imageAsset = $this->getViewAssetImageFactory()->create( + [ + 'miscParams' => $this->getMiscParams(), + 'filePath' => $file, + ] + ); + if ($file == 'no_selection' || !$this->_fileExists($this->imageAsset->getSourceFile()) + || !$this->_checkMemory($this->imageAsset->getSourceFile()) + ) { $this->_isBaseFilePlaceholder = true; - // check if placeholder defined in config - $isConfigPlaceholder = $this->_scopeConfig->getValue( - "catalog/placeholder/{$this->getDestinationSubdir()}_placeholder", - \Magento\Store\Model\ScopeInterface::SCOPE_STORE + $this->imageAsset = $this->getViewAssetPlaceholderFactory()->create( + [ + 'type' => $this->getDestinationSubdir(), + ] ); - $configPlaceholder = '/placeholder/' . $isConfigPlaceholder; - if (!empty($isConfigPlaceholder) && $this->_fileExists($baseDir . $configPlaceholder)) { - $file = $configPlaceholder; - } else { - $this->_newFile = true; - return $this; - } - } - - $baseFile = $baseDir . $file; - - if (!$file || !$this->_mediaDirectory->isFile($baseFile)) { - throw new \Exception(__('We can\'t find the image file.')); } - $this->_baseFile = $baseFile; - - // build new filename (most important params) - $path = [ - $this->_catalogProductMediaConfig->getBaseMediaPath(), - 'cache', - $this->getDestinationSubdir(), - ]; - if (!empty($this->_width) || !empty($this->_height)) { - $path[] = "{$this->_width}x{$this->_height}"; - } - - // add misk params as a hash - $miscParams = [ - ($this->_keepAspectRatio ? '' : 'non') . 'proportional', - ($this->_keepFrame ? '' : 'no') . 'frame', - ($this->_keepTransparency ? '' : 'no') . 'transparency', - ($this->_constrainOnly ? 'do' : 'not') . 'constrainonly', - $this->_rgbToString($this->_backgroundColor), - 'angle' . $this->_angle, - 'quality' . $this->_quality, - ]; - - // if has watermark add watermark params to hash - if ($this->getWatermarkFile()) { - $miscParams[] = $this->getWatermarkFile(); - $miscParams[] = $this->getWatermarkImageOpacity(); - $miscParams[] = $this->getWatermarkPosition(); - $miscParams[] = $this->getWatermarkWidth(); - $miscParams[] = $this->getWatermarkHeight(); - } - - $path[] = md5(implode('_', $miscParams)); - - // append prepared filename - $this->_newFile = implode('/', $path) . $file; - // the $file contains heading slash + $this->_baseFile = $this->imageAsset->getSourceFile(); return $this; } @@ -542,6 +500,7 @@ class Image extends \Magento\Framework\Model\AbstractModel } /** + * @deprecated * @return bool|string */ public function getNewFile() @@ -690,10 +649,10 @@ class Image extends \Magento\Framework\Model\AbstractModel */ public function saveFile() { - if ($this->_isBaseFilePlaceholder && $this->_newFile === true) { + if ($this->_isBaseFilePlaceholder) { return $this; } - $filename = $this->_mediaDirectory->getAbsolutePath($this->getNewFile()); + $filename = $this->getBaseFile() ? $this->imageAsset->getPath() : null; $this->getImageProcessor()->save($filename); $this->_coreFileStorageDatabase->saveFile($filename); return $this; @@ -704,17 +663,7 @@ class Image extends \Magento\Framework\Model\AbstractModel */ public function getUrl() { - if ($this->_newFile === true) { - $url = $this->_assetRepo->getUrl( - "Magento_Catalog::images/product/placeholder/{$this->getDestinationSubdir()}.jpg" - ); - } else { - $url = $this->_storeManager->getStore()->getBaseUrl( - \Magento\Framework\UrlInterface::URL_TYPE_MEDIA - ) . $this->_newFile; - } - - return $url; + return $this->imageAsset->getUrl(); } /** @@ -740,9 +689,7 @@ class Image extends \Magento\Framework\Model\AbstractModel */ public function isCached() { - if (is_string($this->_newFile)) { - return $this->_fileExists($this->_newFile); - } + return file_exists($this->imageAsset->getPath()); } /** @@ -939,18 +886,72 @@ class Image extends \Magento\Framework\Model\AbstractModel */ public function getResizedImageInfo() { - $fileInfo = null; - if ($this->_newFile === true) { - $asset = $this->_assetRepo->createAsset( - "Magento_Catalog::images/product/placeholder/{$this->getDestinationSubdir()}.jpg" - ); - $img = $asset->getSourceFile(); - $fileInfo = getimagesize($img); + if ($this->isBaseFilePlaceholder() == true) { + $image = $this->imageAsset->getSourceFile(); } else { - if ($this->_mediaDirectory->isFile($this->_mediaDirectory->getAbsolutePath($this->_newFile))) { - $fileInfo = getimagesize($this->_mediaDirectory->getAbsolutePath($this->_newFile)); - } + $image = $this->imageAsset->getPath(); } - return $fileInfo; + return getimagesize($image); + } + + /** + * @return \Magento\Catalog\Model\View\Asset\ImageFactory + */ + private function getViewAssetImageFactory() + { + if ($this->viewAssetImageFactory == null) { + $this->viewAssetImageFactory = ObjectManager::getInstance()->get( + \Magento\Catalog\Model\View\Asset\ImageFactory::class + ); + } + + return $this->viewAssetImageFactory; + } + + /** + * @return \Magento\Catalog\Model\View\Asset\PlaceholderFactory + */ + private function getViewAssetPlaceholderFactory() + { + if ($this->viewAssetPlaceholderFactory == null) { + $this->viewAssetPlaceholderFactory = ObjectManager::getInstance()->get( + \Magento\Catalog\Model\View\Asset\PlaceholderFactory::class + ); + } + + return $this->viewAssetPlaceholderFactory; + } + + /** + * Retrieve misc params based on all image attributes + * + * @return array + * @SuppressWarnings(PHPMD.NPathComplexity) + */ + private function getMiscParams() + { + $miscParams = [ + 'image_type' => $this->getDestinationSubdir(), + 'image_height' => $this->getHeight(), + 'image_width' => $this->getWidth(), + 'keep_aspect_ratio' => ($this->_keepAspectRatio ? '' : 'non') . 'proportional', + 'keep_frame' => ($this->_keepFrame ? '' : 'no') . 'frame', + 'keep_transparency' => ($this->_keepTransparency ? '' : 'no') . 'transparency', + 'constrain_only' => ($this->_constrainOnly ? 'do' : 'not') . 'constrainonly', + 'background' => $this->_rgbToString($this->_backgroundColor), + 'angle' => $this->_angle, + 'quality' => $this->_quality, + ]; + + // if has watermark add watermark params to hash + if ($this->getWatermarkFile()) { + $miscParams['watermark_file'] = $this->getWatermarkFile(); + $miscParams['watermark_image_opacity'] = $this->getWatermarkImageOpacity(); + $miscParams['watermark_position'] = $this->getWatermarkPosition(); + $miscParams['watermark_width'] = $this->getWatermarkWidth(); + $miscParams['watermark_height'] = $this->getWatermarkHeight(); + } + + return $miscParams; } } diff --git a/app/code/Magento/Catalog/Model/Product/Pricing/Renderer/SalableResolver.php b/app/code/Magento/Catalog/Model/Product/Pricing/Renderer/SalableResolver.php new file mode 100644 index 0000000000000000000000000000000000000000..c76a5031e8c221bb160a4ed593c721f39c57ad63 --- /dev/null +++ b/app/code/Magento/Catalog/Model/Product/Pricing/Renderer/SalableResolver.php @@ -0,0 +1,24 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Catalog\Model\Product\Pricing\Renderer; + +/** + * Resolvers check whether product available for sale or not + */ +class SalableResolver implements SalableResolverInterface +{ + /** + * Check whether product available for sale + * + * @param \Magento\Framework\Pricing\SaleableInterface $salableItem + * @return boolean + */ + public function isSalable(\Magento\Framework\Pricing\SaleableInterface $salableItem) + { + return $salableItem->getCanShowPrice() !== false && $salableItem->isSalable(); + } +} diff --git a/app/code/Magento/Catalog/Model/Product/Pricing/Renderer/SalableResolverInterface.php b/app/code/Magento/Catalog/Model/Product/Pricing/Renderer/SalableResolverInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..d77015666358ea31135069ca95745ae40c443c2e --- /dev/null +++ b/app/code/Magento/Catalog/Model/Product/Pricing/Renderer/SalableResolverInterface.php @@ -0,0 +1,21 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Catalog\Model\Product\Pricing\Renderer; + +/** + * Interface resolver checks whether product available for sale + */ +interface SalableResolverInterface +{ + /** + * Check whether product available for sale + * + * @param \Magento\Framework\Pricing\SaleableInterface $salableItem + * @return boolean + */ + public function isSalable(\Magento\Framework\Pricing\SaleableInterface $salableItem); +} diff --git a/app/code/Magento/Catalog/Model/ProductOptions/Config.php b/app/code/Magento/Catalog/Model/ProductOptions/Config.php index bd55304e03beface2791526e00d2731ca6285ce9..fa828832bf4a716eddf1eeabdea9befcf94b6ab3 100644 --- a/app/code/Magento/Catalog/Model/ProductOptions/Config.php +++ b/app/code/Magento/Catalog/Model/ProductOptions/Config.php @@ -5,20 +5,29 @@ */ namespace Magento\Catalog\Model\ProductOptions; +use Magento\Framework\Serialize\SerializerInterface; + +/** + * Provides product options configuration + */ class Config extends \Magento\Framework\Config\Data implements \Magento\Catalog\Model\ProductOptions\ConfigInterface { /** + * Constructor + * * @param \Magento\Catalog\Model\ProductOptions\Config\Reader $reader * @param \Magento\Framework\Config\CacheInterface $cache - * @param string $cacheId + * @param string|null $cacheId + * @param SerializerInterface|null $serializer */ public function __construct( \Magento\Catalog\Model\ProductOptions\Config\Reader $reader, \Magento\Framework\Config\CacheInterface $cache, - $cacheId = 'product_options_config' + $cacheId = 'product_options_config', + SerializerInterface $serializer = null ) { - parent::__construct($reader, $cache, $cacheId); + parent::__construct($reader, $cache, $cacheId, $serializer); } /** diff --git a/app/code/Magento/Catalog/Model/ProductTypes/Config.php b/app/code/Magento/Catalog/Model/ProductTypes/Config.php index a80692cfaf945ced5b51fc9118b4a82b597dd9e3..f691e08a34b576e8416e3b07e60cd0d0243274da 100644 --- a/app/code/Magento/Catalog/Model/ProductTypes/Config.php +++ b/app/code/Magento/Catalog/Model/ProductTypes/Config.php @@ -5,19 +5,28 @@ */ namespace Magento\Catalog\Model\ProductTypes; +use Magento\Framework\Serialize\SerializerInterface; + +/** + * Provides product types configuration + */ class Config extends \Magento\Framework\Config\Data implements \Magento\Catalog\Model\ProductTypes\ConfigInterface { /** - * @param \Magento\Catalog\Model\ProductTypes\Config\Reader $reader + * Constructor + * + * @param Config\Reader $reader * @param \Magento\Framework\Config\CacheInterface $cache - * @param string $cacheId + * @param string|null $cacheId + * @param SerializerInterface|null $serializer */ public function __construct( \Magento\Catalog\Model\ProductTypes\Config\Reader $reader, \Magento\Framework\Config\CacheInterface $cache, - $cacheId = 'product_types_config' + $cacheId = 'product_types_config', + SerializerInterface $serializer = null ) { - parent::__construct($reader, $cache, $cacheId); + parent::__construct($reader, $cache, $cacheId, $serializer); } /** diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Eav/Attribute.php b/app/code/Magento/Catalog/Model/ResourceModel/Eav/Attribute.php index 8e93868dc7e51916a1c44997ad98045edbe1bd4f..8fdb867c9dbd84a2903a9a3372144d05c54922f4 100644 --- a/app/code/Magento/Catalog/Model/ResourceModel/Eav/Attribute.php +++ b/app/code/Magento/Catalog/Model/ResourceModel/Eav/Attribute.php @@ -417,6 +417,9 @@ class Attribute extends \Magento\Eav\Model\Entity\Attribute implements if ($this->getAttributeCode() == 'price') { return false; } + if ($this->getAttributeCode() == 'visibility') { + return true; + } if (!$this->getIsFilterableInSearch() && !$this->getIsVisibleInAdvancedSearch() && !$this->getIsFilterable()) { return false; diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Product/Collection.php b/app/code/Magento/Catalog/Model/ResourceModel/Product/Collection.php index c24460981afbf8d6c6cccb79255031d8320b726f..1cf18fc998ef973c0e3735d72cf347430710beda 100644 --- a/app/code/Magento/Catalog/Model/ResourceModel/Product/Collection.php +++ b/app/code/Magento/Catalog/Model/ResourceModel/Product/Collection.php @@ -17,6 +17,7 @@ use Magento\Framework\App\ObjectManager; use Magento\Framework\EntityManager\MetadataPool; use Magento\Store\Model\Store; use Magento\Catalog\Model\Product\Gallery\ReadHandler as GalleryReadHandler; +use Magento\Catalog\Model\ResourceModel\Product\Collection\ProductLimitationFactory; /** * Product collection @@ -261,6 +262,8 @@ class Collection extends \Magento\Catalog\Model\ResourceModel\Collection\Abstrac private $metadataPool; /** + * Collection constructor + * * @param \Magento\Framework\Data\Collection\EntityFactory $entityFactory * @param \Psr\Log\LoggerInterface $logger * @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy @@ -280,7 +283,9 @@ class Collection extends \Magento\Catalog\Model\ResourceModel\Collection\Abstrac * @param \Magento\Customer\Model\Session $customerSession * @param \Magento\Framework\Stdlib\DateTime $dateTime * @param GroupManagementInterface $groupManagement - * @param \Magento\Framework\DB\Adapter\AdapterInterface $connection + * @param \Magento\Framework\DB\Adapter\AdapterInterface|null $connection + * @param ProductLimitationFactory|null $productLimitationFactory + * @param MetadataPool|null $metadataPool * * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ @@ -304,7 +309,9 @@ class Collection extends \Magento\Catalog\Model\ResourceModel\Collection\Abstrac \Magento\Customer\Model\Session $customerSession, \Magento\Framework\Stdlib\DateTime $dateTime, GroupManagementInterface $groupManagement, - \Magento\Framework\DB\Adapter\AdapterInterface $connection = null + \Magento\Framework\DB\Adapter\AdapterInterface $connection = null, + ProductLimitationFactory $productLimitationFactory = null, + MetadataPool $metadataPool = null ) { $this->moduleManager = $moduleManager; $this->_catalogProductFlatState = $catalogProductFlatState; @@ -316,7 +323,11 @@ class Collection extends \Magento\Catalog\Model\ResourceModel\Collection\Abstrac $this->_resourceHelper = $resourceHelper; $this->dateTime = $dateTime; $this->_groupManagement = $groupManagement; - $this->_productLimitationFilters = $this->createLimitationFilters(); + $productLimitationFactory = $productLimitationFactory ?: ObjectManager::getInstance()->get( + \Magento\Catalog\Model\ResourceModel\Product\Collection\ProductLimitationFactory::class + ); + $this->_productLimitationFilters = $productLimitationFactory->create(); + $this->metadataPool = $metadataPool ?: ObjectManager::getInstance()->get(MetadataPool::class); parent::__construct( $entityFactory, $logger, @@ -2181,7 +2192,7 @@ class Collection extends \Magento\Catalog\Model\ResourceModel\Collection\Abstrac ); $mediaGalleries = []; - $linkField = $this->getMetadataPool()->getMetadata(ProductInterface::class)->getLinkField(); + $linkField = $this->getProductEntityMetadata()->getLinkField(); $items = $this->getItems(); $select->where('entity.' . $linkField . ' IN (?)', array_map(function ($item) { @@ -2202,15 +2213,13 @@ class Collection extends \Magento\Catalog\Model\ResourceModel\Collection\Abstrac } /** - * Get MetadataPool instance - * @return MetadataPool + * Get product entity metadata + * + * @return \Magento\Framework\EntityManager\EntityMetadataInterface */ - private function getMetadataPool() + public function getProductEntityMetadata() { - if (!$this->metadataPool) { - $this->metadataPool = ObjectManager::getInstance()->get(MetadataPool::class); - } - return $this->metadataPool; + return $this->metadataPool->getMetadata(ProductInterface::class); } /** @@ -2334,13 +2343,4 @@ class Collection extends \Magento\Catalog\Model\ResourceModel\Collection\Abstrac return $this->_pricesCount; } - - /** - * @return Collection\ProductLimitation - */ - private function createLimitationFilters() - { - return \Magento\Framework\App\ObjectManager::getInstance() - ->create(\Magento\Catalog\Model\ResourceModel\Product\Collection\ProductLimitation::class); - } } diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Product/Link/Product/Collection.php b/app/code/Magento/Catalog/Model/ResourceModel/Product/Link/Product/Collection.php index 239f94e1286b834ab218b1e71530342fd5810a73..116f454cd5e750a43a93a73139521b5aa15a50bc 100644 --- a/app/code/Magento/Catalog/Model/ResourceModel/Product/Link/Product/Collection.php +++ b/app/code/Magento/Catalog/Model/ResourceModel/Product/Link/Product/Collection.php @@ -5,11 +5,6 @@ */ namespace Magento\Catalog\Model\ResourceModel\Product\Link\Product; -use Magento\Catalog\Api\Data\ProductInterface; -use Magento\Customer\Api\GroupManagementInterface; -use Magento\Framework\App\ObjectManager; -use Magento\Framework\EntityManager\MetadataPool; - /** * Catalog product linked products collection * @@ -53,80 +48,6 @@ class Collection extends \Magento\Catalog\Model\ResourceModel\Product\Collection */ protected $_hasLinkFilter = false; - /** - * @var MetadataPool - */ - private $metadataPool; - - /** - * @param \Magento\Framework\Data\Collection\EntityFactory $entityFactory - * @param \Psr\Log\LoggerInterface $logger - * @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy - * @param \Magento\Framework\Event\ManagerInterface $eventManager - * @param \Magento\Eav\Model\Config $eavConfig - * @param \Magento\Framework\App\ResourceConnection $resource - * @param \Magento\Eav\Model\EntityFactory $eavEntityFactory - * @param \Magento\Catalog\Model\ResourceModel\Helper $resourceHelper - * @param \Magento\Framework\Validator\UniversalFactory $universalFactory - * @param \Magento\Store\Model\StoreManagerInterface $storeManager - * @param \Magento\Framework\Module\Manager $moduleManager - * @param \Magento\Catalog\Model\Indexer\Product\Flat\State $catalogProductFlatState - * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig - * @param \Magento\Catalog\Model\Product\OptionFactory $productOptionFactory - * @param \Magento\Catalog\Model\ResourceModel\Url $catalogUrl - * @param \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate - * @param \Magento\Customer\Model\Session $customerSession - * @param \Magento\Framework\Stdlib\DateTime $dateTime - * @param GroupManagementInterface $groupManagement - * @param \Magento\Framework\DB\Adapter\AdapterInterface|null $connection - * @SuppressWarnings(PHPMD.ExcessiveParameterList) - */ - public function __construct( - \Magento\Framework\Data\Collection\EntityFactory $entityFactory, - \Psr\Log\LoggerInterface $logger, - \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy, - \Magento\Framework\Event\ManagerInterface $eventManager, - \Magento\Eav\Model\Config $eavConfig, - \Magento\Framework\App\ResourceConnection $resource, - \Magento\Eav\Model\EntityFactory $eavEntityFactory, - \Magento\Catalog\Model\ResourceModel\Helper $resourceHelper, - \Magento\Framework\Validator\UniversalFactory $universalFactory, - \Magento\Store\Model\StoreManagerInterface $storeManager, - \Magento\Framework\Module\Manager $moduleManager, - \Magento\Catalog\Model\Indexer\Product\Flat\State $catalogProductFlatState, - \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig, - \Magento\Catalog\Model\Product\OptionFactory $productOptionFactory, - \Magento\Catalog\Model\ResourceModel\Url $catalogUrl, - \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate, - \Magento\Customer\Model\Session $customerSession, - \Magento\Framework\Stdlib\DateTime $dateTime, - GroupManagementInterface $groupManagement, - \Magento\Framework\DB\Adapter\AdapterInterface $connection = null - ) { - parent::__construct( - $entityFactory, - $logger, - $fetchStrategy, - $eventManager, - $eavConfig, - $resource, - $eavEntityFactory, - $resourceHelper, - $universalFactory, - $storeManager, - $moduleManager, - $catalogProductFlatState, - $scopeConfig, - $productOptionFactory, - $catalogUrl, - $localeDate, - $customerSession, - $dateTime, - $groupManagement, - $connection - ); - } - /** * Declare link model and initialize type attributes join * @@ -219,7 +140,7 @@ class Collection extends \Magento\Catalog\Model\ResourceModel\Product\Collection if (!is_array($products)) { $products = [$products]; } - $identifierField = $this->getMetadataPool()->getMetadata(ProductInterface::class)->getIdentifierField(); + $identifierField = $this->getProductEntityMetadata()->getIdentifierField(); $this->getSelect()->where("product_entity_table.$identifierField IN (?)", $products); $this->_hasLinkFilter = true; } @@ -279,7 +200,7 @@ class Collection extends \Magento\Catalog\Model\ResourceModel\Product\Collection $connection->quoteInto('links.link_type_id = ?', $this->_linkTypeId), ]; $joinType = 'join'; - $linkField = $this->getMetadataPool()->getMetadata(ProductInterface::class)->getLinkField(); + $linkField = $this->getProductEntityMetadata()->getLinkField(); if ($this->getProduct() && $this->getProduct()->getId()) { $linkFieldId = $this->getProduct()->getData( $linkField @@ -422,19 +343,6 @@ class Collection extends \Magento\Catalog\Model\ResourceModel\Product\Collection return $this; } - /** - * Get MetadataPool instance - * @return MetadataPool - * @deprecated - */ - private function getMetadataPool() - { - if (!$this->metadataPool) { - $this->metadataPool = ObjectManager::getInstance()->get(MetadataPool::class); - } - return $this->metadataPool; - } - /** * Join Product To Links * @return void @@ -442,11 +350,15 @@ class Collection extends \Magento\Catalog\Model\ResourceModel\Product\Collection private function joinProductsToLinks() { if ($this->_hasLinkFilter) { - $metaDataPool = $this->getMetadataPool()->getMetadata(ProductInterface::class); + $metaDataPool = $this->getProductEntityMetadata(); $linkField = $metaDataPool->getLinkField(); $entityTable = $metaDataPool->getEntityTable(); $this->getSelect() - ->join(['product_entity_table' => $entityTable], "links.product_id = product_entity_table.$linkField", []); + ->join( + ['product_entity_table' => $entityTable], + "links.product_id = product_entity_table.$linkField", + [] + ); } } } diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Product/Option/Collection.php b/app/code/Magento/Catalog/Model/ResourceModel/Product/Option/Collection.php index 2d50ead9d56d956a22e36305967b527c8be3a288..68280d5a1d5975714d2d91fd2b94eab08a82dfc6 100644 --- a/app/code/Magento/Catalog/Model/ResourceModel/Product/Option/Collection.php +++ b/app/code/Magento/Catalog/Model/ResourceModel/Product/Option/Collection.php @@ -7,6 +7,7 @@ namespace Magento\Catalog\Model\ResourceModel\Product\Option; use Magento\Catalog\Api\Data\ProductInterface; use Magento\Framework\Api\ExtensionAttribute\JoinProcessorInterface; +use Magento\Framework\EntityManager\MetadataPool; /** * Catalog product options collection @@ -49,6 +50,7 @@ class Collection extends \Magento\Framework\Model\ResourceModel\Db\Collection\Ab * @param \Magento\Store\Model\StoreManagerInterface $storeManager * @param \Magento\Framework\DB\Adapter\AdapterInterface $connection * @param \Magento\Framework\Model\ResourceModel\Db\AbstractDb $resource + * @param MetadataPool $metadataPool * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( @@ -59,10 +61,13 @@ class Collection extends \Magento\Framework\Model\ResourceModel\Db\Collection\Ab \Magento\Catalog\Model\ResourceModel\Product\Option\Value\CollectionFactory $optionValueCollectionFactory, \Magento\Store\Model\StoreManagerInterface $storeManager, \Magento\Framework\DB\Adapter\AdapterInterface $connection = null, - \Magento\Framework\Model\ResourceModel\Db\AbstractDb $resource = null + \Magento\Framework\Model\ResourceModel\Db\AbstractDb $resource = null, + MetadataPool $metadataPool = null ) { $this->_optionValueCollectionFactory = $optionValueCollectionFactory; $this->_storeManager = $storeManager; + $this->metadataPool = $metadataPool ?: \Magento\Framework\App\ObjectManager::getInstance() + ->get(\Magento\Framework\EntityManager\MetadataPool::class); parent::__construct($entityFactory, $logger, $fetchStrategy, $eventManager, $connection, $resource); } @@ -248,7 +253,7 @@ class Collection extends \Magento\Framework\Model\ResourceModel\Db\Collection\Ab ['cpe' => $this->getTable('catalog_product_entity')], sprintf( 'cpe.%s = main_table.product_id', - $this->getMetadataPool()->getMetadata(ProductInterface::class)->getLinkField() + $this->metadataPool->getMetadata(ProductInterface::class)->getLinkField() ), [] ); @@ -318,18 +323,6 @@ class Collection extends \Magento\Framework\Model\ResourceModel\Db\Collection\Ab return $this->_reset(); } - /** - * @return \Magento\Framework\EntityManager\MetadataPool - */ - private function getMetadataPool() - { - if (null === $this->metadataPool) { - $this->metadataPool = \Magento\Framework\App\ObjectManager::getInstance() - ->get(\Magento\Framework\EntityManager\MetadataPool::class); - } - return $this->metadataPool; - } - /** * @return JoinProcessorInterface */ diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Product/StatusBaseSelectProcessor.php b/app/code/Magento/Catalog/Model/ResourceModel/Product/StatusBaseSelectProcessor.php index 656998113fdb92e50e5177db4876651cfcd2023a..b4293a39895850fb349a6232e0c5b95fc1dfa50f 100644 --- a/app/code/Magento/Catalog/Model/ResourceModel/Product/StatusBaseSelectProcessor.php +++ b/app/code/Magento/Catalog/Model/ResourceModel/Product/StatusBaseSelectProcessor.php @@ -11,6 +11,8 @@ use Magento\Catalog\Model\Product\Attribute\Source\Status; use Magento\Eav\Model\Config; use Magento\Framework\DB\Select; use Magento\Framework\EntityManager\MetadataPool; +use Magento\Store\Api\StoreResolverInterface; +use Magento\Store\Model\Store; /** * Class StatusBaseSelectProcessor @@ -27,16 +29,24 @@ class StatusBaseSelectProcessor implements BaseSelectProcessorInterface */ private $metadataPool; + /** + * @var StoreResolverInterface + */ + private $storeResolver; + /** * @param Config $eavConfig * @param MetadataPool $metadataPool + * @param StoreResolverInterface $storeResolver */ public function __construct( Config $eavConfig, - MetadataPool $metadataPool + MetadataPool $metadataPool, + StoreResolverInterface $storeResolver ) { $this->eavConfig = $eavConfig; $this->metadataPool = $metadataPool; + $this->storeResolver = $storeResolver; } /** @@ -48,13 +58,23 @@ class StatusBaseSelectProcessor implements BaseSelectProcessorInterface $linkField = $this->metadataPool->getMetadata(ProductInterface::class)->getLinkField(); $statusAttribute = $this->eavConfig->getAttribute(Product::ENTITY, ProductInterface::STATUS); - $select->join( + $select->joinLeft( + ['status_global_attr' => $statusAttribute->getBackendTable()], + "status_global_attr.{$linkField} = " . self::PRODUCT_TABLE_ALIAS . ".{$linkField}" + . ' AND status_global_attr.attribute_id = ' . (int)$statusAttribute->getAttributeId() + . ' AND status_global_attr.store_id = ' . Store::DEFAULT_STORE_ID, + [] + ); + + $select->joinLeft( ['status_attr' => $statusAttribute->getBackendTable()], - sprintf('status_attr.%s = %s.%1$s', $linkField, self::PRODUCT_TABLE_ALIAS), + "status_attr.{$linkField} = " . self::PRODUCT_TABLE_ALIAS . ".{$linkField}" + . ' AND status_attr.attribute_id = ' . (int)$statusAttribute->getAttributeId() + . ' AND status_attr.store_id = ' . $this->storeResolver->getCurrentStoreId(), [] - ) - ->where('status_attr.attribute_id = ?', $statusAttribute->getAttributeId()) - ->where('status_attr.value = ?', Status::STATUS_ENABLED); + ); + + $select->where('IFNULL(status_attr.value, status_global_attr.value) = ?', Status::STATUS_ENABLED); return $select; } 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/Catalog/Model/View/Asset/Image.php b/app/code/Magento/Catalog/Model/View/Asset/Image.php new file mode 100644 index 0000000000000000000000000000000000000000..31129d7d892d2a3737b4263beb127a37c6e0217b --- /dev/null +++ b/app/code/Magento/Catalog/Model/View/Asset/Image.php @@ -0,0 +1,191 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Catalog\Model\View\Asset; + +use Magento\Catalog\Model\Product\Media\ConfigInterface; +use Magento\Framework\Encryption\Encryptor; +use Magento\Framework\Encryption\EncryptorInterface; +use Magento\Framework\View\Asset\ContextInterface; +use Magento\Framework\View\Asset\LocalInterface; + +/** + * A locally available image file asset that can be referred with a file path + * + * This class is a value object with lazy loading of some of its data (content, physical file path) + */ +class Image implements LocalInterface +{ + /** + * @var string + */ + private $filePath; + + /** + * @var string + */ + private $contentType = 'image'; + + /** + * @var ContextInterface + */ + private $context; + + /** + * Misc image params depend on size, transparency, quality, watermark etc. + * + * @var array + */ + private $miscParams; + + /** + * @var ConfigInterface + */ + private $mediaConfig; + + /** + * @var EncryptorInterface + */ + private $encryptor; + + /** + * Image constructor. + * + * @param ConfigInterface $mediaConfig + * @param ContextInterface $context + * @param EncryptorInterface $encryptor + * @param string $filePath + * @param array $miscParams + */ + public function __construct( + ConfigInterface $mediaConfig, + ContextInterface $context, + EncryptorInterface $encryptor, + $filePath, + array $miscParams = [] + ) { + $this->mediaConfig = $mediaConfig; + $this->context = $context; + $this->filePath = $filePath; + $this->miscParams = $miscParams; + $this->encryptor = $encryptor; + } + + /** + * {@inheritdoc} + */ + public function getUrl() + { + return $this->context->getBaseUrl() . $this->getRelativePath(DIRECTORY_SEPARATOR); + } + + /** + * {@inheritdoc} + */ + public function getContentType() + { + return $this->contentType; + } + + /** + * {@inheritdoc} + */ + public function getPath() + { + return $this->getRelativePath($this->context->getPath()); + } + + /** + * Subroutine for building path + * + * @param string $path + * @param string $item + * @return string + */ + private function join($path, $item) + { + return trim( + $path . ($item ? DIRECTORY_SEPARATOR . ltrim($item, DIRECTORY_SEPARATOR) : ''), + DIRECTORY_SEPARATOR + ); + } + + /** + * {@inheritdoc} + */ + public function getSourceFile() + { + return $this->mediaConfig->getBaseMediaPath() + . DIRECTORY_SEPARATOR . ltrim($this->filePath, DIRECTORY_SEPARATOR); + } + + /** + * Get source content type + * + * @return string + */ + public function getSourceContentType() + { + return $this->contentType; + } + + /** + * {@inheritdoc} + */ + public function getContent() + { + return null; + } + + /** + * {@inheritdoc} + */ + public function getFilePath() + { + return $this->filePath; + } + + /** + * {@inheritdoc} + * @return ContextInterface + */ + public function getContext() + { + return $this->context; + } + + /** + * {@inheritdoc} + */ + public function getModule() + { + return 'cache'; + } + + /** + * Retrieve part of path based on misc params + * + * @return string + */ + private function getMiscPath() + { + return $this->encryptor->hash(implode('_', $this->miscParams), Encryptor::HASH_VERSION_MD5); + } + + /** + * Generate relative path + * + * @param string $result + * @return string + */ + private function getRelativePath($result) + { + $result = $this->join($result, $this->getModule()); + $result = $this->join($result, $this->getMiscPath()); + $result = $this->join($result, $this->getFilePath()); + return DIRECTORY_SEPARATOR . $result; + } +} diff --git a/app/code/Magento/Catalog/Model/View/Asset/Image/Context.php b/app/code/Magento/Catalog/Model/View/Asset/Image/Context.php new file mode 100644 index 0000000000000000000000000000000000000000..33f0adb70c94113f51321ecce40cdffdee1ef769 --- /dev/null +++ b/app/code/Magento/Catalog/Model/View/Asset/Image/Context.php @@ -0,0 +1,59 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Catalog\Model\View\Asset\Image; + +use Magento\Framework\App\Filesystem\DirectoryList; +use Magento\Framework\View\Asset\ContextInterface; + +/** + * A basic path context for assets that includes a directory path + */ +class Context implements ContextInterface +{ + /** + * @var \Magento\Framework\Filesystem\Directory\WriteInterface + */ + private $mediaDirectory; + + /** + * @var \Magento\Catalog\Model\Product\Media\ConfigInterface + */ + private $mediaConfig; + + /** + * @var \Magento\Framework\Filesystem + */ + private $filesystem; + + /** + */ + public function __construct( + \Magento\Catalog\Model\Product\Media\ConfigInterface $mediaConfig, + \Magento\Framework\Filesystem $filesystem + ) { + $this->mediaConfig = $mediaConfig; + $this->filesystem = $filesystem; + $this->mediaDirectory = $this->filesystem->getDirectoryWrite(DirectoryList::MEDIA); + $this->mediaDirectory->create($this->mediaConfig->getBaseMediaPath()); + } + + /** + * {@inheritdoc} + */ + public function getPath() + { + return $this->mediaDirectory->getAbsolutePath($this->mediaConfig->getBaseMediaPath()); + } + + /** + * {@inheritdoc} + */ + public function getBaseUrl() + { + return $this->mediaConfig->getBaseMediaUrl(); + } +} diff --git a/app/code/Magento/Catalog/Model/View/Asset/Placeholder.php b/app/code/Magento/Catalog/Model/View/Asset/Placeholder.php new file mode 100644 index 0000000000000000000000000000000000000000..fd7dcd1c4692ec76af97bdfb782e756345985d4b --- /dev/null +++ b/app/code/Magento/Catalog/Model/View/Asset/Placeholder.php @@ -0,0 +1,181 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Catalog\Model\View\Asset; + +use Magento\Framework\App\Config\ScopeConfigInterface; +use Magento\Framework\View\Asset\ContextInterface; +use Magento\Framework\View\Asset\File\NotFoundException; +use Magento\Framework\View\Asset\LocalInterface; +use Magento\Framework\View\Asset\Repository; + +/** + * A locally available image placeholder file asset that can be referred with a file type + */ +class Placeholder implements LocalInterface +{ + /** + * Type of placeholder + * + * @var string + */ + private $type; + + /** + * Filevpath of placeholder + * + * @var string + */ + private $filePath; + + /** + * @var string + */ + private $contentType = 'image'; + + /** + * @var ContextInterface + */ + private $context; + + /** + * @var Repository + */ + private $assetRepo; + + /** + * Core store config + * + * @var ScopeConfigInterface + */ + private $scopeConfig; + + /** + * Placeholder constructor. + * + * @param ContextInterface $context + * @param ScopeConfigInterface $scopeConfig + * @param Repository $assetRepo + * @param string $type + */ + public function __construct( + ContextInterface $context, + ScopeConfigInterface $scopeConfig, + Repository $assetRepo, + $type + ) { + $this->context = $context; + $this->scopeConfig = $scopeConfig; + $this->assetRepo = $assetRepo; + $this->type = $type; + } + + /** + * {@inheritdoc} + */ + public function getUrl() + { + if ($this->getFilePath() !== null) { + $result = $this->context->getBaseUrl() . '/' . $this->getModule() . '/' . $this->getFilePath(); + } else { + $result = $this->assetRepo->getUrl("Magento_Catalog::images/product/placeholder/{$this->type}.jpg"); + } + + return $result; + } + + /** + * {@inheritdoc} + */ + public function getContentType() + { + return $this->contentType; + } + + /** + * {@inheritdoc} + */ + public function getPath() + { + if ($this->getFilePath() !== null) { + $result = $this->getContext()->getPath() + . DIRECTORY_SEPARATOR . $this->getModule() + . DIRECTORY_SEPARATOR . $this->getFilePath(); + } else { + $defaultPlaceholder = $this->assetRepo->createAsset( + "Magento_Catalog::images/product/placeholder/{$this->type}.jpg" + ); + try { + $result = $defaultPlaceholder->getSourceFile(); + } catch (NotFoundException $e) { + $result = null; + } + } + + return $result; + } + + /** + * {@inheritdoc} + */ + public function getSourceFile() + { + return $this->getPath(); + } + + /** + * Get source content type + * + * @return string + */ + public function getSourceContentType() + { + return $this->contentType; + } + + /** + * {@inheritdoc} + */ + public function getContent() + { + return null; + } + + /** + * {@inheritdoc} + */ + public function getFilePath() + { + if ($this->filePath !== null) { + return $this->filePath; + } + // check if placeholder defined in config + $isConfigPlaceholder = $this->scopeConfig->getValue( + "catalog/placeholder/{$this->type}_placeholder", + \Magento\Store\Model\ScopeInterface::SCOPE_STORE + ); + $this->filePath = $isConfigPlaceholder; + + return $this->filePath; + } + + /** + * {@inheritdoc} + * @return ContextInterface + */ + public function getContext() + { + return $this->context; + } + + /** + * {@inheritdoc} + */ + public function getModule() + { + return 'placeholder'; + } +} diff --git a/app/code/Magento/Catalog/Plugin/Model/ResourceModel/Config.php b/app/code/Magento/Catalog/Plugin/Model/ResourceModel/Config.php index 699feef76c67e281d237a177a4def197c449e750..69c693f4fd01abcb39577b49cffb4ceaab8bf08f 100644 --- a/app/code/Magento/Catalog/Plugin/Model/ResourceModel/Config.php +++ b/app/code/Magento/Catalog/Plugin/Model/ResourceModel/Config.php @@ -5,6 +5,9 @@ */ namespace Magento\Catalog\Plugin\Model\ResourceModel; +use Magento\Framework\App\ObjectManager; +use Magento\Framework\Serialize\SerializerInterface; + class Config { /**#@+ @@ -20,16 +23,24 @@ class Config /** @var bool|null */ protected $isCacheEnabled = null; + /** + * @var SerializerInterface + */ + private $serializer; + /** * @param \Magento\Framework\App\CacheInterface $cache * @param \Magento\Framework\App\Cache\StateInterface $cacheState + * @param SerializerInterface $serializer */ public function __construct( \Magento\Framework\App\CacheInterface $cache, - \Magento\Framework\App\Cache\StateInterface $cacheState + \Magento\Framework\App\Cache\StateInterface $cacheState, + SerializerInterface $serializer = null ) { $this->cache = $cache; $this->isCacheEnabled = $cacheState->isEnabled(\Magento\Eav\Model\Cache\Type::TYPE_IDENTIFIER); + $this->serializer = $serializer ?: ObjectManager::getInstance()->get(SerializerInterface::class); } /** @@ -43,12 +54,12 @@ class Config ) { $cacheId = self::PRODUCT_LISTING_ATTRIBUTES_CACHE_ID . $config->getEntityTypeId() . '_' . $config->getStoreId(); if ($this->isCacheEnabled && ($attributes = $this->cache->load($cacheId))) { - return unserialize($attributes); + return $this->serializer->unserialize($attributes); } $attributes = $proceed(); if ($this->isCacheEnabled) { $this->cache->save( - serialize($attributes), + $this->serializer->serialize($attributes), $cacheId, [ \Magento\Eav\Model\Cache\Type::CACHE_TAG, @@ -71,12 +82,12 @@ class Config $cacheId = self::PRODUCT_LISTING_SORT_BY_ATTRIBUTES_CACHE_ID . $config->getEntityTypeId() . '_' . $config->getStoreId(); if ($this->isCacheEnabled && ($attributes = $this->cache->load($cacheId))) { - return unserialize($attributes); + return $this->serializer->unserialize($attributes); } $attributes = $proceed(); if ($this->isCacheEnabled) { $this->cache->save( - serialize($attributes), + $this->serializer->serialize($attributes), $cacheId, [ \Magento\Eav\Model\Cache\Type::CACHE_TAG, diff --git a/app/code/Magento/Catalog/Pricing/Render/FinalPriceBox.php b/app/code/Magento/Catalog/Pricing/Render/FinalPriceBox.php index a940e09bd57b56a026bba1a45312b94b7f1c80e3..05c1e3a79ce0318f6d4444e8f276318dae7b59dc 100644 --- a/app/code/Magento/Catalog/Pricing/Render/FinalPriceBox.php +++ b/app/code/Magento/Catalog/Pricing/Render/FinalPriceBox.php @@ -10,6 +10,11 @@ use Magento\Catalog\Pricing\Price; use Magento\Framework\Pricing\Render; use Magento\Framework\Pricing\Render\PriceBox as BasePriceBox; use Magento\Msrp\Pricing\Price\MsrpPrice; +use Magento\Catalog\Model\Product\Pricing\Renderer\SalableResolverInterface; +use Magento\Framework\View\Element\Template\Context; +use Magento\Framework\Pricing\SaleableInterface; +use Magento\Framework\Pricing\Price\PriceInterface; +use Magento\Framework\Pricing\Render\RendererPool; /** * Class for final_price rendering @@ -19,28 +24,44 @@ use Magento\Msrp\Pricing\Price\MsrpPrice; */ class FinalPriceBox extends BasePriceBox { + /** + * @var SalableResolverInterface + */ + private $salableResolver; + + /** + * @param Context $context + * @param SaleableInterface $saleableItem + * @param PriceInterface $price + * @param RendererPool $rendererPool + * @param array $data + * @param SalableResolverInterface $salableResolver + */ + public function __construct( + Context $context, + SaleableInterface $saleableItem, + PriceInterface $price, + RendererPool $rendererPool, + array $data = [], + SalableResolverInterface $salableResolver = null + ) { + parent::__construct($context, $saleableItem, $price, $rendererPool, $data); + $this->salableResolver = $salableResolver ?: \Magento\Framework\App\ObjectManager::getInstance() + ->get(SalableResolverInterface::class); + } + /** * @return string */ protected function _toHtml() { - if (!$this->getSaleableItem() || $this->getSaleableItem()->getCanShowPrice() === false) { + if (!$this->salableResolver->isSalable($this->getSaleableItem())) { return ''; } $result = parent::_toHtml(); - - try { - /** @var MsrpPrice $msrpPriceType */ - $msrpPriceType = $this->getSaleableItem()->getPriceInfo()->getPrice('msrp_price'); - } catch (\InvalidArgumentException $e) { - $this->_logger->critical($e); - return $this->wrapResult($result); - } - //Renders MSRP in case it is enabled - $product = $this->getSaleableItem(); - if ($msrpPriceType->canApplyMsrp($product) && $msrpPriceType->isMinimalPriceLessMsrp($product)) { + if ($this->isMsrpPriceApplicable()) { /** @var BasePriceBox $msrpBlock */ $msrpBlock = $this->rendererPool->createPriceRender( MsrpPrice::PRICE_CODE, @@ -56,6 +77,25 @@ class FinalPriceBox extends BasePriceBox return $this->wrapResult($result); } + /** + * Check is MSRP applicable for the current product. + * + * @return bool + */ + protected function isMsrpPriceApplicable() + { + try { + /** @var MsrpPrice $msrpPriceType */ + $msrpPriceType = $this->getSaleableItem()->getPriceInfo()->getPrice('msrp_price'); + } catch (\InvalidArgumentException $e) { + $this->_logger->critical($e); + return false; + } + + $product = $this->getSaleableItem(); + return $msrpPriceType->canApplyMsrp($product) && $msrpPriceType->isMinimalPriceLessMsrp($product); + } + /** * Wrap with standard required container * diff --git a/app/code/Magento/Catalog/Test/Unit/Block/Product/View/GalleryTest.php b/app/code/Magento/Catalog/Test/Unit/Block/Product/View/GalleryTest.php index 2e3a896d956d9cdd1dd82ccee58873bcf6131460..3aee622b5e3b3a48910318157a33faf8498cfd37 100644 --- a/app/code/Magento/Catalog/Test/Unit/Block/Product/View/GalleryTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Block/Product/View/GalleryTest.php @@ -111,8 +111,8 @@ class GalleryTest extends \PHPUnit_Framework_TestCase ->method('init') ->willReturnMap([ [$productMock, 'product_page_image_small', [], $this->imageHelper], - [$productMock, 'product_page_image_medium', [], $this->imageHelper], - [$productMock, 'product_page_image_large', [], $this->imageHelper], + [$productMock, 'product_page_image_medium_no_frame', [], $this->imageHelper], + [$productMock, 'product_page_image_large_no_frame', [], $this->imageHelper], ]) ->willReturnSelf(); $this->imageHelper->expects($this->exactly(3)) @@ -129,19 +129,6 @@ class GalleryTest extends \PHPUnit_Framework_TestCase ->method('getUrl') ->willReturn('product_page_image_large_url'); - $this->imageHelper->expects($this->exactly(2)) - ->method('constrainOnly') - ->with(true) - ->willReturnSelf(); - $this->imageHelper->expects($this->exactly(2)) - ->method('keepAspectRatio') - ->with(true) - ->willReturnSelf(); - $this->imageHelper->expects($this->exactly(2)) - ->method('keepFrame') - ->with(false) - ->willReturnSelf(); - $images = $this->model->getGalleryImages(); $this->assertInstanceOf(\Magento\Framework\Data\Collection::class, $images); } diff --git a/app/code/Magento/Catalog/Test/Unit/Helper/ImageTest.php b/app/code/Magento/Catalog/Test/Unit/Helper/ImageTest.php index 206f20bc98179db80af5fb45014b061149dec8d7..4ed3495f9e34812788baf408632e5af29d521044 100644 --- a/app/code/Magento/Catalog/Test/Unit/Helper/ImageTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Helper/ImageTest.php @@ -424,7 +424,6 @@ class ImageTest extends \PHPUnit_Framework_TestCase * @param string $imageId * @param string $imageFile * @param string $baseFile - * @param string $newFile * @param string $destination * @param boolean $setImageFile * @param boolean $isCached @@ -436,7 +435,6 @@ class ImageTest extends \PHPUnit_Framework_TestCase $imageId, $imageFile, $baseFile, - $newFile, $destination, $setImageFile, $isCached, @@ -477,9 +475,6 @@ class ImageTest extends \PHPUnit_Framework_TestCase $this->image->expects($this->any()) ->method('isBaseFilePlaceholder') ->willReturn($isBaseFilePlaceholder); - $this->image->expects($this->any()) - ->method('getNewFile') - ->willReturn($newFile); $this->prepareAttributes([], $imageId); @@ -502,7 +497,6 @@ class ImageTest extends \PHPUnit_Framework_TestCase 'image_id' => 'test_image_id', 'image_file' => '/path/to/test_image_id.png', 'base_file' => '/path/to/base_image.png', - 'new_file' => '/path/to/base_image.png', 'destination' => 'small_image', 'set_image_file' => true, 'is_cached' => false, @@ -516,7 +510,6 @@ class ImageTest extends \PHPUnit_Framework_TestCase 'image_id' => 'test_image_id', 'image_file' => '/path/to/test_image_id.png', 'base_file' => null, - 'new_file' => true, 'destination' => 'small_image', 'set_image_file' => false, 'is_cached' => false, @@ -530,7 +523,6 @@ class ImageTest extends \PHPUnit_Framework_TestCase 'image_id' => 'test_image_id', 'image_file' => '/path/to/test_image_id.png', 'base_file' => null, - 'new_file' => false, 'destination' => 'small_image', 'set_image_file' => true, 'is_cached' => false, @@ -544,7 +536,6 @@ class ImageTest extends \PHPUnit_Framework_TestCase 'image_id' => 'test_image_id', 'image_file' => '/path/to/test_image_id.png', 'base_file' => null, - 'new_file' => true, 'destination' => 'small_image', 'set_image_file' => true, 'is_cached' => false, @@ -558,7 +549,6 @@ class ImageTest extends \PHPUnit_Framework_TestCase 'image_id' => 'test_image_id', 'image_file' => '/path/to/test_image_id.png', 'base_file' => null, - 'new_file' => '/path/to/test_image_id.png', 'destination' => 'small_image', 'set_image_file' => true, 'is_cached' => false, diff --git a/app/code/Magento/Catalog/Test/Unit/Model/Category/DataProviderTest.php b/app/code/Magento/Catalog/Test/Unit/Model/Category/DataProviderTest.php new file mode 100644 index 0000000000000000000000000000000000000000..4a7971afbbb5074e3338a06a0c61366353dd73b5 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Unit/Model/Category/DataProviderTest.php @@ -0,0 +1,320 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Catalog\Test\Unit\Model\Category; + +use Magento\Catalog\Model\Category\DataProvider; +use Magento\Catalog\Model\Category\FileInfo; +use Magento\Catalog\Model\CategoryFactory; +use Magento\Catalog\Model\ResourceModel\Category\Collection; +use Magento\Catalog\Model\ResourceModel\Category\CollectionFactory; +use Magento\Eav\Model\Config; +use Magento\Eav\Model\Entity\Type; +use Magento\Framework\App\RequestInterface; +use Magento\Framework\Registry; +use Magento\Store\Model\StoreManagerInterface; +use Magento\Ui\DataProvider\EavValidationRules; + +/** + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ +class DataProviderTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var EavValidationRules|\PHPUnit_Framework_MockObject_MockObject + */ + private $eavValidationRules; + + /** + * @var CollectionFactory|\PHPUnit_Framework_MockObject_MockObject + */ + private $categoryCollectionFactory; + + /** + * @var StoreManagerInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $storeManager; + + /** + * @var Registry|\PHPUnit_Framework_MockObject_MockObject + */ + private $registry; + + /** + * @var Config|\PHPUnit_Framework_MockObject_MockObject + */ + private $eavConfig; + + /** + * @var RequestInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $request; + + /** + * @var CategoryFactory|\PHPUnit_Framework_MockObject_MockObject + */ + private $categoryFactory; + + /** + * @var Collection|\PHPUnit_Framework_MockObject_MockObject + */ + private $collection; + + /** + * @var Type|\PHPUnit_Framework_MockObject_MockObject + */ + private $eavEntityMock; + + /** + * @var FileInfo|\PHPUnit_Framework_MockObject_MockObject + */ + private $fileInfo; + + protected function setUp() + { + $this->eavValidationRules = $this->getMockBuilder(EavValidationRules::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->collection = $this->getMockBuilder(Collection::class) + ->disableOriginalConstructor() + ->getMock(); + $this->collection->expects($this->any()) + ->method('addAttributeToSelect') + ->with('*') + ->willReturnSelf(); + + $this->categoryCollectionFactory = $this->getMockBuilder(CollectionFactory::class) + ->disableOriginalConstructor() + ->setMethods(['create']) + ->getMock(); + $this->categoryCollectionFactory->expects($this->any()) + ->method('create') + ->willReturn($this->collection); + + $this->storeManager = $this->getMockBuilder(StoreManagerInterface::class) + ->getMockForAbstractClass(); + + $this->registry = $this->getMockBuilder(Registry::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->eavEntityMock = $this->getMockBuilder(Type::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->eavConfig = $this->getMockBuilder(Config::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->request = $this->getMockBuilder(RequestInterface::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->categoryFactory = $this->getMockBuilder(CategoryFactory::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->fileInfo = $this->getMockBuilder(FileInfo::class) + ->disableOriginalConstructor() + ->getMock(); + } + + /** + * @return DataProvider + */ + private function getModel() + { + $this->eavEntityMock->expects($this->any()) + ->method('getAttributeCollection') + ->willReturn([]); + + $this->eavConfig->expects($this->any()) + ->method('getEntityType') + ->with('catalog_category') + ->willReturn($this->eavEntityMock); + + $objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); + $model = $objectManager->getObject( + DataProvider::class, + [ + 'eavValidationRules' => $this->eavValidationRules, + 'categoryCollectionFactory' => $this->categoryCollectionFactory, + 'storeManager' => $this->storeManager, + 'registry' => $this->registry, + 'eavConfig' => $this->eavConfig, + 'request' => $this->request, + 'categoryFactory' => $this->categoryFactory, + ] + ); + + $objectManager->setBackwardCompatibleProperty( + $model, + 'fileInfo', + $this->fileInfo + ); + + return $model; + } + + public function testGetDataNoCategory() + { + $this->registry->expects($this->once()) + ->method('registry') + ->with('category') + ->willReturn(null); + + $model = $this->getModel(); + $this->assertNull($model->getData()); + } + + public function testGetDataNoFileExists() + { + $fileName = 'filename.ext1'; + $categoryId = 1; + + $categoryData = [ + 'image' => $fileName, + ]; + + $imageBackendMock = $this->getMockBuilder(\Magento\Catalog\Model\Category\Attribute\Backend\Image::class) + ->disableOriginalConstructor() + ->getMock(); + + $attributeMock = $this->getMockBuilder(\Magento\Catalog\Model\ResourceModel\Eav\Attribute::class) + ->disableOriginalConstructor() + ->getMock(); + $attributeMock->expects($this->once()) + ->method('getBackend') + ->willReturn($imageBackendMock); + + $categoryMock = $this->getMockBuilder(\Magento\Catalog\Model\Category::class) + ->disableOriginalConstructor() + ->getMock(); + $categoryMock->expects($this->exactly(2)) + ->method('getData') + ->willReturnMap([ + ['', null, $categoryData], + ['image', null, $categoryData['image']], + ]); + $categoryMock->expects($this->any()) + ->method('getExistsStoreValueFlag') + ->with('url_key') + ->willReturn(false); + $categoryMock->expects($this->any()) + ->method('getStoreId') + ->willReturn(\Magento\Store\Model\Store::DEFAULT_STORE_ID); + $categoryMock->expects($this->once()) + ->method('getId') + ->willReturn($categoryId); + $categoryMock->expects($this->once()) + ->method('getAttributes') + ->willReturn(['image' => $attributeMock]); + + $this->registry->expects($this->once()) + ->method('registry') + ->with('category') + ->willReturn($categoryMock); + + $this->fileInfo->expects($this->once()) + ->method('isExist') + ->with($fileName) + ->willReturn(false); + + $model = $this->getModel(); + $result = $model->getData(); + + $this->assertTrue(is_array($result)); + $this->assertArrayHasKey($categoryId, $result); + $this->assertArrayNotHasKey('image', $result[$categoryId]); + } + + public function testGetData() + { + $fileName = 'filename.png'; + $mime = 'image/png'; + $size = 1; + + $categoryId = 1; + $categoryUrl = 'category_url'; + + $categoryData = [ + 'image' => $fileName, + ]; + + $expects = [ + [ + 'name' => $fileName, + 'url' => $categoryUrl, + 'size' => $size, + 'type' => $mime, + ], + ]; + + $imageBackendMock = $this->getMockBuilder(\Magento\Catalog\Model\Category\Attribute\Backend\Image::class) + ->disableOriginalConstructor() + ->getMock(); + + $attributeMock = $this->getMockBuilder(\Magento\Catalog\Model\ResourceModel\Eav\Attribute::class) + ->disableOriginalConstructor() + ->getMock(); + $attributeMock->expects($this->once()) + ->method('getBackend') + ->willReturn($imageBackendMock); + + $categoryMock = $this->getMockBuilder(\Magento\Catalog\Model\Category::class) + ->disableOriginalConstructor() + ->getMock(); + $categoryMock->expects($this->exactly(2)) + ->method('getData') + ->willReturnMap([ + ['', null, $categoryData], + ['image', null, $categoryData['image']], + ]); + $categoryMock->expects($this->any()) + ->method('getExistsStoreValueFlag') + ->with('url_key') + ->willReturn(false); + $categoryMock->expects($this->any()) + ->method('getStoreId') + ->willReturn(\Magento\Store\Model\Store::DEFAULT_STORE_ID); + $categoryMock->expects($this->once()) + ->method('getId') + ->willReturn($categoryId); + $categoryMock->expects($this->once()) + ->method('getAttributes') + ->willReturn(['image' => $attributeMock]); + $categoryMock->expects($this->once()) + ->method('getImageUrl') + ->willReturn($categoryUrl); + + $this->registry->expects($this->once()) + ->method('registry') + ->with('category') + ->willReturn($categoryMock); + + $this->fileInfo->expects($this->once()) + ->method('isExist') + ->with($fileName) + ->willReturn(true); + $this->fileInfo->expects($this->once()) + ->method('getStat') + ->with($fileName) + ->willReturn(['size' => $size]); + $this->fileInfo->expects($this->once()) + ->method('getMimeType') + ->with($fileName) + ->willReturn($mime); + + $model = $this->getModel(); + $result = $model->getData(); + + $this->assertTrue(is_array($result)); + $this->assertArrayHasKey($categoryId, $result); + $this->assertArrayHasKey('image', $result[$categoryId]); + + $this->assertEquals($expects, $result[$categoryId]['image']); + } +} diff --git a/app/code/Magento/Catalog/Test/Unit/Model/Category/FileInfoTest.php b/app/code/Magento/Catalog/Test/Unit/Model/Category/FileInfoTest.php new file mode 100644 index 0000000000000000000000000000000000000000..abc07425a079a21741e4b4474bca45d907cb10f7 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Unit/Model/Category/FileInfoTest.php @@ -0,0 +1,114 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Catalog\Test\Unit\Model\Category; + +use Magento\Catalog\Model\Category\FileInfo; +use Magento\Framework\App\Filesystem\DirectoryList; +use Magento\Framework\File\Mime; +use Magento\Framework\Filesystem; +use Magento\Framework\Filesystem\Directory\WriteInterface; + +class FileInfoTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var Filesystem|\PHPUnit_Framework_MockObject_MockObject + */ + private $filesystem; + + /** + * @var Mime|\PHPUnit_Framework_MockObject_MockObject + */ + private $mime; + + /** + * @var WriteInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $mediaDirectory; + + /** + * @var FileInfo + */ + private $model; + + protected function setUp() + { + $this->mediaDirectory = $this->getMockBuilder(WriteInterface::class) + ->getMockForAbstractClass(); + + $this->filesystem = $this->getMockBuilder(Filesystem::class) + ->disableOriginalConstructor() + ->getMock(); + $this->filesystem->expects($this->any()) + ->method('getDirectoryWrite') + ->with(DirectoryList::MEDIA) + ->willReturn($this->mediaDirectory); + + $this->mime = $this->getMockBuilder(Mime::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->model = new FileInfo( + $this->filesystem, + $this->mime + ); + } + + public function testGetMimeType() + { + $mediaPath = '/catalog/category'; + + $fileName = '/filename.ext1'; + $absoluteFilePath = '/absolute_path/catalog/category/filename.ext1'; + + $expected = 'ext1'; + + $this->mediaDirectory->expects($this->once()) + ->method('getAbsolutePath') + ->with($mediaPath. '/' . ltrim($fileName, '/')) + ->willReturn($absoluteFilePath); + + $this->mime->expects($this->once()) + ->method('getMimeType') + ->with($absoluteFilePath) + ->willReturn($expected); + + $this->assertEquals($expected, $this->model->getMimeType($fileName)); + } + + public function testGetStat() + { + $mediaPath = '/catalog/category'; + + $fileName = '/filename.ext1'; + + $expected = ['size' => 1]; + + $this->mediaDirectory->expects($this->once()) + ->method('stat') + ->with($mediaPath . $fileName) + ->willReturn($expected); + + $result = $this->model->getStat($fileName); + + $this->assertTrue(is_array($result)); + $this->assertArrayHasKey('size', $result); + $this->assertEquals(1, $result['size']); + } + + public function testIsExist() + { + $mediaPath = '/catalog/category'; + + $fileName = '/filename.ext1'; + + $this->mediaDirectory->expects($this->once()) + ->method('isExist') + ->with($mediaPath . $fileName) + ->willReturn(true); + + $this->assertTrue($this->model->isExist($fileName)); + } +} diff --git a/app/code/Magento/Catalog/Test/Unit/Model/Product/Attribute/Source/CountryofmanufactureTest.php b/app/code/Magento/Catalog/Test/Unit/Model/Product/Attribute/Source/CountryofmanufactureTest.php index 2888a0a84f23069b34b1cb7045adad75ca921163..9ae3f94924855cbda533691292af8d110e7e07da 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/Product/Attribute/Source/CountryofmanufactureTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/Product/Attribute/Source/CountryofmanufactureTest.php @@ -5,6 +5,8 @@ */ namespace Magento\Catalog\Test\Unit\Model\Product\Attribute\Source; +use Magento\Framework\Serialize\SerializerInterface; + class CountryofmanufactureTest extends \PHPUnit_Framework_TestCase { /** @@ -27,12 +29,34 @@ class CountryofmanufactureTest extends \PHPUnit_Framework_TestCase */ protected $objectManagerHelper; + /** @var \Magento\Catalog\Model\Product\Attribute\Source\Countryofmanufacture */ + private $countryOfManufacture; + + /** + * @var \Magento\Framework\Serialize\SerializerInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $serializerMock; + protected function setUp() { $this->storeManagerMock = $this->getMock(\Magento\Store\Model\StoreManagerInterface::class); $this->storeMock = $this->getMock(\Magento\Store\Model\Store::class, [], [], '', false); $this->cacheConfig = $this->getMock(\Magento\Framework\App\Cache\Type\Config::class, [], [], '', false); $this->objectManagerHelper = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); + $this->countryOfManufacture = $this->objectManagerHelper->getObject( + \Magento\Catalog\Model\Product\Attribute\Source\Countryofmanufacture::class, + [ + 'storeManager' => $this->storeManagerMock, + 'configCacheType' => $this->cacheConfig, + ] + ); + + $this->serializerMock = $this->getMock(SerializerInterface::class, [], [], '', false); + $this->objectManagerHelper->setBackwardCompatibleProperty( + $this->countryOfManufacture, + 'serializer', + $this->serializerMock + ); } /** @@ -51,15 +75,10 @@ class CountryofmanufactureTest extends \PHPUnit_Framework_TestCase ->method('load') ->with($this->equalTo('COUNTRYOFMANUFACTURE_SELECT_STORE_store_code')) ->will($this->returnValue($cachedDataSrl)); - - $countryOfManufacture = $this->objectManagerHelper->getObject( - \Magento\Catalog\Model\Product\Attribute\Source\Countryofmanufacture::class, - [ - 'storeManager' => $this->storeManagerMock, - 'configCacheType' => $this->cacheConfig, - ] - ); - $this->assertEquals($cachedDataUnsrl, $countryOfManufacture->getAllOptions()); + $this->serializerMock->expects($this->once()) + ->method('unserialize') + ->willReturn($cachedDataUnsrl); + $this->assertEquals($cachedDataUnsrl, $this->countryOfManufacture->getAllOptions()); } /** @@ -71,7 +90,7 @@ class CountryofmanufactureTest extends \PHPUnit_Framework_TestCase { return [ - ['cachedDataSrl' => 'a:1:{s:3:"key";s:4:"data";}', 'cachedDataUnsrl' => ['key' => 'data']] + ['cachedDataSrl' => json_encode(['key' => 'data']), 'cachedDataUnsrl' => ['key' => 'data']] ]; } } diff --git a/app/code/Magento/Catalog/Test/Unit/Model/Product/Gallery/GalleryManagementTest.php b/app/code/Magento/Catalog/Test/Unit/Model/Product/Gallery/GalleryManagementTest.php index fb2d197749e01bdd15b1574d2fca4831a04e4583..e3845a2b51cec716d37e27430023ee2be2409bef 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/Product/Gallery/GalleryManagementTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/Product/Gallery/GalleryManagementTest.php @@ -191,20 +191,33 @@ class GalleryManagementTest extends \PHPUnit_Framework_TestCase $productSku = 'testProduct'; $entryMock = $this->getMock(\Magento\Catalog\Api\Data\ProductAttributeMediaGalleryEntryInterface::class); $entryId = 42; + $entrySecondId = 43; $this->productRepositoryMock->expects($this->once())->method('get')->with($productSku) ->willReturn($this->productMock); $existingEntryMock = $this->getMock( \Magento\Catalog\Api\Data\ProductAttributeMediaGalleryEntryInterface::class ); + $existingSecondEntryMock = $this->getMock( + \Magento\Catalog\Api\Data\ProductAttributeMediaGalleryEntryInterface::class + ); + $existingEntryMock->expects($this->once())->method('getId')->willReturn($entryId); + $existingEntryMock->expects($this->once())->method('getTypes')->willReturn(['small_image']); + $existingEntryMock->expects($this->once())->method('setTypes')->with(['small_image']); + $existingSecondEntryMock->expects($this->once())->method('getId')->willReturn($entrySecondId); + $existingSecondEntryMock->expects($this->once())->method('getTypes')->willReturn(['image']); + $existingSecondEntryMock->expects($this->once())->method('setTypes')->with([]); $this->productMock->expects($this->once())->method('getMediaGalleryEntries') - ->willReturn([$existingEntryMock]); - $entryMock->expects($this->once())->method('getId')->willReturn($entryId); + ->willReturn([$existingEntryMock, $existingSecondEntryMock]); + + $entryMock->expects($this->exactly(2))->method('getId')->willReturn($entryId); $entryMock->expects($this->once())->method('getFile')->willReturn("base64"); $entryMock->expects($this->once())->method('setId')->with(null); + $entryMock->expects($this->exactly(2))->method('getTypes')->willReturn(['image']); $this->productMock->expects($this->once())->method('setMediaGalleryEntries') - ->willReturn([$entryMock]); + ->with([$entryMock, $existingSecondEntryMock]) + ->willReturnSelf(); $this->productRepositoryMock->expects($this->once())->method('save')->with($this->productMock); $this->assertTrue($this->model->update($productSku, $entryMock)); } diff --git a/app/code/Magento/Catalog/Test/Unit/Model/Product/Gallery/ProcessorTest.php b/app/code/Magento/Catalog/Test/Unit/Model/Product/Gallery/ProcessorTest.php index 61d4e3a5c76d5a3fdf57438c082a210c9b60ac5a..50c3c4ad0122c5490fa535c07fa7d677514d91c9 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/Product/Gallery/ProcessorTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/Product/Gallery/ProcessorTest.php @@ -197,4 +197,56 @@ class ProcessorTest extends \PHPUnit_Framework_TestCase [false] ]; } + + /** + * @param int $setDataExpectsCalls + * @param string|null $setDataArgument + * @param array|string $mediaAttribute + * @dataProvider clearMediaAttributeDataProvider + */ + public function testClearMediaAttribute($setDataExpectsCalls, $setDataArgument, $mediaAttribute) + { + $productMock = $this->getMockBuilder(\Magento\Catalog\Model\Product::class) + ->disableOriginalConstructor() + ->getMock(); + + $productMock->expects($this->exactly($setDataExpectsCalls)) + ->method('setData') + ->with($setDataArgument, 'no_selection'); + + $this->mediaConfig->expects($this->once()) + ->method('getMediaAttributeCodes') + ->willReturn(['image', 'small_image']); + + $this->assertSame($this->model, $this->model->clearMediaAttribute($productMock, $mediaAttribute)); + } + + /** + * @return array + */ + public function clearMediaAttributeDataProvider() + { + return [ + [ + 'setDataExpectsCalls' => 1, + 'setDataArgument' => 'image', + 'mediaAttribute' => 'image', + ], + [ + 'setDataExpectsCalls' => 1, + 'setDataArgument' => 'image', + 'mediaAttribute' => ['image'], + ], + [ + 'setDataExpectsCalls' => 0, + 'setDataArgument' => null, + 'mediaAttribute' => 'some_image', + ], + [ + 'setDataExpectsCalls' => 0, + 'setDataArgument' => null, + 'mediaAttribute' => ['some_image'], + ], + ]; + } } diff --git a/app/code/Magento/Catalog/Test/Unit/Model/Product/ImageTest.php b/app/code/Magento/Catalog/Test/Unit/Model/Product/ImageTest.php index 44f7f87cc2c62afc2c09d262bbd2721683fcfea3..8ee875dad17b1c8fb09a99449c039825f9e1344c 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/Product/ImageTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/Product/ImageTest.php @@ -6,12 +6,17 @@ namespace Magento\Catalog\Test\Unit\Model\Product; +use Magento\Catalog\Model\View\Asset\Image\ContextFactory; +use Magento\Catalog\Model\View\Asset\ImageFactory; +use Magento\Catalog\Model\View\Asset\PlaceholderFactory; use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper; use Magento\Framework\App\Filesystem\DirectoryList; +use Magento\Framework\View\Asset\ContextInterface; /** * Class ImageTest * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + * @SuppressWarnings(PHPMD.TooManyFields) */ class ImageTest extends \PHPUnit_Framework_TestCase { @@ -75,6 +80,21 @@ class ImageTest extends \PHPUnit_Framework_TestCase */ protected $mediaDirectory; + /** + * @var \Magento\Framework\View\Asset\LocalInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $imageAsset; + + /** + * @var ImageFactory|\PHPUnit_Framework_MockObject_MockObject + */ + protected $viewAssetImageFactory; + + /** + * @var PlaceholderFactory|\PHPUnit_Framework_MockObject_MockObject + */ + protected $viewAssetPlaceholderFactory; + protected function setUp() { $this->context = $this->getMock(\Magento\Framework\Model\Context::class, [], [], '', false); @@ -99,7 +119,6 @@ class ImageTest extends \PHPUnit_Framework_TestCase ->disableOriginalConstructor() ->setMethods(['create', 'isFile', 'isExist', 'getAbsolutePath']) ->getMock(); - $this->mediaDirectory->expects($this->once())->method('create')->will($this->returnValue(true)); $this->filesystem = $this->getMock(\Magento\Framework\Filesystem::class, [], [], '', false); $this->filesystem->expects($this->once())->method('getDirectoryWrite') @@ -110,20 +129,49 @@ class ImageTest extends \PHPUnit_Framework_TestCase $this->fileSystem = $this->getMock(\Magento\Framework\View\FileSystem::class, [], [], '', false); $this->scopeConfigInterface = $this->getMock(\Magento\Framework\App\Config\ScopeConfigInterface::class); + $context = $this->getMockBuilder(\Magento\Framework\Model\Context::class) + ->disableOriginalConstructor() + ->getMock(); + $this->image = new \Magento\Catalog\Model\Product\Image( + $context, + $this->registry, + $this->storeManager, + $this->config, + $this->coreFileHelper, + $this->filesystem, + $this->factory, + $this->repository, + $this->fileSystem, + $this->scopeConfigInterface + ); + //Settings for backward compatible property $objectManagerHelper = new ObjectManagerHelper($this); - $this->image = $objectManagerHelper->getObject( - \Magento\Catalog\Model\Product\Image::class, - [ - 'registry' => $this->registry, - 'storeManager' => $this->storeManager, - 'catalogProductMediaConfig' => $this->config, - 'coreFileStorageDatabase' => $this->coreFileHelper, - 'filesystem' => $this->filesystem, - 'imageFactory' => $this->factory, - 'assetRepo' => $this->repository, - 'viewFileSystem' => $this->fileSystem, - 'scopeConfig' => $this->scopeConfigInterface - ] + $this->imageAsset = $this->getMockBuilder(\Magento\Framework\View\Asset\LocalInterface::class) + ->getMockForAbstractClass(); + $objectManagerHelper->setBackwardCompatibleProperty( + $this->image, + 'imageAsset', + $this->imageAsset + ); + + $this->viewAssetImageFactory = $this->getMockBuilder(ImageFactory::class) + ->disableOriginalConstructor() + ->setMethods(['create']) + ->getMock(); + $objectManagerHelper->setBackwardCompatibleProperty( + $this->image, + 'viewAssetImageFactory', + $this->viewAssetImageFactory + ); + + $this->viewAssetPlaceholderFactory = $this->getMockBuilder(PlaceholderFactory::class) + ->disableOriginalConstructor() + ->setMethods(['create']) + ->getMock(); + $objectManagerHelper->setBackwardCompatibleProperty( + $this->image, + 'viewAssetPlaceholderFactory', + $this->viewAssetPlaceholderFactory ); } @@ -177,18 +225,39 @@ class ImageTest extends \PHPUnit_Framework_TestCase $absolutePath = dirname(dirname(__DIR__)) . '/_files/catalog/product/somefile.png'; $this->mediaDirectory->expects($this->any())->method('getAbsolutePath') ->will($this->returnValue($absolutePath)); + $this->viewAssetImageFactory->expects($this->any()) + ->method('create') + ->with( + [ + 'miscParams' => [ + 'image_type' => null, + 'image_height' => null, + 'image_width' => null, + 'keep_aspect_ratio' => 'proportional', + 'keep_frame' => 'frame', + 'keep_transparency' => 'transparency', + 'constrain_only' => 'doconstrainonly', + 'background' => 'ffffff', + 'angle' => null, + 'quality' => 80, + ], + 'filePath' => '/somefile.png', + ] + ) + ->willReturn($this->imageAsset); + $this->viewAssetPlaceholderFactory->expects($this->never())->method('create'); + + $this->imageAsset->expects($this->any())->method('getSourceFile')->willReturn('catalog/product/somefile.png'); $this->image->setBaseFile('/somefile.png'); $this->assertEquals('catalog/product/somefile.png', $this->image->getBaseFile()); - $this->assertEquals( - 'catalog/product/cache//beff4985b56e3afdbeabfc89641a4582/somefile.png', - $this->image->getNewFile() - ); } public function testSetBaseNoSelectionFile() { - $this->image->setBaseFile('/no_selection'); - $this->assertTrue($this->image->getNewFile()); + $this->viewAssetPlaceholderFactory->expects($this->once())->method('create')->willReturn($this->imageAsset); + $this->imageAsset->expects($this->any())->method('getSourceFile')->willReturn('Default Placeholder Path'); + $this->image->setBaseFile('no_selection'); + $this->assertEquals('Default Placeholder Path', $this->image->getBaseFile()); } public function testSetGetImageProcessor() @@ -284,45 +353,45 @@ class ImageTest extends \PHPUnit_Framework_TestCase )->disableOriginalConstructor()->getMock(); $this->image->setImageProcessor($imageProcessor); $this->coreFileHelper->expects($this->once())->method('saveFile')->will($this->returnValue(true)); - $absolutePath = dirname(dirname(__DIR__)) . '/_files/catalog/product/somefile.png'; - $this->mediaDirectory->expects($this->once())->method('getAbsolutePath') - ->will($this->returnValue($absolutePath)); $this->image->saveFile(); } public function testSaveFileNoSelection() { - $this->testSetBaseNoSelectionFile(); + $imageProcessor = $this->getMockBuilder( + \Magento\Framework\Image::class + )->disableOriginalConstructor()->getMock(); + $this->image->setImageProcessor($imageProcessor); $this->assertSame($this->image, $this->image->saveFile()); } public function testGetUrl() { $this->testSetGetBaseFile(); - $url = $this->image->getUrl(); - $this->assertEquals( - 'http://magento.com/media/catalog/product/cache//beff4985b56e3afdbeabfc89641a4582/somefile.png', - $url - ); + $this->imageAsset->expects($this->any())->method('getUrl')->will($this->returnValue('url of exist image')); + $this->assertEquals('url of exist image', $this->image->getUrl()); } public function testGetUrlNoSelection() { - $this->testSetBaseNoSelectionFile(); - $this->repository->expects($this->once())->method('getUrl')->will($this->returnValue('someurl')); - $this->assertEquals('someurl', $this->image->getUrl()); + $this->viewAssetPlaceholderFactory->expects($this->once())->method('create')->willReturn($this->imageAsset); + $this->imageAsset->expects($this->any())->method('getUrl')->will($this->returnValue('Default Placeholder URL')); + $this->image->setBaseFile('no_selection'); + $this->assertEquals('Default Placeholder URL', $this->image->getUrl()); } public function testSetGetDestinationSubdir() { - $this->image->setDestinationSubdir('somesubdir'); - $this->assertEquals('somesubdir', $this->image->getDestinationSubdir()); + $this->image->setDestinationSubdir('image_type'); + $this->assertEquals('image_type', $this->image->getDestinationSubdir()); } public function testIsCached() { $this->testSetGetBaseFile(); + $absolutePath = dirname(dirname(__DIR__)) . '/_files/catalog/product/watermark/somefile.png'; + $this->imageAsset->expects($this->any())->method('getPath')->willReturn($absolutePath); $this->assertTrue($this->image->isCached()); } diff --git a/app/code/Magento/Catalog/Test/Unit/Model/Product/Pricing/Renderer/SalableResolverTest.php b/app/code/Magento/Catalog/Test/Unit/Model/Product/Pricing/Renderer/SalableResolverTest.php new file mode 100644 index 0000000000000000000000000000000000000000..7ef15b0781931d28e899942d47e5fa3dc851349c --- /dev/null +++ b/app/code/Magento/Catalog/Test/Unit/Model/Product/Pricing/Renderer/SalableResolverTest.php @@ -0,0 +1,60 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Catalog\Test\Unit\Model\Product\Pricing\Renderer; + +class SalableResolverTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var \Magento\Catalog\Model\Product\Pricing\Renderer\SalableResolver + */ + protected $object; + + /** + * @var \Magento\Catalog\Model\Product|\PHPUnit_Framework_MockObject_MockObject + */ + protected $product; + + protected function setUp() + { + $this->product = $this->getMock( + \Magento\Catalog\Model\Product::class, + ['__wakeup', 'getCanShowPrice', 'isSalable'], + [], + '', + false + ); + + $objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); + $this->object = $objectManager->getObject( + \Magento\Catalog\Model\Product\Pricing\Renderer\SalableResolver::class + ); + } + + public function testSalableItem() + { + $this->product->expects($this->any()) + ->method('getCanShowPrice') + ->willReturn(true); + + $this->product->expects($this->any())->method('isSalable')->willReturn(true); + + $result = $this->object->isSalable($this->product); + $this->assertTrue($result); + } + + public function testNotSalableItem() + { + $this->product->expects($this->any()) + ->method('getCanShowPrice') + ->willReturn(true); + + $this->product->expects($this->any())->method('isSalable')->willReturn(false); + + $result = $this->object->isSalable($this->product); + $this->assertFalse($result); + } +} diff --git a/app/code/Magento/Catalog/Test/Unit/Model/ProductTypes/ConfigTest.php b/app/code/Magento/Catalog/Test/Unit/Model/ProductTypes/ConfigTest.php index af0c1625f9cb64ea69d807a9e36184288b1b1c39..852eb11c5cfb9f16946781d2ef12c2a6821659a1 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/ProductTypes/ConfigTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/ProductTypes/ConfigTest.php @@ -8,22 +8,33 @@ namespace Magento\Catalog\Test\Unit\Model\ProductTypes; class ConfigTest extends \PHPUnit_Framework_TestCase { /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\TestFramework\Unit\Helper\ObjectManager */ - protected $readerMock; + private $objectManager; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Catalog\Model\ProductTypes\Config\Reader|\PHPUnit_Framework_MockObject_MockObject */ - protected $cacheMock; + private $readerMock; + + /** + * @var \Magento\Framework\Config\CacheInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $cacheMock; + + /** + * @var \Magento\Framework\Serialize\SerializerInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $serializerMock; /** * @var \Magento\Catalog\Model\ProductTypes\Config */ - protected $model; + private $config; protected function setUp() { + $this->objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); $this->readerMock = $this->getMock( \Magento\Catalog\Model\ProductTypes\Config\Reader::class, [], @@ -32,19 +43,35 @@ class ConfigTest extends \PHPUnit_Framework_TestCase false ); $this->cacheMock = $this->getMock(\Magento\Framework\Config\CacheInterface::class); + $this->serializerMock = $this->getMock(\Magento\Framework\Serialize\SerializerInterface::class); } /** - * @dataProvider getTypeDataProvider - * * @param array $value * @param mixed $expected + * @dataProvider getTypeDataProvider */ public function testGetType($value, $expected) { - $this->cacheMock->expects($this->any())->method('load')->will($this->returnValue(serialize($value))); - $this->model = new \Magento\Catalog\Model\ProductTypes\Config($this->readerMock, $this->cacheMock, 'cache_id'); - $this->assertEquals($expected, $this->model->getType('global')); + $this->cacheMock->expects($this->any()) + ->method('load') + ->willReturn('serializedData'); + + $this->serializerMock->expects($this->once()) + ->method('unserialize') + ->with('serializedData') + ->willReturn($value); + + $this->config = $this->objectManager->getObject( + \Magento\Catalog\Model\ProductTypes\Config::class, + [ + 'reader' => $this->readerMock, + 'cache' => $this->cacheMock, + 'cacheId' => 'cache_id', + 'serializer' => $this->serializerMock, + ] + ); + $this->assertEquals($expected, $this->config->getType('global')); } public function getTypeDataProvider() @@ -58,22 +85,43 @@ class ConfigTest extends \PHPUnit_Framework_TestCase public function testGetAll() { $expected = ['Expected Data']; - $this->cacheMock->expects( - $this->once() - )->method( - 'load' - )->will( - $this->returnValue(serialize(['types' => $expected])) + $this->cacheMock->expects($this->once()) + ->method('load') + ->willReturn(json_encode('"types":["Expected Data"]]')); + $this->serializerMock->expects($this->once()) + ->method('unserialize') + ->willReturn(['types' => $expected]); + + $this->config = $this->objectManager->getObject( + \Magento\Catalog\Model\ProductTypes\Config::class, + [ + 'reader' => $this->readerMock, + 'cache' => $this->cacheMock, + 'cacheId' => 'cache_id', + 'serializer' => $this->serializerMock, + ] ); - $this->model = new \Magento\Catalog\Model\ProductTypes\Config($this->readerMock, $this->cacheMock, 'cache_id'); - $this->assertEquals($expected, $this->model->getAll()); + $this->assertEquals($expected, $this->config->getAll()); } public function testIsProductSet() { - $this->cacheMock->expects($this->once())->method('load')->will($this->returnValue(serialize([]))); - $this->model = new \Magento\Catalog\Model\ProductTypes\Config($this->readerMock, $this->cacheMock, 'cache_id'); + $this->cacheMock->expects($this->once()) + ->method('load') + ->willReturn(''); + $this->serializerMock->expects($this->once()) + ->method('unserialize') + ->willReturn([]); - $this->assertEquals(false, $this->model->isProductSet('typeId')); + $this->config = $this->objectManager->getObject( + \Magento\Catalog\Model\ProductTypes\Config::class, + [ + 'reader' => $this->readerMock, + 'cache' => $this->cacheMock, + 'cacheId' => 'cache_id', + 'serializer' => $this->serializerMock, + ] + ); + $this->assertEquals(false, $this->config->isProductSet('typeId')); } } diff --git a/app/code/Magento/Catalog/Test/Unit/Model/ResourceModel/Product/CollectionTest.php b/app/code/Magento/Catalog/Test/Unit/Model/ResourceModel/Product/CollectionTest.php index b97b7d2f9842355af1195b7b0ce7ed1d4aa7e4e8..f19b2c15c8ab20142ad10b6d3ca23282633062db 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/ResourceModel/Product/CollectionTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/ResourceModel/Product/CollectionTest.php @@ -3,18 +3,20 @@ * Copyright © 2016 Magento. All rights reserved. * See COPYING.txt for license details. */ - namespace Magento\Catalog\Test\Unit\Model\ResourceModel\Product; -use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; +use \Magento\Catalog\Model\ResourceModel\Product\Collection\ProductLimitationFactory; /** - * Class CollectionTest - * * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class CollectionTest extends \PHPUnit_Framework_TestCase { + /** + * @var \Magento\Framework\TestFramework\Unit\Helper\ObjectManager + */ + private $objectManager; + /** * @var \PHPUnit_Framework_MockObject_MockObject */ @@ -55,6 +57,7 @@ class CollectionTest extends \PHPUnit_Framework_TestCase */ protected function setUp() { + $this->objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); $entityFactory = $this->getMock(\Magento\Framework\Data\Collection\EntityFactory::class, [], [], '', false); $logger = $this->getMockBuilder(\Psr\Log\LoggerInterface::class) ->disableOriginalConstructor() @@ -145,27 +148,14 @@ class CollectionTest extends \PHPUnit_Framework_TestCase $this->entityMock->expects($this->once())->method('getDefaultAttributes')->willReturn([]); $this->entityMock->expects($this->any())->method('getTable')->willReturnArgument(0); $this->connectionMock->expects($this->atLeastOnce())->method('select')->willReturn($this->selectMock); - $helper = new ObjectManager($this); - $this->prepareObjectManager([ - [ - \Magento\Catalog\Model\ResourceModel\Product\Collection\ProductLimitation::class, - $this->getMock(\Magento\Catalog\Model\ResourceModel\Product\Collection\ProductLimitation::class) - ], - [ - \Magento\Catalog\Model\ResourceModel\Product\Gallery::class, - $this->galleryResourceMock - ], - [ - \Magento\Framework\EntityManager\MetadataPool::class, - $this->metadataPoolMock - ], - [ - \Magento\Catalog\Model\Product\Gallery\ReadHandler::class, - $this->galleryReadHandlerMock - ] - ]); - $this->collection = $helper->getObject( + $productLimitationMock = $this->getMock( + \Magento\Catalog\Model\ResourceModel\Product\Collection\ProductLimitation::class + ); + $productLimitationFactoryMock = $this->getMock(ProductLimitationFactory::class, ['create']); + $productLimitationFactoryMock->method('create') + ->willReturn($productLimitationMock); + $this->collection = $this->objectManager->getObject( \Magento\Catalog\Model\ResourceModel\Product\Collection::class, [ 'entityFactory' => $entityFactory, @@ -187,10 +177,22 @@ class CollectionTest extends \PHPUnit_Framework_TestCase 'customerSession' => $customerSession, 'dateTime' => $dateTime, 'groupManagement' => $groupManagement, - 'connection' => $this->connectionMock + 'connection' => $this->connectionMock, + 'productLimitationFactory' => $productLimitationFactoryMock, + 'metadataPool' => $this->metadataPoolMock, ] ); $this->collection->setConnection($this->connectionMock); + $this->objectManager->setBackwardCompatibleProperty( + $this->collection, + 'mediaGalleryResource', + $this->galleryResourceMock + ); + $this->objectManager->setBackwardCompatibleProperty( + $this->collection, + 'productGalleryReadHandler', + $this->galleryReadHandlerMock + ); } public function testAddProductCategoriesFilter() @@ -259,20 +261,4 @@ class CollectionTest extends \PHPUnit_Framework_TestCase $this->assertSame($this->collection, $this->collection->addMediaGalleryData()); } - - /** - * @param $map - */ - private function prepareObjectManager($map) - { - $objectManagerMock = $this->getMock(\Magento\Framework\ObjectManagerInterface::class); - $objectManagerMock->expects($this->any())->method('getInstance')->willReturnSelf(); - $objectManagerMock->expects($this->any()) - ->method('get') - ->will($this->returnValueMap($map)); - $reflectionClass = new \ReflectionClass(\Magento\Framework\App\ObjectManager::class); - $reflectionProperty = $reflectionClass->getProperty('_instance'); - $reflectionProperty->setAccessible(true); - $reflectionProperty->setValue($objectManagerMock); - } } diff --git a/app/code/Magento/Catalog/Test/Unit/Model/ResourceModel/Product/Link/Product/CollectionTest.php b/app/code/Magento/Catalog/Test/Unit/Model/ResourceModel/Product/Link/Product/CollectionTest.php index 3c92cde30012dc1a4fdc4736f1c68c6a7b071d5b..fe244d01eea80760fcab82b28169f3dda492f9b4 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/ResourceModel/Product/Link/Product/CollectionTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/ResourceModel/Product/Link/Product/CollectionTest.php @@ -3,10 +3,10 @@ * Copyright © 2016 Magento. All rights reserved. * See COPYING.txt for license details. */ - namespace Magento\Catalog\Test\Unit\Model\ResourceModel\Product\Link\Product; -use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper; +use \Magento\Catalog\Model\ResourceModel\Product\Collection\ProductLimitationFactory; +use \Magento\Catalog\Model\ResourceModel\Product\Collection\ProductLimitation; /** * @SuppressWarnings(PHPMD.CouplingBetweenObjects) @@ -17,8 +17,8 @@ class CollectionTest extends \PHPUnit_Framework_TestCase /** @var \Magento\Catalog\Model\ResourceModel\Product\Link\Product\Collection */ protected $collection; - /** @var ObjectManagerHelper */ - protected $objectManagerHelper; + /** @var \Magento\Framework\TestFramework\Unit\Helper\ObjectManager */ + private $objectManager; /** @var \Magento\Framework\Data\Collection\EntityFactory|\PHPUnit_Framework_MockObject_MockObject */ protected $entityFactoryMock; @@ -76,6 +76,7 @@ class CollectionTest extends \PHPUnit_Framework_TestCase protected function setUp() { + $this->objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); $this->entityFactoryMock = $this->getMock( \Magento\Framework\Data\Collection\EntityFactory::class, [], @@ -133,14 +134,11 @@ class CollectionTest extends \PHPUnit_Framework_TestCase $this->timezoneInterfaceMock = $this->getMock(\Magento\Framework\Stdlib\DateTime\TimezoneInterface::class); $this->sessionMock = $this->getMock(\Magento\Customer\Model\Session::class, [], [], '', false); $this->dateTimeMock = $this->getMock(\Magento\Framework\Stdlib\DateTime::class); - $this->objectManagerHelper = new ObjectManagerHelper($this); - $this->prepareObjectManager([ - [\Magento\Catalog\Model\ResourceModel\Product\Collection\ProductLimitation::class, - $this->getMock(\Magento\Catalog\Model\ResourceModel\Product\Collection\ProductLimitation::class) - ] - ]); + $productLimitationFactoryMock = $this->getMock(ProductLimitationFactory::class, ['create']); + $productLimitationFactoryMock->method('create') + ->willReturn($this->getMock(ProductLimitation::class)); - $this->collection = $this->objectManagerHelper->getObject( + $this->collection = $this->objectManager->getObject( \Magento\Catalog\Model\ResourceModel\Product\Link\Product\Collection::class, [ 'entityFactory' => $this->entityFactoryMock, @@ -160,7 +158,8 @@ class CollectionTest extends \PHPUnit_Framework_TestCase 'catalogUrl' => $this->urlMock, 'localeDate' => $this->timezoneInterfaceMock, 'customerSession' => $this->sessionMock, - 'dateTime' => $this->dateTimeMock + 'dateTime' => $this->dateTimeMock, + 'productLimitationFactory' => $productLimitationFactoryMock, ] ); } @@ -175,20 +174,4 @@ class CollectionTest extends \PHPUnit_Framework_TestCase $this->collection->setProduct($product); $this->assertEquals(33, $this->collection->getStoreId()); } - - /** - * @param $map - */ - public function prepareObjectManager($map) - { - $objectManagerMock = $this->getMock(\Magento\Framework\ObjectManagerInterface::class); - $objectManagerMock->expects($this->any())->method('getInstance')->willReturnSelf(); - $objectManagerMock->expects($this->any()) - ->method('get') - ->will($this->returnValueMap($map)); - $reflectionClass = new \ReflectionClass(\Magento\Framework\App\ObjectManager::class); - $reflectionProperty = $reflectionClass->getProperty('_instance'); - $reflectionProperty->setAccessible(true); - $reflectionProperty->setValue($objectManagerMock); - } } diff --git a/app/code/Magento/Catalog/Test/Unit/Model/ResourceModel/Product/Option/CollectionTest.php b/app/code/Magento/Catalog/Test/Unit/Model/ResourceModel/Product/Option/CollectionTest.php index decf8e66f6738e19b98f0a95c782ce5b0e9def34..36afda6287fb92fd922957e1edf09e569f93b434 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/ResourceModel/Product/Option/CollectionTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/ResourceModel/Product/Option/CollectionTest.php @@ -3,20 +3,22 @@ * Copyright © 2016 Magento. All rights reserved. * See COPYING.txt for license details. */ - -// @codingStandardsIgnoreFile - namespace Magento\Catalog\Test\Unit\Model\ResourceModel\Product\Option; use \Magento\Catalog\Model\ResourceModel\Product\Option\Collection; use \Magento\Catalog\Model\ResourceModel\Product\Option\Value; /** - * Class CollectionTest * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + * @codingStandardsIgnoreFile */ class CollectionTest extends \PHPUnit_Framework_TestCase { + /** + * @var \Magento\Framework\TestFramework\Unit\Helper\ObjectManager + */ + private $objectManager; + /** * @var \Magento\Framework\EntityManager\MetadataPool */ @@ -79,6 +81,7 @@ class CollectionTest extends \PHPUnit_Framework_TestCase protected function setUp() { + $this->objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); $this->entityFactoryMock = $this->getMock( \Magento\Framework\Data\Collection\EntityFactory::class, ['create'], [], '', false ); @@ -147,11 +150,6 @@ class CollectionTest extends \PHPUnit_Framework_TestCase $this->metadataPoolMock->expects($this->any())->method('getMetadata')->willReturn($metadata); $this->selectMock->expects($this->exactly(2))->method('join'); - $this->prepareObjectManager([ - [\Magento\Framework\EntityManager\MetadataPool::class, $this->metadataPoolMock], - [\Magento\Framework\Api\ExtensionAttribute\JoinProcessorInterface::class, $this->joinProcessor] - ]); - $this->collection = new Collection( $this->entityFactoryMock, $this->loggerMock, @@ -160,7 +158,13 @@ class CollectionTest extends \PHPUnit_Framework_TestCase $this->optionsFactoryMock, $this->storeManagerMock, null, - $this->resourceMock + $this->resourceMock, + $this->metadataPoolMock + ); + $this->objectManager->setBackwardCompatibleProperty( + $this->collection, + 'joinProcessor', + $this->joinProcessor ); } @@ -168,20 +172,4 @@ class CollectionTest extends \PHPUnit_Framework_TestCase { $this->collection->reset(); } - - /** - * @param $map - */ - private function prepareObjectManager($map) - { - $objectManagerMock = $this->getMock(\Magento\Framework\ObjectManagerInterface::class); - $objectManagerMock->expects($this->any())->method('getInstance')->willReturnSelf(); - $objectManagerMock->expects($this->any()) - ->method('get') - ->will($this->returnValueMap($map)); - $reflectionClass = new \ReflectionClass(\Magento\Framework\App\ObjectManager::class); - $reflectionProperty = $reflectionClass->getProperty('_instance'); - $reflectionProperty->setAccessible(true); - $reflectionProperty->setValue($objectManagerMock); - } } diff --git a/app/code/Magento/Catalog/Test/Unit/Model/ResourceModel/Product/StatusBaseSelectProcessorTest.php b/app/code/Magento/Catalog/Test/Unit/Model/ResourceModel/Product/StatusBaseSelectProcessorTest.php index 0909f754a01c2c937e8c3692c52b1a256a27b0c3..1fada997913b620de06ddedcbffb3fdcdea92620 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/ResourceModel/Product/StatusBaseSelectProcessorTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/ResourceModel/Product/StatusBaseSelectProcessorTest.php @@ -16,7 +16,12 @@ use Magento\Framework\DB\Select; use Magento\Framework\EntityManager\EntityMetadataInterface; use Magento\Framework\EntityManager\MetadataPool; use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; +use Magento\Store\Api\StoreResolverInterface; +use Magento\Store\Model\Store; +/** + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ class StatusBaseSelectProcessorTest extends \PHPUnit_Framework_TestCase { /** @@ -29,6 +34,11 @@ class StatusBaseSelectProcessorTest extends \PHPUnit_Framework_TestCase */ private $metadataPool; + /** + * @var StoreResolverInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $storeResolver; + /** * @var Select|\PHPUnit_Framework_MockObject_MockObject */ @@ -43,11 +53,13 @@ class StatusBaseSelectProcessorTest extends \PHPUnit_Framework_TestCase { $this->eavConfig = $this->getMockBuilder(Config::class)->disableOriginalConstructor()->getMock(); $this->metadataPool = $this->getMockBuilder(MetadataPool::class)->disableOriginalConstructor()->getMock(); + $this->storeResolver = $this->getMockBuilder(StoreResolverInterface::class)->getMock(); $this->select = $this->getMockBuilder(Select::class)->disableOriginalConstructor()->getMock(); $this->statusBaseSelectProcessor = (new ObjectManager($this))->getObject(StatusBaseSelectProcessor::class, [ 'eavConfig' => $this->eavConfig, 'metadataPool' => $this->metadataPool, + 'storeResolver' => $this->storeResolver, ]); } @@ -55,7 +67,8 @@ class StatusBaseSelectProcessorTest extends \PHPUnit_Framework_TestCase { $linkField = 'link_field'; $backendTable = 'backend_table'; - $attributeId = 'attribute_id'; + $attributeId = 2; + $currentStoreId = 1; $metadata = $this->getMock(EntityMetadataInterface::class); $metadata->expects($this->once()) @@ -66,13 +79,14 @@ class StatusBaseSelectProcessorTest extends \PHPUnit_Framework_TestCase ->with(ProductInterface::class) ->willReturn($metadata); + /** @var AttributeInterface|\PHPUnit_Framework_MockObject_MockObject $statusAttribute */ $statusAttribute = $this->getMockBuilder(AttributeInterface::class) ->setMethods(['getBackendTable', 'getAttributeId']) ->getMock(); - $statusAttribute->expects($this->once()) + $statusAttribute->expects($this->atLeastOnce()) ->method('getBackendTable') ->willReturn($backendTable); - $statusAttribute->expects($this->once()) + $statusAttribute->expects($this->atLeastOnce()) ->method('getAttributeId') ->willReturn($attributeId); $this->eavConfig->expects($this->once()) @@ -80,21 +94,34 @@ class StatusBaseSelectProcessorTest extends \PHPUnit_Framework_TestCase ->with(Product::ENTITY, ProductInterface::STATUS) ->willReturn($statusAttribute); - $this->select->expects($this->once()) - ->method('join') + $this->storeResolver->expects($this->once()) + ->method('getCurrentStoreId') + ->willReturn($currentStoreId); + + $this->select->expects($this->at(0)) + ->method('joinLeft') ->with( - ['status_attr' => $backendTable], - sprintf('status_attr.%s = %s.%1$s', $linkField, BaseSelectProcessorInterface::PRODUCT_TABLE_ALIAS), + ['status_global_attr' => $backendTable], + "status_global_attr.{$linkField} = " + . BaseSelectProcessorInterface::PRODUCT_TABLE_ALIAS . ".{$linkField}" + . " AND status_global_attr.attribute_id = {$attributeId}" + . ' AND status_global_attr.store_id = ' . Store::DEFAULT_STORE_ID, [] ) ->willReturnSelf(); $this->select->expects($this->at(1)) - ->method('where') - ->with('status_attr.attribute_id = ?', $attributeId) + ->method('joinLeft') + ->with( + ['status_attr' => $backendTable], + "status_attr.{$linkField} = " . BaseSelectProcessorInterface::PRODUCT_TABLE_ALIAS . ".{$linkField}" + . " AND status_attr.attribute_id = {$attributeId}" + . " AND status_attr.store_id = {$currentStoreId}", + [] + ) ->willReturnSelf(); $this->select->expects($this->at(2)) ->method('where') - ->with('status_attr.value = ?', Status::STATUS_ENABLED) + ->with('IFNULL(status_attr.value, status_global_attr.value) = ?', Status::STATUS_ENABLED) ->willReturnSelf(); $this->assertEquals($this->select, $this->statusBaseSelectProcessor->process($this->select)); diff --git a/app/code/Magento/Catalog/Test/Unit/Model/View/Asset/Image/ContextTest.php b/app/code/Magento/Catalog/Test/Unit/Model/View/Asset/Image/ContextTest.php new file mode 100644 index 0000000000000000000000000000000000000000..cdc1296486eef202a6410b6a3fd3a1d738ca60f9 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Unit/Model/View/Asset/Image/ContextTest.php @@ -0,0 +1,76 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Catalog\Test\Unit\Model\View\Asset\Image; + +use Magento\Catalog\Model\Product\Media\ConfigInterface; +use Magento\Catalog\Model\View\Asset\Image\Context; +use Magento\Framework\App\Filesystem\DirectoryList; +use Magento\Framework\Filesystem; +use Magento\Framework\Filesystem\Directory\WriteInterface; + +/** + * Class ContextTest + */ +class ContextTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var Context + */ + protected $model; + + /** + * @var WriteInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $mediaDirectory; + + /** + * @var ContextInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $mediaConfig; + + /** + * @var Filesystem|\PHPUnit_Framework_MockObject_MockObject + */ + protected $filesystem; + + protected function setUp() + { + $this->mediaConfig = $this->getMockBuilder(ConfigInterface::class)->getMockForAbstractClass(); + $this->mediaConfig->expects($this->any())->method('getBaseMediaPath')->willReturn('catalog/product'); + $this->mediaDirectory = $this->getMockBuilder(WriteInterface::class)->getMockForAbstractClass(); + $this->mediaDirectory->expects($this->once())->method('create')->with('catalog/product'); + $this->filesystem = $this->getMockBuilder(Filesystem::class) + ->disableOriginalConstructor() + ->getMock(); + $this->filesystem->expects($this->once()) + ->method('getDirectoryWrite') + ->with(DirectoryList::MEDIA) + ->willReturn($this->mediaDirectory); + $this->model = new Context( + $this->mediaConfig, + $this->filesystem + ); + } + + public function testGetPath() + { + $path = '/var/www/html/magento2ce/pub/media/catalog/product'; + $this->mediaDirectory->expects($this->once()) + ->method('getAbsolutePath') + ->with('catalog/product') + ->willReturn($path); + + $this->assertEquals($path, $this->model->getPath()); + } + + public function testGetUrl() + { + $baseUrl = 'http://localhost/pub/media/catalog/product'; + $this->mediaConfig->expects($this->once())->method('getBaseMediaUrl')->willReturn($baseUrl); + + $this->assertEquals($baseUrl, $this->model->getBaseUrl()); + } +} diff --git a/app/code/Magento/Catalog/Test/Unit/Model/View/Asset/ImageTest.php b/app/code/Magento/Catalog/Test/Unit/Model/View/Asset/ImageTest.php new file mode 100644 index 0000000000000000000000000000000000000000..5e96cdb1c3395182049e78ae29cd3b44bd0baf17 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Unit/Model/View/Asset/ImageTest.php @@ -0,0 +1,148 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Catalog\Test\Unit\Model\View\Asset; + +use Magento\Catalog\Model\Product\Media\ConfigInterface; +use Magento\Catalog\Model\View\Asset\Image; +use Magento\Framework\Encryption\EncryptorInterface; +use Magento\Framework\View\Asset\ContextInterface; + +/** + * Class ImageTest + */ +class ImageTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var \Magento\Catalog\Model\View\Asset\Image + */ + protected $model; + + /** + * @var ContextInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $mediaConfig; + + /** + * @var EncryptorInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $encryptor; + + /** + * @var ContextInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $imageContext; + + protected function setUp() + { + $this->mediaConfig = $this->getMockBuilder(ConfigInterface::class)->getMockForAbstractClass(); + $this->encryptor = $this->getMockBuilder(EncryptorInterface::class)->getMockForAbstractClass(); + $this->imageContext = $this->getMockBuilder(ContextInterface::class)->getMockForAbstractClass(); + $this->model = new Image( + $this->mediaConfig, + $this->imageContext, + $this->encryptor, + '/somefile.png' + ); + } + + public function testModuleAndContentAndContentType() + { + $contentType = 'image'; + $this->assertEquals($contentType, $this->model->getContentType()); + $this->assertEquals($contentType, $this->model->getSourceContentType()); + $this->assertNull($this->model->getContent()); + $this->assertEquals('cache', $this->model->getModule()); + } + + public function testGetFilePath() + { + $this->assertEquals('/somefile.png', $this->model->getFilePath()); + } + + public function testGetSoureFile() + { + $this->mediaConfig->expects($this->once())->method('getBaseMediaPath')->willReturn('catalog/product'); + $this->assertEquals('catalog/product/somefile.png', $this->model->getSourceFile()); + } + + public function testGetContext() + { + $this->assertInstanceOf(ContextInterface::class, $this->model->getContext()); + } + + /** + * @param string $filePath + * @param array $miscParams + * @dataProvider getPathDataProvider + */ + public function testGetPath($filePath, $miscParams) + { + $imageModel = new Image( + $this->mediaConfig, + $this->imageContext, + $this->encryptor, + $filePath, + $miscParams + ); + $absolutePath = '/var/www/html/magento2ce/pub/media/catalog/product'; + $hashPath = md5(implode('_', $miscParams)); + $this->imageContext->expects($this->once())->method('getPath')->willReturn($absolutePath); + $this->encryptor->expects($this->once())->method('hash')->willReturn($hashPath); + $this->assertEquals( + $absolutePath . DIRECTORY_SEPARATOR . 'cache' . DIRECTORY_SEPARATOR . $hashPath . $filePath, + $imageModel->getPath() + ); + } + + /** + * @param string $filePath + * @param array $miscParams + * @dataProvider getPathDataProvider + */ + public function testGetUrl($filePath, $miscParams) + { + $imageModel = new Image( + $this->mediaConfig, + $this->imageContext, + $this->encryptor, + $filePath, + $miscParams + ); + $absolutePath = 'http://localhost/pub/media/catalog/product'; + $hashPath = md5(implode('_', $miscParams)); + $this->imageContext->expects($this->once())->method('getBaseUrl')->willReturn($absolutePath); + $this->encryptor->expects($this->once())->method('hash')->willReturn($hashPath); + $this->assertEquals( + $absolutePath . DIRECTORY_SEPARATOR . 'cache' . DIRECTORY_SEPARATOR . $hashPath . $filePath, + $imageModel->getUrl() + ); + } + + public function getPathDataProvider() + { + return [ + [ + '/some_file.png', + [], //default value for miscParams + ], + [ + '/some_file_2.png', + [ + 'image_type' => 'thumbnail', + 'image_height' => 75, + 'image_width' => 75, + 'keep_aspect_ratio' => 'proportional', + 'keep_frame' => 'frame', + 'keep_transparency' => 'transparency', + 'constrain_only' => 'doconstrainonly', + 'background' => 'ffffff', + 'angle' => null, + 'quality' => 80, + ], + ] + ]; + } +} diff --git a/app/code/Magento/Catalog/Test/Unit/Model/View/Asset/PlaceholderTest.php b/app/code/Magento/Catalog/Test/Unit/Model/View/Asset/PlaceholderTest.php new file mode 100644 index 0000000000000000000000000000000000000000..38d5ceb16e6b5b17e8e7cbaa1171513d68027e3c --- /dev/null +++ b/app/code/Magento/Catalog/Test/Unit/Model/View/Asset/PlaceholderTest.php @@ -0,0 +1,163 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Catalog\Test\Unit\Model\View\Asset; + +use Magento\Framework\App\Config\ScopeConfigInterface; +use Magento\Catalog\Model\View\Asset\Placeholder; +use Magento\Framework\View\Asset\ContextInterface; +use Magento\Framework\View\Asset\Repository; + +/** + * Class PlaceholderTest + */ +class PlaceholderTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var \Magento\Catalog\Model\View\Asset\Placeholder + */ + protected $model; + + /** + * @var ScopeConfigInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $scopeConfig; + + /** + * @var Repository|\PHPUnit_Framework_MockObject_MockObject + */ + protected $repository; + + /** + * @var ContextInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $imageContext; + + protected function setUp() + { + $this->scopeConfig = $this->getMockBuilder(ScopeConfigInterface::class)->getMockForAbstractClass(); + $this->imageContext = $this->getMockBuilder(ContextInterface::class)->getMockForAbstractClass(); + $this->repository = $this->getMockBuilder(Repository::class)->disableOriginalConstructor()->getMock(); + $this->model = new Placeholder( + $this->imageContext, + $this->scopeConfig, + $this->repository, + 'thumbnail' + ); + } + + public function testModuleAndContentAndContentType() + { + $contentType = 'image'; + $this->assertEquals($contentType, $this->model->getContentType()); + $this->assertEquals($contentType, $this->model->getSourceContentType()); + $this->assertNull($this->model->getContent()); + $this->assertEquals('placeholder', $this->model->getModule()); + } + + public function testGetFilePath() + { + $this->assertNull($this->model->getFilePath()); + $this->scopeConfig->expects($this->once())->method('getValue')->willReturn('default/thumbnail.jpg'); + $this->assertEquals('default/thumbnail.jpg', $this->model->getFilePath()); + } + + public function testGetContext() + { + $this->assertInstanceOf(ContextInterface::class, $this->model->getContext()); + } + + /** + * @param string $imageType + * @param string $placeholderPath + * @dataProvider getPathDataProvider + */ + public function testGetPathAndGetSourceFile($imageType, $placeholderPath) + { + $imageModel = new Placeholder( + $this->imageContext, + $this->scopeConfig, + $this->repository, + $imageType + ); + $absolutePath = '/var/www/html/magento2ce/pub/media/catalog/product'; + + $this->scopeConfig->expects($this->any()) + ->method('getValue') + ->with( + "catalog/placeholder/{$imageType}_placeholder", + \Magento\Store\Model\ScopeInterface::SCOPE_STORE, + null + )->willReturn($placeholderPath); + + if ($placeholderPath == null) { + $this->imageContext->expects($this->never())->method('getPath'); + $assetMock = $this->getMockBuilder(\Magento\Framework\View\Asset\MergeableInterface::class) + ->getMockForAbstractClass(); + $expectedResult = 'path/to_default/placeholder/by_type'; + $assetMock->expects($this->any())->method('getSourceFile')->willReturn($expectedResult); + $this->repository->expects($this->any())->method('createAsset')->willReturn($assetMock); + } else { + $this->imageContext->expects($this->any())->method('getPath')->willReturn($absolutePath); + $expectedResult = $absolutePath + . DIRECTORY_SEPARATOR . $imageModel->getModule() + . DIRECTORY_SEPARATOR . $placeholderPath; + } + + $this->assertEquals($expectedResult, $imageModel->getPath()); + $this->assertEquals($expectedResult, $imageModel->getSourceFile()); + } + + /** + * @param string $imageType + * @param string $placeholderPath + * @dataProvider getPathDataProvider + */ + public function testGetUrl($imageType, $placeholderPath) + { + $imageModel = new Placeholder( + $this->imageContext, + $this->scopeConfig, + $this->repository, + $imageType + ); + + $this->scopeConfig->expects($this->any()) + ->method('getValue') + ->with( + "catalog/placeholder/{$imageType}_placeholder", + \Magento\Store\Model\ScopeInterface::SCOPE_STORE, + null + )->willReturn($placeholderPath); + + if ($placeholderPath == null) { + $this->imageContext->expects($this->never())->method('getBaseUrl'); + $expectedResult = 'http://localhost/pub/media/catalog/product/to_default/placeholder/by_type'; + $this->repository->expects($this->any())->method('getUrl')->willReturn($expectedResult); + } else { + $baseUrl = 'http://localhost/pub/media/catalog/product'; + $this->imageContext->expects($this->any())->method('getBaseUrl')->willReturn($baseUrl); + $expectedResult = $baseUrl + . DIRECTORY_SEPARATOR . $imageModel->getModule() + . DIRECTORY_SEPARATOR . $placeholderPath; + } + + $this->assertEquals($expectedResult, $imageModel->getUrl()); + } + + public function getPathDataProvider() + { + return [ + [ + 'thumbnail', + 'default/thumbnail.jpg', + ], + [ + 'non_exist', + null, + ], + ]; + } +} diff --git a/app/code/Magento/Catalog/Test/Unit/Plugin/Model/ResourceModel/ConfigTest.php b/app/code/Magento/Catalog/Test/Unit/Plugin/Model/ResourceModel/ConfigTest.php index 01f9964f2d83e80be6d13bde407f47014971b3b8..b6f0dcf52bb1ee7169cdb7667b0db52a91127ad1 100644 --- a/app/code/Magento/Catalog/Test/Unit/Plugin/Model/ResourceModel/ConfigTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Plugin/Model/ResourceModel/ConfigTest.php @@ -6,26 +6,29 @@ namespace Magento\Catalog\Test\Unit\Plugin\Model\ResourceModel; +use Magento\Catalog\Plugin\Model\ResourceModel\Config; +use Magento\Framework\Serialize\SerializerInterface; use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; class ConfigTest extends \PHPUnit_Framework_TestCase { - /** @var \Magento\Catalog\Plugin\Model\ResourceModel\Config */ - protected $config; - /** @var \Magento\Framework\App\CacheInterface|\PHPUnit_Framework_MockObject_MockObject */ - protected $cache; + private $cache; /** @var \Magento\Framework\App\Cache\StateInterface|\PHPUnit_Framework_MockObject_MockObject */ - protected $cacheState; + private $cacheState; + + /** @var SerializerInterface|\PHPUnit_Framework_MockObject_MockObject */ + private $serializer; /** @var \Magento\Catalog\Model\ResourceModel\Config|\PHPUnit_Framework_MockObject_MockObject */ - protected $subject; + private $subject; protected function setUp() { $this->cache = $this->getMock(\Magento\Framework\App\CacheInterface::class); $this->cacheState = $this->getMock(\Magento\Framework\App\Cache\StateInterface::class); + $this->serializer = $this->getMock(SerializerInterface::class); $this->subject = $this->getMock(\Magento\Catalog\Model\ResourceModel\Config::class, [], [], '', false); } @@ -47,12 +50,17 @@ class ConfigTest extends \PHPUnit_Framework_TestCase $entityTypeId = 'type'; $storeId = 'store'; $attributes = ['attributes']; + $serializedAttributes = '["attributes"]'; $this->subject->expects($this->any())->method('getEntityTypeId')->willReturn($entityTypeId); $this->subject->expects($this->any())->method('getStoreId')->willReturn($storeId); $cacheId = \Magento\Catalog\Plugin\Model\ResourceModel\Config::PRODUCT_LISTING_ATTRIBUTES_CACHE_ID . $entityTypeId . '_' . $storeId; - $this->cache->expects($this->any())->method('load')->with($cacheId)->willReturn(serialize($attributes)); + $this->cache->expects($this->any())->method('load')->with($cacheId)->willReturn($serializedAttributes); + $this->serializer->expects($this->once()) + ->method('unserialize') + ->with($serializedAttributes) + ->willReturn($attributes); $this->assertEquals( $attributes, @@ -68,14 +76,21 @@ class ConfigTest extends \PHPUnit_Framework_TestCase $entityTypeId = 'type'; $storeId = 'store'; $attributes = ['attributes']; + $serializedAttributes = '["attributes"]'; $this->subject->expects($this->any())->method('getEntityTypeId')->willReturn($entityTypeId); $this->subject->expects($this->any())->method('getStoreId')->willReturn($storeId); $cacheId = \Magento\Catalog\Plugin\Model\ResourceModel\Config::PRODUCT_LISTING_ATTRIBUTES_CACHE_ID . $entityTypeId . '_' . $storeId; $this->cache->expects($this->any())->method('load')->with($cacheId)->willReturn(false); + $this->serializer->expects($this->never()) + ->method('unserialize'); + $this->serializer->expects($this->once()) + ->method('serialize') + ->with($attributes) + ->willReturn($serializedAttributes); $this->cache->expects($this->any())->method('save')->with( - serialize($attributes), + $serializedAttributes, $cacheId, [ \Magento\Eav\Model\Cache\Type::CACHE_TAG, @@ -110,11 +125,16 @@ class ConfigTest extends \PHPUnit_Framework_TestCase $entityTypeId = 'type'; $storeId = 'store'; $attributes = ['attributes']; + $serializedAttributes = '["attributes"]'; $this->subject->expects($this->any())->method('getEntityTypeId')->willReturn($entityTypeId); $this->subject->expects($this->any())->method('getStoreId')->willReturn($storeId); $cacheId = \Magento\Catalog\Plugin\Model\ResourceModel\Config::PRODUCT_LISTING_SORT_BY_ATTRIBUTES_CACHE_ID . $entityTypeId . '_' . $storeId; - $this->cache->expects($this->any())->method('load')->with($cacheId)->willReturn(serialize($attributes)); + $this->cache->expects($this->any())->method('load')->with($cacheId)->willReturn($serializedAttributes); + $this->serializer->expects($this->once()) + ->method('unserialize') + ->with($serializedAttributes) + ->willReturn($attributes); $this->assertEquals( $attributes, @@ -130,13 +150,20 @@ class ConfigTest extends \PHPUnit_Framework_TestCase $entityTypeId = 'type'; $storeId = 'store'; $attributes = ['attributes']; + $serializedAttributes = '["attributes"]'; $this->subject->expects($this->any())->method('getEntityTypeId')->willReturn($entityTypeId); $this->subject->expects($this->any())->method('getStoreId')->willReturn($storeId); $cacheId = \Magento\Catalog\Plugin\Model\ResourceModel\Config::PRODUCT_LISTING_SORT_BY_ATTRIBUTES_CACHE_ID . $entityTypeId . '_' . $storeId; $this->cache->expects($this->any())->method('load')->with($cacheId)->willReturn(false); + $this->serializer->expects($this->never()) + ->method('unserialize'); + $this->serializer->expects($this->once()) + ->method('serialize') + ->with($attributes) + ->willReturn($serializedAttributes); $this->cache->expects($this->any())->method('save')->with( - serialize($attributes), + $serializedAttributes, $cacheId, [ \Magento\Eav\Model\Cache\Type::CACHE_TAG, @@ -165,7 +192,8 @@ class ConfigTest extends \PHPUnit_Framework_TestCase \Magento\Catalog\Plugin\Model\ResourceModel\Config::class, [ 'cache' => $this->cache, - 'cacheState' => $this->cacheState + 'cacheState' => $this->cacheState, + 'serializer' => $this->serializer, ] ); } diff --git a/app/code/Magento/Catalog/Test/Unit/Pricing/Render/FinalPriceBoxTest.php b/app/code/Magento/Catalog/Test/Unit/Pricing/Render/FinalPriceBoxTest.php index bfe4e0c071bec556dc513682583c7f5b55108983..015a641a0df38d1337c99fa6ab8b06b405a76d11 100644 --- a/app/code/Magento/Catalog/Test/Unit/Pricing/Render/FinalPriceBoxTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Pricing/Render/FinalPriceBoxTest.php @@ -6,6 +6,8 @@ namespace Magento\Catalog\Test\Unit\Pricing\Render; +use Magento\Catalog\Model\Product\Pricing\Renderer\SalableResolverInterface; + /** * Class FinalPriceBoxTest * @@ -58,11 +60,16 @@ class FinalPriceBoxTest extends \PHPUnit_Framework_TestCase */ protected $price; + /** + * @var SalableResolverInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $salableResolverMock; + protected function setUp() { $this->product = $this->getMock( \Magento\Catalog\Model\Product::class, - ['getPriceInfo', '__wakeup', 'getCanShowPrice'], + ['getPriceInfo', '__wakeup', 'getCanShowPrice', 'isSalable'], [], '', false @@ -78,9 +85,7 @@ class FinalPriceBoxTest extends \PHPUnit_Framework_TestCase $this->priceBox = $this->getMock(\Magento\Framework\Pricing\Render\PriceBox::class, [], [], '', false); $this->logger = $this->getMock(\Psr\Log\LoggerInterface::class); - $this->layout->expects($this->any()) - ->method('getBlock') - ->will($this->returnValue($this->priceBox)); + $this->layout->expects($this->any())->method('getBlock')->willReturn($this->priceBox); $cacheState = $this->getMockBuilder(\Magento\Framework\App\Cache\StateInterface::class) ->getMockForAbstractClass(); @@ -93,12 +98,9 @@ class FinalPriceBoxTest extends \PHPUnit_Framework_TestCase ->disableOriginalConstructor() ->getMock(); - $urlBuilder = $this->getMockBuilder(\Magento\Framework\UrlInterface::class) - ->getMockForAbstractClass(); - - $store = $this->getMockBuilder(\Magento\Store\Api\Data\StoreInterface::class) - ->getMockForAbstractClass(); + $urlBuilder = $this->getMockBuilder(\Magento\Framework\UrlInterface::class)->getMockForAbstractClass(); + $store = $this->getMockBuilder(\Magento\Store\Api\Data\StoreInterface::class)->getMockForAbstractClass(); $storeManager = $this->getMockBuilder(\Magento\Store\Model\StoreManagerInterface::class) ->setMethods(['getStore', 'getCode']) ->getMockForAbstractClass(); @@ -144,6 +146,10 @@ class FinalPriceBoxTest extends \PHPUnit_Framework_TestCase ->will($this->returnValue(\Magento\Catalog\Pricing\Price\FinalPrice::PRICE_CODE)); $objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); + $this->salableResolverMock = $this->getMockBuilder(SalableResolverInterface::class) + ->disableOriginalConstructor() + ->getMockForAbstractClass(); + $this->object = $objectManager->getObject( \Magento\Catalog\Pricing\Render\FinalPriceBox::class, [ @@ -151,7 +157,8 @@ class FinalPriceBoxTest extends \PHPUnit_Framework_TestCase 'saleableItem' => $this->product, 'rendererPool' => $this->rendererPool, 'price' => $this->price, - 'data' => ['zone' => 'test_zone', 'list_category_page' => true] + 'data' => ['zone' => 'test_zone', 'list_category_page' => true], + 'salableResolver' => $this->salableResolverMock ] ); } @@ -169,6 +176,8 @@ class FinalPriceBoxTest extends \PHPUnit_Framework_TestCase ->with($this->equalTo($this->product)) ->will($this->returnValue(false)); + $this->salableResolverMock->expects($this->once())->method('isSalable')->with($this->product)->willReturn(true); + $result = $this->object->toHtml(); //assert price wrapper @@ -177,6 +186,18 @@ class FinalPriceBoxTest extends \PHPUnit_Framework_TestCase $this->assertRegExp('/[final_price]/', $result); } + public function testNotSalableItem() + { + $this->salableResolverMock + ->expects($this->once()) + ->method('isSalable') + ->with($this->product) + ->willReturn(false); + $result = $this->object->toHtml(); + + $this->assertEmpty($result); + } + public function testRenderMsrpEnabled() { $priceType = $this->getMock(\Magento\Msrp\Pricing\Price\MsrpPrice::class, [], [], '', false); @@ -211,6 +232,8 @@ class FinalPriceBoxTest extends \PHPUnit_Framework_TestCase ->with('msrp_price', $this->product, $arguments) ->will($this->returnValue($priceBoxRender)); + $this->salableResolverMock->expects($this->once())->method('isSalable')->with($this->product)->willReturn(true); + $result = $this->object->toHtml(); //assert price wrapper @@ -230,6 +253,8 @@ class FinalPriceBoxTest extends \PHPUnit_Framework_TestCase ->with($this->equalTo('msrp_price')) ->will($this->throwException(new \InvalidArgumentException())); + $this->salableResolverMock->expects($this->once())->method('isSalable')->with($this->product)->willReturn(true); + $result = $this->object->toHtml(); //assert price wrapper diff --git a/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Categories.php b/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Categories.php index 0e46b5899851f477abaae8a0591c4e95e872ef3e..0ee761646616ee96f5dfff870593cd9869b221cc 100644 --- a/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Categories.php +++ b/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Categories.php @@ -11,6 +11,7 @@ use Magento\Framework\App\ObjectManager; use Magento\Framework\App\CacheInterface; use Magento\Framework\DB\Helper as DbHelper; use Magento\Catalog\Model\Category as CategoryModel; +use Magento\Framework\Serialize\SerializerInterface; use Magento\Framework\UrlInterface; use Magento\Framework\Stdlib\ArrayManager; @@ -62,25 +63,33 @@ class Categories extends AbstractModifier */ private $cacheManager; + /** + * @var SerializerInterface + */ + private $serializer; + /** * @param LocatorInterface $locator * @param CategoryCollectionFactory $categoryCollectionFactory * @param DbHelper $dbHelper * @param UrlInterface $urlBuilder * @param ArrayManager $arrayManager + * @param SerializerInterface $serializer */ public function __construct( LocatorInterface $locator, CategoryCollectionFactory $categoryCollectionFactory, DbHelper $dbHelper, UrlInterface $urlBuilder, - ArrayManager $arrayManager + ArrayManager $arrayManager, + SerializerInterface $serializer = null ) { $this->locator = $locator; $this->categoryCollectionFactory = $categoryCollectionFactory; $this->dbHelper = $dbHelper; $this->urlBuilder = $urlBuilder; $this->arrayManager = $arrayManager; + $this->serializer = $serializer ?: ObjectManager::getInstance()->get(SerializerInterface::class); } /** @@ -286,7 +295,7 @@ class Categories extends AbstractModifier { $categoryTree = $this->getCacheManager()->load(self::CATEGORY_TREE_ID . '_' . $filter); if ($categoryTree) { - return unserialize($categoryTree); + return $this->serializer->unserialize($categoryTree); } $storeId = $this->locator->getStore()->getId(); @@ -340,7 +349,7 @@ class Categories extends AbstractModifier } $this->getCacheManager()->save( - serialize($categoryById[CategoryModel::TREE_ROOT_ID]['optgroup']), + $this->serializer->serialize($categoryById[CategoryModel::TREE_ROOT_ID]['optgroup']), self::CATEGORY_TREE_ID . '_' . $filter, [ \Magento\Catalog\Model\Category::CACHE_TAG, diff --git a/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/TierPrice.php b/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/TierPrice.php index ac511edcf2e5338eba6b83c60cf38a749406cf89..9b382464e8e2392fb07d81c070bae66cce7c203f 100644 --- a/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/TierPrice.php +++ b/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/TierPrice.php @@ -109,6 +109,7 @@ class TierPrice extends AbstractModifier 'label' => __('Price'), 'enableLabel' => true, 'dataScope' => '', + 'additionalClasses' => 'control-grouped', 'sortOrder' => isset($priceMeta['arguments']['data']['config']['sortOrder']) ? $priceMeta['arguments']['data']['config']['sortOrder'] : 40, ], diff --git a/app/code/Magento/Catalog/etc/di.xml b/app/code/Magento/Catalog/etc/di.xml index 6b39520ae021e9eb3bfafa20bda03e42c7db907a..27b9a19065e99f22fccf4f2f42076c69d0f1e0c2 100644 --- a/app/code/Magento/Catalog/etc/di.xml +++ b/app/code/Magento/Catalog/etc/di.xml @@ -48,6 +48,9 @@ <preference for="Magento\Catalog\Api\Data\CategorySearchResultsInterface" type="Magento\Framework\Api\SearchResults" /> <preference for="Magento\Catalog\Model\Config\Source\ProductPriceOptionsInterface" type="Magento\Catalog\Model\Config\Source\Product\Options\Price"/> <preference for="Magento\Catalog\Model\Indexer\Product\Flat\Table\BuilderInterface" type="Magento\Catalog\Model\Indexer\Product\Flat\Table\Builder"/> + <preference for="Magento\Catalog\Model\Product\Pricing\Renderer\SalableResolverInterface" type="Magento\Catalog\Model\Product\Pricing\Renderer\SalableResolver"/> + <preference for="Magento\Catalog\Model\Product\Media\ConfigInterface" type="Magento\Catalog\Model\Product\Media\Config"/> + <preference for="Magento\Framework\View\Asset\ContextInterface" type="Magento\Catalog\Model\View\Asset\Image\Context"/> <type name="Magento\Customer\Model\ResourceModel\Visitor"> <plugin name="catalogLog" type="Magento\Catalog\Model\Plugin\Log" /> </type> diff --git a/app/code/Magento/Catalog/view/adminhtml/web/template/image-preview.html b/app/code/Magento/Catalog/view/adminhtml/web/template/image-preview.html index fa8a4fec7cc78c6211194558421400c49660914a..3bc6e0a359c5ea710fdb7605a931464d7c26af17 100644 --- a/app/code/Magento/Catalog/view/adminhtml/web/template/image-preview.html +++ b/app/code/Magento/Catalog/view/adminhtml/web/template/image-preview.html @@ -31,5 +31,6 @@ <div class="file-uploader-filename" text="$file.name"/> <div class="file-uploader-meta"> <text args="$file.previewWidth"/>x<text args="$file.previewHeight"/> + <text args="$parent.formatSize($file.size)"/> </div> </div> diff --git a/app/code/Magento/CatalogImportExport/Model/Import/Product/Type/AbstractType.php b/app/code/Magento/CatalogImportExport/Model/Import/Product/Type/AbstractType.php index 0d19b9fcbedc85e4df47ab745759282f4824b060..ac39cea10cbe3b1046d8c93af5613ad6ec518b6f 100644 --- a/app/code/Magento/CatalogImportExport/Model/Import/Product/Type/AbstractType.php +++ b/app/code/Magento/CatalogImportExport/Model/Import/Product/Type/AbstractType.php @@ -8,6 +8,7 @@ namespace Magento\CatalogImportExport\Model\Import\Product\Type; use Magento\Framework\App\ResourceConnection; use Magento\CatalogImportExport\Model\Import\Product\RowValidatorInterface; use Magento\CatalogImportExport\Model\Import\Product; +use Magento\Framework\EntityManager\MetadataPool; /** * Import entity abstract product type model @@ -142,22 +143,27 @@ abstract class AbstractType private $productEntityLinkField; /** + * AbstractType constructor + * * @param \Magento\Eav\Model\ResourceModel\Entity\Attribute\Set\CollectionFactory $attrSetColFac * @param \Magento\Catalog\Model\ResourceModel\Product\Attribute\CollectionFactory $prodAttrColFac - * @param \Magento\Framework\App\ResourceConnection $resource + * @param ResourceConnection $resource * @param array $params + * @param MetadataPool|null $metadataPool * @throws \Magento\Framework\Exception\LocalizedException */ public function __construct( \Magento\Eav\Model\ResourceModel\Entity\Attribute\Set\CollectionFactory $attrSetColFac, \Magento\Catalog\Model\ResourceModel\Product\Attribute\CollectionFactory $prodAttrColFac, \Magento\Framework\App\ResourceConnection $resource, - array $params + array $params, + MetadataPool $metadataPool = null ) { $this->_attrSetColFac = $attrSetColFac; $this->_prodAttrColFac = $prodAttrColFac; $this->_resource = $resource; - $this->_connection = $resource->getConnection(); + $this->connection = $resource->getConnection(); + $this->metadataPool = $metadataPool ?: $this->getMetadataPool(); if ($this->isSuitable()) { if (!isset($params[0]) || !isset($params[1]) @@ -246,8 +252,8 @@ abstract class AbstractType { // temporary storage for attributes' parameters to avoid double querying inside the loop $entityId = $this->_entityModel->getEntityTypeId(); - $entityAttributes = $this->_connection->fetchAll( - $this->_connection->select()->from( + $entityAttributes = $this->connection->fetchAll( + $this->connection->select()->from( ['attr' => $this->_resource->getTableName('eav_entity_attribute')], ['attr.attribute_id'] )->joinLeft( @@ -255,7 +261,7 @@ abstract class AbstractType 'set.attribute_set_id = attr.attribute_set_id', ['set.attribute_set_name'] )->where( - $this->_connection->quoteInto('attr.entity_type_id IN (?)', $entityId) + $this->connection->quoteInto('attr.entity_type_id IN (?)', $entityId) ) ); $absentKeys = []; @@ -563,7 +569,7 @@ abstract class AbstractType protected function getProductEntityLinkField() { if (!$this->productEntityLinkField) { - $this->productEntityLinkField = $this->getMetadataPool() + $this->productEntityLinkField = $this->metadataPool ->getMetadata(\Magento\Catalog\Api\Data\ProductInterface::class) ->getLinkField(); } diff --git a/app/code/Magento/CatalogInventory/Setup/InstallSchema.php b/app/code/Magento/CatalogInventory/Setup/InstallSchema.php index a19eb9d1cc57344e6f2fcce5f94b81be113cc84f..cbe1aa3d066651a7d90f75b655da1ef79c95cf49 100644 --- a/app/code/Magento/CatalogInventory/Setup/InstallSchema.php +++ b/app/code/Magento/CatalogInventory/Setup/InstallSchema.php @@ -254,10 +254,10 @@ class InstallSchema implements InstallSchemaInterface ->addIndex( $installer->getIdxName( 'cataloginventory_stock_item', - ['product_id', 'website_id'], + ['product_id', 'stock_id'], \Magento\Framework\DB\Adapter\AdapterInterface::INDEX_TYPE_UNIQUE ), - ['product_id', 'website_id'], + ['product_id', 'stock_id'], ['type' => \Magento\Framework\DB\Adapter\AdapterInterface::INDEX_TYPE_UNIQUE] ) ->addIndex( diff --git a/app/code/Magento/CatalogInventory/Setup/UpgradeSchema.php b/app/code/Magento/CatalogInventory/Setup/UpgradeSchema.php new file mode 100644 index 0000000000000000000000000000000000000000..8fd3d264ee67d6a5bef74cebb829f82b9a324e92 --- /dev/null +++ b/app/code/Magento/CatalogInventory/Setup/UpgradeSchema.php @@ -0,0 +1,123 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\CatalogInventory\Setup; + +use Magento\Framework\Setup\UpgradeSchemaInterface; +use Magento\Framework\Setup\ModuleContextInterface; +use Magento\Framework\Setup\SchemaSetupInterface; +use Magento\CatalogInventory\Model\Stock\Item as StockItem; + +class UpgradeSchema implements UpgradeSchemaInterface +{ + /** + * @var string + */ + private $productCompositeKeyVersion = '2.2.0'; + + /** + * {@inheritdoc} + */ + public function upgrade(SchemaSetupInterface $setup, ModuleContextInterface $context) + { + $setup->startSetup(); + + if (version_compare($context->getVersion(), $this->productCompositeKeyVersion, '<')) { + $this->upgradeProductCompositeKey($setup); + } + + $setup->endSetup(); + } + + /** + * @param SchemaSetupInterface $setup + * @return void + */ + private function upgradeProductCompositeKey(SchemaSetupInterface $setup) + { + $oldCompositeKeyColumns = ['product_id', 'website_id']; + $newCompositeKeyColumns = ['product_id', 'stock_id']; + + $foreignKeys = $this->getForeignKeys($setup, $oldCompositeKeyColumns); + // drop foreign keys + $this->dropForeignKeys($setup, $foreignKeys); + + $oldIndexName = $setup->getIdxName( + $setup->getTable(StockItem::ENTITY), + $oldCompositeKeyColumns, + \Magento\Framework\DB\Adapter\AdapterInterface::INDEX_TYPE_UNIQUE + ); + + $newIndexName = $setup->getIdxName( + $setup->getTable(StockItem::ENTITY), + $newCompositeKeyColumns, + \Magento\Framework\DB\Adapter\AdapterInterface::INDEX_TYPE_UNIQUE + ); + + // Drop a key based on the following columns: "product_id","website_id" + $setup->getConnection()->dropIndex($setup->getTable(StockItem::ENTITY), $oldIndexName); + + // Create a key based on the following columns: "product_id","stock_id" + $setup->getConnection() + ->addIndex( + $setup->getTable(StockItem::ENTITY), + $newIndexName, + $newCompositeKeyColumns, + \Magento\Framework\DB\Adapter\AdapterInterface::INDEX_TYPE_UNIQUE + ); + // restore deleted foreign keys + $this->createForeignKeys($setup, $foreignKeys); + } + + /** + * @param SchemaSetupInterface $setup + * @param array $keys + * @return void + */ + private function dropForeignKeys(SchemaSetupInterface $setup, array $keys) + { + foreach ($keys as $key) { + $setup->getConnection()->dropForeignKey($key['TABLE_NAME'], $key['FK_NAME']); + } + } + + /** + * @param SchemaSetupInterface $setup + * @param array $keys + * @return void + */ + private function createForeignKeys(SchemaSetupInterface $setup, array $keys) + { + foreach ($keys as $key) { + $setup->getConnection()->addForeignKey( + $key['FK_NAME'], + $key['TABLE_NAME'], + $key['COLUMN_NAME'], + $key['REF_TABLE_NAME'], + $key['REF_COLUMN_NAME'], + $key['ON_DELETE'] + ); + } + } + + /** + * @param SchemaSetupInterface $setup + * @param array $compositeKeys + * @return array + */ + private function getForeignKeys(SchemaSetupInterface $setup, array $compositeKeys) + { + $foreignKeys = []; + $allForeignKeys = $setup->getConnection()->getForeignKeys($setup->getTable(StockItem::ENTITY)); + foreach ($allForeignKeys as $key) { + if (in_array($key['COLUMN_NAME'], $compositeKeys)) { + $foreignKeys[] = $key; + } + } + + return $foreignKeys; + } +} diff --git a/app/code/Magento/CatalogRule/Model/Rule.php b/app/code/Magento/CatalogRule/Model/Rule.php index 0da658be4cc219597faf847785e76c87fb327590..8a820fd5846e38bb3ed907fbf9020ccaf9dbd448 100644 --- a/app/code/Magento/CatalogRule/Model/Rule.php +++ b/app/code/Magento/CatalogRule/Model/Rule.php @@ -7,6 +7,8 @@ namespace Magento\CatalogRule\Model; use Magento\Catalog\Model\Product; use Magento\CatalogRule\Api\Data\RuleInterface; +use Magento\Framework\Api\AttributeValueFactory; +use Magento\Framework\Api\ExtensionAttributesFactory; use Magento\Framework\DataObject\IdentityInterface; /** @@ -137,7 +139,8 @@ class Rule extends \Magento\Rule\Model\AbstractModel implements RuleInterface, I protected $ruleConditionConverter; /** - * Rule constructor. + * Rule constructor + * * @param \Magento\Framework\Model\Context $context * @param \Magento\Framework\Registry $registry * @param \Magento\Framework\Data\FormFactory $formFactory @@ -157,6 +160,8 @@ class Rule extends \Magento\Rule\Model\AbstractModel implements RuleInterface, I * @param \Magento\Framework\Data\Collection\AbstractDb|null $resourceCollection * @param array $relatedCacheTypes * @param array $data + * @param ExtensionAttributesFactory|null $extensionFactory + * @param AttributeValueFactory|null $customAttributeFactory * * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ @@ -179,7 +184,9 @@ class Rule extends \Magento\Rule\Model\AbstractModel implements RuleInterface, I \Magento\Framework\Model\ResourceModel\AbstractResource $resource = null, \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $relatedCacheTypes = [], - array $data = [] + array $data = [], + ExtensionAttributesFactory $extensionFactory = null, + AttributeValueFactory $customAttributeFactory = null ) { $this->_productCollectionFactory = $productCollectionFactory; $this->_storeManager = $storeManager; @@ -201,7 +208,9 @@ class Rule extends \Magento\Rule\Model\AbstractModel implements RuleInterface, I $localeDate, $resource, $resourceCollection, - $data + $data, + $extensionFactory, + $customAttributeFactory ); } @@ -558,14 +567,8 @@ class Rule extends \Magento\Rule\Model\AbstractModel implements RuleInterface, I $result = []; foreach ($array1 as $key => $value) { if (array_key_exists($key, $array2)) { - if (is_array($value)) { - if ($value != $array2[$key]) { - $result[$key] = true; - } - } else { - if ($value != $array2[$key]) { - $result[$key] = true; - } + if ($value != $array2[$key]) { + $result[$key] = true; } } else { $result[$key] = true; diff --git a/app/code/Magento/CatalogRule/Test/Unit/Model/RuleTest.php b/app/code/Magento/CatalogRule/Test/Unit/Model/RuleTest.php index a624b87ebbe13efa061c7e97a8590e78bd5b70fe..b3f35dbe98e0dcc042ce4272337a6ea740147d70 100644 --- a/app/code/Magento/CatalogRule/Test/Unit/Model/RuleTest.php +++ b/app/code/Magento/CatalogRule/Test/Unit/Model/RuleTest.php @@ -3,14 +3,9 @@ * Copyright © 2016 Magento. All rights reserved. * See COPYING.txt for license details. */ - namespace Magento\CatalogRule\Test\Unit\Model; -use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper; - /** - * Class RuleTest - * @package Magento\CatalogRule\Test\Unit\Model * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class RuleTest extends \PHPUnit_Framework_TestCase @@ -18,8 +13,8 @@ class RuleTest extends \PHPUnit_Framework_TestCase /** @var \Magento\CatalogRule\Model\Rule */ protected $rule; - /** @var ObjectManagerHelper */ - protected $objectManagerHelper; + /** @var \Magento\Framework\TestFramework\Unit\Helper\ObjectManager */ + private $objectManager; /** @var \Magento\Store\Model\StoreManagerInterface|\PHPUnit_Framework_MockObject_MockObject */ protected $storeManager; @@ -63,6 +58,7 @@ class RuleTest extends \PHPUnit_Framework_TestCase */ protected function setUp() { + $this->objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); $this->storeManager = $this->getMock(\Magento\Store\Model\StoreManagerInterface::class); $this->storeModel = $this->getMock(\Magento\Store\Model\Store::class, ['__wakeup', 'getId'], [], '', false); $this->combineFactory = $this->getMock( @@ -128,20 +124,22 @@ class RuleTest extends \PHPUnit_Framework_TestCase false ); - $this->objectManagerHelper = new ObjectManagerHelper($this); - - $this->prepareObjectManager([ - [ - \Magento\Framework\Api\ExtensionAttributesFactory::class, - $this->getMock(\Magento\Framework\Api\ExtensionAttributesFactory::class, [], [], '', false) - ], - [ - \Magento\Framework\Api\AttributeValueFactory::class, - $this->getMock(\Magento\Framework\Api\AttributeValueFactory::class, [], [], '', false) - ], - ]); + $extensionFactoryMock = $this->getMock( + \Magento\Framework\Api\ExtensionAttributesFactory::class, + [], + [], + '', + false + ); + $attributeValueFactoryMock = $this->getMock( + \Magento\Framework\Api\AttributeValueFactory::class, + [], + [], + '', + false + ); - $this->rule = $this->objectManagerHelper->getObject( + $this->rule = $this->objectManager->getObject( \Magento\CatalogRule\Model\Rule::class, [ 'storeManager' => $this->storeManager, @@ -149,6 +147,8 @@ class RuleTest extends \PHPUnit_Framework_TestCase 'ruleProductProcessor' => $this->_ruleProductProcessor, 'productCollectionFactory' => $this->_productCollectionFactory, 'resourceIterator' => $this->_resourceIterator, + 'extensionFactory' => $extensionFactoryMock, + 'customAttributeFactory' => $attributeValueFactoryMock, ] ); } @@ -375,20 +375,4 @@ class RuleTest extends \PHPUnit_Framework_TestCase $expectedResult = 'form_namerule_conditions_fieldset_100'; $this->assertEquals($expectedResult, $this->rule->getConditionsFieldSetId($formName)); } - - /** - * @param $map - */ - private function prepareObjectManager($map) - { - $objectManagerMock = $this->getMock(\Magento\Framework\ObjectManagerInterface::class); - $objectManagerMock->expects($this->any())->method('getInstance')->willReturnSelf(); - $objectManagerMock->expects($this->any()) - ->method('get') - ->will($this->returnValueMap($map)); - $reflectionClass = new \ReflectionClass(\Magento\Framework\App\ObjectManager::class); - $reflectionProperty = $reflectionClass->getProperty('_instance'); - $reflectionProperty->setAccessible(true); - $reflectionProperty->setValue($objectManagerMock); - } } diff --git a/app/code/Magento/CatalogSearch/Model/Layer/Filter/Decimal.php b/app/code/Magento/CatalogSearch/Model/Layer/Filter/Decimal.php index a0f988276fd792696d65dedd1ad7f5d55838b9e1..25b8900db8f48e257cdf0ad99267ec862d9fc494 100644 --- a/app/code/Magento/CatalogSearch/Model/Layer/Filter/Decimal.php +++ b/app/code/Magento/CatalogSearch/Model/Layer/Filter/Decimal.php @@ -115,7 +115,7 @@ class Decimal extends AbstractFilter } $label = $this->renderRangeLabel( empty($from) ? 0 : $from, - empty($to) ? $to : $to + empty($to) ? 0 : $to ); $value = $from . '-' . $to; diff --git a/app/code/Magento/CatalogSearch/Model/ResourceModel/Advanced/Collection.php b/app/code/Magento/CatalogSearch/Model/ResourceModel/Advanced/Collection.php index a8ada4d409f61d908639f2a628dc766678f182cf..f63e06efc18d5dc4d59d991d0d94b7d915416dde 100644 --- a/app/code/Magento/CatalogSearch/Model/ResourceModel/Advanced/Collection.php +++ b/app/code/Magento/CatalogSearch/Model/ResourceModel/Advanced/Collection.php @@ -9,10 +9,12 @@ use Magento\Catalog\Model\Product; use Magento\Framework\Api\FilterBuilder; use Magento\Framework\Api\Search\SearchCriteriaBuilder; use Magento\Framework\Api\Search\SearchResultFactory; +use Magento\Framework\EntityManager\MetadataPool; use Magento\Framework\Exception\LocalizedException; use Magento\Framework\Search\Adapter\Mysql\TemporaryStorage; use Magento\Framework\Search\Request\EmptyRequestDataException; use Magento\Framework\Search\Request\NonExistingRequestNameException; +use Magento\Catalog\Model\ResourceModel\Product\Collection\ProductLimitationFactory; /** * Collection Advanced @@ -54,7 +56,8 @@ class Collection extends \Magento\Catalog\Model\ResourceModel\Product\Collection private $filterBuilder; /** - * Collection constructor. + * Collection constructor + * * @param \Magento\Framework\Data\Collection\EntityFactory $entityFactory * @param \Psr\Log\LoggerInterface $logger * @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy @@ -77,8 +80,11 @@ class Collection extends \Magento\Catalog\Model\ResourceModel\Product\Collection * @param \Magento\CatalogSearch\Model\Advanced\Request\Builder $requestBuilder * @param \Magento\Search\Model\SearchEngine $searchEngine * @param \Magento\Framework\Search\Adapter\Mysql\TemporaryStorageFactory $temporaryStorageFactory - * @param \Zend_Db_Adapter_Abstract $connection - * @param SearchResultFactory $searchResultFactory + * @param \Magento\Framework\DB\Adapter\AdapterInterface|null $connection + * @param SearchResultFactory|null $searchResultFactory + * @param ProductLimitationFactory|null $productLimitationFactory + * @param MetadataPool|null $metadataPool + * * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( @@ -104,8 +110,10 @@ class Collection extends \Magento\Catalog\Model\ResourceModel\Product\Collection \Magento\CatalogSearch\Model\Advanced\Request\Builder $requestBuilder, \Magento\Search\Model\SearchEngine $searchEngine, \Magento\Framework\Search\Adapter\Mysql\TemporaryStorageFactory $temporaryStorageFactory, - $connection = null, - SearchResultFactory $searchResultFactory = null + \Magento\Framework\DB\Adapter\AdapterInterface $connection = null, + SearchResultFactory $searchResultFactory = null, + ProductLimitationFactory $productLimitationFactory = null, + MetadataPool $metadataPool = null ) { $this->requestBuilder = $requestBuilder; $this->searchEngine = $searchEngine; @@ -134,7 +142,9 @@ class Collection extends \Magento\Catalog\Model\ResourceModel\Product\Collection $customerSession, $dateTime, $groupManagement, - $connection + $connection, + $productLimitationFactory, + $metadataPool ); } diff --git a/app/code/Magento/CatalogSearch/Model/ResourceModel/Fulltext/Collection.php b/app/code/Magento/CatalogSearch/Model/ResourceModel/Fulltext/Collection.php index 8a9e2b1917407d42089c1a1b5958eee0d51d8a25..bc7568a471160dbb9376e9a4482a5b0ef43ca28e 100644 --- a/app/code/Magento/CatalogSearch/Model/ResourceModel/Fulltext/Collection.php +++ b/app/code/Magento/CatalogSearch/Model/ResourceModel/Fulltext/Collection.php @@ -7,6 +7,7 @@ namespace Magento\CatalogSearch\Model\ResourceModel\Fulltext; use Magento\CatalogSearch\Model\Search\RequestGenerator; use Magento\Framework\DB\Select; +use Magento\Framework\EntityManager\MetadataPool; use Magento\Framework\Exception\StateException; use Magento\Framework\Search\Adapter\Mysql\TemporaryStorage; use Magento\Framework\Search\Response\QueryResponse; @@ -15,6 +16,7 @@ use Magento\Framework\Search\Request\NonExistingRequestNameException; use Magento\Framework\Api\Search\SearchResultFactory; use Magento\Framework\Exception\LocalizedException; use Magento\Framework\App\ObjectManager; +use Magento\Catalog\Model\ResourceModel\Product\Collection\ProductLimitationFactory; /** * Fulltext Collection @@ -94,6 +96,8 @@ class Collection extends \Magento\Catalog\Model\ResourceModel\Product\Collection private $filterBuilder; /** + * Collection constructor + * * @param \Magento\Framework\Data\Collection\EntityFactory $entityFactory * @param \Psr\Log\LoggerInterface $logger * @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy @@ -117,9 +121,12 @@ class Collection extends \Magento\Catalog\Model\ResourceModel\Product\Collection * @param \Magento\Framework\Search\Request\Builder $requestBuilder * @param \Magento\Search\Model\SearchEngine $searchEngine * @param \Magento\Framework\Search\Adapter\Mysql\TemporaryStorageFactory $temporaryStorageFactory - * @param \Magento\Framework\DB\Adapter\AdapterInterface $connection + * @param \Magento\Framework\DB\Adapter\AdapterInterface|null $connection * @param string $searchRequestName - * @param SearchResultFactory $searchResultFactory + * @param SearchResultFactory|null $searchResultFactory + * @param ProductLimitationFactory|null $productLimitationFactory + * @param MetadataPool|null $metadataPool + * * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( @@ -148,7 +155,9 @@ class Collection extends \Magento\Catalog\Model\ResourceModel\Product\Collection \Magento\Framework\Search\Adapter\Mysql\TemporaryStorageFactory $temporaryStorageFactory, \Magento\Framework\DB\Adapter\AdapterInterface $connection = null, $searchRequestName = 'catalog_view_container', - SearchResultFactory $searchResultFactory = null + SearchResultFactory $searchResultFactory = null, + ProductLimitationFactory $productLimitationFactory = null, + MetadataPool $metadataPool = null ) { $this->queryFactory = $catalogSearchData; if ($searchResultFactory === null) { @@ -175,7 +184,9 @@ class Collection extends \Magento\Catalog\Model\ResourceModel\Product\Collection $customerSession, $dateTime, $groupManagement, - $connection + $connection, + $productLimitationFactory, + $metadataPool ); $this->requestBuilder = $requestBuilder; $this->searchEngine = $searchEngine; diff --git a/app/code/Magento/CatalogSearch/Test/Unit/Model/ResourceModel/Advanced/CollectionTest.php b/app/code/Magento/CatalogSearch/Test/Unit/Model/ResourceModel/Advanced/CollectionTest.php index 96580c6764e9387e522a8c6d3a92d43e45869594..4b04e7d66ab569ab3d2e6219cef4e2b69268d8e0 100644 --- a/app/code/Magento/CatalogSearch/Test/Unit/Model/ResourceModel/Advanced/CollectionTest.php +++ b/app/code/Magento/CatalogSearch/Test/Unit/Model/ResourceModel/Advanced/CollectionTest.php @@ -7,7 +7,7 @@ namespace Magento\CatalogSearch\Test\Unit\Model\ResourceModel\Advanced; use Magento\Catalog\Model\Product; use Magento\CatalogSearch\Test\Unit\Model\ResourceModel\BaseCollectionTest; -use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper; +use \Magento\Catalog\Model\ResourceModel\Product\Collection\ProductLimitationFactory; /** * Tests Magento\CatalogSearch\Model\ResourceModel\Advanced\Collection @@ -16,6 +16,11 @@ use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHe */ class CollectionTest extends BaseCollectionTest { + /** + * @var \Magento\Framework\TestFramework\Unit\Helper\ObjectManager + */ + private $objectManager; + /** * @var \Magento\CatalogSearch\Model\ResourceModel\Advanced\Collection */ @@ -51,8 +56,7 @@ class CollectionTest extends BaseCollectionTest */ protected function setUp() { - $helper = new ObjectManagerHelper($this); - + $this->objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); $this->eavConfig = $this->getMock(\Magento\Eav\Model\Config::class, [], [], '', false); $storeManager = $this->getStoreManager(); $universalFactory = $this->getUniversalFactory(); @@ -67,13 +71,14 @@ class CollectionTest extends BaseCollectionTest ); $this->search = $this->getMock(\Magento\Search\Api\SearchInterface::class, [], [], '', false); - $this->prepareObjectManager([ - [\Magento\Catalog\Model\ResourceModel\Product\Collection\ProductLimitation::class, - $this->getMock(\Magento\Catalog\Model\ResourceModel\Product\Collection\ProductLimitation::class) - ], - ]); + $productLimitationMock = $this->getMock( + \Magento\Catalog\Model\ResourceModel\Product\Collection\ProductLimitation::class + ); + $productLimitationFactoryMock = $this->getMock(ProductLimitationFactory::class, ['create']); + $productLimitationFactoryMock->method('create') + ->willReturn($productLimitationMock); - $this->advancedCollection = $helper->getObject( + $this->advancedCollection = $this->objectManager->getObject( \Magento\CatalogSearch\Model\ResourceModel\Advanced\Collection::class, [ 'eavConfig' => $this->eavConfig, @@ -83,6 +88,7 @@ class CollectionTest extends BaseCollectionTest 'filterBuilder' => $this->filterBuilder, 'temporaryStorageFactory' => $this->temporaryStorageFactory, 'search' => $this->search, + 'productLimitationFactory' => $productLimitationFactoryMock, ] ); } @@ -150,20 +156,4 @@ class CollectionTest extends BaseCollectionTest ->getMock(); return $criteriaBuilder; } - - /** - * @param $map - */ - private function prepareObjectManager($map) - { - $objectManagerMock = $this->getMock(\Magento\Framework\ObjectManagerInterface::class); - $objectManagerMock->expects($this->any())->method('getInstance')->willReturnSelf(); - $objectManagerMock->expects($this->any()) - ->method('get') - ->will($this->returnValueMap($map)); - $reflectionClass = new \ReflectionClass(\Magento\Framework\App\ObjectManager::class); - $reflectionProperty = $reflectionClass->getProperty('_instance'); - $reflectionProperty->setAccessible(true); - $reflectionProperty->setValue($objectManagerMock); - } } diff --git a/app/code/Magento/CatalogSearch/Test/Unit/Model/ResourceModel/Fulltext/CollectionTest.php b/app/code/Magento/CatalogSearch/Test/Unit/Model/ResourceModel/Fulltext/CollectionTest.php index 84430c56476c05463043670d024b79b3482affcb..5e56a253563592a55b80b00d26432028d9f4c5fa 100644 --- a/app/code/Magento/CatalogSearch/Test/Unit/Model/ResourceModel/Fulltext/CollectionTest.php +++ b/app/code/Magento/CatalogSearch/Test/Unit/Model/ResourceModel/Fulltext/CollectionTest.php @@ -8,12 +8,18 @@ namespace Magento\CatalogSearch\Test\Unit\Model\ResourceModel\Fulltext; use Magento\CatalogSearch\Test\Unit\Model\ResourceModel\BaseCollectionTest; use Magento\Framework\Search\Adapter\Mysql\TemporaryStorageFactory; use PHPUnit_Framework_MockObject_MockObject as MockObject; +use Magento\Catalog\Model\ResourceModel\Product\Collection\ProductLimitationFactory; /** * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class CollectionTest extends BaseCollectionTest { + /** + * @var \Magento\Framework\TestFramework\Unit\Helper\ObjectManager + */ + private $objectManager; + /** * @var \Magento\Framework\Search\Adapter\Mysql\TemporaryStorage|\PHPUnit_Framework_MockObject_MockObject */ @@ -64,22 +70,19 @@ class CollectionTest extends BaseCollectionTest */ protected function setUp() { - $helper = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); - + $this->objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); $this->storeManager = $this->getStoreManager(); $this->universalFactory = $this->getUniversalFactory(); $this->scopeConfig = $this->getScopeConfig(); $this->criteriaBuilder = $this->getCriteriaBuilder(); $this->filterBuilder = $this->getFilterBuilder(); - $this->prepareObjectManager( - [ - [ - \Magento\Catalog\Model\ResourceModel\Product\Collection\ProductLimitation::class, - $this->getMock(\Magento\Catalog\Model\ResourceModel\Product\Collection\ProductLimitation::class) - ], - ] + $productLimitationMock = $this->getMock( + \Magento\Catalog\Model\ResourceModel\Product\Collection\ProductLimitation::class ); + $productLimitationFactoryMock = $this->getMock(ProductLimitationFactory::class, ['create']); + $productLimitationFactoryMock->method('create') + ->willReturn($productLimitationMock); $this->temporaryStorage = $this->getMockBuilder(\Magento\Framework\Search\Adapter\Mysql\TemporaryStorage::class) ->disableOriginalConstructor() @@ -92,13 +95,14 @@ class CollectionTest extends BaseCollectionTest ->method('create') ->willReturn($this->temporaryStorage); - $this->model = $helper->getObject( + $this->model = $this->objectManager->getObject( \Magento\CatalogSearch\Model\ResourceModel\Fulltext\Collection::class, [ 'storeManager' => $this->storeManager, 'universalFactory' => $this->universalFactory, 'scopeConfig' => $this->scopeConfig, - 'temporaryStorageFactory' => $temporaryStorageFactory + 'temporaryStorageFactory' => $temporaryStorageFactory, + 'productLimitationFactory' => $productLimitationFactoryMock ] ); @@ -110,6 +114,13 @@ class CollectionTest extends BaseCollectionTest $this->model->setFilterBuilder($this->filterBuilder); } + protected function tearDown() + { + $reflectionProperty = new \ReflectionProperty(\Magento\Framework\App\ObjectManager::class, '_instance'); + $reflectionProperty->setAccessible(true); + $reflectionProperty->setValue(null); + } + /** * @expectedException \Exception * @expectedExceptionCode 333 @@ -208,22 +219,6 @@ class CollectionTest extends BaseCollectionTest return $filterBuilder; } - /** - * @param $map - */ - private function prepareObjectManager($map) - { - $objectManagerMock = $this->getMock(\Magento\Framework\ObjectManagerInterface::class); - $objectManagerMock->expects($this->any())->method('getInstance')->willReturnSelf(); - $objectManagerMock->expects($this->any()) - ->method('get') - ->will($this->returnValueMap($map)); - $reflectionClass = new \ReflectionClass(\Magento\Framework\App\ObjectManager::class); - $reflectionProperty = $reflectionClass->getProperty('_instance'); - $reflectionProperty->setAccessible(true); - $reflectionProperty->setValue($objectManagerMock); - } - protected function createFilter() { $filter = $this->getMockBuilder(\Magento\Framework\Api\Filter::class) 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/CatalogWidget/Block/Product/Widget/Conditions.php b/app/code/Magento/CatalogWidget/Block/Product/Widget/Conditions.php index d57db33131b9d3cbe16f60119b9e97b82d72cdad..9a407b118461c19e0db02b92ad2b16a8eb8f5816 100644 --- a/app/code/Magento/CatalogWidget/Block/Product/Widget/Conditions.php +++ b/app/code/Magento/CatalogWidget/Block/Product/Widget/Conditions.php @@ -85,7 +85,7 @@ class Conditions extends Template implements RendererInterface $widget = $this->registry->registry('current_widget_instance'); if ($widget) { $widgetParameters = $widget->getWidgetParameters(); - } elseif($widgetOptions = $this->getLayout()->getBlock('wysiwyg_widget.options')) { + } elseif ($widgetOptions = $this->getLayout()->getBlock('wysiwyg_widget.options')) { $widgetParameters = $widgetOptions->getWidgetValues(); } @@ -100,6 +100,7 @@ class Conditions extends Template implements RendererInterface public function render(AbstractElement $element) { $this->element = $element; + $this->rule->getConditions()->setJsFormObject($this->getHtmlId()); return $this->toHtml(); } diff --git a/app/code/Magento/CatalogWidget/Model/Rule.php b/app/code/Magento/CatalogWidget/Model/Rule.php index 8258d3f1a8b4ff603650d99cc0dc7d38940cbd15..06bc8cba74dd6a86a84a959464f93bbc52ecbd45 100644 --- a/app/code/Magento/CatalogWidget/Model/Rule.php +++ b/app/code/Magento/CatalogWidget/Model/Rule.php @@ -5,6 +5,8 @@ */ namespace Magento\CatalogWidget\Model; +use Magento\Framework\Api\AttributeValueFactory; +use Magento\Framework\Api\ExtensionAttributesFactory; /** * Class Rule @@ -17,6 +19,8 @@ class Rule extends \Magento\Rule\Model\AbstractModel protected $conditionsFactory; /** + * Rule constructor + * * @param \Magento\Framework\Model\Context $context * @param \Magento\Framework\Registry $registry * @param \Magento\Framework\Data\FormFactory $formFactory @@ -25,6 +29,9 @@ class Rule extends \Magento\Rule\Model\AbstractModel * @param \Magento\Framework\Model\ResourceModel\AbstractResource|null $resource * @param \Magento\Framework\Data\Collection\AbstractDb|null $resourceCollection * @param array $data + * @param ExtensionAttributesFactory|null $extensionFactory + * @param AttributeValueFactory|null $customAttributeFactory + * * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( @@ -35,7 +42,9 @@ class Rule extends \Magento\Rule\Model\AbstractModel \Magento\CatalogWidget\Model\Rule\Condition\CombineFactory $conditionsFactory, \Magento\Framework\Model\ResourceModel\AbstractResource $resource = null, \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, - array $data = [] + array $data = [], + ExtensionAttributesFactory $extensionFactory = null, + AttributeValueFactory $customAttributeFactory = null ) { $this->conditionsFactory = $conditionsFactory; parent::__construct( @@ -45,7 +54,9 @@ class Rule extends \Magento\Rule\Model\AbstractModel $localeDate, $resource, $resourceCollection, - $data + $data, + $extensionFactory, + $customAttributeFactory ); } diff --git a/app/code/Magento/CatalogWidget/Model/Rule/Condition/Combine.php b/app/code/Magento/CatalogWidget/Model/Rule/Condition/Combine.php index 283309247cd9d0fbdc9edc8b0cb2bf2d06b2f33c..e40aae5d189b04b9e63911fddbe4813e378fcfa8 100644 --- a/app/code/Magento/CatalogWidget/Model/Rule/Condition/Combine.php +++ b/app/code/Magento/CatalogWidget/Model/Rule/Condition/Combine.php @@ -82,7 +82,7 @@ class Combine extends \Magento\Rule\Model\Condition\Combine public function collectValidatedAttributes($productCollection) { foreach ($this->getConditions() as $condition) { - $condition->addToCollection($productCollection); + $condition->collectValidatedAttributes($productCollection); } return $this; } diff --git a/app/code/Magento/CatalogWidget/Model/Rule/Condition/Product.php b/app/code/Magento/CatalogWidget/Model/Rule/Condition/Product.php index 262ba8f6a6d8dd198da0cb85c87e37a4c1d73795..7d41741135b80498f9b77cc77e4014369efaefc1 100644 --- a/app/code/Magento/CatalogWidget/Model/Rule/Condition/Product.php +++ b/app/code/Magento/CatalogWidget/Model/Rule/Condition/Product.php @@ -223,4 +223,12 @@ class Product extends \Magento\Rule\Model\Condition\Product\AbstractProduct return $result; } + + /** + * {@inheritdoc} + */ + public function collectValidatedAttributes($productCollection) + { + return $this->addToCollection($productCollection); + } } diff --git a/app/code/Magento/CatalogWidget/Test/Unit/Block/Product/Widget/ConditionsTest.php b/app/code/Magento/CatalogWidget/Test/Unit/Block/Product/Widget/ConditionsTest.php index 8d87c0ebf0d21768bbe05f5903aded09011e1663..b825e92bab1c2ef2eea4d2c08cd8da1ac1e9e192 100644 --- a/app/code/Magento/CatalogWidget/Test/Unit/Block/Product/Widget/ConditionsTest.php +++ b/app/code/Magento/CatalogWidget/Test/Unit/Block/Product/Widget/ConditionsTest.php @@ -15,6 +15,7 @@ use Magento\Framework\View\Element\BlockInterface; /** * Test class for \Magento\CatalogWidget\Block\Product\Widget\Conditions + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class ConditionsTest extends \PHPUnit_Framework_TestCase { @@ -175,4 +176,116 @@ class ConditionsTest extends \PHPUnit_Framework_TestCase ] ); } + + /** + * @return void + * @SuppressWarnings(PHPMD.ExcessiveMethodLength) + */ + public function testRender() + { + $data = ['area' => 'backend']; + $abstractElementMock = $this->getMock( + \Magento\Framework\Data\Form\Element\AbstractElement::class, + ['getContainer'], + [], + '', + false + ); + $eventManagerMock = $this->getMock( + \Magento\Framework\Event\ManagerInterface::class, + [], + [], + '', + false + ); + $scopeConfigMock = $this->getMock( + \Magento\Framework\App\Config\ScopeConfigInterface::class, + [], + [], + '', + false + ); + $fieldsetMock = $this->getMock( + \Magento\Framework\Data\Form\Element\Fieldset::class, + [], + [], + '', + false + ); + $combineMock = $this->getMock( + \Magento\Rule\Model\Condition\Combine::class, + [], + [], + '', + false + ); + $resolverMock = $this->getMock( + \Magento\Framework\View\Element\Template\File\Resolver::class, + [], + [], + '', + false + ); + $filesystemMock = $this->getMock( + \Magento\Framework\Filesystem::class, + ['getDirectoryRead'], + [], + '', + false + ); + $validatorMock = $this->getMock( + \Magento\Framework\View\Element\Template\File\Validator::class, + [], + [], + '', + false + ); + $templateEnginePoolMock = $this->getMock( + \Magento\Framework\View\TemplateEnginePool::class, + [], + [], + '', + false + ); + $templateEngineMock = $this->getMock( + \Magento\Framework\View\TemplateEngineInterface::class, + [], + [], + '', + false + ); + $directoryReadMock = $this->getMock( + \Magento\Framework\Filesystem\Directory\ReadInterface::class, + [], + [], + '', + false + ); + + $this->ruleMock->expects($this->once())->method('getConditions')->willReturn($combineMock); + $combineMock->expects($this->once())->method('setJsFormObject')->willReturnSelf(); + $abstractElementMock->expects($this->any())->method('getContainer')->willReturn($fieldsetMock); + $filesystemMock->expects($this->once())->method('getDirectoryRead')->willReturn($directoryReadMock); + $validatorMock->expects($this->once())->method('isValid')->willReturn(true); + $this->contextMock->expects($this->once())->method('getEnginePool')->willReturn($templateEnginePoolMock); + $templateEnginePoolMock->expects($this->once())->method('get')->willReturn($templateEngineMock); + $templateEngineMock->expects($this->once())->method('render')->willReturn('html'); + + $this->widgetConditions = $this->objectManagerHelper->getObject( + Conditions::class, + [ + 'context' => $this->contextMock, + 'registry' => $this->registryMock, + 'rule' => $this->ruleMock, + '_eventManager' => $eventManagerMock, + '_filesystem' => $filesystemMock, + '_scopeConfig' => $scopeConfigMock, + 'validator' => $validatorMock, + 'resolver' => $resolverMock, + 'data' => $data + ] + ); + + $this->assertEquals($this->widgetConditions->render($abstractElementMock), 'html'); + } } diff --git a/app/code/Magento/CatalogWidget/Test/Unit/Model/Rule/Condition/CombineTest.php b/app/code/Magento/CatalogWidget/Test/Unit/Model/Rule/Condition/CombineTest.php index fa6474e31e7ccb715c09d1b8d2df5523f2ec9f13..dd42ee1c7c9216fc3749a92c643c4afc972bc233 100644 --- a/app/code/Magento/CatalogWidget/Test/Unit/Model/Rule/Condition/CombineTest.php +++ b/app/code/Magento/CatalogWidget/Test/Unit/Model/Rule/Condition/CombineTest.php @@ -80,9 +80,9 @@ class CombineTest extends \PHPUnit_Framework_TestCase ->disableOriginalConstructor() ->getMock(); $condition = $this->getMockBuilder(\Magento\CatalogWidget\Model\Rule\Condition\Combine::class) - ->disableOriginalConstructor()->setMethods(['addToCollection']) + ->disableOriginalConstructor()->setMethods(['collectValidatedAttributes']) ->getMock(); - $condition->expects($this->any())->method('addToCollection')->with($collection) + $condition->expects($this->any())->method('collectValidatedAttributes')->with($collection) ->will($this->returnSelf()); $this->condition->setConditions([$condition]); diff --git a/app/code/Magento/CatalogWidget/Test/Unit/Model/RuleTest.php b/app/code/Magento/CatalogWidget/Test/Unit/Model/RuleTest.php index afcc540a375458a6fc0be2f0740b7e4d0ff58c23..a6468cc77a47f093a7f95f1694f10f4812ce0e1c 100644 --- a/app/code/Magento/CatalogWidget/Test/Unit/Model/RuleTest.php +++ b/app/code/Magento/CatalogWidget/Test/Unit/Model/RuleTest.php @@ -3,13 +3,15 @@ * Copyright © 2016 Magento. All rights reserved. * See COPYING.txt for license details. */ - namespace Magento\CatalogWidget\Test\Unit\Model; -use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper; - class RuleTest extends \PHPUnit_Framework_TestCase { + /** + * @var \Magento\Framework\TestFramework\Unit\Helper\ObjectManager + */ + private $objectManager; + /** * @var \Magento\CatalogWidget\Model\Rule */ @@ -22,25 +24,13 @@ class RuleTest extends \PHPUnit_Framework_TestCase protected function setUp() { + $this->objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); $this->combineFactory = $this->getMockBuilder(\Magento\CatalogWidget\Model\Rule\Condition\CombineFactory::class) ->setMethods(['create']) ->disableOriginalConstructor() ->getMock(); - $objectManagerHelper = new ObjectManagerHelper($this); - - $this->prepareObjectManager([ - [ - \Magento\Framework\Api\ExtensionAttributesFactory::class, - $this->getMock(\Magento\Framework\Api\ExtensionAttributesFactory::class, [], [], '', false) - ], - [ - \Magento\Framework\Api\AttributeValueFactory::class, - $this->getMock(\Magento\Framework\Api\AttributeValueFactory::class, [], [], '', false) - ], - ]); - - $this->rule = $objectManagerHelper->getObject( + $this->rule = $this->objectManager->getObject( \Magento\CatalogWidget\Model\Rule::class, [ 'conditionsFactory' => $this->combineFactory @@ -62,20 +52,4 @@ class RuleTest extends \PHPUnit_Framework_TestCase { $this->assertNull($this->rule->getActionsInstance()); } - - /** - * @param $map - */ - private function prepareObjectManager($map) - { - $objectManagerMock = $this->getMock(\Magento\Framework\ObjectManagerInterface::class); - $objectManagerMock->expects($this->any())->method('getInstance')->willReturnSelf(); - $objectManagerMock->expects($this->any()) - ->method('get') - ->will($this->returnValueMap($map)); - $reflectionClass = new \ReflectionClass(\Magento\Framework\App\ObjectManager::class); - $reflectionProperty = $reflectionClass->getProperty('_instance'); - $reflectionProperty->setAccessible(true); - $reflectionProperty->setValue($objectManagerMock); - } } diff --git a/app/code/Magento/Checkout/Block/Cart/LayoutProcessor.php b/app/code/Magento/Checkout/Block/Cart/LayoutProcessor.php index a492002b0a5a5f55219efe09c3422c39f46e9fee..a042c41634bcb615921b93e01c4c42b23bfb8cd4 100644 --- a/app/code/Magento/Checkout/Block/Cart/LayoutProcessor.php +++ b/app/code/Magento/Checkout/Block/Cart/LayoutProcessor.php @@ -85,14 +85,14 @@ class LayoutProcessor implements \Magento\Checkout\Block\Checkout\LayoutProcesso 'visible' => true, 'formElement' => 'select', 'label' => __('Country'), - 'options' => $this->countryCollection->loadByStore()->toOptionArray(), + 'options' => [], 'value' => null ], 'region_id' => [ 'visible' => true, 'formElement' => 'select', 'label' => __('State/Province'), - 'options' => $this->regionCollection->load()->toOptionArray(), + 'options' => [], 'value' => null ], 'postcode' => [ @@ -103,6 +103,13 @@ class LayoutProcessor implements \Magento\Checkout\Block\Checkout\LayoutProcesso ] ]; + if (!isset($jsLayout['components']['checkoutProvider']['dictionaries'])) { + $jsLayout['components']['checkoutProvider']['dictionaries'] = [ + 'country_id' => $this->countryCollection->loadByStore()->toOptionArray(), + 'region_id' => $this->regionCollection->addAllowedCountriesFilter()->toOptionArray(), + ]; + } + if (isset($jsLayout['components']['block-summary']['children']['block-shipping']['children'] ['address-fieldsets']['children']) ) { diff --git a/app/code/Magento/Checkout/Block/Checkout/AttributeMerger.php b/app/code/Magento/Checkout/Block/Checkout/AttributeMerger.php index 1882d88e04a8b25f51ccf0afbd92a1635f443735..bbb2c69cc39027ee962a64917c46131d65f7a278 100644 --- a/app/code/Magento/Checkout/Block/Checkout/AttributeMerger.php +++ b/app/code/Magento/Checkout/Block/Checkout/AttributeMerger.php @@ -23,6 +23,8 @@ class AttributeMerger 'textarea' => 'Magento_Ui/js/form/element/textarea', 'multiline' => 'Magento_Ui/js/form/components/group', 'multiselect' => 'Magento_Ui/js/form/element/multiselect', + 'image' => 'Magento_Ui/js/form/element/media', + 'file' => 'Magento_Ui/js/form/element/media', ]; /** @@ -32,6 +34,7 @@ class AttributeMerger */ protected $templateMap = [ 'image' => 'media', + 'file' => 'media', ]; /** @@ -192,6 +195,15 @@ class AttributeMerger 'visible' => isset($additionalConfig['visible']) ? $additionalConfig['visible'] : true, ]; + if ($attributeCode === 'region_id' || $attributeCode === 'country_id') { + unset($element['options']); + $element['deps'] = [$providerName]; + $element['imports'] = [ + 'initialOptions' => 'index = ' . $providerName . ':dictionaries.' . $attributeCode, + 'setOptions' => 'index = ' . $providerName . ':dictionaries.' . $attributeCode + ]; + } + if (isset($attributeConfig['value']) && $attributeConfig['value'] != null) { $element['value'] = $attributeConfig['value']; } elseif (isset($attributeConfig['default']) && $attributeConfig['default'] != null) { @@ -341,11 +353,11 @@ class AttributeMerger * @param string $attributeCode * @param array $attributeConfig * @return array + * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ protected function getFieldOptions($attributeCode, array $attributeConfig) { - $options = isset($attributeConfig['options']) ? $attributeConfig['options'] : []; - return ($attributeCode == 'country_id') ? $this->orderCountryOptions($options) : $options; + return isset($attributeConfig['options']) ? $attributeConfig['options'] : []; } /** @@ -353,6 +365,7 @@ class AttributeMerger * * @param array $countryOptions * @return array + * @deprecated */ protected function orderCountryOptions(array $countryOptions) { diff --git a/app/code/Magento/Checkout/Block/Checkout/DirectoryDataProcessor.php b/app/code/Magento/Checkout/Block/Checkout/DirectoryDataProcessor.php new file mode 100644 index 0000000000000000000000000000000000000000..4a02ebbd079a407e531f17168531a5f9439915fb --- /dev/null +++ b/app/code/Magento/Checkout/Block/Checkout/DirectoryDataProcessor.php @@ -0,0 +1,146 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Checkout\Block\Checkout; + +use Magento\Directory\Helper\Data as DirectoryHelper; +use Magento\Store\Api\StoreResolverInterface; + +/** + * Directory data processor. + * + * This class adds various country and region dictionaries to checkout page. + * This data can be used by other UI components during checkout flow. + */ +class DirectoryDataProcessor implements \Magento\Checkout\Block\Checkout\LayoutProcessorInterface +{ + /** + * @var array + */ + private $countryOptions; + + /** + * @var array + */ + private $regionOptions; + + /** + * @var \Magento\Directory\Model\ResourceModel\Region\CollectionFactory + */ + private $regionCollectionFactory; + + /** + * @var \Magento\Directory\Model\ResourceModel\Region\CollectionFactory + */ + private $countryCollectionFactory; + + /** + * @var StoreResolverInterface + */ + private $storeResolver; + + /** + * @var DirectoryHelper + */ + private $directoryHelper; + + /** + * @param \Magento\Directory\Model\ResourceModel\Country\CollectionFactory $countryCollection + * @param \Magento\Directory\Model\ResourceModel\Region\CollectionFactory $regionCollection + * @param StoreResolverInterface $storeResolver + * @param DirectoryHelper $directoryHelper + */ + public function __construct( + \Magento\Directory\Model\ResourceModel\Country\CollectionFactory $countryCollection, + \Magento\Directory\Model\ResourceModel\Region\CollectionFactory $regionCollection, + StoreResolverInterface $storeResolver, + DirectoryHelper $directoryHelper + ) { + $this->countryCollectionFactory = $countryCollection; + $this->regionCollectionFactory = $regionCollection; + $this->storeResolver = $storeResolver; + $this->directoryHelper = $directoryHelper; + } + + /** + * Process js Layout of block + * + * @param array $jsLayout + * @return array + */ + public function process($jsLayout) + { + if (!isset($jsLayout['components']['checkoutProvider']['dictionaries'])) { + $jsLayout['components']['checkoutProvider']['dictionaries'] = [ + 'country_id' => $this->getCountryOptions(), + 'region_id' => $this->getRegionOptions(), + ]; + } + + return $jsLayout; + } + + /** + * Get country options list. + * + * @return array + */ + private function getCountryOptions() + { + if (!isset($this->countryOptions)) { + $this->countryOptions = $this->countryCollectionFactory->create()->loadByStore( + $this->storeResolver->getCurrentStoreId() + )->toOptionArray(); + $this->countryOptions = $this->orderCountryOptions($this->countryOptions); + } + + return $this->countryOptions; + } + + /** + * Get region options list. + * + * @return array + */ + private function getRegionOptions() + { + if (!isset($this->regionOptions)) { + $this->regionOptions = $this->regionCollectionFactory->create()->addAllowedCountriesFilter( + $this->storeResolver->getCurrentStoreId() + )->toOptionArray(); + } + + return $this->regionOptions; + } + + /** + * Sort country options by top country codes. + * + * @param array $countryOptions + * @return array + */ + private function orderCountryOptions(array $countryOptions) + { + $topCountryCodes = $this->directoryHelper->getTopCountryCodes(); + if (empty($topCountryCodes)) { + return $countryOptions; + } + + $headOptions = []; + $tailOptions = [[ + 'value' => 'delimiter', + 'label' => '──────────', + 'disabled' => true, + ]]; + foreach ($countryOptions as $countryOption) { + if (empty($countryOption['value']) || in_array($countryOption['value'], $topCountryCodes)) { + array_push($headOptions, $countryOption); + } else { + array_push($tailOptions, $countryOption); + } + } + return array_merge($headOptions, $tailOptions); + } +} diff --git a/app/code/Magento/Checkout/Block/Checkout/LayoutProcessor.php b/app/code/Magento/Checkout/Block/Checkout/LayoutProcessor.php index 1b2c7444198915c866a55ca2cc9b8e6b29544e39..fd8434703ab756a2664e235332d09e13e7890e19 100644 --- a/app/code/Magento/Checkout/Block/Checkout/LayoutProcessor.php +++ b/app/code/Magento/Checkout/Block/Checkout/LayoutProcessor.php @@ -7,7 +7,11 @@ namespace Magento\Checkout\Block\Checkout; use Magento\Checkout\Helper\Data; use Magento\Framework\App\ObjectManager; +use Magento\Store\Api\StoreResolverInterface; +/** + * Class LayoutProcessor + */ class LayoutProcessor implements \Magento\Checkout\Block\Checkout\LayoutProcessorInterface { /** @@ -35,6 +39,16 @@ class LayoutProcessor implements \Magento\Checkout\Block\Checkout\LayoutProcesso */ private $checkoutDataHelper; + /** + * @var StoreResolverInterface + */ + private $storeResolver; + + /** + * @var \Magento\Shipping\Model\Config + */ + private $shippingConfig; + /** * @param \Magento\Customer\Model\AttributeMetadataDataProvider $attributeMetadataDataProvider * @param \Magento\Ui\Component\Form\AttributeMapper $attributeMapper @@ -146,6 +160,16 @@ class LayoutProcessor implements \Magento\Checkout\Block\Checkout\LayoutProcesso $elements ); } + if (isset($jsLayout['components']['checkout']['children']['steps']['children']['shipping-step']['children'] + ['step-config']['children']['shipping-rates-validation']['children'] + )) { + $jsLayout['components']['checkout']['children']['steps']['children']['shipping-step']['children'] + ['step-config']['children']['shipping-rates-validation']['children'] = + $this->processShippingChildrenComponents( + $jsLayout['components']['checkout']['children']['steps']['children']['shipping-step']['children'] + ['step-config']['children']['shipping-rates-validation']['children'] + ); + } if (isset($jsLayout['components']['checkout']['children']['steps']['children']['shipping-step'] ['children']['shippingAddress']['children']['shipping-address-fieldset']['children'] @@ -163,6 +187,26 @@ class LayoutProcessor implements \Magento\Checkout\Block\Checkout\LayoutProcesso return $jsLayout; } + /** + * Process shipping configuration to exclude inactive carriers. + * + * @param array $shippingRatesLayout + * @return array + */ + private function processShippingChildrenComponents($shippingRatesLayout) + { + $activeCarriers = $this->getShippingConfig()->getActiveCarriers( + $this->getStoreResolver()->getCurrentStoreId() + ); + foreach (array_keys($shippingRatesLayout) as $carrierName) { + $carrierKey = str_replace('-rates-validation', '', $carrierName); + if (!array_key_exists($carrierKey, $activeCarriers)) { + unset($shippingRatesLayout[$carrierName]); + } + } + return $shippingRatesLayout; + } + /** * Appends billing address form component to payment layout * @param array $paymentLayout @@ -314,4 +358,34 @@ class LayoutProcessor implements \Magento\Checkout\Block\Checkout\LayoutProcesso return $this->checkoutDataHelper; } + + /** + * Retrieve Shipping Configuration. + * + * @return \Magento\Shipping\Model\Config + * @deprecated + */ + private function getShippingConfig() + { + if (!$this->shippingConfig) { + $this->shippingConfig = ObjectManager::getInstance()->get(\Magento\Shipping\Model\Config::class); + } + + return $this->shippingConfig; + } + + /** + * Get store resolver. + * + * @return StoreResolverInterface + * @deprecated + */ + private function getStoreResolver() + { + if (!$this->storeResolver) { + $this->storeResolver = ObjectManager::getInstance()->get(StoreResolverInterface::class); + } + + return $this->storeResolver; + } } diff --git a/app/code/Magento/Checkout/Test/Unit/Block/Cart/LayoutProcessorTest.php b/app/code/Magento/Checkout/Test/Unit/Block/Cart/LayoutProcessorTest.php index 95ffed86cbb35177051303726222813942336c72..5eabb6c9c86a47def05a69762c21f0b47f5a608f 100644 --- a/app/code/Magento/Checkout/Test/Unit/Block/Cart/LayoutProcessorTest.php +++ b/app/code/Magento/Checkout/Test/Unit/Block/Cart/LayoutProcessorTest.php @@ -69,7 +69,7 @@ class LayoutProcessorTest extends \PHPUnit_Framework_TestCase $this->countryCollection->expects($this->once())->method('loadByStore')->willReturnSelf(); $this->countryCollection->expects($this->once())->method('toOptionArray')->willReturn($countries); - $this->regionCollection->expects($this->once())->method('load')->willReturnSelf(); + $this->regionCollection->expects($this->once())->method('addAllowedCountriesFilter')->willReturnSelf(); $this->regionCollection->expects($this->once())->method('toOptionArray')->willReturn($regions); $layoutMerged = $layout; @@ -77,7 +77,12 @@ class LayoutProcessorTest extends \PHPUnit_Framework_TestCase ['address-fieldsets']['children']['fieldThree'] = ['param' => 'value']; $layoutMergedPointer = &$layoutMerged['components']['block-summary']['children']['block-shipping'] ['children']['address-fieldsets']['children']; - + $layoutMerged['components']['checkoutProvider'] = [ + 'dictionaries' => [ + 'country_id' => [], + 'region_id' => [], + ] + ]; $elements = [ 'city' => [ 'visible' => false, diff --git a/app/code/Magento/Checkout/Test/Unit/Block/Checkout/DirectoryDataProcessorTest.php b/app/code/Magento/Checkout/Test/Unit/Block/Checkout/DirectoryDataProcessorTest.php new file mode 100644 index 0000000000000000000000000000000000000000..c84fac464c047ad611268d26ac988adb2b419596 --- /dev/null +++ b/app/code/Magento/Checkout/Test/Unit/Block/Checkout/DirectoryDataProcessorTest.php @@ -0,0 +1,114 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Checkout\Test\Unit\Block\Checkout; + +class DirectoryDataProcessorTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var \Magento\Checkout\Block\Checkout\DirectoryDataProcessor + */ + protected $model; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $countryCollectionFactoryMock; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $countryCollectionMock; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $regionCollectionFactoryMock; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $regionCollectionMock; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $storeResolverMock; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $directoryDataHelperMock; + + protected function setUp() + { + $this->countryCollectionFactoryMock = $this->getMock( + \Magento\Directory\Model\ResourceModel\Country\CollectionFactory::class, + ['create'], + [], + '', + false + ); + $this->countryCollectionMock = $this->getMock( + \Magento\Directory\Model\ResourceModel\Country\Collection::class, + [], + [], + '', + false + ); + $this->regionCollectionFactoryMock = $this->getMock( + \Magento\Directory\Model\ResourceModel\Region\CollectionFactory::class, + ['create'], + [], + '', + false + ); + $this->regionCollectionMock = $this->getMock( + \Magento\Directory\Model\ResourceModel\Region\Collection::class, + [], + [], + '', + false + ); + $this->storeResolverMock = $this->getMock( + \Magento\Store\Api\StoreResolverInterface::class + ); + $this->directoryDataHelperMock = $this->getMock( + \Magento\Directory\Helper\Data::class, + [], + [], + '', + false + ); + + $this->model = new \Magento\Checkout\Block\Checkout\DirectoryDataProcessor( + $this->countryCollectionFactoryMock, + $this->regionCollectionFactoryMock, + $this->storeResolverMock, + $this->directoryDataHelperMock + ); + } + + public function testProcess() + { + $expectedResult['components']['checkoutProvider']['dictionaries'] = [ + 'country_id' => [], + 'region_id' => [], + ]; + + $this->countryCollectionFactoryMock->expects($this->once()) + ->method('create') + ->willReturn($this->countryCollectionMock); + $this->countryCollectionMock->expects($this->once())->method('loadByStore')->willReturnSelf(); + $this->countryCollectionMock->expects($this->once())->method('toOptionArray')->willReturn([]); + $this->regionCollectionFactoryMock->expects($this->once()) + ->method('create') + ->willReturn($this->regionCollectionMock); + $this->regionCollectionMock->expects($this->once())->method('addAllowedCountriesFilter')->willReturnSelf(); + $this->regionCollectionMock->expects($this->once())->method('toOptionArray')->willReturn([]); + + $this->assertEquals($expectedResult, $this->model->process([])); + } +} diff --git a/app/code/Magento/Checkout/Test/Unit/Block/Checkout/LayoutProcessorTest.php b/app/code/Magento/Checkout/Test/Unit/Block/Checkout/LayoutProcessorTest.php index 1351213f990b54a573a5d5d3a015e7b940a5f7ee..95aed9b56afc33d2f08f778a2e4b1e2162d35fe6 100644 --- a/app/code/Magento/Checkout/Test/Unit/Block/Checkout/LayoutProcessorTest.php +++ b/app/code/Magento/Checkout/Test/Unit/Block/Checkout/LayoutProcessorTest.php @@ -17,6 +17,8 @@ use PHPUnit_Framework_MockObject_MockObject as MockObject; /** * LayoutProcessorTest covers a list of variations for * checkout layout processor + * + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class LayoutProcessorTest extends \PHPUnit_Framework_TestCase { @@ -45,6 +47,11 @@ class LayoutProcessorTest extends \PHPUnit_Framework_TestCase */ private $layoutProcessor; + /** + * @var MockObject + */ + private $storeResolver; + protected function setUp() { $objectManager = new ObjectManager($this); @@ -79,8 +86,11 @@ class LayoutProcessorTest extends \PHPUnit_Framework_TestCase $this->attributeMerger ); + $this->storeResolver = $this->getMock(\Magento\Store\Api\StoreResolverInterface::class); + $objectManager->setBackwardCompatibleProperty($this->layoutProcessor, 'checkoutDataHelper', $this->dataHelper); $objectManager->setBackwardCompatibleProperty($this->layoutProcessor, 'options', $options); + $objectManager->setBackwardCompatibleProperty($this->layoutProcessor, 'storeResolver', $this->storeResolver); } /** diff --git a/app/code/Magento/Checkout/Test/Unit/Model/ShippingInformationManagementTest.php b/app/code/Magento/Checkout/Test/Unit/Model/ShippingInformationManagementTest.php index 04d347ec237a9435964a5f4fcce784708c4365a4..402a0c8228356a7ae8a148d7626e06bb5dc15a27 100644 --- a/app/code/Magento/Checkout/Test/Unit/Model/ShippingInformationManagementTest.php +++ b/app/code/Magento/Checkout/Test/Unit/Model/ShippingInformationManagementTest.php @@ -11,6 +11,11 @@ namespace Magento\Checkout\Test\Unit\Model; */ class ShippingInformationManagementTest extends \PHPUnit_Framework_TestCase { + /** + * @var \Magento\Framework\TestFramework\Unit\Helper\ObjectManager + */ + private $objectManager; + /** * @var \PHPUnit_Framework_MockObject_MockObject */ @@ -31,26 +36,6 @@ class ShippingInformationManagementTest extends \PHPUnit_Framework_TestCase */ protected $quoteRepositoryMock; - /** - * @var \PHPUnit_Framework_MockObject_MockObject - */ - protected $addressValidatorMock; - - /** - * @var \PHPUnit_Framework_MockObject_MockObject - */ - protected $loggerMock; - - /** - * @var \PHPUnit_Framework_MockObject_MockObject - */ - protected $addressRepositoryMock; - - /** - * @var \PHPUnit_Framework_MockObject_MockObject - */ - protected $scopeConfigMock; - /** * @var \PHPUnit_Framework_MockObject_MockObject */ @@ -61,11 +46,6 @@ class ShippingInformationManagementTest extends \PHPUnit_Framework_TestCase */ protected $quoteMock; - /** - * @var \PHPUnit_Framework_MockObject_MockObject - */ - protected $totalsCollectorMock; - /** * @var \Magento\Checkout\Model\ShippingInformationManagement */ @@ -103,6 +83,7 @@ class ShippingInformationManagementTest extends \PHPUnit_Framework_TestCase protected function setUp() { + $this->objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); $this->paymentMethodManagementMock = $this->getMock(\Magento\Quote\Api\PaymentMethodManagementInterface::class); $this->paymentDetailsFactoryMock = $this->getMock( \Magento\Checkout\Model\PaymentDetailsFactory::class, @@ -113,18 +94,6 @@ class ShippingInformationManagementTest extends \PHPUnit_Framework_TestCase ); $this->cartTotalsRepositoryMock = $this->getMock(\Magento\Quote\Api\CartTotalRepositoryInterface::class); $this->quoteRepositoryMock = $this->getMock(\Magento\Quote\Api\CartRepositoryInterface::class); - $this->addressValidatorMock = $this->getMock( - \Magento\Quote\Model\QuoteAddressValidator::class, - [], - [], - '', - false - ); - $this->loggerMock = $this->getMock(\Psr\Log\LoggerInterface::class); - $this->addressRepositoryMock = $this->getMock(\Magento\Customer\Api\AddressRepositoryInterface::class); - $this->scopeConfigMock = $this->getMock(\Magento\Framework\App\Config\ScopeConfigInterface::class); - $this->totalsCollectorMock = - $this->getMock(\Magento\Quote\Model\Quote\TotalsCollector::class, [], [], '', false); $this->shippingAddressMock = $this->getMock( \Magento\Quote\Model\Quote\Address::class, [ @@ -175,22 +144,29 @@ class ShippingInformationManagementTest extends \PHPUnit_Framework_TestCase $this->shippingFactoryMock = $this->getMock(\Magento\Quote\Model\ShippingFactory::class, ['create'], [], '', false); - $this->prepareObjectManager([ - [\Magento\Quote\Model\ShippingAssignmentFactory::class, $this->shippingAssignmentFactoryMock], - [\Magento\Quote\Api\Data\CartExtensionFactory::class, $this->cartExtensionFactoryMock], - [\Magento\Quote\Model\ShippingFactory::class, $this->shippingFactoryMock], - ]); - - $this->model = new \Magento\Checkout\Model\ShippingInformationManagement( - $this->paymentMethodManagementMock, - $this->paymentDetailsFactoryMock, - $this->cartTotalsRepositoryMock, - $this->quoteRepositoryMock, - $this->addressValidatorMock, - $this->loggerMock, - $this->addressRepositoryMock, - $this->scopeConfigMock, - $this->totalsCollectorMock + $this->model = $this->objectManager->getObject( + \Magento\Checkout\Model\ShippingInformationManagement::class, + [ + 'paymentMethodManagement' => $this->paymentMethodManagementMock, + 'paymentDetailsFactory' => $this->paymentDetailsFactoryMock, + 'cartTotalsRepository' => $this->cartTotalsRepositoryMock, + 'quoteRepository' => $this->quoteRepositoryMock, + ] + ); + $this->objectManager->setBackwardCompatibleProperty( + $this->model, + 'shippingAssignmentFactory', + $this->shippingAssignmentFactoryMock + ); + $this->objectManager->setBackwardCompatibleProperty( + $this->model, + 'cartExtensionFactory', + $this->cartExtensionFactoryMock + ); + $this->objectManager->setBackwardCompatibleProperty( + $this->model, + 'shippingFactory', + $this->shippingFactoryMock ); } @@ -457,20 +433,4 @@ class ShippingInformationManagementTest extends \PHPUnit_Framework_TestCase $this->model->saveAddressInformation($cartId, $addressInformationMock) ); } - - /** - * @param array $map - */ - private function prepareObjectManager($map) - { - $objectManagerMock = $this->getMock(\Magento\Framework\ObjectManagerInterface::class); - $objectManagerMock->expects($this->any())->method('getInstance')->willReturnSelf(); - $objectManagerMock->expects($this->any()) - ->method('get') - ->will($this->returnValueMap($map)); - $reflectionClass = new \ReflectionClass(\Magento\Framework\App\ObjectManager::class); - $reflectionProperty = $reflectionClass->getProperty('_instance'); - $reflectionProperty->setAccessible(true); - $reflectionProperty->setValue($objectManagerMock); - } } diff --git a/app/code/Magento/Checkout/etc/di.xml b/app/code/Magento/Checkout/etc/di.xml index a2243b33a04edc0af4dc71ed79b802eac68f4cc2..81a430d52c49933cf70013f8856a96f5b6c26377 100644 --- a/app/code/Magento/Checkout/etc/di.xml +++ b/app/code/Magento/Checkout/etc/di.xml @@ -42,4 +42,11 @@ </argument> </arguments> </type> + <type name="Magento\Config\Model\Config\Export\ExcludeList"> + <arguments> + <argument name="configs" xsi:type="array"> + <item name="checkout/payment_failed/copy_to" xsi:type="string">1</item> + </argument> + </arguments> + </type> </config> diff --git a/app/code/Magento/Checkout/etc/frontend/di.xml b/app/code/Magento/Checkout/etc/frontend/di.xml index 6fb9058c3b7681c8905a40a5eace5d88d8566b6f..69ed33721740d680ec6662e43858e9c42a1c6629 100644 --- a/app/code/Magento/Checkout/etc/frontend/di.xml +++ b/app/code/Magento/Checkout/etc/frontend/di.xml @@ -55,6 +55,7 @@ <argument name="layoutProcessors" xsi:type="array"> <item name="addressFormAttributes" xsi:type="object">Magento\Checkout\Block\Checkout\LayoutProcessor</item> <item name="totalsSortOrder" xsi:type="object">Magento\Checkout\Block\Checkout\TotalsProcessor</item> + <item name="directoryData" xsi:type="object">Magento\Checkout\Block\Checkout\DirectoryDataProcessor</item> </argument> </arguments> </type> diff --git a/app/code/Magento/Checkout/view/frontend/web/js/model/new-customer-address.js b/app/code/Magento/Checkout/view/frontend/web/js/model/new-customer-address.js index 9a3685b212b435e8c03adb7be2cd7a182e591b87..c215b1989edbeafe273819b09f2588f06169b4e5 100644 --- a/app/code/Magento/Checkout/view/frontend/web/js/model/new-customer-address.js +++ b/app/code/Magento/Checkout/view/frontend/web/js/model/new-customer-address.js @@ -10,13 +10,13 @@ define([], function () { * Returns new address object */ return function (addressData) { - var identifier = Date.now(); - var regionId = null; + var identifier = Date.now(), + regionId; if (addressData.region && addressData.region.region_id) { regionId = addressData.region.region_id; } else if (addressData.country_id && addressData.country_id == window.checkoutConfig.defaultCountryId) { - regionId = window.checkoutConfig.defaultRegionId; + regionId = window.checkoutConfig.defaultRegionId || undefined; } return { @@ -25,7 +25,7 @@ define([], function () { regionId: regionId || addressData.regionId, regionCode: (addressData.region) ? addressData.region.region_code : null, region: (addressData.region) ? addressData.region.region : null, - customerId: addressData.customer_id, + customerId: addressData.customer_id || addressData.customerId, street: addressData.street, company: addressData.company, telephone: addressData.telephone, diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/cart/shipping-estimation.js b/app/code/Magento/Checkout/view/frontend/web/js/view/cart/shipping-estimation.js index 08641f015f609a9b8c75e80e0cfd39a82a6f5b1e..cd43dc646584d52708f3923c042889fdb20e0d82 100644 --- a/app/code/Magento/Checkout/view/frontend/web/js/view/cart/shipping-estimation.js +++ b/app/code/Magento/Checkout/view/frontend/web/js/view/cart/shipping-estimation.js @@ -50,9 +50,13 @@ define( if (address) { estimatedAddress = address.isEditable() ? addressConverter.quoteAddressToFormAddressData(address) : - addressConverter.quoteAddressToFormAddressData( - addressConverter.addressToEstimationAddress(address) - ); + { + // only the following fields must be used by estimation form data provider + 'country_id': address.countryId, + region: address.region, + 'region_id': address.regionId, + postcode: address.postcode + }; checkoutProvider.set( 'shippingAddress', $.extend({}, checkoutProvider.get('shippingAddress'), estimatedAddress) diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/shipping.js b/app/code/Magento/Checkout/view/frontend/web/js/view/shipping.js index 8910e41731d11a9be99bf1777dc13e3550781976..fb15e47eaf7d487da1c8671c545f0b99ce2a7445 100644 --- a/app/code/Magento/Checkout/view/frontend/web/js/view/shipping.js +++ b/app/code/Magento/Checkout/view/frontend/web/js/view/shipping.js @@ -79,7 +79,6 @@ define( fieldsetName = 'checkout.steps.shipping-step.shippingAddress.shipping-address-fieldset'; this._super(); - shippingRatesValidator.initFields(fieldsetName); if (!quote.isVirtual()) { stepNavigator.registerStep( @@ -120,6 +119,7 @@ define( checkoutProvider.on('shippingAddress', function (shippingAddressData) { checkoutData.setShippingAddressFromData(shippingAddressData); }); + shippingRatesValidator.initFields(fieldsetName); }); return this; diff --git a/app/code/Magento/Checkout/view/frontend/web/template/billing-address/details.html b/app/code/Magento/Checkout/view/frontend/web/template/billing-address/details.html index da625c51d4b7734ccc4808fd9161502e15acf1a9..798be1f978f54e3cd7e4c51bfb0e3e20e8ae82e2 100644 --- a/app/code/Magento/Checkout/view/frontend/web/template/billing-address/details.html +++ b/app/code/Magento/Checkout/view/frontend/web/template/billing-address/details.html @@ -15,7 +15,12 @@ <!-- /ko --><br/> <!-- ko foreach: { data: currentBillingAddress().customAttributes, as: 'element' } --> <!-- ko foreach: { data: Object.keys(element), as: 'attribute' } --> - <!-- ko text: element[attribute].value --><!-- /ko --> + <!-- ko if: (typeof element[attribute] === "object") --> + <!-- ko text: element[attribute].value --><!-- /ko --> + <!-- /ko --> + <!-- ko if: (typeof element[attribute] === "string") --> + <!-- ko text: element[attribute] --><!-- /ko --> + <!-- /ko --><br/> <!-- /ko --> <!-- /ko --> <button type="button" diff --git a/app/code/Magento/Checkout/view/frontend/web/template/shipping-address/address-renderer/default.html b/app/code/Magento/Checkout/view/frontend/web/template/shipping-address/address-renderer/default.html index a2b83ead6b354451b99a4a1003a0f04df905dbbc..92469fdec3d7fcc8660d7d5a385cfa9c28c18252 100644 --- a/app/code/Magento/Checkout/view/frontend/web/template/shipping-address/address-renderer/default.html +++ b/app/code/Magento/Checkout/view/frontend/web/template/shipping-address/address-renderer/default.html @@ -15,7 +15,12 @@ <!-- /ko --><br/> <!-- ko foreach: { data: address().customAttributes, as: 'element' } --> <!-- ko foreach: { data: Object.keys(element), as: 'attribute' } --> - <!-- ko text: element[attribute].value --><!-- /ko --> + <!-- ko if: (typeof element[attribute] === "object") --> + <!-- ko text: element[attribute].value --><!-- /ko --> + <!-- /ko --> + <!-- ko if: (typeof element[attribute] === "string") --> + <!-- ko text: element[attribute] --><!-- /ko --> + <!-- /ko --><br/> <!-- /ko --> <!-- /ko --> <!-- ko if: (address().isEditable()) --> diff --git a/app/code/Magento/Checkout/view/frontend/web/template/shipping-information/address-renderer/default.html b/app/code/Magento/Checkout/view/frontend/web/template/shipping-information/address-renderer/default.html index 440a2c7fc468fc493d10eb0cb57320c5593e1bf8..36ea556ae9ec95f09496094771a1340305ffdd43 100644 --- a/app/code/Magento/Checkout/view/frontend/web/template/shipping-information/address-renderer/default.html +++ b/app/code/Magento/Checkout/view/frontend/web/template/shipping-information/address-renderer/default.html @@ -15,7 +15,12 @@ <!-- /ko --><br/> <!-- ko foreach: { data: address().customAttributes, as: 'element' } --> <!-- ko foreach: { data: Object.keys(element), as: 'attribute' } --> - <!-- ko text: element[attribute].value --><!-- /ko --> + <!-- ko if: (typeof element[attribute] === "object") --> + <!-- ko text: element[attribute].value --><!-- /ko --> + <!-- /ko --> + <!-- ko if: (typeof element[attribute] === "string") --> + <!-- ko text: element[attribute] --><!-- /ko --> + <!-- /ko --><br/> <!-- /ko --> <!-- /ko --> <!-- /ko --> diff --git a/app/code/Magento/Checkout/view/frontend/web/template/summary/cart-items.html b/app/code/Magento/Checkout/view/frontend/web/template/summary/cart-items.html index ed7ad193a12fde35dd2226afdf11f1233887afd8..498a9f852d06be2cc5787091aca7b641b7a45e8a 100644 --- a/app/code/Magento/Checkout/view/frontend/web/template/summary/cart-items.html +++ b/app/code/Magento/Checkout/view/frontend/web/template/summary/cart-items.html @@ -4,8 +4,7 @@ * See COPYING.txt for license details. */ --> -<!-- ko ifnot: isItemsBlockExpanded() --> -<div class="block items-in-cart" data-bind="mageInit: {'collapsible':{'openedState': 'active'}}"> +<div class="block items-in-cart" data-bind="mageInit: {'collapsible':{'openedState': 'active', 'active': isItemsBlockExpanded()}}"> <div class="title" data-role="title"> <strong role="heading"><span data-bind="text: getItemsQty()"></span> <!-- ko if: getItemsQty() == 1 --> @@ -32,33 +31,3 @@ </div> </div> </div> -<!-- /ko --> -<!-- ko if: isItemsBlockExpanded() --> -<div class="block items-in-cart" data-bind="mageInit: {'collapsible':{'openedState': 'active', 'active': true}}"> - <div class="title" data-role="title"> - <strong role="heading"><span data-bind="text: getItemsQty()"></span> - <!-- ko if: getItemsQty() == 1 --> - <!-- ko i18n: 'Item in Cart' --><!-- /ko --> - <!-- /ko --> - <!-- ko if: getItemsQty() > 1 --> - <!-- ko i18n: 'Items in Cart' --><!-- /ko --> - <!-- /ko --> - </strong> - </div> - <div class="content minicart-items" data-role="content"> - <div class="minicart-items-wrapper overflowed"> - <ol class="minicart-items"> - <!-- ko foreach: getItems() --> - <li class="product-item"> - <div class="product"> - <!-- ko foreach: $parent.elems() --> - <!-- ko template: getTemplate() --><!-- /ko --> - <!-- /ko --> - </div> - </li> - <!-- /ko --> - </ol> - </div> - </div> -</div> -<!-- /ko --> 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/DumpConfigSourceAggregated.php b/app/code/Magento/Config/App/Config/Source/DumpConfigSourceAggregated.php new file mode 100644 index 0000000000000000000000000000000000000000..80567d0504ee9c31d8cadef957c1d12dad9f1508 --- /dev/null +++ b/app/code/Magento/Config/App/Config/Source/DumpConfigSourceAggregated.php @@ -0,0 +1,152 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Config\App\Config\Source; + +use Magento\Config\Model\Config\Export\ExcludeList; +use Magento\Framework\App\Config\ConfigSourceInterface; +use Magento\Framework\App\Config\ScopeConfigInterface; + +/** + * Class DumpConfigSourceAggregated aggregates configurations from all available sources + */ +class DumpConfigSourceAggregated implements DumpConfigSourceInterface +{ + /** + * @var ExcludeList + */ + private $excludeList; + + /** + * @var ConfigSourceInterface[] + */ + private $sources; + + /** + * @var array + */ + private $excludedFields; + + /** + * @var array + */ + private $data; + + /** + * @param ExcludeList $excludeList + * @param array $sources + */ + public function __construct(ExcludeList $excludeList, array $sources = []) + { + $this->excludeList = $excludeList; + $this->sources = $sources; + } + + /** + * Retrieve aggregated configuration from all available sources. + * + * @param string $path + * @return array + */ + public function get($path = '') + { + $path = (string)$path; + $data = []; + + if (isset($this->data[$path])) { + return $this->data[$path]; + } + + $this->sortSources(); + + foreach ($this->sources as $sourceConfig) { + /** @var ConfigSourceInterface $source */ + $source = $sourceConfig['source']; + $data = array_replace_recursive($data, $source->get($path)); + } + + $this->excludedFields = []; + $this->filterChain($path, $data); + + return $this->data[$path] = $data; + } + + /** + * Recursive filtering of sensitive data + * + * @param string $path + * @param array $data + * @return void + */ + private function filterChain($path, &$data) + { + foreach ($data as $subKey => &$subData) { + $newPath = $path ? $path . '/' . $subKey : $subKey; + $filteredPath = $this->filterPath($newPath); + + if ( + $filteredPath + && !is_array($data[$subKey]) + && $this->excludeList->isPresent($filteredPath) + ) { + $this->excludedFields[$newPath] = $filteredPath; + + unset($data[$subKey]); + } elseif (is_array($subData)) { + $this->filterChain($newPath, $subData); + } + } + } + + /** + * Eliminating scope info from path + * + * @param string $path + * @return null|string + */ + private function filterPath($path) + { + $parts = explode('/', $path); + + // Check if there are enough parts to recognize scope + if (count($parts) < 3) { + return null; + } + + if ($parts[0] === ScopeConfigInterface::SCOPE_TYPE_DEFAULT) { + unset($parts[0]); + } else { + unset($parts[0], $parts[1]); + } + + return implode('/', $parts); + } + + /** + * Sort sources ASC from higher priority to lower + * + * @return void + */ + private function sortSources() + { + uasort($this->sources, function ($firstItem, $secondItem) { + return $firstItem['sortOrder'] > $secondItem['sortOrder']; + }); + } + + /** + * Retrieves list of field paths were excluded from config dump + * @return array + */ + public function getExcludedFields() + { + $this->get(); + + $fields = array_values($this->excludedFields); + $fields = array_unique($fields); + + return $fields; + } +} diff --git a/app/code/Magento/Config/App/Config/Source/DumpConfigSourceInterface.php b/app/code/Magento/Config/App/Config/Source/DumpConfigSourceInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..cf0ce492b7d5265a5445a3fbe3f4e6d68ec384a4 --- /dev/null +++ b/app/code/Magento/Config/App/Config/Source/DumpConfigSourceInterface.php @@ -0,0 +1,21 @@ +<?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; + +/** + * Interface DumpConfigSourceInterface + */ +interface DumpConfigSourceInterface extends ConfigSourceInterface +{ + /** + * Retrieves list of field paths were excluded from config dump + * + * @return array + */ + public function getExcludedFields(); +} 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..a0fc0f1f10ebdfbbcd78695ee223e48efdd21b7a --- /dev/null +++ b/app/code/Magento/Config/App/Config/Type/System.php @@ -0,0 +1,128 @@ +<?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\DataObject; + +/** + * Class process source, cache them and retrieve value by path + */ +class System implements ConfigTypeInterface +{ + const CACHE_TAG = 'config_scopes'; + + const CONFIG_TYPE = 'system'; + + /** + * @var \Magento\Framework\App\Config\ConfigSourceInterface + */ + private $source; + + /** + * @var DataObject[] + */ + private $data; + + /** + * @var \Magento\Framework\App\Config\Spi\PostProcessorInterface + */ + private $postProcessor; + + /** + * @var \Magento\Framework\App\Config\Spi\PreProcessorInterface + */ + private $preProcessor; + + /** + * @var \Magento\Framework\Cache\FrontendInterface + */ + private $cache; + + /** + * @var int + */ + private $cachingNestedLevel; + + /** + * @var \Magento\Store\Model\Config\Processor\Fallback + */ + private $fallback; + + /** + * @var \Magento\Framework\Serialize\SerializerInterface + */ + private $serializer; + + /** + * @param \Magento\Framework\App\Config\ConfigSourceInterface $source + * @param \Magento\Framework\App\Config\Spi\PostProcessorInterface $postProcessor + * @param \Magento\Store\Model\Config\Processor\Fallback $fallback + * @param \Magento\Framework\Cache\FrontendInterface $cache + * @param \Magento\Framework\Serialize\SerializerInterface $serializer + * @param \Magento\Framework\App\Config\Spi\PreProcessorInterface $preProcessor + * @param int $cachingNestedLevel + */ + public function __construct( + \Magento\Framework\App\Config\ConfigSourceInterface $source, + \Magento\Framework\App\Config\Spi\PostProcessorInterface $postProcessor, + \Magento\Store\Model\Config\Processor\Fallback $fallback, + \Magento\Framework\Cache\FrontendInterface $cache, + \Magento\Framework\Serialize\SerializerInterface $serializer, + \Magento\Framework\App\Config\Spi\PreProcessorInterface $preProcessor, + $cachingNestedLevel = 1 + ) { + $this->source = $source; + $this->postProcessor = $postProcessor; + $this->preProcessor = $preProcessor; + $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->preProcessor->process($this->source->get()); + $this->data = new DataObject($data); + $data = $this->fallback->process($data); + $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..f0ad7e4a28b1a365b6596f7175ae34434e09e59c 100644 --- a/app/code/Magento/Config/Block/System/Config/Form.php +++ b/app/code/Magento/Config/Block/System/Config/Form.php @@ -5,6 +5,13 @@ */ 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\Config\ScopeConfigInterface; +use Magento\Framework\App\DeploymentConfig; +use Magento\Framework\App\ObjectManager; +use Magento\Framework\DataObject; + /** * System config form block * @@ -96,6 +103,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 +146,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 * @@ -304,27 +333,9 @@ class Form extends \Magento\Backend\Block\Widget\Form\Generic $fieldPrefix = '', $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(); - } - - } elseif ($field->getConfigPath() !== null) { - $data = $this->getConfigValue($field->getConfigPath()); - } else { - $data = $this->getConfigValue($path); - } + $inherit = !array_key_exists($path, $this->_configData); + $data = $this->getFieldData($field, $path); + $fieldRendererClass = $field->getFrontendModel(); if ($fieldRendererClass) { $fieldRenderer = $this->_layout->getBlockSingleton($fieldRendererClass); @@ -344,6 +355,7 @@ 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->getStringScopeCode()); $formField = $fieldset->addField( $elementId, $field->getType(), @@ -362,7 +374,9 @@ class Form extends \Magento\Backend\Block\Widget\Form\Generic '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_restore_to_default' => $this->isCanRestoreToDefault($field->canRestore()), + 'disabled' => $isReadOnly, + 'is_disable_inheritance' => $isReadOnly ] ); $field->populateInput($formField); @@ -379,6 +393,74 @@ class Form extends \Magento\Backend\Block\Widget\Form\Generic $formField->setRenderer($fieldRenderer); } + /** + * Get data of field by path + * + * @param \Magento\Config\Model\Config\Structure\Element\Field $field + * @param string $path + * @return mixed|null|string + */ + private function getFieldData(\Magento\Config\Model\Config\Structure\Element\Field $field, $path) + { + $data = $this->getAppConfigDataValue($path); + + $placeholderValue = $this->getSettingChecker()->getPlaceholderValue( + $path, + $this->getScope(), + $this->getStringScopeCode() + ); + + if ($placeholderValue) { + $data = $placeholderValue; + } + if ($data === null) { + if (array_key_exists($path, $this->_configData)) { + $data = $this->_configData[$path]; + + 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); + } + } + + return $data; + } + + /** + * Retrieve Scope string code + * + * @return string + */ + private function getStringScopeCode() + { + $scopeCode = $this->getData('scope_string_code'); + + if (null === $scopeCode) { + if ($this->getStoreCode()) { + $scopeCode = $this->_storeManager->getStore($this->getStoreCode())->getCode(); + } elseif ($this->getWebsiteCode()) { + $scopeCode = $this->_storeManager->getWebsite($this->getWebsiteCode())->getCode(); + } else { + $scopeCode = ''; + } + + $this->setData('scope_string_code', $scopeCode); + } + + return $scopeCode; + } + /** * Populate dependencies block * @@ -689,4 +771,38 @@ 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(); + $scopeCode = $this->getStringScopeCode(); + + if ($scope === ScopeConfigInterface::SCOPE_TYPE_DEFAULT) { + $data = new DataObject(isset($appConfig[$scope]) ? $appConfig[$scope] : []); + } else { + $data = new DataObject(isset($appConfig[$scope][$scopeCode]) ? $appConfig[$scope][$scopeCode] : []); + } + return $data->getData($path); + } } 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/Export/Comment.php b/app/code/Magento/Config/Model/Config/Export/Comment.php new file mode 100644 index 0000000000000000000000000000000000000000..ae0431c82daa031523f464ea1539209ca324996c --- /dev/null +++ b/app/code/Magento/Config/Model/Config/Export/Comment.php @@ -0,0 +1,59 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Config\Model\Config\Export; + +use Magento\Config\App\Config\Source\DumpConfigSourceInterface; +use Magento\Config\Model\Placeholder\PlaceholderFactory; +use Magento\Config\Model\Placeholder\PlaceholderInterface; +use Magento\Framework\App\Config\CommentInterface; + +/** + * Class Comment. Is used to retrieve comment for config dump file + */ +class Comment implements CommentInterface +{ + /** + * @var PlaceholderInterface + */ + private $placeholder; + + /** + * @var DumpConfigSourceInterface + */ + private $source; + + /** + * @param PlaceholderFactory $placeholderFactory + * @param DumpConfigSourceInterface $source + */ + public function __construct( + PlaceholderFactory $placeholderFactory, + DumpConfigSourceInterface $source + ) { + $this->placeholder = $placeholderFactory->create(PlaceholderFactory::TYPE_ENVIRONMENT); + $this->source = $source; + } + + /** + * Retrieves comments for config export file. + * + * @return string + */ + public function get() + { + $comment = ''; + $fields = $this->source->getExcludedFields(); + foreach ($fields as $path) { + $comment .= "\n" . $this->placeholder->generate($path) . ' for ' . $path ; + } + if ($comment) { + $comment = 'The configuration file doesn\'t contain sensitive data for security reasons. ' + . 'Sensitive data can be stored in the following environment variables:' + . $comment; + } + return $comment; + } +} diff --git a/app/code/Magento/Config/Model/Config/Export/ExcludeList.php b/app/code/Magento/Config/Model/Config/Export/ExcludeList.php new file mode 100644 index 0000000000000000000000000000000000000000..f3c10b4100ed3a068b56873553c96e2e5852073b --- /dev/null +++ b/app/code/Magento/Config/Model/Config/Export/ExcludeList.php @@ -0,0 +1,55 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Config\Model\Config\Export; + +use Magento\Framework\App\Config\ScopeConfigInterface; + +/** + * Class ExcludeList contains list of config fields which should be excluded from config export file + */ +class ExcludeList +{ + /** + * @var array + */ + private $configs; + + /** + * @param array $configs + */ + public function __construct(array $configs = []) + { + $this->configs = $configs; + } + + /** + * Check whether config item is excluded from export + * + * @param string $path + * @return bool + */ + public function isPresent($path) + { + return !empty($this->configs[$path]) ; + } + + /** + * Retrieves all excluded field paths for export + * + * @return array + */ + public function get() + { + return array_keys( + array_filter( + $this->configs, + function ($value) { + return filter_var($value, FILTER_VALIDATE_BOOLEAN); + } + ) + ); + } +} 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/Processor/EnvironmentPlaceholder.php b/app/code/Magento/Config/Model/Config/Processor/EnvironmentPlaceholder.php new file mode 100644 index 0000000000000000000000000000000000000000..efbe888f2ebd62e0376e567e4046080af6ba8658 --- /dev/null +++ b/app/code/Magento/Config/Model/Config/Processor/EnvironmentPlaceholder.php @@ -0,0 +1,70 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Config\Model\Config\Processor; + +use Magento\Config\Model\Placeholder\PlaceholderFactory; +use Magento\Config\Model\Placeholder\PlaceholderInterface; +use Magento\Framework\App\Config\Spi\PreProcessorInterface; +use Magento\Framework\Stdlib\ArrayManager; + +/** + * Allows to extract configurations from environment variables. + */ +class EnvironmentPlaceholder implements PreProcessorInterface +{ + /** + * @var PlaceholderFactory + */ + private $placeholderFactory; + + /** + * @var ArrayManager + */ + private $arrayManager; + + /** + * @var PlaceholderInterface + */ + private $placeholder; + + /** + * @param PlaceholderFactory $placeholderFactory + * @param ArrayManager $arrayManager + */ + public function __construct( + PlaceholderFactory $placeholderFactory, + ArrayManager $arrayManager + ) { + $this->placeholderFactory = $placeholderFactory; + $this->arrayManager = $arrayManager; + $this->placeholder = $placeholderFactory->create(PlaceholderFactory::TYPE_ENVIRONMENT); + } + + /** + * Method extracts environment variables. + * If environment variable is matching the desired rule - it's being used as value. + * + * {@inheritdoc} + */ + public function process(array $config) + { + $environmentVariables = $_ENV; + + foreach ($environmentVariables as $template => $value) { + if (!$this->placeholder->isApplicable($template)) { + continue; + } + + $config = $this->arrayManager->set( + $this->placeholder->restore($template), + $config, + $value + ); + } + + return $config; + } +} 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..7e673401c7348c0721d917b5417c9940ceae16e3 --- /dev/null +++ b/app/code/Magento/Config/Model/Config/Reader/Source/Deployed/SettingChecker.php @@ -0,0 +1,119 @@ +<?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\ScopeConfigInterface; +use Magento\Framework\App\DeploymentConfig; +use Magento\Config\Model\Placeholder\PlaceholderInterface; +use Magento\Config\Model\Placeholder\PlaceholderFactory; +use Magento\Framework\App\Config\ScopeCodeResolver; + +/** + * Class for checking settings that defined in config file + */ +class SettingChecker +{ + /** + * @var DeploymentConfig + */ + private $config; + + /** + * @var PlaceholderInterface + */ + private $placeholder; + + /** + * @var ScopeCodeResolver + */ + private $scopeCodeResolver; + + /** + * @param DeploymentConfig $config + * @param PlaceholderFactory $placeholderFactory + * @param ScopeCodeResolver $scopeCodeResolver + */ + public function __construct( + DeploymentConfig $config, + PlaceholderFactory $placeholderFactory, + ScopeCodeResolver $scopeCodeResolver + ) { + $this->config = $config; + $this->scopeCodeResolver = $scopeCodeResolver; + $this->placeholder = $placeholderFactory->create(PlaceholderFactory::TYPE_ENVIRONMENT); + } + + /** + * Check that setting defined in deployed configuration + * + * @param string $path + * @param string $scope + * @param string|null $scopeCode + * @return boolean + */ + public function isReadOnly($path, $scope, $scopeCode = null) + { + $config = $this->getEnvValue( + $this->placeholder->generate($path, $scope, $scopeCode) + ); + + if (null === $config) { + $config = $this->config->get($this->resolvePath($scope, $scopeCode) . "/" . $path); + } + + return $config !== null; + } + + /** + * Check that there is value for generated placeholder + * + * Placeholder is generated from values of $path, $scope and $scopeCode + * + * @param string $path + * @param string $scope + * @param string $scopeCode + * @param string|null $scopeCode + * @return string|null + */ + public function getPlaceholderValue($path, $scope, $scopeCode = null) + { + return $this->getEnvValue($this->placeholder->generate($path, $scope, $scopeCode)); + } + + /** + * Retrieve value of environment variable by placeholder + * + * @param string $placeholder + * @return string|null + */ + public function getEnvValue($placeholder) + { + if ($this->placeholder->isApplicable($placeholder) && isset($_ENV[$placeholder])) { + return $_ENV[$placeholder]; + } + + return null; + } + + /** + * 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; + } +} diff --git a/app/code/Magento/Config/Model/Config/Structure/Data.php b/app/code/Magento/Config/Model/Config/Structure/Data.php index 414addf5b6f06ba4518897f0f7c6440156863bb7..6c926e7c1da1a79e8043944117b6230e5bf5517d 100644 --- a/app/code/Magento/Config/Model/Config/Structure/Data.php +++ b/app/code/Magento/Config/Model/Config/Structure/Data.php @@ -5,21 +5,30 @@ */ namespace Magento\Config\Model\Config\Structure; +use Magento\Framework\Serialize\SerializerInterface; + +/** + * Provides configuration + */ class Data extends \Magento\Framework\Config\Data\Scoped { /** + * Constructor + * * @param Reader $reader * @param \Magento\Framework\Config\ScopeInterface $configScope * @param \Magento\Framework\Config\CacheInterface $cache * @param string $cacheId + * @param SerializerInterface|null $serializer */ public function __construct( Reader $reader, \Magento\Framework\Config\ScopeInterface $configScope, \Magento\Framework\Config\CacheInterface $cache, - $cacheId + $cacheId, + SerializerInterface $serializer = null ) { - parent::__construct($reader, $configScope, $cache, $cacheId); + parent::__construct($reader, $configScope, $cache, $cacheId, $serializer); } /** diff --git a/app/code/Magento/Config/Model/Placeholder/Environment.php b/app/code/Magento/Config/Model/Placeholder/Environment.php new file mode 100644 index 0000000000000000000000000000000000000000..96ffadc96c6f9a958ebc61e6626bcc02ac178237 --- /dev/null +++ b/app/code/Magento/Config/Model/Placeholder/Environment.php @@ -0,0 +1,76 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Config\Model\Placeholder; + +use Magento\Framework\App\Config\ScopeConfigInterface; +use Magento\Framework\App\DeploymentConfig; + +/** + * Class is used to work with placeholders for environment variables names based on config paths + */ +class Environment implements PlaceholderInterface +{ + /** + * @const string Prefix for placeholder + */ + const PREFIX = 'CONFIG__'; + + /** + * @var DeploymentConfig + */ + private $deploymentConfig; + + /** + * @param DeploymentConfig $deploymentConfig + */ + public function __construct(DeploymentConfig $deploymentConfig) + { + $this->deploymentConfig = $deploymentConfig; + } + + /** + * Generates placeholder like CONFIG__DEFAULT__TEST__TEST_VALUE + * + * @inheritdoc + */ + public function generate($path, $scopeType = ScopeConfigInterface::SCOPE_TYPE_DEFAULT, $scopeCode = null) + { + $parts = $scopeType ? [$scopeType] : []; + + if ($scopeType !== ScopeConfigInterface::SCOPE_TYPE_DEFAULT && $scopeCode) { + $parts[] = $scopeCode; + } + + $parts[] = $path; + + $template = implode('__', $parts); + $template = str_replace('/', '__', $template); + $template = static::PREFIX . $template; + $template = strtoupper($template); + + return $template; + } + + /** + * @inheritdoc + */ + public function restore($template) + { + $template = preg_replace('/^' . static::PREFIX . '/', '', $template); + $template = str_replace('__', '/', $template); + $template = strtolower($template); + + return $template; + } + + /** + * @inheritdoc + */ + public function isApplicable($placeholder) + { + return 1 === preg_match('/^' . static::PREFIX . '([a-zA-Z]+)([a-zA-Z0-9_])*$/', $placeholder); + } +} diff --git a/app/code/Magento/Config/Model/Placeholder/PlaceholderFactory.php b/app/code/Magento/Config/Model/Placeholder/PlaceholderFactory.php new file mode 100644 index 0000000000000000000000000000000000000000..3f88bc2a289c4b32e47f24ef43223a868ea99267 --- /dev/null +++ b/app/code/Magento/Config/Model/Placeholder/PlaceholderFactory.php @@ -0,0 +1,59 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Config\Model\Placeholder; + +use Magento\Framework\Exception\LocalizedException; +use Magento\Framework\ObjectManagerInterface; + +class PlaceholderFactory +{ + /** + * @const string Environment type + */ + const TYPE_ENVIRONMENT = 'environment'; + + /** + * @var ObjectManagerInterface + */ + private $objectManager; + + /** + * @var array + */ + private $types; + + /** + * @param ObjectManagerInterface $objectManager + * @param array $types + */ + public function __construct(ObjectManagerInterface $objectManager, array $types = []) + { + $this->objectManager = $objectManager; + $this->types = $types; + } + + /** + * Create placeholder + * + * @param string $type + * @return PlaceholderInterface + * @throws LocalizedException + */ + public function create($type) + { + if (!isset($this->types[$type])) { + throw new LocalizedException(__('There is no defined type ' . $type)); + } + + $object = $this->objectManager->create($this->types[$type]); + + if (!$object instanceof PlaceholderInterface) { + throw new LocalizedException(__('Object is not instance of ' . PlaceholderInterface::class)); + } + + return $object; + } +} diff --git a/app/code/Magento/Config/Model/Placeholder/PlaceholderInterface.php b/app/code/Magento/Config/Model/Placeholder/PlaceholderInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..286eb0034a55063b8dcbf35cc13474ef144fd656 --- /dev/null +++ b/app/code/Magento/Config/Model/Placeholder/PlaceholderInterface.php @@ -0,0 +1,40 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Config\Model\Placeholder; + +use Magento\Framework\App\Config\ScopeConfigInterface; + +/** + * Interface PlaceholderInterface + */ +interface PlaceholderInterface +{ + /** + * Generating placeholder from value + * + * @param string $path + * @param string $scopeType + * @param string $scopeCode + * @return string + */ + public function generate($path, $scopeType = ScopeConfigInterface::SCOPE_TYPE_DEFAULT, $scopeCode = null); + + /** + * Restoring path parts from template. + * + * @param string $template + * @return string + */ + public function restore($template); + + /** + * Check whether provided string is placeholder + * + * @param string $placeholder + * @return bool + */ + public function isApplicable($placeholder); +} diff --git a/app/code/Magento/Config/Test/Unit/App/Config/Source/DumpConfigSourceAggregatedTest.php b/app/code/Magento/Config/Test/Unit/App/Config/Source/DumpConfigSourceAggregatedTest.php new file mode 100644 index 0000000000000000000000000000000000000000..9c6aef37540e5d69f071b8f4f9ccb465f69233ff --- /dev/null +++ b/app/code/Magento/Config/Test/Unit/App/Config/Source/DumpConfigSourceAggregatedTest.php @@ -0,0 +1,171 @@ +<?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\DumpConfigSourceAggregated; +use Magento\Config\Model\Config\Export\ExcludeList; +use Magento\Framework\App\Config\ConfigSourceInterface; + +class DumpConfigSourceAggregatedTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var ConfigSourceInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $sourceMock; + + /** + * @var ConfigSourceInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $sourceMockTwo; + + /** + * @var DumpConfigSourceAggregated + */ + private $model; + + /** + * @var ExcludeList|\PHPUnit_Framework_MockObject_MockObject + */ + private $excludeListMock; + + public function setUp() + { + $this->sourceMock = $this->getMockBuilder(ConfigSourceInterface::class) + ->getMockForAbstractClass(); + $this->sourceMockTwo = $this->getMockBuilder(ConfigSourceInterface::class) + ->getMockForAbstractClass(); + $this->excludeListMock = $this->getMockBuilder(ExcludeList::class) + ->disableOriginalConstructor() + ->getMock(); + + $sources = [ + [ + 'source' => $this->sourceMockTwo, + 'sortOrder' => 100 + ], + [ + 'source' => $this->sourceMock, + 'sortOrder' => 10 + ], + + ]; + + $this->model = new DumpConfigSourceAggregated($this->excludeListMock, $sources); + } + + public function testGet() + { + $path = ''; + $data = [ + 'default' => [ + 'web' => [ + 'unsecure' => [ + 'base_url' => 'http://test.local', + ], + 'secure' => [ + 'base_url' => 'https://test.local', + ] + ] + ], + 'test' => [ + 'test' => [ + 'test1' => [ + 'test2' => [ + 'test3' => 5, + ] + ] + ] + ] + ]; + + $this->sourceMock->expects($this->once()) + ->method('get') + ->with($path) + ->willReturn($data); + $this->sourceMockTwo->expects($this->once()) + ->method('get') + ->with($path) + ->willReturn(['key' => 'value2']); + $this->excludeListMock->expects($this->any()) + ->method('isPresent') + ->willReturnMap([ + ['web/unsecure/base_url', false], + ['web/secure/base_url', true], + ['test1/test2/test/3', false] + ]); + + $this->assertEquals( + [ + 'test' => [ + 'test' => [ + 'test1' => [ + 'test2' => [ + 'test3' => 5, + ] + ] + ], + ], + 'key' => 'value2', + 'default' => [ + 'web' => [ + 'unsecure' => [ + 'base_url' => 'http://test.local', + ], + 'secure' => [] + ] + ], + ], + $this->model->get($path) + ); + } + + public function testGetExcludedFields() + { + $path = ''; + $data = [ + 'default' => [ + 'web' => [ + 'unsecure' => [ + 'base_url' => 'http://test.local', + ], + 'secure' => [ + 'base_url' => 'https://test.local', + ] + ] + ], + 'test' => [ + 'test' => [ + 'test1' => [ + 'test2' => [ + 'test3' => 5, + ] + ] + ] + ] + ]; + + $this->sourceMock->expects($this->once()) + ->method('get') + ->with($path) + ->willReturn($data); + $this->sourceMockTwo->expects($this->once()) + ->method('get') + ->with($path) + ->willReturn(['key' => 'value2']); + $this->excludeListMock->expects($this->any()) + ->method('isPresent') + ->willReturnMap([ + ['web/unsecure/base_url', false], + ['web/secure/base_url', true], + ['test1/test2/test/3', false] + ]); + + $this->assertEquals( + ['web/secure/base_url'], + $this->model->getExcludedFields() + ); + } +} 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..8409e96db552e61a8ee3a8a4ec788d457d84ba5c --- /dev/null +++ b/app/code/Magento/Config/Test/Unit/App/Config/Type/SystemTest.php @@ -0,0 +1,153 @@ +<?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\Config\Spi\PreProcessorInterface; +use Magento\Framework\Cache\FrontendInterface; +use Magento\Framework\Serialize\SerializerInterface; +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 PreProcessorInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $preProcessor; + + /** + * @var Fallback|\PHPUnit_Framework_MockObject_MockObject + */ + private $fallback; + + /** + * @var FrontendInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $cache; + + /** + * @var System + */ + private $configType; + + /** + * @var SerializerInterface|\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->preProcessor = $this->getMockBuilder(PreProcessorInterface::class) + ->getMockForAbstractClass(); + $this->serializer = $this->getMockBuilder(SerializerInterface::class) + ->disableOriginalConstructor() + ->getMock(); + $this->configType = new System( + $this->source, + $this->postProcessor, + $this->fallback, + $this->cache, + $this->serializer, + $this->preProcessor + ); + } + + /** + * @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->preProcessor->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..5c7bf92f954285571bc6620a1726d2ccfd9432f4 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,16 @@ namespace Magento\Config\Test\Unit\Block\System\Config; +use Magento\Config\Model\Config\Reader\Source\Deployed\SettingChecker; +use Magento\Framework\App\DeploymentConfig; +use Magento\Store\Model\StoreManagerInterface; + +/** + * Test System config form block + * + * @package Magento\Config\Test\Unit\Block\System\Config + */ + /** * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ @@ -63,6 +73,11 @@ class FormTest extends \PHPUnit_Framework_TestCase */ protected $_fieldsetFactoryMock; + /** + * @var StoreManagerInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $storeManagerMock; + /** * @return void * @SuppressWarnings(PHPMD.ExcessiveMethodLength) @@ -152,6 +167,9 @@ class FormTest extends \PHPUnit_Framework_TestCase false ); + $this->storeManagerMock = $this->getMockBuilder(StoreManagerInterface::class) + ->getMockForAbstractClass(); + $helper = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); $context = $helper->getObject( @@ -159,7 +177,8 @@ class FormTest extends \PHPUnit_Framework_TestCase [ 'scopeConfig' => $this->_coreConfigMock, 'request' => $requestMock, - 'urlBuilder' => $this->_urlModelMock + 'urlBuilder' => $this->_urlModelMock, + 'storeManager' => $this->storeManagerMock ] ); @@ -178,6 +197,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); } @@ -400,6 +433,7 @@ class FormTest extends \PHPUnit_Framework_TestCase * @param string|null $configPath * @param bool $inherit * @param string $expectedValue + * @param string|null $placeholderValue * @param int $hasBackendModel * * @dataProvider initFieldsDataProvider @@ -411,6 +445,7 @@ class FormTest extends \PHPUnit_Framework_TestCase $configPath, $inherit, $expectedValue, + $placeholderValue, $hasBackendModel ) { // Parameters initialization @@ -480,6 +515,18 @@ class FormTest extends \PHPUnit_Framework_TestCase $this->returnValue($configValue) ); + /** @var \Magento\Store\Api\Data\StoreInterface|\PHPUnit_Framework_MockObject_MockObject $storeMock */ + $storeMock = $this->getMockBuilder(\Magento\Store\Api\Data\StoreInterface::class) + ->getMockForAbstractClass(); + $storeMock->expects($this->once()) + ->method('getCode') + ->willReturn('store_code'); + + $this->storeManagerMock->expects($this->atLeastOnce()) + ->method('getStore') + ->with('store_code') + ->willReturn($storeMock); + // Field mock configuration $fieldMock = $this->getMock( \Magento\Config\Model\Config\Structure\Element\Field::class, @@ -549,10 +596,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 +620,21 @@ class FormTest extends \PHPUnit_Framework_TestCase $fieldMock->expects($this->once())->method('populateInput'); + $settingCheckerMock = $this->getMockBuilder(SettingChecker::class) + ->disableOriginalConstructor() + ->getMock(); + $settingCheckerMock->expects($this->once()) + ->method('isReadOnly') + ->willReturn(false); + + $settingCheckerMock->expects($this->once()) + ->method('getPlaceholderValue') + ->willReturn($placeholderValue); + + $helper = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); + + $helper->setBackwardCompatibleProperty($this->object, 'settingChecker', $settingCheckerMock); + $this->object->initFields($fieldsetMock, $groupMock, $sectionMock, $fieldPrefix, $labelPrefix); } @@ -580,8 +644,9 @@ class FormTest extends \PHPUnit_Framework_TestCase public function initFieldsDataProvider() { return [ - [['section1/group1/field1' => 'some_value'], false, null, false, 'some_value', 1], - [[], 'Config Value', 'some/config/path', true, 'Config Value', 0] + [['section1/group1/field1' => 'some_value'], false, null, false, 'some_value', null, 1], + [[], 'Config Value', 'some/config/path', true, 'Config Value', null, 0], + [[], 'Config Value', 'some/config/path', true, 'Placeholder Value', 'Placeholder Value', 0] ]; } } diff --git a/app/code/Magento/Config/Test/Unit/Model/Config/Export/CommentTest.php b/app/code/Magento/Config/Test/Unit/Model/Config/Export/CommentTest.php new file mode 100644 index 0000000000000000000000000000000000000000..c8b10bcf4ddcd5393a62307c873646f87d1419e8 --- /dev/null +++ b/app/code/Magento/Config/Test/Unit/Model/Config/Export/CommentTest.php @@ -0,0 +1,88 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Config\Test\Unit\Model\Config\Export; + +use Magento\Config\Model\Config\Export\Comment; +use Magento\Config\App\Config\Source\DumpConfigSourceInterface; +use Magento\Config\Model\Placeholder\PlaceholderFactory; +use Magento\Config\Model\Placeholder\PlaceholderInterface; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; + +class CommentTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var DumpConfigSourceInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $configSourceMock; + + /** + * @var PlaceholderInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $placeholderMock; + + /** + * @var Comment + */ + private $model; + + protected function setUp() + { + $objectManager = new ObjectManager($this); + + $this->placeholderMock = $this->getMockBuilder(PlaceholderInterface::class) + ->disableOriginalConstructor() + ->getMockForAbstractClass(); + + $placeholderFactoryMock = $this->getMockBuilder(PlaceholderFactory::class) + ->setMethods(['create']) + ->disableOriginalConstructor() + ->getMock(); + $placeholderFactoryMock->expects($this->once()) + ->method('create') + ->with(PlaceholderFactory::TYPE_ENVIRONMENT) + ->willReturn($this->placeholderMock); + + $this->configSourceMock = $this->getMockBuilder(DumpConfigSourceInterface::class) + ->disableOriginalConstructor() + ->getMockForAbstractClass(); + + $this->model = $objectManager->getObject( + Comment::class, + [ + 'placeholderFactory' => $placeholderFactoryMock, + 'source' => $this->configSourceMock + ] + ); + } + + public function testGetEmpty() + { + $this->configSourceMock->expects($this->once()) + ->method('getExcludedFields') + ->willReturn([]); + $this->assertEmpty($this->model->get()); + } + + public function testGet() + { + $path = 'one/two'; + $placeholder = 'one__two'; + $expectedResult = 'The configuration file doesn\'t contain sensitive data for security reasons. ' + . 'Sensitive data can be stored in the following environment variables:' + . "\n$placeholder for $path"; + + $this->configSourceMock->expects($this->once()) + ->method('getExcludedFields') + ->willReturn([$path]); + + $this->placeholderMock->expects($this->once()) + ->method('generate') + ->with($path) + ->willReturn($placeholder); + + $this->assertEquals($expectedResult, $this->model->get()); + } +} diff --git a/app/code/Magento/Config/Test/Unit/Model/Config/Export/ExcludeListTest.php b/app/code/Magento/Config/Test/Unit/Model/Config/Export/ExcludeListTest.php new file mode 100644 index 0000000000000000000000000000000000000000..3156ad1ec549325839bbf9470c6396d101ee557f --- /dev/null +++ b/app/code/Magento/Config/Test/Unit/Model/Config/Export/ExcludeListTest.php @@ -0,0 +1,40 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Config\Test\Unit\Model\Config\Export; + +use Magento\Config\Model\Config\Export\ExcludeList; + +class ExcludeListTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var ExcludeList + */ + private $model; + + protected function setUp() + { + $this->model = new ExcludeList( + [ + 'web/unsecure/base_url' => '', + 'web/test/test_value' => '0', + 'web/test/test_sensitive' => '1', + ] + ); + } + + public function testGet() + { + $this->assertEquals(['web/test/test_sensitive'], $this->model->get()); + } + + public function testIsPresent() + { + $this->assertFalse($this->model->isPresent('some/new/path')); + $this->assertFalse($this->model->isPresent('web/unsecure/base_url')); + $this->assertFalse($this->model->isPresent('web/test/test_value')); + $this->assertTrue($this->model->isPresent('web/test/test_sensitive')); + } +} 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/Processor/EnvironmentPlaceholderTest.php b/app/code/Magento/Config/Test/Unit/Model/Config/Processor/EnvironmentPlaceholderTest.php new file mode 100644 index 0000000000000000000000000000000000000000..25f9f6b3cb83222dd9c196114729e8b10465072b --- /dev/null +++ b/app/code/Magento/Config/Test/Unit/Model/Config/Processor/EnvironmentPlaceholderTest.php @@ -0,0 +1,131 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Config\Test\Unit\Model\Config\Processor; + +use Magento\Config\Model\Config\Processor\EnvironmentPlaceholder; +use Magento\Config\Model\Placeholder\PlaceholderFactory; +use Magento\Config\Model\Placeholder\PlaceholderInterface; +use Magento\Framework\Stdlib\ArrayManager; +use \PHPUnit_Framework_MockObject_MockObject as Mock; + +class EnvironmentPlaceholderTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var EnvironmentPlaceholder + */ + private $model; + + /** + * @var PlaceholderFactory|Mock + */ + private $placeholderFactoryMock; + + /** + * @var ArrayManager|Mock + */ + private $arrayManagerMock; + + /** + * @var PlaceholderInterface|Mock + */ + private $placeholderMock; + + /** + * @var array + */ + private $env; + + protected function setUp() + { + $this->placeholderFactoryMock = $this->getMockBuilder(PlaceholderFactory::class) + ->disableOriginalConstructor() + ->getMock(); + $this->arrayManagerMock = $this->getMockBuilder(ArrayManager::class) + ->disableOriginalConstructor() + ->getMock(); + $this->placeholderMock = $this->getMockBuilder(PlaceholderInterface::class) + ->getMockForAbstractClass(); + $this->env = $_ENV; + + $this->placeholderFactoryMock->expects($this->any()) + ->method('create') + ->with(PlaceholderFactory::TYPE_ENVIRONMENT) + ->willReturn($this->placeholderMock); + + $this->model = new EnvironmentPlaceholder( + $this->placeholderFactoryMock, + $this->arrayManagerMock + ); + } + + public function testProcess() + { + $_ENV = array_merge( + $this->env, + [ + 'CONFIG_DEFAULT_TEST' => 1, + 'CONFIG_DEFAULT_TEST2' => 2, + 'BAD_CONFIG' => 3, + ] + ); + + $this->placeholderMock->expects($this->any()) + ->method('isApplicable') + ->willReturnMap( + [ + ['CONFIG_DEFAULT_TEST', true], + ['CONFIG_DEFAULT_TEST2', true], + ['BAD_CONFIG', false], + ] + ); + $this->placeholderMock->expects($this->any()) + ->method('restore') + ->willReturnMap( + [ + ['CONFIG_DEFAULT_TEST', 'default/test'], + ['CONFIG_DEFAULT_TEST2', 'default/test2'], + ] + ); + $this->arrayManagerMock->expects($this->any()) + ->method('set') + ->willReturnMap( + [ + ['default/test', [], 1, '/', ['default' => ['test' => 1]]], + [ + 'default/test2', + [ + 'default' => [ + 'test' => 1 + ] + ], + 2, + '/', + [ + 'default' => [ + 'test' => 1, + 'test2' => 2 + ] + ], + ] + ] + ); + + $this->assertSame( + [ + 'default' => [ + 'test' => 1, + 'test2' => 2 + ] + ], + $this->model->process([]) + ); + } + + protected function tearDown() + { + $_ENV = $this->env; + } +} 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..75bfab85616b588975175abe8976a8e57ec65e04 --- /dev/null +++ b/app/code/Magento/Config/Test/Unit/Model/Config/Reader/Source/Deployed/SettingCheckerTest.php @@ -0,0 +1,146 @@ +<?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; +use Magento\Framework\App\DeploymentConfig; +use Magento\Config\Model\Placeholder\PlaceholderInterface; +use Magento\Config\Model\Placeholder\PlaceholderFactory; + +/** + * Test class for checking settings that defined in config file + */ +class SettingCheckerTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var Config|\PHPUnit_Framework_MockObject_MockObject + */ + private $configMock; + + /** + * @var PlaceholderInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $placeholderMock; + + /** + * @var Config\ScopeCodeResolver|\PHPUnit_Framework_MockObject_MockObject + */ + private $scopeCodeResolverMock; + + /** + * @var SettingChecker + */ + private $checker; + + /** + * @var array + */ + private $env; + + public function setUp() + { + $this->configMock = $this->getMockBuilder(DeploymentConfig::class) + ->disableOriginalConstructor() + ->getMock(); + $this->placeholderMock = $this->getMockBuilder(PlaceholderInterface::class) + ->getMockForAbstractClass(); + $this->scopeCodeResolverMock = $this->getMockBuilder(Config\ScopeCodeResolver::class) + ->disableOriginalConstructor() + ->getMock(); + $placeholderFactoryMock = $this->getMockBuilder(PlaceholderFactory::class) + ->disableOriginalConstructor() + ->getMock(); + $this->env = $_ENV; + + $placeholderFactoryMock->expects($this->once()) + ->method('create') + ->with(PlaceholderFactory::TYPE_ENVIRONMENT) + ->willReturn($this->placeholderMock); + + $this->checker = new SettingChecker($this->configMock, $placeholderFactoryMock, $this->scopeCodeResolverMock); + } + + /** + * @param string $path + * @param string $scope + * @param string $scopeCode + * @param string|null $confValue + * @param array $variables + * @param bool $expectedResult + * @dataProvider isReadonlyDataProvider + */ + public function testIsReadonly($path, $scope, $scopeCode, $confValue, array $variables, $expectedResult) + { + $this->placeholderMock->expects($this->once()) + ->method('isApplicable') + ->willReturn(true); + $this->placeholderMock->expects($this->once()) + ->method('generate') + ->with($path, $scope, $scopeCode) + ->willReturn('SOME_PLACEHOLDER'); + $this->scopeCodeResolverMock->expects($this->any()) + ->method('resolve') + ->willReturnMap( + [ + ['website', 'myWebsite', ($scopeCode ? $scopeCode : '')] + ] + ); + + $_ENV = array_merge($this->env, $variables); + + $this->configMock->expects($this->any()) + ->method('get') + ->willReturnMap([ + [ + 'system/' . $scope . "/" . ($scopeCode ? $scopeCode . '/' : '') . $path, + null, + $confValue + ], + ]); + + $this->assertSame($expectedResult, $this->checker->isReadOnly($path, $scope, $scopeCode)); + } + + /** + * @return array + */ + public function isReadonlyDataProvider() + { + return [ + [ + 'path' => 'general/web/locale', + 'scope' => 'website', + 'scopeCode' => 'myWebsite', + 'confValue' => 'value', + 'variables' => [], + 'expectedResult' => true, + ], + [ + 'path' => 'general/web/locale', + 'scope' => 'website', + 'scopeCode' => 'myWebsite', + 'confValue' => null, + 'variables' => ['SOME_PLACEHOLDER' => 'value'], + 'expectedResult' => true, + ], + [ + 'path' => 'general/web/locale', + 'scope' => 'website', + 'scopeCode' => 'myWebsite', + 'confValue' => null, + 'variables' => [], + 'expectedResult' => false, + ] + ]; + } + + protected function tearDown() + { + $_ENV = $this->env; + } +} diff --git a/app/code/Magento/Config/Test/Unit/Model/Placeholder/EnvironmentTest.php b/app/code/Magento/Config/Test/Unit/Model/Placeholder/EnvironmentTest.php new file mode 100644 index 0000000000000000000000000000000000000000..64b4e6e37fb94867854da15f8e0f72d9b0ccbf3c --- /dev/null +++ b/app/code/Magento/Config/Test/Unit/Model/Placeholder/EnvironmentTest.php @@ -0,0 +1,131 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Config\Test\Unit\Model\Placeholder; + +use Magento\Config\Model\Placeholder\Environment; +use Magento\Framework\App\Config\ScopeConfigInterface; +use Magento\Framework\App\DeploymentConfig; +use Magento\Framework\Config\ConfigOptionsListConstants; +use \PHPUnit_Framework_MockObject_MockObject as Mock; + +/** + * Class EnvironmentTest + */ +class EnvironmentTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var Environment + */ + private $model; + + /** + * @var DeploymentConfig|Mock + */ + private $deploymentConfigMock; + + protected function setUp() + { + $this->deploymentConfigMock = $this->getMockBuilder(DeploymentConfig::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->model = new Environment( + $this->deploymentConfigMock + ); + } + + /** + * @param string $path + * @param string $scope + * @param string $scopeId + * @param string $expected + * @dataProvider getGenerateDataProvider + */ + public function testGenerate($path, $scope, $scopeId, $expected) + { + $this->assertSame( + $expected, + $this->model->generate($path, $scope, $scopeId) + ); + } + + public function getGenerateDataProvider() + { + return [ + [ + 'web/unsecure/base_url', + ScopeConfigInterface::SCOPE_TYPE_DEFAULT, + null, + Environment::PREFIX . 'DEFAULT__WEB__UNSECURE__BASE_URL' + ], + [ + 'web/unsecure/base_url', + 'web', + 'test', + Environment::PREFIX . 'WEB__TEST__WEB__UNSECURE__BASE_URL' + ], + [ + 'web/unsecure/base_url', + 'web', + null, + Environment::PREFIX . 'WEB__WEB__UNSECURE__BASE_URL' + ], + ]; + } + + /** + * @param string $placeholder + * @param bool $expected + * @dataProvider getIsPlaceholderDataProvider + */ + public function testIsApplicable($placeholder, $expected) + { + $this->assertSame( + $expected, + $this->model->isApplicable($placeholder) + ); + } + + /** + * @return array + */ + public function getIsPlaceholderDataProvider() + { + return [ + [Environment::PREFIX . 'TEST', true], + ['TEST', false], + [Environment::PREFIX . 'TEST_test', true], + [Environment::PREFIX . '-:A', false], + [Environment::PREFIX . '_A', false], + [Environment::PREFIX . 'A@#$', false] + ]; + } + + /** + * @param string $template + * @param string $expected + * @dataProvider restoreDataProvider + */ + public function testRestore($template, $expected) + { + $this->assertSame( + $expected, + $this->model->restore($template) + ); + } + + /** + * @return array + */ + public function restoreDataProvider() + { + return [ + [Environment::PREFIX . 'TEST__CONFIG', 'test/config'], + [Environment::PREFIX . 'TEST__CONFIG__VALUE', 'test/config/value'], + [Environment::PREFIX . 'TEST__CONFIG_VALUE', 'test/config_value'], + ]; + } +} diff --git a/app/code/Magento/Config/Test/Unit/Model/Placeholder/PlaceholderFactoryTest.php b/app/code/Magento/Config/Test/Unit/Model/Placeholder/PlaceholderFactoryTest.php new file mode 100644 index 0000000000000000000000000000000000000000..e8f646e984187ed49ffc7df0798c8efa689ba767 --- /dev/null +++ b/app/code/Magento/Config/Test/Unit/Model/Placeholder/PlaceholderFactoryTest.php @@ -0,0 +1,76 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Config\Test\Unit\Model\Placeholder; + +use Magento\Config\Model\Placeholder\Environment; +use Magento\Config\Model\Placeholder\PlaceholderFactory; +use Magento\Framework\ObjectManagerInterface; + +class PlaceholderFactoryTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var PlaceholderFactory + */ + private $model; + + /** + * @var ObjectManagerInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $objectManagerMock; + + /** + * @var Environment|\PHPUnit_Framework_MockObject_MockObject + */ + private $environmentMock; + + protected function setUp() + { + $this->objectManagerMock = $this->getMockBuilder(ObjectManagerInterface::class) + ->getMockForAbstractClass(); + $this->environmentMock = $this->getMockBuilder(Environment::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->model = new PlaceholderFactory( + $this->objectManagerMock, + [ + PlaceholderFactory::TYPE_ENVIRONMENT => Environment::class, + 'wrongClass' => \stdClass::class, + ] + ); + } + + public function testCreate() + { + $this->objectManagerMock->expects($this->once()) + ->method('create') + ->with(Environment::class) + ->willReturn($this->environmentMock); + + $this->assertInstanceOf( + Environment::class, + $this->model->create(PlaceholderFactory::TYPE_ENVIRONMENT) + ); + } + + /** + * @expectedException \Magento\Framework\Exception\LocalizedException + * @expectedExceptionMessage There is no defined type dummyClass + */ + public function testCreateNonExisted() + { + $this->model->create('dummyClass'); + } + + /** + * @expectedException \Magento\Framework\Exception\LocalizedException + * @expectedExceptionMessage Object is not instance of Magento\Config\Model\Placeholder\PlaceholderInterface + */ + public function testCreateWrongImplementation() + { + $this->model->create('wrongClass'); + } +} 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..3e2fa4fbecf6da0a712a1df313eb5b63812a5a20 100644 --- a/app/code/Magento/Config/etc/di.xml +++ b/app/code/Magento/Config/etc/di.xml @@ -69,4 +69,119 @@ <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> + <argument name="preProcessor" xsi:type="object">systemConfigPreProcessorComposite</argument> + <argument name="serializer" xsi:type="object">Magento\Framework\Serialize\Serializer\Serialize</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="systemConfigPreProcessorComposite" type="Magento\Framework\App\Config\PreProcessorComposite"> + <arguments> + <argument name="processors" xsi:type="array"> + <item name="environmentPlaceholder" xsi:type="object">Magento\Config\Model\Config\Processor\EnvironmentPlaceholder</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\Config\App\Config\Source\DumpConfigSourceAggregated"> + <arguments> + <argument name="sources" xsi:type="array"> + <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> + <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 name="comment" xsi:type="object">Magento\Config\Model\Config\Export\Comment</item> + </item> + </argument> + </arguments> + </type> + <type name="Magento\Config\Model\Config\Export\Comment"> + <arguments> + <argument name="source" xsi:type="object">appDumpSystemSource</argument> + </arguments> + </type> + <type name="Magento\Config\Model\Placeholder\PlaceholderFactory"> + <arguments> + <argument name="types" xsi:type="array"> + <item name="environment" xsi:type="string">Magento\Config\Model\Placeholder\Environment</item> + </argument> + </arguments> + </type> </config> diff --git a/app/code/Magento/ConfigurableImportExport/Model/Import/Product/Type/Configurable.php b/app/code/Magento/ConfigurableImportExport/Model/Import/Product/Type/Configurable.php index 29e670e9f7f4fc95ccc51974d484dc0d802c13e2..9eedf22fbc1ae721fa6f453617c2a68ad6ea32e2 100644 --- a/app/code/Magento/ConfigurableImportExport/Model/Import/Product/Type/Configurable.php +++ b/app/code/Magento/ConfigurableImportExport/Model/Import/Product/Type/Configurable.php @@ -12,6 +12,7 @@ namespace Magento\ConfigurableImportExport\Model\Import\Product\Type; use Magento\Catalog\Api\Data\ProductInterface; use Magento\CatalogImportExport\Model\Import\Product as ImportProduct; +use Magento\Framework\EntityManager\MetadataPool; /** * Importing configurable products @@ -140,6 +141,7 @@ class Configurable extends \Magento\CatalogImportExport\Model\Import\Product\Typ * Instance of database adapter. * * @var \Magento\Framework\DB\Adapter\AdapterInterface + * @deprecated */ protected $_connection; @@ -200,6 +202,7 @@ class Configurable extends \Magento\CatalogImportExport\Model\Import\Product\Typ * @param \Magento\Catalog\Model\ProductTypes\ConfigInterface $productTypesConfig * @param \Magento\ImportExport\Model\ResourceModel\Helper $resourceHelper * @param \Magento\Catalog\Model\ResourceModel\Product\CollectionFactory $_productColFac + * @param MetadataPool $metadataPool */ public function __construct( \Magento\Eav\Model\ResourceModel\Entity\Attribute\Set\CollectionFactory $attrSetColFac, @@ -208,12 +211,12 @@ class Configurable extends \Magento\CatalogImportExport\Model\Import\Product\Typ array $params, \Magento\Catalog\Model\ProductTypes\ConfigInterface $productTypesConfig, \Magento\ImportExport\Model\ResourceModel\Helper $resourceHelper, - \Magento\Catalog\Model\ResourceModel\Product\CollectionFactory $_productColFac + \Magento\Catalog\Model\ResourceModel\Product\CollectionFactory $_productColFac, + MetadataPool $metadataPool = null ) { - parent::__construct($attrSetColFac, $prodAttrColFac, $resource, $params); + parent::__construct($attrSetColFac, $prodAttrColFac, $resource, $params, $metadataPool); $this->_productTypesConfig = $productTypesConfig; $this->_resourceHelper = $resourceHelper; - $this->_resource = $resource; $this->_productColFac = $_productColFac; $this->_connection = $this->_entityModel->getConnection(); } @@ -379,14 +382,14 @@ class Configurable extends \Magento\CatalogImportExport\Model\Import\Product\Typ if (!empty($productIds)) { $mainTable = $this->_resource->getTableName('catalog_product_super_attribute'); $optionTable = $this->_resource->getTableName('eav_attribute_option'); - $select = $this->_connection->select()->from( + $select = $this->connection->select()->from( ['m' => $mainTable], ['product_id', 'attribute_id', 'product_super_attribute_id'] )->joinLeft( ['o' => $optionTable], - $this->_connection->quoteIdentifier( + $this->connection->quoteIdentifier( 'o.attribute_id' - ) . ' = ' . $this->_connection->quoteIdentifier( + ) . ' = ' . $this->connection->quoteIdentifier( 'o.attribute_id' ), ['option_id'] @@ -395,7 +398,7 @@ class Configurable extends \Magento\CatalogImportExport\Model\Import\Product\Typ $productIds ); - foreach ($this->_connection->fetchAll($select) as $row) { + foreach ($this->connection->fetchAll($select) as $row) { $attrId = $row['attribute_id']; $productId = $row['product_id']; if ($row['option_id']) { @@ -448,8 +451,8 @@ class Configurable extends \Magento\CatalogImportExport\Model\Import\Product\Typ 'product_id' => $this->_productSuperData['assoc_entity_ids'][$assocId], 'parent_id' => $this->_productSuperData['product_id'], ]; - $subEntityId = $this->_connection->fetchOne( - $this->_connection->select()->from( + $subEntityId = $this->connection->fetchOne( + $this->connection->select()->from( ['cpe' => $this->_resource->getTableName('catalog_product_entity')], ['entity_id'] )->where($metadata->getLinkField() . ' = ?', $assocId) ); @@ -557,10 +560,10 @@ class Configurable extends \Magento\CatalogImportExport\Model\Import\Product\Typ && !empty($this->_productSuperData['product_id']) && !empty($this->_simpleIdsToDelete) ) { - $quoted = $this->_connection->quoteInto('IN (?)', [$this->_productSuperData['product_id']]); - $quotedChildren = $this->_connection->quoteInto('IN (?)', $this->_simpleIdsToDelete); - $this->_connection->delete($linkTable, "parent_id {$quoted} AND product_id {$quotedChildren}"); - $this->_connection->delete($relationTable, "parent_id {$quoted} AND child_id {$quotedChildren}"); + $quoted = $this->connection->quoteInto('IN (?)', [$this->_productSuperData['product_id']]); + $quotedChildren = $this->connection->quoteInto('IN (?)', $this->_simpleIdsToDelete); + $this->connection->delete($linkTable, "parent_id {$quoted} AND product_id {$quotedChildren}"); + $this->connection->delete($relationTable, "parent_id {$quoted} AND child_id {$quotedChildren}"); } return $this; } @@ -587,16 +590,16 @@ class Configurable extends \Magento\CatalogImportExport\Model\Import\Product\Typ } } if ($mainData) { - $this->_connection->insertOnDuplicate($mainTable, $mainData); + $this->connection->insertOnDuplicate($mainTable, $mainData); } if ($this->_superAttributesData['labels']) { - $this->_connection->insertOnDuplicate($labelTable, $this->_superAttributesData['labels']); + $this->connection->insertOnDuplicate($labelTable, $this->_superAttributesData['labels']); } if ($this->_superAttributesData['super_link']) { - $this->_connection->insertOnDuplicate($linkTable, $this->_superAttributesData['super_link']); + $this->connection->insertOnDuplicate($linkTable, $this->_superAttributesData['super_link']); } if ($this->_superAttributesData['relation']) { - $this->_connection->insertOnDuplicate($relationTable, $this->_superAttributesData['relation']); + $this->connection->insertOnDuplicate($relationTable, $this->_superAttributesData['relation']); } return $this; } diff --git a/app/code/Magento/ConfigurableImportExport/Test/Unit/Model/Import/Product/Type/ConfigurableTest.php b/app/code/Magento/ConfigurableImportExport/Test/Unit/Model/Import/Product/Type/ConfigurableTest.php index 8ce7489db932ef9f21eb5eb1ae21d6341e1658c9..4cc4e6648a0ef8d63c6ae13e28c547b6e9019155 100644 --- a/app/code/Magento/ConfigurableImportExport/Test/Unit/Model/Import/Product/Type/ConfigurableTest.php +++ b/app/code/Magento/ConfigurableImportExport/Test/Unit/Model/Import/Product/Type/ConfigurableTest.php @@ -312,15 +312,10 @@ class ConfigurableTest extends \Magento\ImportExport\Test\Unit\Model\Import\Abst 'prodAttrColFac' => $this->attrCollectionFactory, 'params' => $this->params, 'resource' => $this->resource, - 'productColFac' => $this->productCollectionFactory + 'productColFac' => $this->productCollectionFactory, + 'metadataPool' => $metadataPoolMock, ] ); - $reflection = new \ReflectionClass( - \Magento\ConfigurableImportExport\Model\Import\Product\Type\Configurable::class - ); - $reflectionProperty = $reflection->getProperty('metadataPool'); - $reflectionProperty->setAccessible(true); - $reflectionProperty->setValue($this->configurable, $metadataPoolMock); } /** diff --git a/app/code/Magento/ConfigurableProduct/Block/Product/View/Type/Configurable.php b/app/code/Magento/ConfigurableProduct/Block/Product/View/Type/Configurable.php index 51c68145b24cf5e72061a51647d4b311f39e60bf..a5f85df1c96f66bb911bf92303c40d14c3be49b6 100644 --- a/app/code/Magento/ConfigurableProduct/Block/Product/View/Type/Configurable.php +++ b/app/code/Magento/ConfigurableProduct/Block/Product/View/Type/Configurable.php @@ -193,6 +193,7 @@ class Configurable extends \Magento\Catalog\Block\Product\View\AbstractView $config = [ 'attributes' => $attributesData['attributes'], 'template' => str_replace('%s', '<%- data.price %>', $store->getCurrentCurrency()->getOutputFormat()), + 'currencyFormat' => $store->getCurrentCurrency()->getOutputFormat(), 'optionPrices' => $this->getOptionPrices(), 'prices' => [ 'oldPrice' => [ @@ -229,7 +230,17 @@ class Configurable extends \Magento\Catalog\Block\Product\View\AbstractView { $prices = []; foreach ($this->getAllowProducts() as $product) { + $tierPrices = []; $priceInfo = $product->getPriceInfo(); + $tierPriceModel = $priceInfo->getPrice('tier_price'); + $tierPricesList = $tierPriceModel->getTierPriceList(); + foreach ($tierPricesList as $tierPrice) { + $tierPrices[] = [ + 'qty' => $this->_registerJsPrice($tierPrice['price_qty']), + 'price' => $this->_registerJsPrice($tierPrice['price']->getValue()), + 'percentage' => $this->_registerJsPrice($tierPriceModel->getSavePercent($tierPrice['price'])), + ]; + } $prices[$product->getId()] = [ @@ -247,8 +258,9 @@ class Configurable extends \Magento\Catalog\Block\Product\View\AbstractView 'amount' => $this->_registerJsPrice( $priceInfo->getPrice('final_price')->getAmount()->getValue() ), - ] - ]; + ], + 'tierPrices' => $tierPrices, + ]; } return $prices; } @@ -263,4 +275,14 @@ class Configurable extends \Magento\Catalog\Block\Product\View\AbstractView { return str_replace(',', '.', $price); } + + /** + * Should we generate "As low as" block or not + * + * @return bool + */ + public function showMinimalPrice() + { + return true; + } } diff --git a/app/code/Magento/ConfigurableProduct/Helper/Data.php b/app/code/Magento/ConfigurableProduct/Helper/Data.php index 079aee7b23750bbb08d01ecae4c672c50bf1eeb2..4c1370b1a0d7aed1c786d318c3c65382277e2afe 100644 --- a/app/code/Magento/ConfigurableProduct/Helper/Data.php +++ b/app/code/Magento/ConfigurableProduct/Helper/Data.php @@ -50,15 +50,13 @@ class Data ); $image->setData( 'medium_image_url', - $this->imageHelper->init($product, 'product_page_image_medium') - ->constrainOnly(true)->keepAspectRatio(true)->keepFrame(false) + $this->imageHelper->init($product, 'product_page_image_medium_no_frame') ->setImageFile($image->getFile()) ->getUrl() ); $image->setData( 'large_image_url', - $this->imageHelper->init($product, 'product_page_image_large') - ->constrainOnly(true)->keepAspectRatio(true)->keepFrame(false) + $this->imageHelper->init($product, 'product_page_image_large_no_frame') ->setImageFile($image->getFile()) ->getUrl() ); diff --git a/app/code/Magento/ConfigurableProduct/Model/ResourceModel/Product/Indexer/Price/Configurable.php b/app/code/Magento/ConfigurableProduct/Model/ResourceModel/Product/Indexer/Price/Configurable.php index fbb69798ff94fbdf8caafc7486e564da662cf655..ed4863342a9670699fd544b7c7838697dd06eef7 100644 --- a/app/code/Magento/ConfigurableProduct/Model/ResourceModel/Product/Indexer/Price/Configurable.php +++ b/app/code/Magento/ConfigurableProduct/Model/ResourceModel/Product/Indexer/Price/Configurable.php @@ -9,9 +9,45 @@ namespace Magento\ConfigurableProduct\Model\ResourceModel\Product\Indexer\Price; use Magento\Catalog\Api\Data\ProductInterface; use Magento\Catalog\Model\Product\Attribute\Source\Status as ProductStatus; +use Magento\Catalog\Model\Product\Attribute\Source\Status; +use Magento\Store\Api\StoreResolverInterface; +use Magento\Store\Model\Store; +/** + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ class Configurable extends \Magento\Catalog\Model\ResourceModel\Product\Indexer\Price\DefaultPrice { + /** + * @var StoreResolverInterface + */ + private $storeResolver; + + /** + * Class constructor + * + * @param \Magento\Framework\Model\ResourceModel\Db\Context $context + * @param \Magento\Framework\Indexer\Table\StrategyInterface $tableStrategy + * @param \Magento\Eav\Model\Config $eavConfig + * @param \Magento\Framework\Event\ManagerInterface $eventManager + * @param \Magento\Framework\Module\Manager $moduleManager + * @param string $connectionName + * @param StoreResolverInterface $storeResolver + */ + public function __construct( + \Magento\Framework\Model\ResourceModel\Db\Context $context, + \Magento\Framework\Indexer\Table\StrategyInterface $tableStrategy, + \Magento\Eav\Model\Config $eavConfig, + \Magento\Framework\Event\ManagerInterface $eventManager, + \Magento\Framework\Module\Manager $moduleManager, + $connectionName = null, + StoreResolverInterface $storeResolver = null + ) { + parent::__construct($context, $tableStrategy, $eavConfig, $eventManager, $moduleManager, $connectionName); + $this->storeResolver = $storeResolver ?: + \Magento\Framework\App\ObjectManager::getInstance()->get(StoreResolverInterface::class); + } + /** * Reindex temporary (price result data) for all products * @@ -190,16 +226,21 @@ class Configurable extends \Magento\Catalog\Model\ResourceModel\Product\Indexer\ [] )->where( 'le.required_options=0' - )->join( - ['product_status' => $this->getTable($statusAttribute->getBackend()->getTable())], - sprintf( - 'le.%1$s = product_status.%1$s AND product_status.attribute_id = %2$s', - $linkField, - $statusAttribute->getAttributeId() - ), + )->joinLeft( + ['status_global_attr' => $statusAttribute->getBackendTable()], + "status_global_attr.{$linkField} = le.{$linkField}" + . ' AND status_global_attr.attribute_id = ' . (int)$statusAttribute->getAttributeId() + . ' AND status_global_attr.store_id = ' . Store::DEFAULT_STORE_ID, + [] + )->joinLeft( + ['status_attr' => $statusAttribute->getBackendTable()], + "status_attr.{$linkField} = le.{$linkField}" + . ' AND status_attr.attribute_id = ' . (int)$statusAttribute->getAttributeId() + . ' AND status_attr.store_id = ' . $this->storeResolver->getCurrentStoreId(), [] )->where( - 'product_status.value=' . ProductStatus::STATUS_ENABLED + 'IFNULL(status_attr.value, status_global_attr.value) = ?', + Status::STATUS_ENABLED )->group( ['e.entity_id', 'i.customer_group_id', 'i.website_id', 'l.product_id'] ); diff --git a/app/code/Magento/ConfigurableProduct/Model/ResourceModel/Product/Type/Configurable/Product/Collection.php b/app/code/Magento/ConfigurableProduct/Model/ResourceModel/Product/Type/Configurable/Product/Collection.php index 5216f13355970c153c05fa239fd1e9272354d6bb..44a4d468cd0978b1c46eee68a9b3ff384147ffea 100644 --- a/app/code/Magento/ConfigurableProduct/Model/ResourceModel/Product/Type/Configurable/Product/Collection.php +++ b/app/code/Magento/ConfigurableProduct/Model/ResourceModel/Product/Type/Configurable/Product/Collection.php @@ -7,10 +7,6 @@ */ namespace Magento\ConfigurableProduct\Model\ResourceModel\Product\Type\Configurable\Product; -use Magento\Customer\Api\GroupManagementInterface; -use Magento\Framework\EntityManager\MetadataPool; -use Magento\Catalog\Api\Data\ProductInterface; - /** * Class Collection * @@ -25,84 +21,6 @@ class Collection extends \Magento\Catalog\Model\ResourceModel\Product\Collection */ protected $_linkTable; - /** - * @var MetadataPool - */ - private $metadataPool; - - /** - * @param \Magento\Framework\Data\Collection\EntityFactory $entityFactory - * @param \Psr\Log\LoggerInterface $logger - * @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy - * @param \Magento\Framework\Event\ManagerInterface $eventManager - * @param \Magento\Eav\Model\Config $eavConfig - * @param \Magento\Framework\App\ResourceConnection $resource - * @param \Magento\Eav\Model\EntityFactory $eavEntityFactory - * @param \Magento\Catalog\Model\ResourceModel\Helper $resourceHelper - * @param \Magento\Framework\Validator\UniversalFactory $universalFactory - * @param \Magento\Store\Model\StoreManagerInterface $storeManager - * @param \Magento\Framework\Module\Manager $moduleManager - * @param \Magento\Catalog\Model\Indexer\Product\Flat\State $catalogProductFlatState - * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig - * @param \Magento\Catalog\Model\Product\OptionFactory $productOptionFactory - * @param \Magento\Catalog\Model\ResourceModel\Url $catalogUrl - * @param \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate - * @param \Magento\Customer\Model\Session $customerSession - * @param \Magento\Framework\Stdlib\DateTime $dateTime - * @param GroupManagementInterface $groupManagement - * @param MetadataPool $metadataPool - * @param \Magento\Framework\DB\Adapter\AdapterInterface|null $connection - * - * @SuppressWarnings(PHPMD.ExcessiveParameterList) - */ - public function __construct( - \Magento\Framework\Data\Collection\EntityFactory $entityFactory, - \Psr\Log\LoggerInterface $logger, - \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy, - \Magento\Framework\Event\ManagerInterface $eventManager, - \Magento\Eav\Model\Config $eavConfig, - \Magento\Framework\App\ResourceConnection $resource, - \Magento\Eav\Model\EntityFactory $eavEntityFactory, - \Magento\Catalog\Model\ResourceModel\Helper $resourceHelper, - \Magento\Framework\Validator\UniversalFactory $universalFactory, - \Magento\Store\Model\StoreManagerInterface $storeManager, - \Magento\Framework\Module\Manager $moduleManager, - \Magento\Catalog\Model\Indexer\Product\Flat\State $catalogProductFlatState, - \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig, - \Magento\Catalog\Model\Product\OptionFactory $productOptionFactory, - \Magento\Catalog\Model\ResourceModel\Url $catalogUrl, - \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate, - \Magento\Customer\Model\Session $customerSession, - \Magento\Framework\Stdlib\DateTime $dateTime, - GroupManagementInterface $groupManagement, - MetadataPool $metadataPool, - \Magento\Framework\DB\Adapter\AdapterInterface $connection = null - ) { - $this->metadataPool = $metadataPool; - parent::__construct( - $entityFactory, - $logger, - $fetchStrategy, - $eventManager, - $eavConfig, - $resource, - $eavEntityFactory, - $resourceHelper, - $universalFactory, - $storeManager, - $moduleManager, - $catalogProductFlatState, - $scopeConfig, - $productOptionFactory, - $catalogUrl, - $localeDate, - $customerSession, - $dateTime, - $groupManagement, - $connection - ); - } - /** * Assign link table name * @@ -139,7 +57,7 @@ class Collection extends \Magento\Catalog\Model\ResourceModel\Product\Collection */ public function setProductFilter($product) { - $metadata = $this->metadataPool->getMetadata(ProductInterface::class); + $metadata = $this->getProductEntityMetadata(); $this->getSelect()->where('link_table.parent_id = ?', $product->getData($metadata->getLinkField())); return $this; diff --git a/app/code/Magento/ConfigurableProduct/Pricing/Price/ConfigurablePriceResolver.php b/app/code/Magento/ConfigurableProduct/Pricing/Price/ConfigurablePriceResolver.php index 68e82ed76a23fbdda404c32eb7406d3117b3cd0e..eb3040ad2f66866269c46febf3c014b9d01bf31b 100644 --- a/app/code/Magento/ConfigurableProduct/Pricing/Price/ConfigurablePriceResolver.php +++ b/app/code/Magento/ConfigurableProduct/Pricing/Price/ConfigurablePriceResolver.php @@ -64,11 +64,6 @@ class ConfigurablePriceResolver implements PriceResolverInterface $productPrice = $this->priceResolver->resolvePrice($subProduct); $price = $price ? min($price, $productPrice) : $productPrice; } - if ($price === null) { - throw new \Magento\Framework\Exception\LocalizedException( - __('Configurable product "%1" does not have sub-products', $product->getSku()) - ); - } return (float)$price; } diff --git a/app/code/Magento/ConfigurableProduct/Pricing/Render/TierPriceBox.php b/app/code/Magento/ConfigurableProduct/Pricing/Render/TierPriceBox.php new file mode 100644 index 0000000000000000000000000000000000000000..af2414204fd1a3aea6acecceb34f28c613f3c6dc --- /dev/null +++ b/app/code/Magento/ConfigurableProduct/Pricing/Render/TierPriceBox.php @@ -0,0 +1,25 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\ConfigurableProduct\Pricing\Render; + +/** + * Responsible for displaying tier price box on configurable product page. + * + * @package Magento\ConfigurableProduct\Pricing\Render + */ +class TierPriceBox extends FinalPriceBox +{ + /** + * @inheritdoc + */ + public function toHtml() + { + // Hide tier price block in case of MSRP. + if (!$this->isMsrpPriceApplicable()) { + return parent::toHtml(); + } + } +} 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/ConfigurableProduct/Test/Unit/Helper/DataTest.php b/app/code/Magento/ConfigurableProduct/Test/Unit/Helper/DataTest.php index be1f4c76a4f45e3051c4d39f87c4619ffac1de3a..efb11e6b13a1d63d4fb9fbb37b5d5a89f5a8f511 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Unit/Helper/DataTest.php +++ b/app/code/Magento/ConfigurableProduct/Test/Unit/Helper/DataTest.php @@ -35,7 +35,7 @@ class DataTest extends \PHPUnit_Framework_TestCase public function testGetAllowAttributes() { - $typeInstanceMock = $this->getMock( + $typeInstanceMock = $this->getMock( \Magento\ConfigurableProduct\Model\Product\Type\Configurable::class, [], [], '', false ); $typeInstanceMock->expects($this->once()) @@ -91,7 +91,7 @@ class DataTest extends \PHPUnit_Framework_TestCase */ public function getOptionsDataProvider() { - $currentProductMock = $this->getMock( + $currentProductMock = $this->getMock( \Magento\Catalog\Model\Product::class, ['getTypeInstance', '__wakeup'], [], '', false ); $provider = []; @@ -106,10 +106,10 @@ class DataTest extends \PHPUnit_Framework_TestCase $attributesCount = 3; $attributes = []; for ($i = 1; $i < $attributesCount; $i++) { - $attribute = $this->getMock( + $attribute = $this->getMock( \Magento\Framework\DataObject::class, ['getProductAttribute'], [], '', false ); - $productAttribute = $this->getMock( + $productAttribute = $this->getMock( \Magento\Framework\DataObject::class, ['getId', 'getAttributeCode'], [], @@ -127,7 +127,7 @@ class DataTest extends \PHPUnit_Framework_TestCase ->will($this->returnValue($productAttribute)); $attributes[] = $attribute; } - $typeInstanceMock = $this->getMock( + $typeInstanceMock = $this->getMock( \Magento\ConfigurableProduct\Model\Product\Type\Configurable::class, [], [], '', false ); $typeInstanceMock->expects($this->any()) @@ -138,7 +138,7 @@ class DataTest extends \PHPUnit_Framework_TestCase ->will($this->returnValue($typeInstanceMock)); $allowedProducts = []; for ($i = 1; $i <= 2; $i++) { - $productMock = $this->getMock( + $productMock = $this->getMock( \Magento\Catalog\Model\Product::class, ['getData', 'getImage', 'getId', '__wakeup', 'getMediaGalleryImages'], [], '', false ); $productMock->expects($this->any()) @@ -195,4 +195,64 @@ class DataTest extends \PHPUnit_Framework_TestCase } return $map[$key]; } + + public function testGetGalleryImages() + { + $productMock = $this->getMockBuilder(\Magento\Catalog\Api\Data\ProductInterface::class) + ->setMethods(['getMediaGalleryImages']) + ->getMockForAbstractClass(); + $productMock->expects($this->once()) + ->method('getMediaGalleryImages') + ->willReturn($this->getImagesCollection()); + + $this->_imageHelperMock->expects($this->exactly(3)) + ->method('init') + ->willReturnMap([ + [$productMock, 'product_page_image_small', [], $this->_imageHelperMock], + [$productMock, 'product_page_image_medium_no_frame', [], $this->_imageHelperMock], + [$productMock, 'product_page_image_large_no_frame', [], $this->_imageHelperMock], + ]) + ->willReturnSelf(); + $this->_imageHelperMock->expects($this->exactly(3)) + ->method('setImageFile') + ->with('test_file') + ->willReturnSelf(); + $this->_imageHelperMock->expects($this->at(0)) + ->method('getUrl') + ->willReturn('product_page_image_small_url'); + $this->_imageHelperMock->expects($this->at(1)) + ->method('getUrl') + ->willReturn('product_page_image_medium_url'); + $this->_imageHelperMock->expects($this->at(2)) + ->method('getUrl') + ->willReturn('product_page_image_large_url'); + + $this->assertInstanceOf( + \Magento\Framework\Data\Collection::class, + $this->_model->getGalleryImages($productMock) + ); + + } + + /** + * @return \Magento\Framework\Data\Collection + */ + private function getImagesCollection() + { + $collectionMock = $this->getMockBuilder(\Magento\Framework\Data\Collection::class) + ->disableOriginalConstructor() + ->getMock(); + + $items = [ + new \Magento\Framework\DataObject([ + 'file' => 'test_file' + ]), + ]; + + $collectionMock->expects($this->any()) + ->method('getIterator') + ->willReturn(new \ArrayIterator($items)); + + return $collectionMock; + } } diff --git a/app/code/Magento/ConfigurableProduct/Test/Unit/Pricing/Price/ConfigurablePriceResolverTest.php b/app/code/Magento/ConfigurableProduct/Test/Unit/Pricing/Price/ConfigurablePriceResolverTest.php index 8db61bb5e0a4322ff3d614348616dfc0e2f34e27..78ac3a309745825b20e09e0e097d9217d6691ac9 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Unit/Pricing/Price/ConfigurablePriceResolverTest.php +++ b/app/code/Magento/ConfigurableProduct/Test/Unit/Pricing/Price/ConfigurablePriceResolverTest.php @@ -51,24 +51,6 @@ class ConfigurablePriceResolverTest extends \PHPUnit_Framework_TestCase ); } - /** - * situation: There are no used products, thus there are no prices - * - * @expectedException \Magento\Framework\Exception\LocalizedException - */ - public function testResolvePriceWithNoPrices() - { - $product = $this->getMockBuilder( - \Magento\Catalog\Model\Product::class - )->disableOriginalConstructor()->getMock(); - - $product->expects($this->once())->method('getSku')->willReturn('Kiwi'); - - $this->lowestPriceOptionsProvider->expects($this->once())->method('getProducts')->willReturn([]); - - $this->resolver->resolvePrice($product); - } - /** * situation: one product is supplying the price, which could be a price of zero (0) * diff --git a/app/code/Magento/ConfigurableProduct/view/base/layout/catalog_product_prices.xml b/app/code/Magento/ConfigurableProduct/view/base/layout/catalog_product_prices.xml index 47fe31681b5bf0d96ba4cf4935283d415de23ce7..545b04dc0a3279c92100166bda0ff3922b820bb9 100644 --- a/app/code/Magento/ConfigurableProduct/view/base/layout/catalog_product_prices.xml +++ b/app/code/Magento/ConfigurableProduct/view/base/layout/catalog_product_prices.xml @@ -10,6 +10,10 @@ <arguments> <argument name="configurable" xsi:type="array"> <item name="prices" xsi:type="array"> + <item name="tier_price" xsi:type="array"> + <item name="render_class" xsi:type="string">Magento\ConfigurableProduct\Pricing\Render\TierPriceBox</item> + <item name="render_template" xsi:type="string">Magento_ConfigurableProduct::product/price/tier_price.phtml</item> + </item> <item name="final_price" xsi:type="array"> <item name="render_class" xsi:type="string">Magento\ConfigurableProduct\Pricing\Render\FinalPriceBox</item> <item name="render_template" xsi:type="string">Magento_ConfigurableProduct::product/price/final_price.phtml</item> diff --git a/app/code/Magento/ConfigurableProduct/view/base/templates/product/price/tier_price.phtml b/app/code/Magento/ConfigurableProduct/view/base/templates/product/price/tier_price.phtml new file mode 100644 index 0000000000000000000000000000000000000000..01e6bb4222fd3cf6b178a350b0a3c0667c0263ca --- /dev/null +++ b/app/code/Magento/ConfigurableProduct/view/base/templates/product/price/tier_price.phtml @@ -0,0 +1,26 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +?> +<script type="text/x-magento-template" id="tier-prices-template"> + <ul class="prices-tier items"> + <% _.each(tierPrices, function(item, key) { %> + <% var priceStr = '<span class="price-container price-tier_price">' + + '<span data-price-amount="' + priceUtils.formatPrice(item.price, currencyFormat) + '"' + + ' data-price-type=""' + ' class="price-wrapper ">' + + '<span class="price">' + priceUtils.formatPrice(item.price, currencyFormat) + '</span>' + + '</span>' + + '</span>'; %> + <li class="item"> + <%= $t('Buy %1 for %2 each and').replace('%1', item.qty).replace('%2', priceStr) %> + <strong class="benefit"> + <%= $t('save') %><span class="percent tier-<%= key %>"> <%= item.percentage %></span>% + </strong> + </li> + <% }); %> + </ul> +</script> +<div data-role="tier-price-block"></div> diff --git a/app/code/Magento/ConfigurableProduct/view/frontend/web/js/configurable.js b/app/code/Magento/ConfigurableProduct/view/frontend/web/js/configurable.js index 59b313bcb497ddb64e1fdca9bc480afdbbb2f1d9..0c7157f920d9c5f97ec6429fea11bc2aa0af9403 100644 --- a/app/code/Magento/ConfigurableProduct/view/frontend/web/js/configurable.js +++ b/app/code/Magento/ConfigurableProduct/view/frontend/web/js/configurable.js @@ -7,11 +7,12 @@ define([ 'jquery', 'underscore', 'mage/template', + 'mage/translate', 'priceUtils', 'priceBox', 'jquery/ui', 'jquery/jquery.parsequery' -], function ($, _, mageTemplate) { +], function ($, _, mageTemplate, $t, priceUtils) { 'use strict'; $.widget('mage.configurable', { @@ -38,7 +39,10 @@ define([ * * @type {String} */ - gallerySwitchStrategy: 'replace' + gallerySwitchStrategy: 'replace', + tierPriceTemplateSelector: '#tier-prices-template', + tierPriceBlockSelector: '[data-role="tier-price-block"]', + tierPriceTemplate: '' }, /** @@ -84,6 +88,7 @@ define([ options.priceFormat = priceBoxOptions.priceFormat; } options.optionTemplate = mageTemplate(options.optionTemplate); + options.tierPriceTemplate = $(this.options.tierPriceTemplateSelector).html(); options.settings = options.spConfig.containerId ? $(options.spConfig.containerId).find(options.superSelector) : @@ -259,6 +264,7 @@ define([ } this._reloadPrice(); this._displayRegularPriceBlock(this.simpleProduct); + this._displayTierPriceBlock(this.simpleProduct); this._changeProductImage(); }, @@ -513,6 +519,31 @@ define([ var galleryObject = element.data('gallery'); this.options.mediaGalleryInitial = galleryObject.returnCurrentImages(); + }, + + /** + * Show or hide tier price block + * + * @param {*} optionId + * @private + */ + _displayTierPriceBlock: function (optionId) { + if (typeof optionId != 'undefined' && + this.options.spConfig.optionPrices[optionId].tierPrices != [] + ) { + var options = this.options.spConfig.optionPrices[optionId]; + if (this.options.tierPriceTemplate) { + var tierPriceHtml = mageTemplate(this.options.tierPriceTemplate, { + 'tierPrices': options.tierPrices, + '$t': $t, + 'currencyFormat': this.options.spConfig.currencyFormat, + 'priceUtils': priceUtils + }); + $(this.options.tierPriceBlockSelector).html(tierPriceHtml).show(); + } + } else { + $(this.options.tierPriceBlockSelector).hide(); + } } }); diff --git a/app/code/Magento/Contact/etc/di.xml b/app/code/Magento/Contact/etc/di.xml new file mode 100644 index 0000000000000000000000000000000000000000..95cd40cb55e3171e025e3482a290168799395212 --- /dev/null +++ b/app/code/Magento/Contact/etc/di.xml @@ -0,0 +1,16 @@ +<?xml version="1.0"?> +<!-- +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd"> + <type name="Magento\Config\Model\Config\Export\ExcludeList"> + <arguments> + <argument name="configs" xsi:type="array"> + <item name="contact/email/recipient_email" xsi:type="string">1</item> + </argument> + </arguments> + </type> +</config> diff --git a/app/code/Magento/Cron/Console/Command/CronInstallCommand.php b/app/code/Magento/Cron/Console/Command/CronInstallCommand.php new file mode 100644 index 0000000000000000000000000000000000000000..2835244599d38943fea5b2162814bbd6b9edb32e --- /dev/null +++ b/app/code/Magento/Cron/Console/Command/CronInstallCommand.php @@ -0,0 +1,79 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Cron\Console\Command; + +use Magento\Framework\Crontab\CrontabManagerInterface; +use Magento\Framework\Crontab\TasksProviderInterface; +use Magento\Framework\Exception\LocalizedException; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; +use Magento\Framework\Console\Cli; +use Symfony\Component\Console\Input\InputOption; + +/** + * CronInstallCommand installs Magento cron tasks + */ +class CronInstallCommand extends Command +{ + /** + * @var CrontabManagerInterface + */ + private $crontabManager; + + /** + * @var TasksProviderInterface + */ + private $tasksProvider; + + /** + * @param CrontabManagerInterface $crontabManager + * @param TasksProviderInterface $tasksProvider + */ + public function __construct( + CrontabManagerInterface $crontabManager, + TasksProviderInterface $tasksProvider + ) { + $this->crontabManager = $crontabManager; + $this->tasksProvider = $tasksProvider; + + parent::__construct(); + } + + /** + * {@inheritdoc} + */ + protected function configure() + { + $this->setName('cron:install') + ->setDescription('Generates and installs crontab for current user') + ->addOption('force', 'f', InputOption::VALUE_NONE, 'Force install tasks'); + + parent::configure(); + } + + /** + * {@inheritdoc} + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + if ($this->crontabManager->getTasks() && !$input->getOption('force')) { + $output->writeln('<error>Crontab has already been generated and saved</error>'); + return Cli::RETURN_FAILURE; + } + + try { + $this->crontabManager->saveTasks($this->tasksProvider->getTasks()); + } catch (LocalizedException $e) { + $output->writeln('<error>' . $e->getMessage() . '</error>'); + return Cli::RETURN_FAILURE; + } + + $output->writeln('<info>Crontab has been generated and saved</info>'); + + return Cli::RETURN_SUCCESS; + } +} diff --git a/app/code/Magento/Cron/Console/Command/CronRemoveCommand.php b/app/code/Magento/Cron/Console/Command/CronRemoveCommand.php new file mode 100644 index 0000000000000000000000000000000000000000..11c666a556f899e9d7c6358c09291ee9df904998 --- /dev/null +++ b/app/code/Magento/Cron/Console/Command/CronRemoveCommand.php @@ -0,0 +1,62 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Cron\Console\Command; + +use Magento\Framework\Crontab\CrontabManagerInterface; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; +use Magento\Framework\Console\Cli; +use Magento\Framework\Exception\LocalizedException; + +/** + * CronRemoveCommand removes Magento cron tasks + */ +class CronRemoveCommand extends Command +{ + /** + * @var CrontabManagerInterface + */ + private $crontabManager; + + /** + * @param CrontabManagerInterface $crontabManager + */ + public function __construct(CrontabManagerInterface $crontabManager) + { + $this->crontabManager = $crontabManager; + + parent::__construct(); + } + + /** + * {@inheritdoc} + */ + protected function configure() + { + $this->setName('cron:remove') + ->setDescription('Removes tasks from crontab'); + + parent::configure(); + } + + /** + * {@inheritdoc} + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + try { + $this->crontabManager->removeTasks(); + } catch (LocalizedException $e) { + $output->writeln('<error>' . $e->getMessage() . '</error>'); + return Cli::RETURN_FAILURE; + } + + $output->writeln('<info>Magento cron tasks have been removed</info>'); + + return Cli::RETURN_SUCCESS; + } +} diff --git a/app/code/Magento/Cron/Model/Config/Data.php b/app/code/Magento/Cron/Model/Config/Data.php index d09b830d1b539240dce0e81300bc72b4adf46acc..bcfaef37ece7b70b0ca9afe976ccf196aae179b1 100644 --- a/app/code/Magento/Cron/Model/Config/Data.php +++ b/app/code/Magento/Cron/Model/Config/Data.php @@ -3,29 +3,32 @@ * Copyright © 2016 Magento. All rights reserved. * See COPYING.txt for license details. */ +namespace Magento\Cron\Model\Config; + +use Magento\Framework\Serialize\SerializerInterface; /** - * Prepare cron jobs data + * Provides cron configuration */ -namespace Magento\Cron\Model\Config; - class Data extends \Magento\Framework\Config\Data { /** - * Initialize parameters + * Constructor * - * @param \Magento\Cron\Model\Config\Reader\Xml $reader - * @param \Magento\Framework\Config\CacheInterface $cache - * @param \Magento\Cron\Model\Config\Reader\Db $dbReader - * @param string $cacheId + * @param Reader\Xml $reader + * @param \Magento\Framework\Config\CacheInterface $cache + * @param Reader\Db $dbReader + * @param string|null $cacheId + * @param SerializerInterface|null $serializer */ public function __construct( \Magento\Cron\Model\Config\Reader\Xml $reader, \Magento\Framework\Config\CacheInterface $cache, \Magento\Cron\Model\Config\Reader\Db $dbReader, - $cacheId = 'crontab_config_cache' + $cacheId = 'crontab_config_cache', + SerializerInterface $serializer = null ) { - parent::__construct($reader, $cache, $cacheId); + parent::__construct($reader, $cache, $cacheId, $serializer); $this->merge($dbReader->get()); } 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/Model/Groups/Config/Data.php b/app/code/Magento/Cron/Model/Groups/Config/Data.php index 29b70b90195bc49e27013d74a3532de44e076cbf..82c35abff22b08bdb3ff29edbd084eebc19a184c 100644 --- a/app/code/Magento/Cron/Model/Groups/Config/Data.php +++ b/app/code/Magento/Cron/Model/Groups/Config/Data.php @@ -3,25 +3,30 @@ * Copyright © 2016 Magento. All rights reserved. * See COPYING.txt for license details. */ +namespace Magento\Cron\Model\Groups\Config; + +use Magento\Framework\Serialize\SerializerInterface; /** - * Prepare cron jobs data + * Provides cron groups configuration */ -namespace Magento\Cron\Model\Groups\Config; - class Data extends \Magento\Framework\Config\Data { /** + * Constructor + * * @param \Magento\Cron\Model\Groups\Config\Reader\Xml $reader * @param \Magento\Framework\Config\CacheInterface $cache - * @param string $cacheId + * @param string|null $cacheId + * @param SerializerInterface|null $serializer */ public function __construct( \Magento\Cron\Model\Groups\Config\Reader\Xml $reader, \Magento\Framework\Config\CacheInterface $cache, - $cacheId = 'cron_groups_config_cache' + $cacheId = 'cron_groups_config_cache', + SerializerInterface $serializer = null ) { - parent::__construct($reader, $cache, $cacheId); + parent::__construct($reader, $cache, $cacheId, $serializer); } /** diff --git a/app/code/Magento/Cron/Test/Unit/Console/Command/CronInstallCommandTest.php b/app/code/Magento/Cron/Test/Unit/Console/Command/CronInstallCommandTest.php new file mode 100644 index 0000000000000000000000000000000000000000..09949cf78dc8f267fe2bb668d91f2b28032ed8c1 --- /dev/null +++ b/app/code/Magento/Cron/Test/Unit/Console/Command/CronInstallCommandTest.php @@ -0,0 +1,126 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Cron\Test\Unit\Console\Command; + +use Symfony\Component\Console\Tester\CommandTester; +use Magento\Cron\Console\Command\CronInstallCommand; +use Magento\Framework\Crontab\CrontabManagerInterface; +use Magento\Framework\Crontab\TasksProviderInterface; +use Magento\Framework\Console\Cli; +use Magento\Framework\Exception\LocalizedException; +use Magento\Framework\Phrase; + +class CronInstallCommandTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var CrontabManagerInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $crontabManagerMock; + + /** + * @var TasksProviderInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $tasksProviderMock; + + /** + * @var CommandTester + */ + private $commandTester; + + /** + * @return void + */ + protected function setUp() + { + $this->crontabManagerMock = $this->getMockBuilder(CrontabManagerInterface::class) + ->getMockForAbstractClass(); + $this->tasksProviderMock = $this->getMockBuilder(TasksProviderInterface::class) + ->getMockForAbstractClass(); + + $this->commandTester = new CommandTester( + new CronInstallCommand($this->crontabManagerMock, $this->tasksProviderMock) + ); + } + + /** + * @return void + */ + public function testExecuteAlreadyInstalled() + { + $this->crontabManagerMock->expects($this->once()) + ->method('getTasks') + ->willReturn([['* * * * * /bin/php /var/run.php']]); + $this->tasksProviderMock->expects($this->never()) + ->method('getTasks'); + + $this->commandTester->execute([]); + $this->assertEquals( + 'Crontab has already been generated and saved' . PHP_EOL, + $this->commandTester->getDisplay() + ); + $this->assertEquals(Cli::RETURN_FAILURE, $this->commandTester->getStatusCode()); + } + + /** + * @return void + */ + public function testExecuteWithException() + { + $this->crontabManagerMock->expects($this->once()) + ->method('getTasks') + ->willReturn([]); + $this->tasksProviderMock->expects($this->once()) + ->method('getTasks') + ->willReturn([]); + $this->crontabManagerMock->expects($this->once()) + ->method('saveTasks') + ->willThrowException(new LocalizedException(new Phrase('Some error'))); + + $this->commandTester->execute([]); + $this->assertEquals( + 'Some error' . PHP_EOL, + $this->commandTester->getDisplay() + ); + $this->assertEquals(Cli::RETURN_FAILURE, $this->commandTester->getStatusCode()); + } + + /** + * @param array $existingTasks + * @param array $options + * @return void + * @dataProvider executeDataProvider + */ + public function testExecute($existingTasks, $options) + { + $this->crontabManagerMock->expects($this->once()) + ->method('getTasks') + ->willReturn($existingTasks); + $this->tasksProviderMock->expects($this->once()) + ->method('getTasks') + ->willReturn([]); + $this->crontabManagerMock->expects($this->once()) + ->method('saveTasks') + ->with([]); + + $this->commandTester->execute($options); + $this->assertEquals( + 'Crontab has been generated and saved' . PHP_EOL, + $this->commandTester->getDisplay() + ); + $this->assertEquals(Cli::RETURN_SUCCESS, $this->commandTester->getStatusCode()); + } + + /** + * @return array + */ + public function executeDataProvider() + { + return [ + ['existingTasks' => [], 'options' => []], + ['existingTasks' => ['* * * * * /bin/php /var/www/run.php'], 'options' => ['-f'=> true]] + ]; + } +} diff --git a/app/code/Magento/Cron/Test/Unit/Console/Command/CronRemoveCommandTest.php b/app/code/Magento/Cron/Test/Unit/Console/Command/CronRemoveCommandTest.php new file mode 100644 index 0000000000000000000000000000000000000000..cd017b26d758578482bffa137a3f221650619bae --- /dev/null +++ b/app/code/Magento/Cron/Test/Unit/Console/Command/CronRemoveCommandTest.php @@ -0,0 +1,72 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Cron\Test\Unit\Console\Command; + +use Symfony\Component\Console\Tester\CommandTester; +use Magento\Cron\Console\Command\CronRemoveCommand; +use Magento\Framework\Crontab\CrontabManagerInterface; +use Magento\Framework\Console\Cli; +use Magento\Framework\Exception\LocalizedException; +use Magento\Framework\Phrase; + +class CronRemoveCommandTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var CrontabManagerInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $crontabManagerMock; + + /** + * @var CommandTester + */ + private $commandTester; + + /** + * @return void + */ + protected function setUp() + { + $this->crontabManagerMock = $this->getMockBuilder(CrontabManagerInterface::class) + ->getMockForAbstractClass(); + + $this->commandTester = new CommandTester( + new CronRemoveCommand($this->crontabManagerMock) + ); + } + + /** + * @return void + */ + public function testExecute() + { + $this->crontabManagerMock->expects($this->once()) + ->method('RemoveTasks'); + + $this->commandTester->execute([]); + $this->assertEquals( + 'Magento cron tasks have been removed' . PHP_EOL, + $this->commandTester->getDisplay() + ); + $this->assertEquals(Cli::RETURN_SUCCESS, $this->commandTester->getStatusCode()); + } + + /** + * @return void + */ + public function testExecuteFailed() + { + $this->crontabManagerMock->expects($this->once()) + ->method('RemoveTasks') + ->willThrowException(new LocalizedException(new Phrase('Some error'))); + + $this->commandTester->execute([]); + $this->assertEquals( + 'Some error' . PHP_EOL, + $this->commandTester->getDisplay() + ); + $this->assertEquals(Cli::RETURN_FAILURE, $this->commandTester->getStatusCode()); + } +} diff --git a/app/code/Magento/Cron/Test/Unit/Model/Config/DataTest.php b/app/code/Magento/Cron/Test/Unit/Model/Config/DataTest.php index 1803deb002f6d20cec2ebaa83298e549d1f85477..e25fdfe71d2d105f1c956dc4ea3cfe9dac1088f3 100644 --- a/app/code/Magento/Cron/Test/Unit/Model/Config/DataTest.php +++ b/app/code/Magento/Cron/Test/Unit/Model/Config/DataTest.php @@ -30,19 +30,18 @@ class DataTest extends \PHPUnit_Framework_TestCase 'job2' => ['schedule' => '* * * * *', 'instance' => 'JobModel2', 'method' => 'method2'], ]; - $cache->expects( - $this->any() - )->method( - 'load' - )->with( - $this->equalTo('test_cache_id') - )->will( - $this->returnValue(serialize($jobs)) - ); + $cache->expects($this->any()) + ->method('load') + ->with('test_cache_id') + ->willReturn(json_encode($jobs)); $dbReader->expects($this->once())->method('get')->will($this->returnValue($dbReaderData)); - $configData = new \Magento\Cron\Model\Config\Data($reader, $cache, $dbReader, 'test_cache_id'); + $serializerMock = $this->getMock(\Magento\Framework\Serialize\SerializerInterface::class); + $serializerMock->method('unserialize') + ->willReturn($jobs); + + $configData = new \Magento\Cron\Model\Config\Data($reader, $cache, $dbReader, 'test_cache_id', $serializerMock); $expected = [ 'job1' => ['schedule' => '* * * * *', 'instance' => 'JobModel1', 'method' => 'method1'], 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..6abc9096f24012309a3b56cb0b84912d3a8d1e26 100644 --- a/app/code/Magento/Cron/etc/di.xml +++ b/app/code/Magento/Cron/etc/di.xml @@ -8,11 +8,8 @@ <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> + <preference for="Magento\Framework\Crontab\CrontabManagerInterface" type="Magento\Framework\Crontab\CrontabManager" /> + <preference for="Magento\Framework\Crontab\TasksProviderInterface" type="Magento\Framework\Crontab\TasksProvider" /> <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> @@ -33,6 +30,8 @@ <arguments> <argument name="commands" xsi:type="array"> <item name="cronCommand" xsi:type="object">Magento\Cron\Console\Command\CronCommand</item> + <item name="cronInstall" xsi:type="object">Magento\Cron\Console\Command\CronInstallCommand</item> + <item name="cronRemove" xsi:type="object">Magento\Cron\Console\Command\CronRemoveCommand</item> </argument> </arguments> </type> @@ -43,4 +42,24 @@ </argument> </arguments> </type> + <type name="Magento\Framework\Crontab\CrontabManager"> + <arguments> + <argument name="shell" xsi:type="object">Magento\Framework\App\Shell</argument> + </arguments> + </type> + <type name="Magento\Framework\Crontab\TasksProviderInterface"> + <arguments> + <argument name="tasks" xsi:type="array"> + <item name="cronMagento" xsi:type="array"> + <item name="command" xsi:type="string">{magentoRoot}bin/magento cron:run | grep -v "Ran jobs by schedule" >> {magentoLog}magento.cron.log</item> + </item> + <item name="cronUpdate" xsi:type="array"> + <item name="command" xsi:type="string">{magentoRoot}update/cron.php >> {magentoLog}update.cron.log</item> + </item> + <item name="cronSetup" xsi:type="array"> + <item name="command" xsi:type="string">{magentoRoot}bin/magento setup:cron:run >> {magentoLog}setup.cron.log</item> + </item> + </argument> + </arguments> + </type> </config> diff --git a/app/code/Magento/Customer/Model/Address/AbstractAddress.php b/app/code/Magento/Customer/Model/Address/AbstractAddress.php index 7b32da94ddedb476eda579521c1a19c002618ec4..786c5f9770a2e56123983c7b82c63ea369bec0a4 100644 --- a/app/code/Magento/Customer/Model/Address/AbstractAddress.php +++ b/app/code/Magento/Customer/Model/Address/AbstractAddress.php @@ -554,6 +554,8 @@ class AbstractAddress extends AbstractExtensibleModel implements AddressModelInt /** * Validate address attribute values * + * + * * @return bool|array * @SuppressWarnings(PHPMD.CyclomaticComplexity) * @SuppressWarnings(PHPMD.NPathComplexity) @@ -562,23 +564,24 @@ class AbstractAddress extends AbstractExtensibleModel implements AddressModelInt { $errors = []; if (!\Zend_Validate::is($this->getFirstname(), 'NotEmpty')) { - $errors[] = __('Please enter the first name.'); + $errors[] = __('%fieldName is a required field.', ['fieldName' => 'firstname']); } if (!\Zend_Validate::is($this->getLastname(), 'NotEmpty')) { - $errors[] = __('Please enter the last name.'); + $errors[] = __('%fieldName is a required field.', ['fieldName' => 'lastname']); } if (!\Zend_Validate::is($this->getStreetLine(1), 'NotEmpty')) { - $errors[] = __('Please enter the street.'); + $errors[] = __('%fieldName is a required field.', ['fieldName' => 'street']); } if (!\Zend_Validate::is($this->getCity(), 'NotEmpty')) { - $errors[] = __('Please enter the city.'); + $errors[] = __('%fieldName is a required field.', ['fieldName' => 'city']); } if (!\Zend_Validate::is($this->getTelephone(), 'NotEmpty')) { - $errors[] = __('Please enter the phone number.'); + $errors[] = __('%fieldName is a required field.', ['fieldName' => 'telephone']); + } $_havingOptionalZip = $this->_directoryData->getCountriesWithOptionalZip(); @@ -590,11 +593,11 @@ class AbstractAddress extends AbstractExtensibleModel implements AddressModelInt 'NotEmpty' ) ) { - $errors[] = __('Please enter the zip/postal code.'); + $errors[] = __('%fieldName is a required field.', ['fieldName' => 'postcode']); } if (!\Zend_Validate::is($this->getCountryId(), 'NotEmpty')) { - $errors[] = __('Please enter the country.'); + $errors[] = __('%fieldName is a required field.', ['fieldName' => 'countryId']); } if ($this->getCountryModel()->getRegionCollection()->getSize() && !\Zend_Validate::is( @@ -604,7 +607,7 @@ class AbstractAddress extends AbstractExtensibleModel implements AddressModelInt $this->getCountryId() ) ) { - $errors[] = __('Please enter the state/province.'); + $errors[] = __('%fieldName is a required field.', ['fieldName' => 'regionId']); } if (empty($errors) || $this->getShouldIgnoreValidation()) { diff --git a/app/code/Magento/Customer/Model/Address/Config.php b/app/code/Magento/Customer/Model/Address/Config.php index cd76fd253f499ea9a951cee0bd6b27d15016706a..18a043bc019bb26b5732d2dc2f2d5359be96648c 100644 --- a/app/code/Magento/Customer/Model/Address/Config.php +++ b/app/code/Magento/Customer/Model/Address/Config.php @@ -7,12 +7,11 @@ namespace Magento\Customer\Model\Address; use Magento\Framework\Config\Data as ConfigData; use Magento\Framework\DataObject; +use Magento\Framework\Serialize\SerializerInterface; use Magento\Store\Model\ScopeInterface; /** - * Customer address config - * - * @author Magento Core Team <core@magentocommerce.com> + * Customer address configuration */ class Config extends ConfigData { @@ -23,7 +22,7 @@ class Config extends ConfigData const DEFAULT_ADDRESS_FORMAT = 'oneline'; /** - * Customer Address Templates per store + * Customer address templates per store * * @var array */ @@ -37,8 +36,7 @@ class Config extends ConfigData protected $_store = null; /** - * Default types per store - * Using for invalid code + * Default types per store, used for invalid code * * @var array */ @@ -60,12 +58,15 @@ class Config extends ConfigData protected $_scopeConfig; /** - * @param \Magento\Customer\Model\Address\Config\Reader $reader + * Constructor + * + * @param Config\Reader $reader * @param \Magento\Framework\Config\CacheInterface $cache * @param \Magento\Store\Model\StoreManagerInterface $storeManager * @param \Magento\Customer\Helper\Address $addressHelper * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig - * @param string $cacheId + * @param string|null $cacheId + * @param SerializerInterface|null $serializer */ public function __construct( \Magento\Customer\Model\Address\Config\Reader $reader, @@ -73,9 +74,10 @@ class Config extends ConfigData \Magento\Store\Model\StoreManagerInterface $storeManager, \Magento\Customer\Helper\Address $addressHelper, \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig, - $cacheId = 'address_format' + $cacheId = 'address_format', + SerializerInterface $serializer = null ) { - parent::__construct($reader, $cache, $cacheId); + parent::__construct($reader, $cache, $cacheId, $serializer); $this->_storeManager = $storeManager; $this->_addressHelper = $addressHelper; $this->_scopeConfig = $scopeConfig; diff --git a/app/code/Magento/Customer/Model/Customer/DataProvider.php b/app/code/Magento/Customer/Model/Customer/DataProvider.php index 2f46459a794eca284e91c1dddf3c2e39def0cd9f..b01b8b7d833e278d8d8f157910f9056e20099222 100644 --- a/app/code/Magento/Customer/Model/Customer/DataProvider.php +++ b/app/code/Magento/Customer/Model/Customer/DataProvider.php @@ -271,23 +271,18 @@ class DataProvider extends \Magento\Ui\DataProvider\AbstractDataProvider ) { $stat = $fileProcessor->getStat($file); $viewUrl = $fileProcessor->getViewUrl($file, $attribute->getFrontendInput()); - } - - $fileName = $file; - if (strrpos($fileName, '/') !== false) { - $fileName = substr($fileName, strrpos($fileName, '/') + 1); - } - if (!empty($file)) { return [ [ 'file' => $file, 'size' => isset($stat) ? $stat['size'] : 0, 'url' => isset($viewUrl) ? $viewUrl : '', - 'name' => $fileName, + 'name' => basename($file), + 'type' => $fileProcessor->getMimeType($file), ], ]; } + return []; } diff --git a/app/code/Magento/Customer/Model/Customer/NotificationStorage.php b/app/code/Magento/Customer/Model/Customer/NotificationStorage.php index 93cb2e24d40f3fcee1f50409b9d999e33f28e00c..67ee60971d98ac7c2cd089428ad923a4580dfd78 100644 --- a/app/code/Magento/Customer/Model/Customer/NotificationStorage.php +++ b/app/code/Magento/Customer/Model/Customer/NotificationStorage.php @@ -6,6 +6,7 @@ namespace Magento\Customer\Model\Customer; use Magento\Framework\Cache\FrontendInterface; +use Magento\Framework\Serialize\SerializerInterface; class NotificationStorage { @@ -19,6 +20,16 @@ class NotificationStorage /** * @param FrontendInterface $cache */ + + /** + * @var SerializerInterface + */ + private $serializer; + + /** + * NotificationStorage constructor. + * @param FrontendInterface $cache + */ public function __construct(FrontendInterface $cache) { $this->cache = $cache; @@ -34,7 +45,7 @@ class NotificationStorage public function add($notificationType, $customerId) { $this->cache->save( - serialize([ + $this->getSerializer()->serialize([ 'customer_id' => $customerId, 'notification_type' => $notificationType ]), @@ -77,4 +88,19 @@ class NotificationStorage { return 'notification_' . $notificationType . '_' . $customerId; } + + /** + * Get serializer + * + * @return SerializerInterface + * @deprecated + */ + private function getSerializer() + { + if ($this->serializer === null) { + $this->serializer = \Magento\Framework\App\ObjectManager::getInstance() + ->get(SerializerInterface::class); + } + return $this->serializer; + } } diff --git a/app/code/Magento/Customer/Model/FileProcessor.php b/app/code/Magento/Customer/Model/FileProcessor.php index c98a85cc18463306b3360982b336a945ed63de3c..3e0ae375fcff132cb90d85ddfff0b71b04aa66e4 100644 --- a/app/code/Magento/Customer/Model/FileProcessor.php +++ b/app/code/Magento/Customer/Model/FileProcessor.php @@ -5,17 +5,6 @@ */ namespace Magento\Customer\Model; -use Magento\Customer\Api\AddressMetadataInterface; -use Magento\Customer\Api\CustomerMetadataInterface; -use Magento\Framework\App\Filesystem\DirectoryList; -use Magento\Framework\Exception\LocalizedException; -use Magento\Framework\Filesystem; -use Magento\Framework\Filesystem\Directory\WriteInterface; -use Magento\Framework\Url\EncoderInterface; -use Magento\Framework\UrlInterface; -use Magento\MediaStorage\Model\File\Uploader; -use Magento\MediaStorage\Model\File\UploaderFactory; - class FileProcessor { /** @@ -24,22 +13,22 @@ class FileProcessor const TMP_DIR = 'tmp'; /** - * @var WriteInterface + * @var \Magento\Framework\Filesystem\Directory\WriteInterface */ private $mediaDirectory; /** - * @var UploaderFactory + * @var \Magento\MediaStorage\Model\File\UploaderFactory */ private $uploaderFactory; /** - * @var UrlInterface + * @var \Magento\Framework\UrlInterface */ private $urlBuilder; /** - * @var EncoderInterface + * @var \Magento\Framework\Url\EncoderInterface */ private $urlEncoder; @@ -54,26 +43,34 @@ class FileProcessor private $allowedExtensions = []; /** - * @param Filesystem $filesystem - * @param UploaderFactory $uploaderFactory - * @param UrlInterface $urlBuilder - * @param EncoderInterface $urlEncoder + * @var \Magento\Framework\File\Mime + */ + private $mime; + + /** + * @param \Magento\Framework\Filesystem $filesystem + * @param \Magento\MediaStorage\Model\File\UploaderFactory $uploaderFactory + * @param \Magento\Framework\UrlInterface $urlBuilder + * @param \Magento\Framework\Url\EncoderInterface $urlEncoder * @param string $entityTypeCode + * @param \Magento\Framework\File\Mime $mime * @param array $allowedExtensions */ public function __construct( - Filesystem $filesystem, - UploaderFactory $uploaderFactory, - UrlInterface $urlBuilder, - EncoderInterface $urlEncoder, + \Magento\Framework\Filesystem $filesystem, + \Magento\MediaStorage\Model\File\UploaderFactory $uploaderFactory, + \Magento\Framework\UrlInterface $urlBuilder, + \Magento\Framework\Url\EncoderInterface $urlEncoder, $entityTypeCode, + \Magento\Framework\File\Mime $mime, array $allowedExtensions = [] ) { - $this->mediaDirectory = $filesystem->getDirectoryWrite(DirectoryList::MEDIA); + $this->mediaDirectory = $filesystem->getDirectoryWrite(\Magento\Framework\App\Filesystem\DirectoryList::MEDIA); $this->uploaderFactory = $uploaderFactory; $this->urlBuilder = $urlBuilder; $this->urlEncoder = $urlEncoder; $this->entityTypeCode = $entityTypeCode; + $this->mime = $mime; $this->allowedExtensions = $allowedExtensions; } @@ -107,6 +104,21 @@ class FileProcessor return $result; } + /** + * Retrieve MIME type of requested file + * + * @param string $fileName + * @return string + */ + public function getMimeType($fileName) + { + $filePath = $this->entityTypeCode . '/' . ltrim($fileName, '/'); + $absoluteFilePath = $this->mediaDirectory->getAbsolutePath($filePath); + + $result = $this->mime->getMimeType($absoluteFilePath); + return $result; + } + /** * Check if the file exists * @@ -132,13 +144,13 @@ class FileProcessor { $viewUrl = ''; - if ($this->entityTypeCode == AddressMetadataInterface::ENTITY_TYPE_ADDRESS) { + if ($this->entityTypeCode == \Magento\Customer\Api\AddressMetadataInterface::ENTITY_TYPE_ADDRESS) { $filePath = $this->entityTypeCode . '/' . ltrim($filePath, '/'); - $viewUrl = $this->urlBuilder->getBaseUrl(['_type' => UrlInterface::URL_TYPE_MEDIA]) + $viewUrl = $this->urlBuilder->getBaseUrl(['_type' => \Magento\Framework\UrlInterface::URL_TYPE_MEDIA]) . $this->mediaDirectory->getRelativePath($filePath); } - if ($this->entityTypeCode == CustomerMetadataInterface::ENTITY_TYPE_CUSTOMER) { + if ($this->entityTypeCode == \Magento\Customer\Api\CustomerMetadataInterface::ENTITY_TYPE_CUSTOMER) { $viewUrl = $this->urlBuilder->getUrl( 'customer/index/viewfile', [$type => $this->urlEncoder->encode(ltrim($filePath, '/'))] @@ -153,11 +165,11 @@ class FileProcessor * * @param string $fileId * @return \string[] - * @throws LocalizedException + * @throws \Magento\Framework\Exception\LocalizedException */ public function saveTemporaryFile($fileId) { - /** @var Uploader $uploader */ + /** @var \Magento\MediaStorage\Model\File\Uploader $uploader */ $uploader = $this->uploaderFactory->create(['fileId' => $fileId]); $uploader->setFilesDispersion(false); $uploader->setFilenamesCaseSensitivity(false); @@ -170,7 +182,9 @@ class FileProcessor $result = $uploader->save($path); if (!$result) { - throw new LocalizedException(__('File can not be saved to the destination folder.')); + throw new \Magento\Framework\Exception\LocalizedException( + __('File can not be saved to the destination folder.') + ); } return $result; @@ -181,28 +195,28 @@ class FileProcessor * * @param string $fileName * @return string - * @throws LocalizedException + * @throws \Magento\Framework\Exception\LocalizedException */ public function moveTemporaryFile($fileName) { $fileName = ltrim($fileName, '/'); - $dispersionPath = Uploader::getDispretionPath($fileName); + $dispersionPath = \Magento\MediaStorage\Model\File\Uploader::getDispretionPath($fileName); $destinationPath = $this->entityTypeCode . $dispersionPath; if (!$this->mediaDirectory->create($destinationPath)) { - throw new LocalizedException( + throw new \Magento\Framework\Exception\LocalizedException( __('Unable to create directory %1.', $destinationPath) ); } if (!$this->mediaDirectory->isWritable($destinationPath)) { - throw new LocalizedException( + throw new \Magento\Framework\Exception\LocalizedException( __('Destination folder is not writable or does not exists.') ); } - $destinationFileName = Uploader::getNewFileName( + $destinationFileName = \Magento\MediaStorage\Model\File\Uploader::getNewFileName( $this->mediaDirectory->getAbsolutePath($destinationPath) . '/' . $fileName ); @@ -212,7 +226,7 @@ class FileProcessor $destinationPath . '/' . $destinationFileName ); } catch (\Exception $e) { - throw new LocalizedException( + throw new \Magento\Framework\Exception\LocalizedException( __('Something went wrong while saving the file.') ); } diff --git a/app/code/Magento/Customer/Model/ResourceModel/AddressRepository.php b/app/code/Magento/Customer/Model/ResourceModel/AddressRepository.php index 67d4ea32369ba8a37fef329d2aec809037fcac75..24df57e07e84826dcd7a19cdd84e5e6ca70ac37c 100644 --- a/app/code/Magento/Customer/Model/ResourceModel/AddressRepository.php +++ b/app/code/Magento/Customer/Model/ResourceModel/AddressRepository.php @@ -124,8 +124,12 @@ class AddressRepository implements \Magento\Customer\Api\AddressRepositoryInterf $addressModel->updateData($address); } - $inputException = $this->_validate($addressModel); - if ($inputException->wasErrorAdded()) { + $errors = $addressModel->validate(); + if ($errors !== true) { + $inputException = new InputException(); + foreach ($errors as $error) { + $inputException->addError($error); + } throw $inputException; } $addressModel->save(); @@ -255,70 +259,6 @@ class AddressRepository implements \Magento\Customer\Api\AddressRepositoryInterf return true; } - /** - * Validate Customer Addresses attribute values. - * - * @param CustomerAddressModel $customerAddressModel the model to validate - * @return InputException - * - * @SuppressWarnings(PHPMD.NPathComplexity) - * @SuppressWarnings(PHPMD.CyclomaticComplexity) - */ - private function _validate(CustomerAddressModel $customerAddressModel) - { - $exception = new InputException(); - if ($customerAddressModel->getShouldIgnoreValidation()) { - return $exception; - } - - if (!\Zend_Validate::is($customerAddressModel->getFirstname(), 'NotEmpty')) { - $exception->addError(__('%fieldName is a required field.', ['fieldName' => 'firstname'])); - } - - if (!\Zend_Validate::is($customerAddressModel->getLastname(), 'NotEmpty')) { - $exception->addError(__('%fieldName is a required field.', ['fieldName' => 'lastname'])); - } - - if (!\Zend_Validate::is($customerAddressModel->getStreetLine(1), 'NotEmpty')) { - $exception->addError(__('%fieldName is a required field.', ['fieldName' => 'street'])); - } - - if (!\Zend_Validate::is($customerAddressModel->getCity(), 'NotEmpty')) { - $exception->addError(__('%fieldName is a required field.', ['fieldName' => 'city'])); - } - - if (!\Zend_Validate::is($customerAddressModel->getTelephone(), 'NotEmpty')) { - $exception->addError(__('%fieldName is a required field.', ['fieldName' => 'telephone'])); - } - - $havingOptionalZip = $this->directoryData->getCountriesWithOptionalZip(); - if (!in_array($customerAddressModel->getCountryId(), $havingOptionalZip) - && !\Zend_Validate::is($customerAddressModel->getPostcode(), 'NotEmpty') - ) { - $exception->addError(__('%fieldName is a required field.', ['fieldName' => 'postcode'])); - } - - if (!\Zend_Validate::is($customerAddressModel->getCountryId(), 'NotEmpty')) { - $exception->addError(__('%fieldName is a required field.', ['fieldName' => 'countryId'])); - } - - if ($this->directoryData->isRegionRequired($customerAddressModel->getCountryId())) { - $regionCollection = $customerAddressModel->getCountryModel()->getRegionCollection(); - if (!$regionCollection->count() && empty($customerAddressModel->getRegion())) { - $exception->addError(__('%fieldName is a required field.', ['fieldName' => 'region'])); - } elseif ( - $regionCollection->count() - && !in_array( - $customerAddressModel->getRegionId(), - array_column($regionCollection->getData(), 'region_id') - ) - ) { - $exception->addError(__('%fieldName is a required field.', ['fieldName' => 'regionId'])); - } - } - return $exception; - } - /** * Retrieve collection processor * diff --git a/app/code/Magento/Customer/Test/Unit/Model/Address/AbstractAddressTest.php b/app/code/Magento/Customer/Test/Unit/Model/Address/AbstractAddressTest.php index 32112ccdeb1aec053955226a49eb1838f8c4276b..ba833221aba18cb2b4f2b1e90a9c8b59d78327f5 100644 --- a/app/code/Magento/Customer/Test/Unit/Model/Address/AbstractAddressTest.php +++ b/app/code/Magento/Customer/Test/Unit/Model/Address/AbstractAddressTest.php @@ -336,31 +336,31 @@ class AbstractAddressTest extends \PHPUnit_Framework_TestCase return [ 'firstname' => [ array_merge(array_diff_key($data, ['firstname' => '']), ['country_id' => $countryId++]), - ['Please enter the first name.'], + ['firstname is a required field.'], ], 'lastname' => [ array_merge(array_diff_key($data, ['lastname' => '']), ['country_id' => $countryId++]), - ['Please enter the last name.'], + ['lastname is a required field.'], ], 'street' => [ array_merge(array_diff_key($data, ['street' => '']), ['country_id' => $countryId++]), - ['Please enter the street.'], + ['street is a required field.'], ], 'city' => [ array_merge(array_diff_key($data, ['city' => '']), ['country_id' => $countryId++]), - ['Please enter the city.'], + ['city is a required field.'], ], 'telephone' => [ array_merge(array_diff_key($data, ['telephone' => '']), ['country_id' => $countryId++]), - ['Please enter the phone number.'], + ['telephone is a required field.'], ], 'postcode' => [ array_merge(array_diff_key($data, ['postcode' => '']), ['country_id' => $countryId++]), - ['Please enter the zip/postal code.'], + ['postcode is a required field.'], ], 'country_id' => [ array_diff_key($data, ['country_id' => '']), - ['Please enter the country.'], + ['countryId is a required field.'], ], 'validated' => [array_merge($data, ['country_id' => $countryId++]), true], ]; diff --git a/app/code/Magento/Customer/Test/Unit/Model/Address/ConfigTest.php b/app/code/Magento/Customer/Test/Unit/Model/Address/ConfigTest.php index 5c2aeec636cecf90bc4d6abf383dcaef53190c89..2b4a93084c7ac40ec5909d484079245f161c35f3 100644 --- a/app/code/Magento/Customer/Test/Unit/Model/Address/ConfigTest.php +++ b/app/code/Magento/Customer/Test/Unit/Model/Address/ConfigTest.php @@ -10,122 +10,110 @@ class ConfigTest extends \PHPUnit_Framework_TestCase /** * @var \PHPUnit_Framework_MockObject_MockObject */ - protected $_readerMock; + protected $addressHelperMock; /** * @var \PHPUnit_Framework_MockObject_MockObject */ - protected $_cacheMock; + protected $storeMock; /** * @var \PHPUnit_Framework_MockObject_MockObject */ - protected $_storeManagerMock; - - /** - * @var \PHPUnit_Framework_MockObject_MockObject - */ - protected $_addressHelperMock; - - /** - * @var \PHPUnit_Framework_MockObject_MockObject - */ - protected $_storeMock; - - /** - * @var \PHPUnit_Framework_MockObject_MockObject - */ - protected $_scopeConfigMock; + protected $scopeConfigMock; /** * @var \Magento\Customer\Model\Address\Config */ - protected $_model; - - /** - * @var string - */ - protected $_cacheId = 'cache_id'; + protected $model; protected function setUp() { - $this->_storeMock = $this->getMock(\Magento\Store\Model\Store::class, [], [], '', false); - $this->_scopeConfigMock = $this->getMock(\Magento\Framework\App\Config\ScopeConfigInterface::class); + $cacheId = 'cache_id'; + $objectManagerHelper = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); + $this->storeMock = $this->getMock(\Magento\Store\Model\Store::class, [], [], '', false); + $this->scopeConfigMock = $this->getMock(\Magento\Framework\App\Config\ScopeConfigInterface::class); - $this->_readerMock = $this->getMock( + $readerMock = $this->getMock( \Magento\Customer\Model\Address\Config\Reader::class, [], [], '', false ); - $this->_cacheMock = $this->getMock(\Magento\Framework\Config\CacheInterface::class); - $this->_storeManagerMock = $this->getMock(\Magento\Store\Model\StoreManager::class, [], [], '', false); - $this->_storeManagerMock->expects( + $cacheMock = $this->getMock(\Magento\Framework\Config\CacheInterface::class); + $storeManagerMock = $this->getMock(\Magento\Store\Model\StoreManager::class, [], [], '', false); + $storeManagerMock->expects( $this->once() )->method( 'getStore' )->will( - $this->returnValue($this->_storeMock) + $this->returnValue($this->storeMock) ); - $this->_addressHelperMock = $this->getMock(\Magento\Customer\Helper\Address::class, [], [], '', false); + $this->addressHelperMock = $this->getMock(\Magento\Customer\Helper\Address::class, [], [], '', false); - $this->_cacheMock->expects( + $cacheMock->expects( $this->once() )->method( 'load' )->with( - $this->_cacheId + $cacheId )->will( $this->returnValue(false) ); $fixtureConfigData = require __DIR__ . '/Config/_files/formats_merged.php'; - $this->_readerMock->expects($this->once())->method('read')->will($this->returnValue($fixtureConfigData)); - - $this->_cacheMock->expects( - $this->once() - )->method( - 'save' - )->with( - serialize($fixtureConfigData), - $this->_cacheId - ); - - $this->_model = new \Magento\Customer\Model\Address\Config( - $this->_readerMock, - $this->_cacheMock, - $this->_storeManagerMock, - $this->_addressHelperMock, - $this->_scopeConfigMock, - $this->_cacheId + $readerMock->expects($this->once())->method('read')->will($this->returnValue($fixtureConfigData)); + + $cacheMock->expects($this->once()) + ->method('save') + ->with( + json_encode($fixtureConfigData), + $cacheId + ); + + $serializerMock = $this->getMock(\Magento\Framework\Serialize\SerializerInterface::class); + $serializerMock->method('serialize') + ->willReturn(json_encode($fixtureConfigData)); + $serializerMock->method('unserialize') + ->willReturn($fixtureConfigData); + + $this->model = $objectManagerHelper->getObject( + \Magento\Customer\Model\Address\Config::class, + [ + 'reader' => $readerMock, + 'cache' => $cacheMock, + 'storeManager' => $storeManagerMock, + 'scopeConfig' => $this->scopeConfigMock, + 'cacheId' => $cacheId, + 'serializer' => $serializerMock, + 'addressHelper' => $this->addressHelperMock, + ] ); } public function testGetStore() { - $this->assertEquals($this->_storeMock, $this->_model->getStore()); + $this->assertEquals($this->storeMock, $this->model->getStore()); } public function testSetStore() { - $this->_model->setStore($this->_storeMock); - - //no call to $_storeManagerMock's method - $this->assertEquals($this->_storeMock, $this->_model->getStore()); + $this->model->setStore($this->storeMock); + $this->assertEquals($this->storeMock, $this->model->getStore()); } public function testGetFormats() { - $this->_storeMock->expects($this->once())->method('getId'); + $this->storeMock->expects($this->once())->method('getId'); - $this->_scopeConfigMock->expects($this->any())->method('getValue')->will($this->returnValue('someValue')); + $this->scopeConfigMock->expects($this->any())->method('getValue')->will($this->returnValue('someValue')); $rendererMock = $this->getMock(\Magento\Framework\DataObject::class); - $this->_addressHelperMock->expects( + $this->addressHelperMock->expects( $this->any() )->method( 'getRenderer' @@ -160,6 +148,6 @@ class ConfigTest extends \PHPUnit_Framework_TestCase ); $expectedResult = [$firstExpected, $secondExpected]; - $this->assertEquals($expectedResult, $this->_model->getFormats()); + $this->assertEquals($expectedResult, $this->model->getFormats()); } } diff --git a/app/code/Magento/Customer/Test/Unit/Model/Customer/DataProviderTest.php b/app/code/Magento/Customer/Test/Unit/Model/Customer/DataProviderTest.php index e594432b5bd66358a2ed13f3d93d41f26f73a7bd..1077736bd44651d470591141fd1cdb230de8cb1e 100644 --- a/app/code/Magento/Customer/Test/Unit/Model/Customer/DataProviderTest.php +++ b/app/code/Magento/Customer/Test/Unit/Model/Customer/DataProviderTest.php @@ -688,6 +688,7 @@ class DataProviderTest extends \PHPUnit_Framework_TestCase $filename = '/filename.ext1'; $viewUrl = 'viewUrl'; + $mime = 'image/png'; $expectedData = [ $customerId => [ @@ -699,6 +700,7 @@ class DataProviderTest extends \PHPUnit_Framework_TestCase 'size' => 1, 'url' => $viewUrl, 'name' => 'filename.ext1', + 'type' => $mime, ], ], ], @@ -778,6 +780,10 @@ class DataProviderTest extends \PHPUnit_Framework_TestCase ->method('getViewUrl') ->with('/filename.ext1', 'image') ->willReturn($viewUrl); + $this->fileProcessor->expects($this->once()) + ->method('getMimeType') + ->with($filename) + ->willReturn($mime); $objectManager = new ObjectManager($this); $dataProvider = $objectManager->getObject( diff --git a/app/code/Magento/Customer/Test/Unit/Model/Customer/NotificationStorageTest.php b/app/code/Magento/Customer/Test/Unit/Model/Customer/NotificationStorageTest.php index 0d2b32f747a80a1f564755a21f47771b5673d27f..644d0a2d7012227ae6a30cfd2e7b3b9ceb8dbd9d 100644 --- a/app/code/Magento/Customer/Test/Unit/Model/Customer/NotificationStorageTest.php +++ b/app/code/Magento/Customer/Test/Unit/Model/Customer/NotificationStorageTest.php @@ -7,81 +7,87 @@ namespace Magento\Customer\Test\Unit\Model\Customer; use Magento\Customer\Model\Customer\NotificationStorage; -/** - * Class NotificationStorageTest - * - * Test for class \Magento\Customer\Model\Customer\NotificationStorage - */ class NotificationStorageTest extends \PHPUnit_Framework_TestCase { /** - * @var NotificationStorage|\PHPUnit_Framework_MockObject_MockObject + * @var NotificationStorage */ - protected $model; + private $notificationStorage; /** * @var \Magento\Framework\Cache\FrontendInterface|\PHPUnit_Framework_MockObject_MockObject */ - protected $cache; + private $cacheMock; /** - * Set up - * - * @return void + * @var \Magento\Framework\Serialize\SerializerInterface|\PHPUnit_Framework_MockObject_MockObject */ + private $serializerMock; + protected function setUp() { - $this->cache = $this->getMockBuilder(\Magento\Framework\Cache\FrontendInterface::class) - ->getMockForAbstractClass(); - $this->model = new NotificationStorage($this->cache); + $objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); + $this->cacheMock = $this->getMock(\Magento\Framework\Cache\FrontendInterface::class); + $this->notificationStorage = $objectManager->getObject( + NotificationStorage::class, + ['cache' => $this->cacheMock] + ); + $this->serializerMock = $this->getMock(\Magento\Framework\Serialize\SerializerInterface::class); + $objectManager->setBackwardCompatibleProperty($this->notificationStorage, 'serializer', $this->serializerMock); } public function testAdd() { $customerId = 1; $notificationType = 'some_type'; - $this->cache->expects($this->once()) + $data = [ + 'customer_id' => $customerId, + 'notification_type' => $notificationType + ]; + $serializedData = 'serialized data'; + $this->serializerMock->expects($this->once()) + ->method('serialize') + ->with($data) + ->willReturn($serializedData); + $this->cacheMock->expects($this->once()) ->method('save') ->with( - serialize([ - 'customer_id' => $customerId, - 'notification_type' => $notificationType - ]), + $serializedData, $this->getCacheKey($notificationType, $customerId) ); - $this->model->add($notificationType, $customerId); + $this->notificationStorage->add($notificationType, $customerId); } public function testIsExists() { $customerId = 1; $notificationType = 'some_type'; - $this->cache->expects($this->once()) + $this->cacheMock->expects($this->once()) ->method('test') ->with($this->getCacheKey($notificationType, $customerId)) ->willReturn(true); - $this->assertTrue($this->model->isExists($notificationType, $customerId)); + $this->assertTrue($this->notificationStorage->isExists($notificationType, $customerId)); } public function testRemove() { $customerId = 1; $notificationType = 'some_type'; - $this->cache->expects($this->once()) + $this->cacheMock->expects($this->once()) ->method('remove') ->with($this->getCacheKey($notificationType, $customerId)); - $this->model->remove($notificationType, $customerId); + $this->notificationStorage->remove($notificationType, $customerId); } /** - * Retrieve cache key + * Get cache key * * @param string $notificationType * @param string $customerId * @return string */ - protected function getCacheKey($notificationType, $customerId) + private function getCacheKey($notificationType, $customerId) { return 'notification_' . $notificationType . '_' . $customerId; } diff --git a/app/code/Magento/Customer/Test/Unit/Model/FileProcessorTest.php b/app/code/Magento/Customer/Test/Unit/Model/FileProcessorTest.php index 69064dbc1a420106a26bc6daba0a35db4b82800d..8a0cacf02baa2d20d9187acb9240d28a39b1a374 100644 --- a/app/code/Magento/Customer/Test/Unit/Model/FileProcessorTest.php +++ b/app/code/Magento/Customer/Test/Unit/Model/FileProcessorTest.php @@ -37,6 +37,11 @@ class FileProcessorTest extends \PHPUnit_Framework_TestCase */ private $mediaDirectory; + /** + * @var \Magento\Framework\File\Mime|\PHPUnit_Framework_MockObject_MockObject + */ + private $mime; + protected function setUp() { $this->mediaDirectory = $this->getMockBuilder(\Magento\Framework\Filesystem\Directory\WriteInterface::class) @@ -60,6 +65,10 @@ class FileProcessorTest extends \PHPUnit_Framework_TestCase $this->urlEncoder = $this->getMockBuilder(\Magento\Framework\Url\EncoderInterface::class) ->getMockForAbstractClass(); + + $this->mime = $this->getMockBuilder(\Magento\Framework\File\Mime::class) + ->disableOriginalConstructor() + ->getMock(); } private function getModel($entityTypeCode, array $allowedExtensions = []) @@ -70,6 +79,7 @@ class FileProcessorTest extends \PHPUnit_Framework_TestCase $this->urlBuilder, $this->urlEncoder, $entityTypeCode, + $this->mime, $allowedExtensions ); return $model; @@ -376,4 +386,26 @@ class FileProcessorTest extends \PHPUnit_Framework_TestCase $model = $this->getModel(CustomerMetadataInterface::ENTITY_TYPE_CUSTOMER); $model->moveTemporaryFile($filePath); } + + public function testGetMimeType() + { + $fileName = '/filename.ext1'; + $absoluteFilePath = '/absolute_path/customer/filename.ext1'; + + $expected = 'ext1'; + + $this->mediaDirectory->expects($this->once()) + ->method('getAbsolutePath') + ->with(CustomerMetadataInterface::ENTITY_TYPE_CUSTOMER . '/' . ltrim($fileName, '/')) + ->willReturn($absoluteFilePath); + + $this->mime->expects($this->once()) + ->method('getMimeType') + ->with($absoluteFilePath) + ->willReturn($expected); + + $model = $this->getModel(CustomerMetadataInterface::ENTITY_TYPE_CUSTOMER); + + $this->assertEquals($expected, $model->getMimeType($fileName)); + } } diff --git a/app/code/Magento/Customer/Test/Unit/Model/ResourceModel/AddressRepositoryTest.php b/app/code/Magento/Customer/Test/Unit/Model/ResourceModel/AddressRepositoryTest.php index b72a5f6a417d4ab77d2c025e1f43b6e58f72ccc2..5f6bc315acd16f6a79d82c5ee2566e240c6572a6 100644 --- a/app/code/Magento/Customer/Test/Unit/Model/ResourceModel/AddressRepositoryTest.php +++ b/app/code/Magento/Customer/Test/Unit/Model/ResourceModel/AddressRepositoryTest.php @@ -128,6 +128,7 @@ class AddressRepositoryTest extends \PHPUnit_Framework_TestCase 'setCustomer', 'getCountryModel', 'getShouldIgnoreValidation', + 'validate', 'save', 'getDataModel', 'getCustomerId', @@ -191,6 +192,9 @@ class AddressRepositoryTest extends \PHPUnit_Framework_TestCase $this->address->expects($this->once()) ->method('setCustomer') ->with($this->customer); + $this->address->expects($this->once()) + ->method('validate') + ->willReturn(true); $this->address->expects($this->once()) ->method('save'); $this->addressRegistry->expects($this->once()) @@ -208,9 +212,6 @@ class AddressRepositoryTest extends \PHPUnit_Framework_TestCase $this->address->expects($this->once()) ->method('getDataModel') ->willReturn($customerAddress); - $this->address->expects($this->once()) - ->method('getShouldIgnoreValidation') - ->willReturn(true); $this->repository->save($customerAddress); } @@ -222,6 +223,7 @@ class AddressRepositoryTest extends \PHPUnit_Framework_TestCase { $customerId = 34; $addressId = 53; + $errors[] = __('Please enter the state/province.'); $customerAddress = $this->getMockForAbstractClass( \Magento\Customer\Api\Data\AddressInterface::class, [], @@ -245,7 +247,9 @@ class AddressRepositoryTest extends \PHPUnit_Framework_TestCase $this->address->expects($this->once()) ->method('updateData') ->with($customerAddress); - $this->prepareMocksForInvalidAddressValidation(); + $this->address->expects($this->once()) + ->method('validate') + ->willReturn($errors); $this->repository->save($customerAddress); } @@ -258,6 +262,7 @@ class AddressRepositoryTest extends \PHPUnit_Framework_TestCase { $customerId = 34; $addressId = 53; + $errors[] = __('region is a required field.'); $customerAddress = $this->getMockForAbstractClass( \Magento\Customer\Api\Data\AddressInterface::class, [], @@ -281,60 +286,13 @@ class AddressRepositoryTest extends \PHPUnit_Framework_TestCase $this->address->expects($this->once()) ->method('updateData') ->with($customerAddress); - $countryModel = $this->getMock(\Magento\Directory\Model\Country::class, [], [], '', false); - $regionCollection = $this->getMock( - \Magento\Directory\Model\ResourceModel\Region\Collection::class, - [], - [], - '', - false - ); - $this->address->expects($this->once()) - ->method('getShouldIgnoreValidation') - ->willReturn(false); - $this->address->expects($this->atLeastOnce()) - ->method('getCountryId') - ->willReturn(1); - $this->address->expects($this->once()) - ->method('getFirstname') - ->willReturn('firstname'); - $this->address->expects($this->once()) - ->method('getLastname') - ->willReturn('lastname'); - $this->address->expects($this->once()) - ->method('getStreetLine') - ->with(1) - ->willReturn('street line'); - $this->address->expects($this->once()) - ->method('getCity') - ->willReturn('city'); - $this->address->expects($this->once()) - ->method('getTelephone') - ->willReturn('23423423423'); $this->address->expects($this->never()) ->method('getRegionId') ->willReturn(null); - - $this->directoryData->expects($this->once()) - ->method('getCountriesWithOptionalZip') - ->willReturn([1]); - $this->address->expects($this->once()) - ->method('getCountryModel') - ->willReturn($countryModel); - $countryModel->expects($this->once()) - ->method('getRegionCollection') - ->willReturn($regionCollection); - $regionCollection->expects($this->once()) - ->method('count') - ->willReturn(0); - $this->directoryData->expects($this->once()) - ->method('isRegionRequired') - ->with(1) - ->willReturn(true); $this->address->expects($this->once()) - ->method('getRegion') - ->willReturn(''); + ->method('validate') + ->willReturn($errors); $this->repository->save($customerAddress); } @@ -347,6 +305,7 @@ class AddressRepositoryTest extends \PHPUnit_Framework_TestCase { $customerId = 34; $addressId = 53; + $errors[] = __('regionId is a required field.'); $customerAddress = $this->getMockForAbstractClass( \Magento\Customer\Api\Data\AddressInterface::class, [], @@ -370,114 +329,14 @@ class AddressRepositoryTest extends \PHPUnit_Framework_TestCase $this->address->expects($this->once()) ->method('updateData') ->with($customerAddress); - $countryModel = $this->getMock(\Magento\Directory\Model\Country::class, [], [], '', false); - $regionCollection = $this->getMock( - \Magento\Directory\Model\ResourceModel\Region\Collection::class, - [], - [], - '', - false - ); - - $this->address->expects($this->once()) - ->method('getShouldIgnoreValidation') - ->willReturn(false); - $this->address->expects($this->atLeastOnce()) - ->method('getCountryId') - ->willReturn(1); - $this->address->expects($this->once()) - ->method('getFirstname') - ->willReturn('firstname'); - $this->address->expects($this->once()) - ->method('getLastname') - ->willReturn('lastname'); - $this->address->expects($this->once()) - ->method('getStreetLine') - ->with(1) - ->willReturn('street line'); - $this->address->expects($this->once()) - ->method('getCity') - ->willReturn('city'); - $this->address->expects($this->once()) - ->method('getTelephone') - ->willReturn('23423423423'); - $this->address->expects($this->once()) - ->method('getRegionId') - ->willReturn(2); - - $this->directoryData->expects($this->once()) - ->method('getCountriesWithOptionalZip') - ->willReturn([1]); - $this->address->expects($this->once()) - ->method('getCountryModel') - ->willReturn($countryModel); - $countryModel->expects($this->once()) - ->method('getRegionCollection') - ->willReturn($regionCollection); - $regionCollection->expects($this->atLeastOnce()) - ->method('count') - ->willReturn(2); - $regionCollection->expects($this->once()) - ->method('getData') - ->willReturn([5, 6, 7, 8, 9]); - $this->directoryData->expects($this->once()) - ->method('isRegionRequired') - ->with(1) - ->willReturn(true); $this->address->expects($this->never()) ->method('getRegion') ->willReturn(''); - - $this->repository->save($customerAddress); - } - - protected function prepareMocksForInvalidAddressValidation() - { - $countryModel = $this->getMock(\Magento\Directory\Model\Country::class, [], [], '', false); - $regionCollection = $this->getMock( - \Magento\Directory\Model\ResourceModel\Region\Collection::class, - [], - [], - '', - false - ); - - $this->address->expects($this->once()) - ->method('getShouldIgnoreValidation') - ->willReturn(false); - $this->address->expects($this->atLeastOnce()) - ->method('getCountryId'); - $this->address->expects($this->once()) - ->method('getFirstname'); - $this->address->expects($this->once()) - ->method('getLastname'); - $this->address->expects($this->once()) - ->method('getStreetLine') - ->with(1); $this->address->expects($this->once()) - ->method('getCity'); - $this->address->expects($this->once()) - ->method('getTelephone'); - $this->address->expects($this->never()) - ->method('getRegionId') - ->willReturn(null); + ->method('validate') + ->willReturn($errors); - $this->directoryData->expects($this->once()) - ->method('getCountriesWithOptionalZip') - ->willReturn([]); - $this->address->expects($this->once()) - ->method('getCountryModel') - ->willReturn($countryModel); - $countryModel->expects($this->once()) - ->method('getRegionCollection') - ->willReturn($regionCollection); - $regionCollection->expects($this->once()) - ->method('count') - ->willReturn(0); - $this->directoryData->expects($this->once()) - ->method('isRegionRequired') - ->with(null) - ->willReturn(true); + $this->repository->save($customerAddress); } public function testGetById() diff --git a/app/code/Magento/Customer/Test/Unit/Ui/Component/Listing/Column/AccountLockTest.php b/app/code/Magento/Customer/Test/Unit/Ui/Component/Listing/Column/AccountLockTest.php index c72cf9fddd0b7043759b0c1706e3018f51bce174..c6f113d56c38f587ffa10c0d21f3d6fe8a5c2ac2 100644 --- a/app/code/Magento/Customer/Test/Unit/Ui/Component/Listing/Column/AccountLockTest.php +++ b/app/code/Magento/Customer/Test/Unit/Ui/Component/Listing/Column/AccountLockTest.php @@ -46,27 +46,9 @@ class AccountLockTest extends \PHPUnit_Framework_TestCase */ public function testPrepareDataSource($lockExpirationDate, $expectedResult) { - $dataSource = [ - 'data' => [ - 'items' => [ - [ - 'lock_expires' => $lockExpirationDate - ], - ] - ] - ]; - $expectedDataSource = [ - 'data' => [ - 'items' => [ - [ - 'lock_expires' => $expectedResult, - ], - ] - ] - ]; - $dataSource = $this->component->prepareDataSource($dataSource); + $dataSource = $this->component->prepareDataSource($lockExpirationDate); - $this->assertEquals($expectedDataSource, $dataSource); + $this->assertEquals($expectedResult, $dataSource); } /** @@ -76,13 +58,77 @@ class AccountLockTest extends \PHPUnit_Framework_TestCase { return [ [ - 'lockExpirationDate' => date("F j, Y", strtotime('-1 days')), - 'expectedResult' => new \Magento\Framework\Phrase('Unlocked') + 'lockExpirationDate' => [ + 'data' => [ + 'items' => [['lock_expires' => null]], + ] + ], + 'expectedResult' => [ + 'data' => [ + 'items' => [ + [ + 'lock_expires' => new \Magento\Framework\Phrase('Unlocked') + ], + ] + ] + ] ], [ - 'lockExpirationDate' => date("F j, Y", strtotime('+1 days')), - 'expectedResult' => new \Magento\Framework\Phrase('Locked') - ] + 'lockExpirationDate' => [ + 'data' => [ + 'items' => [[]]//Non exist lock_expires data + ] + ], + 'expectedResult' => [ + 'data' => [ + 'items' => [ + [ + 'lock_expires' => new \Magento\Framework\Phrase('Unlocked') + ], + ] + ] + ] + ], + [ + 'lockExpirationDate' => [ + 'data' => [ + 'items' => [ + [ + 'lock_expires' => date("F j, Y", strtotime('-1 days')) + ], + ] + ] + ], + 'expectedResult' => [ + 'data' => [ + 'items' => [ + [ + 'lock_expires' => new \Magento\Framework\Phrase('Unlocked') + ], + ] + ] + ] + ], + [ + 'lockExpirationDate' => [ + 'data' => [ + 'items' => [ + [ + 'lock_expires' => date("F j, Y", strtotime('+1 days')) + ], + ] + ] + ], + 'expectedResult' => [ + 'data' => [ + 'items' => [ + [ + 'lock_expires' => new \Magento\Framework\Phrase('Locked') + ], + ] + ] + ] + ], ]; } } diff --git a/app/code/Magento/Customer/Ui/Component/Listing/Column/AccountLock.php b/app/code/Magento/Customer/Ui/Component/Listing/Column/AccountLock.php index 5e2e92e1c933e070c04b26713c067c51d14397e5..3622829f53f0cfd74c82820d32f56f6a11bb91ee 100644 --- a/app/code/Magento/Customer/Ui/Component/Listing/Column/AccountLock.php +++ b/app/code/Magento/Customer/Ui/Component/Listing/Column/AccountLock.php @@ -41,9 +41,13 @@ class AccountLock extends Column { if (isset($dataSource['data']['items'])) { foreach ($dataSource['data']['items'] as & $item) { - $lockExpires = new \DateTime($item['lock_expires']); - if ($lockExpires > new \DateTime()) { - $item['lock_expires'] = __('Locked'); + if (array_key_exists('lock_expires', $item)) { + $lockExpires = new \DateTime($item['lock_expires']); + if ($lockExpires > new \DateTime()) { + $item['lock_expires'] = __('Locked'); + } else { + $item['lock_expires'] = __('Unlocked'); + } } else { $item['lock_expires'] = __('Unlocked'); } diff --git a/app/code/Magento/Customer/view/frontend/web/js/model/customer/address.js b/app/code/Magento/Customer/view/frontend/web/js/model/customer/address.js index 30fbef98fd39ab15db1c7971e3e86ad82e367253..e013a96e4890aee11d30641a2f2ee31c4e6088c2 100644 --- a/app/code/Magento/Customer/view/frontend/web/js/model/customer/address.js +++ b/app/code/Magento/Customer/view/frontend/web/js/model/customer/address.js @@ -10,11 +10,17 @@ define([], function() { * Returns new address object */ return function (addressData) { + var regionId; + + if (addressData.region['region_id'] && addressData.region['region_id'] !== '0') { + regionId = addressData.region['region_id'] + ''; + } + return { customerAddressId: addressData.id, email: addressData.email, countryId: addressData.country_id, - regionId: addressData.region_id, + regionId: regionId, regionCode: addressData.region.region_code, region: addressData.region.region, customerId: addressData.customer_id, 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..40b262e3e4f5176f87d306be8babb5cfb2ba1898 --- /dev/null +++ b/app/code/Magento/Deploy/Console/Command/App/ApplicationDumpCommand.php @@ -0,0 +1,92 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Deploy\Console\Command\App; + +use Magento\Framework\App\Config\ConfigSourceInterface; +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 ConfigSourceInterface[] + */ + 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 = []; + $comments = []; + foreach ($this->sources as $sourceData) { + /** @var ConfigSourceInterface $source */ + $source = $sourceData['source']; + $namespace = $sourceData['namespace']; + $dump[$namespace] = $source->get(); + if (!empty($sourceData['comment'])) { + $comments[$namespace] = is_string($sourceData['comment']) + ? $sourceData['comment'] + : $sourceData['comment']->get(); + } + } + $this->writer + ->saveConfig( + [ConfigFilePool::APP_CONFIG => $dump], + true, + ConfigFilePool::LOCAL, + $comments + ); + if (!empty($comments)) { + $output->writeln($comments); + } + $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/Developer/etc/di.xml b/app/code/Magento/Developer/etc/di.xml index 80433242853b85378a31b50133716e8399084c29..2362aaa0780debfcdc0e55b270ed733dc1237e5b 100644 --- a/app/code/Magento/Developer/etc/di.xml +++ b/app/code/Magento/Developer/etc/di.xml @@ -252,4 +252,11 @@ </argument> </arguments> </type> + <type name="Magento\Config\Model\Config\Export\ExcludeList"> + <arguments> + <argument name="configs" xsi:type="array"> + <item name="dev/restrict/allow_ips" xsi:type="string">1</item> + </argument> + </arguments> + </type> </config> diff --git a/app/code/Magento/Dhl/etc/di.xml b/app/code/Magento/Dhl/etc/di.xml index a215c2e82182535e14e659d20cf1f7db2317e915..cbe795791147cc03de7eb060c84108c6cbeb53fa 100644 --- a/app/code/Magento/Dhl/etc/di.xml +++ b/app/code/Magento/Dhl/etc/di.xml @@ -9,4 +9,13 @@ <type name="Magento\Checkout\Block\Cart\LayoutProcessor"> <plugin name="checkout_cart_shipping_dhl" type="Magento\Dhl\Model\Plugin\Checkout\Block\Cart\Shipping"/> </type> + <type name="Magento\Config\Model\Config\Export\ExcludeList"> + <arguments> + <argument name="configs" xsi:type="array"> + <item name="carriers/dhl/id" xsi:type="string">1</item> + <item name="carriers/dhl/password" xsi:type="string">1</item> + <item name="carriers/dhl/account" xsi:type="string">1</item> + </argument> + </arguments> + </type> </config> diff --git a/app/code/Magento/Directory/Block/Data.php b/app/code/Magento/Directory/Block/Data.php index 627e34d9ff40455e277b5813319837f764cd937b..3c8b682d1a1e8ad1dd066bd5300373f5a05c8859 100644 --- a/app/code/Magento/Directory/Block/Data.php +++ b/app/code/Magento/Directory/Block/Data.php @@ -5,6 +5,9 @@ */ namespace Magento\Directory\Block; +/** + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ class Data extends \Magento\Framework\View\Element\Template { /** @@ -32,6 +35,11 @@ class Data extends \Magento\Framework\View\Element\Template */ protected $directoryHelper; + /** + * @var \Magento\Framework\Serialize\SerializerInterface + */ + private $serializer; + /** * @param \Magento\Framework\View\Element\Template\Context $context * @param \Magento\Directory\Helper\Data $directoryHelper @@ -110,12 +118,12 @@ class Data extends \Magento\Framework\View\Element\Template $cacheKey = 'DIRECTORY_COUNTRY_SELECT_STORE_' . $this->_storeManager->getStore()->getCode(); $cache = $this->_configCacheType->load($cacheKey); if ($cache) { - $options = unserialize($cache); + $options = $this->getSerializer()->unserialize($cache); } else { $options = $this->getCountryCollection() ->setForegroundCountries($this->getTopDestinations()) ->toOptionArray(); - $this->_configCacheType->save(serialize($options), $cacheKey); + $this->_configCacheType->save($this->getSerializer()->serialize($options), $cacheKey); } $html = $this->getLayout()->createBlock( \Magento\Framework\View\Element\Html\Select::class @@ -160,10 +168,10 @@ class Data extends \Magento\Framework\View\Element\Template $cacheKey = 'DIRECTORY_REGION_SELECT_STORE' . $this->_storeManager->getStore()->getId(); $cache = $this->_configCacheType->load($cacheKey); if ($cache) { - $options = unserialize($cache); + $options = $this->getSerializer()->unserialize($cache); } else { $options = $this->getRegionCollection()->toOptionArray(); - $this->_configCacheType->save(serialize($options), $cacheKey); + $this->_configCacheType->save($this->getSerializer()->serialize($options), $cacheKey); } $html = $this->getLayout()->createBlock( \Magento\Framework\View\Element\Html\Select::class @@ -224,4 +232,19 @@ class Data extends \Magento\Framework\View\Element\Template \Magento\Framework\Profiler::stop('TEST: ' . __METHOD__); return $regionsJs; } + + /** + * Get serializer + * + * @return \Magento\Framework\Serialize\SerializerInterface + * @deprecated + */ + private function getSerializer() + { + if ($this->serializer === null) { + $this->serializer = \Magento\Framework\App\ObjectManager::getInstance() + ->get(\Magento\Framework\Serialize\SerializerInterface::class); + } + return $this->serializer; + } } diff --git a/app/code/Magento/Directory/Model/Country/Postcode/Config/Data.php b/app/code/Magento/Directory/Model/Country/Postcode/Config/Data.php index 879eccd9879193691809706008a3b1dee922d54f..c24da536e779c1b6f6e78716be2dc6e253a6057d 100644 --- a/app/code/Magento/Directory/Model/Country/Postcode/Config/Data.php +++ b/app/code/Magento/Directory/Model/Country/Postcode/Config/Data.php @@ -5,16 +5,27 @@ */ namespace Magento\Directory\Model\Country\Postcode\Config; +use Magento\Framework\Serialize\SerializerInterface; + +/** + * Provides country postcodes configuration + */ class Data extends \Magento\Framework\Config\Data { /** - * @param \Magento\Directory\Model\Country\Postcode\Config\Reader $reader + * Constructor + * + * @param Reader $reader * @param \Magento\Framework\Config\CacheInterface $cache + * @param string|null $cacheId + * @param SerializerInterface|null $serializer */ public function __construct( \Magento\Directory\Model\Country\Postcode\Config\Reader $reader, - \Magento\Framework\Config\CacheInterface $cache + \Magento\Framework\Config\CacheInterface $cache, + $cacheId = 'country_postcodes', + SerializerInterface $serializer = null ) { - parent::__construct($reader, $cache, 'country_postcodes'); + parent::__construct($reader, $cache, $cacheId, $serializer); } } diff --git a/app/code/Magento/Directory/Model/ResourceModel/Region/Collection.php b/app/code/Magento/Directory/Model/ResourceModel/Region/Collection.php index 718e0c0223d767dd3857f5c796d9b7f9d918900a..7d3f63e257e5e23ecf49c3845d34aad0ced2287f 100644 --- a/app/code/Magento/Directory/Model/ResourceModel/Region/Collection.php +++ b/app/code/Magento/Directory/Model/ResourceModel/Region/Collection.php @@ -9,6 +9,14 @@ */ namespace Magento\Directory\Model\ResourceModel\Region; +use Magento\Directory\Model\AllowedCountries; +use Magento\Framework\App\ObjectManager; +use Magento\Store\Model\ScopeInterface; + +/** + * Class Collection + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ class Collection extends \Magento\Framework\Model\ResourceModel\Db\Collection\AbstractCollection { /** @@ -30,6 +38,11 @@ class Collection extends \Magento\Framework\Model\ResourceModel\Db\Collection\Ab */ protected $_localeResolver; + /** + * @var AllowedCountries + */ + private $allowedCountriesReader; + /** * @param \Magento\Framework\Data\Collection\EntityFactory $entityFactory * @param \Psr\Log\LoggerInterface $logger @@ -89,6 +102,40 @@ class Collection extends \Magento\Framework\Model\ResourceModel\Db\Collection\Ab return $this; } + /** + * Return Allowed Countries reader + * + * @return \Magento\Directory\Model\AllowedCountries + * @deprecated + */ + private function getAllowedCountriesReader() + { + if (!$this->allowedCountriesReader) { + $this->allowedCountriesReader = ObjectManager::getInstance()->get(AllowedCountries::class); + } + + return $this->allowedCountriesReader; + } + + /** + * Set allowed countries filter based on the given store. + * This is a convenience method for collection filtering based on store configuration settings. + * + * @param null|int|string|\Magento\Store\Model\Store $store + * @return \Magento\Directory\Model\ResourceModel\Region\Collection + */ + public function addAllowedCountriesFilter($store = null) + { + $allowedCountries = $this->getAllowedCountriesReader() + ->getAllowedCountries(ScopeInterface::SCOPE_STORE, $store); + + if (!empty($allowedCountries)) { + $this->addFieldToFilter('main_table.country_id', ['in' => $allowedCountries]); + } + + return $this; + } + /** * Filter by country_id * @@ -206,7 +253,7 @@ class Collection extends \Magento\Framework\Model\ResourceModel\Db\Collection\Ab if (count($options) > 0) { array_unshift( $options, - ['title' => null, 'value' => null, 'label' => __('Please select a region, state or province.')] + ['title' => '', 'value' => '', 'label' => __('Please select a region, state or province.')] ); } return $options; diff --git a/app/code/Magento/Directory/Test/Unit/Block/DataTest.php b/app/code/Magento/Directory/Test/Unit/Block/DataTest.php index 165a369b119b9b9d9ebb0fff9fcb69069ce34924..8bad1c1efee375eabe08ebe0e94b4bfc86ee4fad 100644 --- a/app/code/Magento/Directory/Test/Unit/Block/DataTest.php +++ b/app/code/Magento/Directory/Test/Unit/Block/DataTest.php @@ -9,10 +9,9 @@ use Magento\Directory\Block\Data; use Magento\Directory\Helper\Data as HelperData; use Magento\Directory\Model\ResourceModel\Country\Collection as CountryCollection; use Magento\Directory\Model\ResourceModel\Country\CollectionFactory as CountryCollectionFactory; -use Magento\Directory\Model\ResourceModel\Region\CollectionFactory as RegionCollectionFactory; use Magento\Framework\App\Cache\Type\Config; use Magento\Framework\App\Config\ScopeConfigInterface; -use Magento\Framework\Json\EncoderInterface; +use Magento\Framework\Serialize\SerializerInterface; use Magento\Framework\View\Element\Template\Context; use Magento\Framework\View\LayoutInterface; use Magento\Store\Model\ScopeInterface; @@ -25,117 +24,114 @@ use Magento\Store\Model\StoreManagerInterface; class DataTest extends \PHPUnit_Framework_TestCase { /** @var Data */ - protected $model; + private $block; /** @var Context |\PHPUnit_Framework_MockObject_MockObject */ - protected $context; + private $contextMock; /** @var HelperData |\PHPUnit_Framework_MockObject_MockObject */ - protected $helperData; - - /** @var EncoderInterface |\PHPUnit_Framework_MockObject_MockObject */ - protected $jsonEncoder; + private $helperDataMock; /** @var Config |\PHPUnit_Framework_MockObject_MockObject */ - protected $cacheTypeConfig; - - /** @var RegionCollectionFactory |\PHPUnit_Framework_MockObject_MockObject */ - protected $regionCollectionFactory; + private $cacheTypeConfigMock; /** @var CountryCollectionFactory |\PHPUnit_Framework_MockObject_MockObject */ - protected $countryCollectionFactory; + private $countryCollectionFactoryMock; /** @var ScopeConfigInterface |\PHPUnit_Framework_MockObject_MockObject */ - protected $scopeConfig; + private $scopeConfigMock; /** @var StoreManagerInterface |\PHPUnit_Framework_MockObject_MockObject */ - protected $storeManager; + private $storeManagerMock; /** @var Store |\PHPUnit_Framework_MockObject_MockObject */ - protected $store; + private $storeMock; /** @var CountryCollection |\PHPUnit_Framework_MockObject_MockObject */ - protected $countryCollection; + private $countryCollectionMock; /** @var LayoutInterface |\PHPUnit_Framework_MockObject_MockObject */ - protected $layout; + private $layoutMock; + + /** @var SerializerInterface|\PHPUnit_Framework_MockObject_MockObject */ + private $serializerMock; protected function setUp() { + $objectManagerHelper = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); $this->prepareContext(); - $this->helperData = $this->getMockBuilder(\Magento\Directory\Helper\Data::class) + $this->helperDataMock = $this->getMockBuilder(\Magento\Directory\Helper\Data::class) ->disableOriginalConstructor() ->getMock(); - $this->jsonEncoder = $this->getMockBuilder(\Magento\Framework\Json\EncoderInterface::class) - ->getMockForAbstractClass(); - - $this->cacheTypeConfig = $this->getMockBuilder(\Magento\Framework\App\Cache\Type\Config::class) - ->disableOriginalConstructor() - ->getMock(); - - $this->regionCollectionFactory = $this->getMockBuilder( - \Magento\Directory\Model\ResourceModel\Region\CollectionFactory::class - ) + $this->cacheTypeConfigMock = $this->getMockBuilder(\Magento\Framework\App\Cache\Type\Config::class) ->disableOriginalConstructor() ->getMock(); $this->prepareCountryCollection(); - $this->model = new Data( - $this->context, - $this->helperData, - $this->jsonEncoder, - $this->cacheTypeConfig, - $this->regionCollectionFactory, - $this->countryCollectionFactory + $this->block = $objectManagerHelper->getObject( + Data::class, + [ + 'context' => $this->contextMock, + 'directoryHelper' => $this->helperDataMock, + 'configCacheType' => $this->cacheTypeConfigMock, + 'countryCollectionFactory' => $this->countryCollectionFactoryMock + ] + ); + + $this->serializerMock = $this->getMock(SerializerInterface::class, [], [], '', false); + $objectManagerHelper->setBackwardCompatibleProperty( + $this->block, + 'serializer', + $this->serializerMock ); } protected function prepareContext() { - $this->store = $this->getMockBuilder(\Magento\Store\Model\Store::class) + $this->storeMock = $this->getMockBuilder(\Magento\Store\Model\Store::class) ->disableOriginalConstructor() ->getMock(); - $this->scopeConfig = $this->getMockBuilder(\Magento\Framework\App\Config\ScopeConfigInterface::class) + $this->scopeConfigMock = $this->getMockBuilder(\Magento\Framework\App\Config\ScopeConfigInterface::class) ->getMockForAbstractClass(); - $this->storeManager = $this->getMockBuilder(\Magento\Store\Model\StoreManagerInterface::class) + $this->storeManagerMock = $this->getMockBuilder(\Magento\Store\Model\StoreManagerInterface::class) ->getMockForAbstractClass(); - $this->storeManager->expects($this->any()) + $this->storeManagerMock->expects($this->any()) ->method('getStore') - ->willReturn($this->store); + ->willReturn($this->storeMock); - $this->layout = $this->getMockBuilder(\Magento\Framework\View\LayoutInterface::class) + $this->layoutMock = $this->getMockBuilder(\Magento\Framework\View\LayoutInterface::class) ->getMockForAbstractClass(); - $this->context = $this->getMockBuilder(\Magento\Framework\View\Element\Template\Context::class) + $this->contextMock = $this->getMockBuilder(\Magento\Framework\View\Element\Template\Context::class) ->disableOriginalConstructor() ->getMock(); - $this->context->expects($this->any()) + $this->contextMock->expects($this->any()) ->method('getScopeConfig') - ->willReturn($this->scopeConfig); + ->willReturn($this->scopeConfigMock); - $this->context->expects($this->any()) + $this->contextMock->expects($this->any()) ->method('getStoreManager') - ->willReturn($this->storeManager); + ->willReturn($this->storeManagerMock); - $this->context->expects($this->any()) + $this->contextMock->expects($this->any()) ->method('getLayout') - ->willReturn($this->layout); + ->willReturn($this->layoutMock); } protected function prepareCountryCollection() { - $this->countryCollection = $this->getMockBuilder( + $this->countryCollectionMock = $this->getMockBuilder( \Magento\Directory\Model\ResourceModel\Country\Collection::class )->disableOriginalConstructor()->getMock(); - $this->countryCollectionFactory = $this->getMockBuilder( + $this->countryCollectionFactoryMock = $this->getMockBuilder( \Magento\Directory\Model\ResourceModel\Country\CollectionFactory::class ) ->disableOriginalConstructor() @@ -144,9 +140,9 @@ class DataTest extends \PHPUnit_Framework_TestCase ]) ->getMock(); - $this->countryCollectionFactory->expects($this->any()) + $this->countryCollectionFactoryMock->expects($this->any()) ->method('create') - ->willReturn($this->countryCollection); + ->willReturn($this->countryCollectionMock); } /** @@ -166,46 +162,50 @@ class DataTest extends \PHPUnit_Framework_TestCase $options, $resultHtml ) { - $this->helperData->expects($this->once()) + $this->helperDataMock->expects($this->once()) ->method('getDefaultCountry') ->willReturn($defaultCountry); - $this->store->expects($this->once()) + $this->storeMock->expects($this->once()) ->method('getCode') ->willReturn($storeCode); - $this->cacheTypeConfig->expects($this->once()) + $this->serializerMock->expects($this->once()) + ->method('serialize') + ->willReturn('serializedData'); + + $this->cacheTypeConfigMock->expects($this->once()) ->method('load') ->with('DIRECTORY_COUNTRY_SELECT_STORE_' . $storeCode) ->willReturn(false); - $this->cacheTypeConfig->expects($this->once()) + $this->cacheTypeConfigMock->expects($this->once()) ->method('save') - ->with(serialize($options), 'DIRECTORY_COUNTRY_SELECT_STORE_' . $storeCode) + ->with('serializedData', 'DIRECTORY_COUNTRY_SELECT_STORE_' . $storeCode) ->willReturnSelf(); - $this->scopeConfig->expects($this->once()) + $this->scopeConfigMock->expects($this->once()) ->method('getValue') ->with('general/country/destinations', ScopeInterface::SCOPE_STORE) ->willReturn($destinations); - $this->countryCollection->expects($this->once()) + $this->countryCollectionMock->expects($this->once()) ->method('loadByStore') ->willReturnSelf(); - $this->countryCollection->expects($this->any()) + $this->countryCollectionMock->expects($this->any()) ->method('setForegroundCountries') ->with($expectedDestinations) ->willReturnSelf(); - $this->countryCollection->expects($this->once()) + $this->countryCollectionMock->expects($this->once()) ->method('toOptionArray') ->willReturn($options); $elementHtmlSelect = $this->mockElementHtmlSelect($defaultCountry, $options, $resultHtml); - $this->layout->expects($this->once()) + $this->layoutMock->expects($this->once()) ->method('createBlock') ->willReturn($elementHtmlSelect); - $this->assertEquals($resultHtml, $this->model->getCountryHtmlSelect()); + $this->assertEquals($resultHtml, $this->block->getCountryHtmlSelect()); } /** diff --git a/app/code/Magento/Directory/Test/Unit/Model/Country/Postcode/Config/DataTest.php b/app/code/Magento/Directory/Test/Unit/Model/Country/Postcode/Config/DataTest.php index c4681d88d28e73dba119810e1e29ca0133dc2fbb..57c86ab58c91b84ba7d22465a3bb382011bd1912 100644 --- a/app/code/Magento/Directory/Test/Unit/Model/Country/Postcode/Config/DataTest.php +++ b/app/code/Magento/Directory/Test/Unit/Model/Country/Postcode/Config/DataTest.php @@ -8,31 +8,54 @@ namespace Magento\Directory\Test\Unit\Model\Country\Postcode\Config; class DataTest extends \PHPUnit_Framework_TestCase { /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Directory\Model\Country\Postcode\Config\Reader|\PHPUnit_Framework_MockObject_MockObject */ - protected $readerMock; + private $readerMock; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\App\Cache\Type\Config|\PHPUnit_Framework_MockObject_MockObject */ - protected $cacheMock; + private $cacheMock; + + /** + * @var \Magento\Framework\Serialize\SerializerInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $serializerMock; protected function setUp() { - $this->readerMock = $this->getMockBuilder( - \Magento\Directory\Model\Country\Postcode\Config\Reader::class - )->disableOriginalConstructor()->getMock(); - $this->cacheMock = $this->getMockBuilder( - \Magento\Framework\App\Cache\Type\Config::class - )->disableOriginalConstructor()->getMock(); + $this->readerMock = $this->getMock( + \Magento\Directory\Model\Country\Postcode\Config\Reader::class, + [], + [], + '', + false + ); + $this->cacheMock = $this->getMock( + \Magento\Framework\App\Cache\Type\Config::class, + [], + [], + '', + false + ); + $this->serializerMock = $this->getMock(\Magento\Framework\Serialize\SerializerInterface::class); } public function testGet() { $expected = ['someData' => ['someValue', 'someKey' => 'someValue']]; - $this->cacheMock->expects($this->any())->method('load')->will($this->returnValue(serialize($expected))); - $configData = new \Magento\Directory\Model\Country\Postcode\Config\Data($this->readerMock, $this->cacheMock); - + $this->cacheMock->expects($this->once()) + ->method('load') + ->willReturn(json_encode($expected)); + $this->serializerMock->expects($this->once()) + ->method('unserialize') + ->willReturn($expected); + $configData = new \Magento\Directory\Model\Country\Postcode\Config\Data( + $this->readerMock, + $this->cacheMock, + 'country_postcodes', + $this->serializerMock + ); $this->assertEquals($expected, $configData->get()); } } diff --git a/app/code/Magento/Directory/Test/Unit/Model/ResourceModel/Region/CollectionTest.php b/app/code/Magento/Directory/Test/Unit/Model/ResourceModel/Region/CollectionTest.php index 59c054b00a5f9c11607ca2126c0e0174918785e6..5c09ab119295a4e511f99f80f8320950a2a8ff57 100644 --- a/app/code/Magento/Directory/Test/Unit/Model/ResourceModel/Region/CollectionTest.php +++ b/app/code/Magento/Directory/Test/Unit/Model/ResourceModel/Region/CollectionTest.php @@ -6,6 +6,7 @@ namespace Magento\Directory\Test\Unit\Model\ResourceModel\Region; use Magento\Directory\Model\ResourceModel\Region\Collection; +use Magento\Directory\Model\AllowedCountries; use Magento\Framework\DB\Adapter\Pdo\Mysql; use Magento\Framework\DB\Select; use Magento\Framework\Model\ResourceModel\Db\AbstractDb; @@ -15,7 +16,14 @@ use Magento\Framework\Data\Collection\EntityFactory; use Magento\Framework\Locale\ResolverInterface; use Magento\Framework\DataObject; use Psr\Log\LoggerInterface; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; +use PHPUnit_Framework_MockObject_MockObject as MockObject; +/** + * Class CollectionTest + * + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ class CollectionTest extends \PHPUnit_Framework_TestCase { /** @@ -23,15 +31,22 @@ class CollectionTest extends \PHPUnit_Framework_TestCase */ private $collection; + /** + * @var MockObject + */ + private $allowedCountries; + protected function setUp() { + $objectManager = new ObjectManager($this); $entityFactoryMock = $this->getMock(EntityFactory::class, [], [], '', false); $loggerMock = $this->getMock(LoggerInterface::class); $fetchStrategyMock = $this->getMock(FetchStrategyInterface::class); $eventManagerMock = $this->getMock(ManagerInterface::class); $localeResolverMock = $this->getMock(ResolverInterface::class); $connectionMock = $this->getMock(Mysql::class, [], [], '', false); - $resourceMock = $this->getMockForAbstractClass(AbstractDb::class, + $resourceMock = $this->getMockForAbstractClass( + AbstractDb::class, [], '', false, @@ -39,6 +54,7 @@ class CollectionTest extends \PHPUnit_Framework_TestCase true, ['getConnection', 'getMainTable', 'getTable', '__wakeup'] ); + $this->allowedCountries = $this->getMock(AllowedCountries::class, [], [], '', false); $selectMock = $this->getMock(Select::class, [], [], '', false); $connectionMock->expects($this->any())->method('select')->will($this->returnValue($selectMock)); @@ -54,6 +70,12 @@ class CollectionTest extends \PHPUnit_Framework_TestCase $connectionMock, $resourceMock ); + + $objectManager->setBackwardCompatibleProperty( + $this->collection, + 'allowedCountriesReader', + $this->allowedCountries + ); } public function testToOptionArray() @@ -98,4 +120,14 @@ class CollectionTest extends \PHPUnit_Framework_TestCase $this->assertEquals($expectedResult, $this->collection->toOptionArray()); } + + public function testAddAllowedCountriesFilter() + { + $allowedCountries = [1, 2, 3]; + $this->allowedCountries->expects($this->once())->method('getAllowedCountries')->with( + \Magento\Store\Model\ScopeInterface::SCOPE_STORE, + null + )->willReturn($allowedCountries); + $this->assertEquals($this->collection->addAllowedCountriesFilter(), $this->collection); + } } diff --git a/app/code/Magento/Directory/etc/di.xml b/app/code/Magento/Directory/etc/di.xml index f868197e60593cb59292a060b473f1d87d55820e..b4da40d119fe3e2269d1d33f47c5e2009a3379b1 100644 --- a/app/code/Magento/Directory/etc/di.xml +++ b/app/code/Magento/Directory/etc/di.xml @@ -47,4 +47,12 @@ <preference for="Magento\Directory\Api\CountryInformationAcquirerInterface" type="Magento\Directory\Model\CountryInformationAcquirer" /> <preference for="Magento\Directory\Api\Data\CountryInformationInterface" type="Magento\Directory\Model\Data\CountryInformation" /> <preference for="Magento\Directory\Api\Data\RegionInformationInterface" type="Magento\Directory\Model\Data\RegionInformation" /> + + <type name="Magento\Config\Model\Config\Export\ExcludeList"> + <arguments> + <argument name="configs" xsi:type="array"> + <item name="currency/import/error_email" xsi:type="string">1</item> + </argument> + </arguments> + </type> </config> diff --git a/app/code/Magento/Downloadable/view/adminhtml/web/template/components/file-uploader.html b/app/code/Magento/Downloadable/view/adminhtml/web/template/components/file-uploader.html index 907c184dfce575c9ed1e9eb8a1be9de3c042f8f0..8cbe03034aa4408d3a84335dce6395e78427faae 100644 --- a/app/code/Magento/Downloadable/view/adminhtml/web/template/components/file-uploader.html +++ b/app/code/Magento/Downloadable/view/adminhtml/web/template/components/file-uploader.html @@ -1,3 +1,10 @@ +<!-- +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> + <div class="admin__field-control"> <div class="file-uploader" data-role="drop-zone" css="_loading: isLoading"> <each args="data: value, as: '$file'"> @@ -16,4 +23,4 @@ <span class="file-uploader-spinner"/> </div> </div> -</div> \ No newline at end of file +</div> diff --git a/app/code/Magento/DownloadableImportExport/Model/Import/Product/Type/Downloadable.php b/app/code/Magento/DownloadableImportExport/Model/Import/Product/Type/Downloadable.php index a641093f5454033fe4c628587e23f47b4d1ac9df..7a447aa90eea8f6eb39100e0218bbc90302a715f 100644 --- a/app/code/Magento/DownloadableImportExport/Model/Import/Product/Type/Downloadable.php +++ b/app/code/Magento/DownloadableImportExport/Model/Import/Product/Type/Downloadable.php @@ -7,7 +7,7 @@ */ namespace Magento\DownloadableImportExport\Model\Import\Product\Type; -use Magento\CatalogImportExport\Model\Import\Product; +use Magento\Framework\EntityManager\MetadataPool; use \Magento\Store\Model\Store; /** @@ -244,7 +244,7 @@ class Downloadable extends \Magento\CatalogImportExport\Model\Import\Product\Typ protected $downloadableHelper; /** - * Constructor + * Downloadable constructor * * @param \Magento\Eav\Model\ResourceModel\Entity\Attribute\Set\CollectionFactory $attrSetColFac * @param \Magento\Catalog\Model\ResourceModel\Product\Attribute\CollectionFactory $prodAttrColFac @@ -252,7 +252,7 @@ class Downloadable extends \Magento\CatalogImportExport\Model\Import\Product\Typ * @param array $params * @param \Magento\DownloadableImportExport\Helper\Uploader $uploaderHelper * @param \Magento\DownloadableImportExport\Helper\Data $downloadableHelper - * @throws \Magento\Framework\Exception\LocalizedException + * @param MetadataPool $metadataPool */ public function __construct( \Magento\Eav\Model\ResourceModel\Entity\Attribute\Set\CollectionFactory $attrSetColFac, @@ -260,12 +260,12 @@ class Downloadable extends \Magento\CatalogImportExport\Model\Import\Product\Typ \Magento\Framework\App\ResourceConnection $resource, array $params, \Magento\DownloadableImportExport\Helper\Uploader $uploaderHelper, - \Magento\DownloadableImportExport\Helper\Data $downloadableHelper + \Magento\DownloadableImportExport\Helper\Data $downloadableHelper, + MetadataPool $metadataPool = null ) { - parent::__construct($attrSetColFac, $prodAttrColFac, $resource, $params); + parent::__construct($attrSetColFac, $prodAttrColFac, $resource, $params, $metadataPool); $this->parameters = $this->_entityModel->getParameters(); $this->_resource = $resource; - $this->connection = $resource->getConnection('write'); $this->uploaderHelper = $uploaderHelper; $this->downloadableHelper = $downloadableHelper; } diff --git a/app/code/Magento/DownloadableImportExport/Test/Unit/Model/Import/Product/Type/DownloadableTest.php b/app/code/Magento/DownloadableImportExport/Test/Unit/Model/Import/Product/Type/DownloadableTest.php index d3cd979b31a9118250062408205c38c7a7c8adb7..c4799bcc42ae9c8d81b6ec321370e8684265a654 100644 --- a/app/code/Magento/DownloadableImportExport/Test/Unit/Model/Import/Product/Type/DownloadableTest.php +++ b/app/code/Magento/DownloadableImportExport/Test/Unit/Model/Import/Product/Type/DownloadableTest.php @@ -710,10 +710,6 @@ class DownloadableTest extends \Magento\ImportExport\Test\Unit\Model\Import\Abst ->getMock(\Magento\Framework\EntityManager\MetadataPool::class, ['getLinkField'], [], '', false); $metadataPoolMock->expects($this->any())->method('getMetadata')->willReturnSelf(); - $this->prepareObjectManager([ - [\Magento\Framework\EntityManager\MetadataPool::class, $metadataPoolMock], - ]); - $this->downloadableModelMock = $this->objectManagerHelper->getObject( \Magento\DownloadableImportExport\Model\Import\Product\Type\Downloadable::class, [ @@ -722,7 +718,8 @@ class DownloadableTest extends \Magento\ImportExport\Test\Unit\Model\Import\Abst 'resource' => $this->resourceMock, 'params' => $this->paramsArray, 'uploaderHelper' => $this->uploaderHelper, - 'downloadableHelper' => $this->downloadableHelper + 'downloadableHelper' => $this->downloadableHelper, + 'metadataPool' => $metadataPoolMock, ] ); $this->entityModelMock->expects($this->once())->method('getNewSku')->will($this->returnValue($newSku)); @@ -870,20 +867,4 @@ class DownloadableTest extends \Magento\ImportExport\Test\Unit\Model\Import\Abst $reflectionProperty->setValue($object, $value); return $object; } - - /** - * @param $map - */ - private function prepareObjectManager($map) - { - $objectManagerMock = $this->getMock(\Magento\Framework\ObjectManagerInterface::class); - $objectManagerMock->expects($this->any())->method('getInstance')->willReturnSelf(); - $objectManagerMock->expects($this->any()) - ->method('get') - ->will($this->returnValueMap($map)); - $reflectionClass = new \ReflectionClass(\Magento\Framework\App\ObjectManager::class); - $reflectionProperty = $reflectionClass->getProperty('_instance'); - $reflectionProperty->setAccessible(true); - $reflectionProperty->setValue($objectManagerMock); - } } diff --git a/app/code/Magento/Eav/Model/Config.php b/app/code/Magento/Eav/Model/Config.php index 36be7733dcd75a1fed3c7f63072f546d32378416..0d0237a1f6732cd06f540caa0c4f114947afeb6e 100644 --- a/app/code/Magento/Eav/Model/Config.php +++ b/app/code/Magento/Eav/Model/Config.php @@ -6,6 +6,8 @@ namespace Magento\Eav\Model; use Magento\Eav\Model\Entity\Type; +use Magento\Framework\Serialize\SerializerInterface; +use Magento\Framework\App\ObjectManager; /** * @SuppressWarnings(PHPMD.CouplingBetweenObjects) @@ -92,12 +94,18 @@ class Config */ protected $_universalFactory; + /** + * @var SerializerInterface + */ + private $serializer; + /** * @param \Magento\Framework\App\CacheInterface $cache * @param \Magento\Eav\Model\Entity\TypeFactory $entityTypeFactory * @param \Magento\Eav\Model\ResourceModel\Entity\Type\CollectionFactory $entityTypeCollectionFactory * @param \Magento\Framework\App\Cache\StateInterface $cacheState * @param \Magento\Framework\Validator\UniversalFactory $universalFactory + * @param SerializerInterface $serializer * @codeCoverageIgnore */ public function __construct( @@ -105,13 +113,15 @@ class Config \Magento\Eav\Model\Entity\TypeFactory $entityTypeFactory, \Magento\Eav\Model\ResourceModel\Entity\Type\CollectionFactory $entityTypeCollectionFactory, \Magento\Framework\App\Cache\StateInterface $cacheState, - \Magento\Framework\Validator\UniversalFactory $universalFactory + \Magento\Framework\Validator\UniversalFactory $universalFactory, + SerializerInterface $serializer = null ) { $this->_cache = $cache; $this->_entityTypeFactory = $entityTypeFactory; $this->entityTypeCollectionFactory = $entityTypeCollectionFactory; $this->_cacheState = $cacheState; $this->_universalFactory = $universalFactory; + $this->serializer = $serializer ?: ObjectManager::getInstance()->get(SerializerInterface::class); } /** @@ -278,7 +288,7 @@ class Config \Magento\Framework\Profiler::start('EAV: ' . __METHOD__, ['group' => 'EAV', 'method' => __METHOD__]); if ($this->isCacheEnabled() && ($cache = $this->_cache->load(self::ENTITIES_CACHE_ID))) { - $this->_entityTypeData = unserialize($cache); + $this->_entityTypeData = $this->serializer->unserialize($cache); foreach ($this->_entityTypeData as $typeCode => $data) { $typeId = $data['entity_type_id']; $this->_addEntityTypeReference($typeId, $typeCode); @@ -302,7 +312,7 @@ class Config if ($this->isCacheEnabled()) { $this->_cache->save( - serialize($this->_entityTypeData), + $this->serializer->serialize($this->_entityTypeData), self::ENTITIES_CACHE_ID, [ \Magento\Eav\Model\Cache\Type::CACHE_TAG, @@ -372,7 +382,7 @@ class Config } $cacheKey = self::ATTRIBUTES_CACHE_ID . $entityTypeCode; if ($this->isCacheEnabled() && ($attributes = $this->_cache->load($cacheKey))) { - $attributes = unserialize($attributes); + $attributes = $this->serializer->unserialize($attributes); if ($attributes) { foreach ($attributes as $attribute) { $this->_createAttribute($entityType, $attribute); @@ -402,7 +412,7 @@ class Config } if ($this->isCacheEnabled()) { $this->_cache->save( - serialize($this->_attributeData[$entityTypeCode]), + $this->serializer->serialize($this->_attributeData[$entityTypeCode]), $cacheKey, [ \Magento\Eav\Model\Cache\Type::CACHE_TAG, @@ -487,7 +497,7 @@ class Config } if ($this->isCacheEnabled() && ($attributes = $this->_cache->load($cacheKey))) { - $this->_attributeCodes[$cacheKey] = unserialize($attributes); + $this->_attributeCodes[$cacheKey] = $this->serializer->unserialize($attributes); return $this->_attributeCodes[$cacheKey]; } @@ -514,7 +524,7 @@ class Config $this->_attributeCodes[$cacheKey] = $attributes; if ($this->isCacheEnabled()) { $this->_cache->save( - serialize($attributes), + $this->serializer->serialize($attributes), $cacheKey, [ \Magento\Eav\Model\Cache\Type::CACHE_TAG, diff --git a/app/code/Magento/Eav/Model/Entity/Attribute/Config.php b/app/code/Magento/Eav/Model/Entity/Attribute/Config.php index ae5c2f5e2339fd7b16f071c333971c3707a211e4..1bc5bba6d5e79fdfbd9cf5343f21f299121ceb43 100644 --- a/app/code/Magento/Eav/Model/Entity/Attribute/Config.php +++ b/app/code/Magento/Eav/Model/Entity/Attribute/Config.php @@ -5,20 +5,28 @@ */ namespace Magento\Eav\Model\Entity\Attribute; +use Magento\Framework\Serialize\SerializerInterface; + +/** + * Provides EAV attributes configuration + */ class Config extends \Magento\Framework\Config\Data { /** - * @param \Magento\Eav\Model\Entity\Attribute\Config\Reader $reader + * Constructor + * + * @param Config\Reader $reader * @param \Magento\Framework\Config\CacheInterface $cache - * @param string $cacheId - * @codeCoverageIgnore + * @param string|null $cacheId + * @param SerializerInterface|null $serializer */ public function __construct( \Magento\Eav\Model\Entity\Attribute\Config\Reader $reader, \Magento\Framework\Config\CacheInterface $cache, - $cacheId = "eav_attributes" + $cacheId = 'eav_attributes', + SerializerInterface $serializer = null ) { - parent::__construct($reader, $cache, $cacheId); + parent::__construct($reader, $cache, $cacheId, $serializer); } /** 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/Eav/Model/ResourceModel/Entity/Attribute/Set.php b/app/code/Magento/Eav/Model/ResourceModel/Entity/Attribute/Set.php index 4e6e45f5d2270aa42e049ae2fe52c60bd1bce82b..b3e7bf2bc3925224cace683b4aba2fe57b29e63e 100644 --- a/app/code/Magento/Eav/Model/ResourceModel/Entity/Attribute/Set.php +++ b/app/code/Magento/Eav/Model/ResourceModel/Entity/Attribute/Set.php @@ -5,11 +5,8 @@ */ namespace Magento\Eav\Model\ResourceModel\Entity\Attribute; -/** - * Eav attribute set resource model - * - * @author Magento Core Team <core@magentocommerce.com> - */ +use Magento\Framework\Serialize\SerializerInterface; + class Set extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb { /** @@ -27,6 +24,11 @@ class Set extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb */ protected $eavConfig; + /** + * @var SerializerInterface + */ + private $serializer; + /** * @param \Magento\Framework\Model\ResourceModel\Db\Context $context * @param GroupFactory $attrGroupFactory @@ -152,7 +154,7 @@ class Set extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb $cacheKey = self::ATTRIBUTES_CACHE_ID . $setId; if ($this->eavConfig->isCacheEnabled() && ($cache = $this->eavConfig->getCache()->load($cacheKey))) { - $setInfoData = unserialize($cache); + $setInfoData = $this->getSerializer()->unserialize($cache); } else { $attributeSetData = $this->fetchAttributeSetData($setId); @@ -168,7 +170,7 @@ class Set extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb if ($this->eavConfig->isCacheEnabled()) { $this->eavConfig->getCache()->save( - serialize($setInfoData), + $this->getSerializer()->serialize($setInfoData), $cacheKey, [ \Magento\Eav\Model\Cache\Type::CACHE_TAG, @@ -233,4 +235,19 @@ class Set extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb } return $connection->fetchAll($select, $bind); } + + /** + * Get serializer + * + * @return SerializerInterface + * @deprecated + */ + private function getSerializer() + { + if (null === $this->serializer) { + $this->serializer = \Magento\Framework\App\ObjectManager::getInstance() + ->get(SerializerInterface::class); + } + return $this->serializer; + } } diff --git a/app/code/Magento/Eav/Plugin/Model/ResourceModel/Entity/Attribute.php b/app/code/Magento/Eav/Plugin/Model/ResourceModel/Entity/Attribute.php index c76449b1223ed3369df37202da1415c7f14a5187..56bad8bf75e11e8329f895d62f5ccb9e5faa3148 100644 --- a/app/code/Magento/Eav/Plugin/Model/ResourceModel/Entity/Attribute.php +++ b/app/code/Magento/Eav/Plugin/Model/ResourceModel/Entity/Attribute.php @@ -5,6 +5,13 @@ */ namespace Magento\Eav\Plugin\Model\ResourceModel\Entity; +use Magento\Framework\App\CacheInterface; +use Magento\Framework\App\Cache\StateInterface; +use Magento\Framework\Serialize\SerializerInterface; +use Magento\Eav\Model\ResourceModel\Entity\Attribute as AttributeResource; +use Magento\Eav\Model\Cache\Type; +use Magento\Eav\Model\Entity\Attribute as EntityAttribute; + class Attribute { /** @@ -12,52 +19,74 @@ class Attribute */ const STORE_LABEL_ATTRIBUTE = 'EAV_STORE_LABEL_ATTRIBUTE'; - /** @var \Magento\Framework\App\CacheInterface */ - protected $cache; + /** + * @var CacheInterface + */ + private $cache; + + /** + * @var StateInterface + */ + private $cacheState; - /** @var bool|null */ - protected $isCacheEnabled = null; + /** + * @var SerializerInterface + */ + private $serializer; /** - * @param \Magento\Framework\App\CacheInterface $cache - * @param \Magento\Framework\App\Cache\StateInterface $cacheState + * @param CacheInterface $cache + * @param StateInterface $cacheState + * @param SerializerInterface $serializer * @codeCoverageIgnore */ public function __construct( - \Magento\Framework\App\CacheInterface $cache, - \Magento\Framework\App\Cache\StateInterface $cacheState + CacheInterface $cache, + StateInterface $cacheState, + SerializerInterface $serializer ) { $this->cache = $cache; - $this->isCacheEnabled = $cacheState->isEnabled(\Magento\Eav\Model\Cache\Type::TYPE_IDENTIFIER); + $this->serializer = $serializer; + $this->cacheState = $cacheState; } /** - * @param \Magento\Eav\Model\ResourceModel\Entity\Attribute $subject + * @param AttributeResource $subject * @param callable $proceed * @param int $attributeId * @return array * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ public function aroundGetStoreLabelsByAttributeId( - \Magento\Eav\Model\ResourceModel\Entity\Attribute $subject, + AttributeResource $subject, \Closure $proceed, $attributeId ) { $cacheId = self::STORE_LABEL_ATTRIBUTE . $attributeId; - if ($this->isCacheEnabled && ($storeLabels = $this->cache->load($cacheId))) { - return unserialize($storeLabels); + if ($this->isCacheEnabled() && ($storeLabels = $this->cache->load($cacheId))) { + return $this->serializer->unserialize($storeLabels); } $storeLabels = $proceed($attributeId); - if ($this->isCacheEnabled) { + if ($this->isCacheEnabled()) { $this->cache->save( - serialize($storeLabels), + $this->serializer->serialize($storeLabels), $cacheId, [ - \Magento\Eav\Model\Cache\Type::CACHE_TAG, - \Magento\Eav\Model\Entity\Attribute::CACHE_TAG + Type::CACHE_TAG, + EntityAttribute::CACHE_TAG ] ); } return $storeLabels; } + + /** + * Check if cache is enabled + * + * @return bool + */ + private function isCacheEnabled() + { + return $this->cacheState->isEnabled(Type::TYPE_IDENTIFIER); + } } diff --git a/app/code/Magento/Eav/Test/Unit/Model/ConfigTest.php b/app/code/Magento/Eav/Test/Unit/Model/ConfigTest.php index f5fad571f205c14232676327269c52b3cb61370a..ff1e186de604a0b71b0bf765579f74fdd73aa4c4 100644 --- a/app/code/Magento/Eav/Test/Unit/Model/ConfigTest.php +++ b/app/code/Magento/Eav/Test/Unit/Model/ConfigTest.php @@ -3,11 +3,15 @@ * Copyright © 2016 Magento. All rights reserved. * See COPYING.txt for license details. */ - namespace Magento\Eav\Test\Unit\Model; use Magento\Framework\DataObject; use Magento\Eav\Model\Config; +use Magento\Framework\Serialize\SerializerInterface; +use Magento\Eav\Model\Entity\Type; +use Magento\Eav\Model\Cache\Type as Cache; +use Magento\Eav\Model\Entity\Attribute; +use Magento\Eav\Model\ResourceModel\Entity\Attribute\Collection; class ConfigTest extends \PHPUnit_Framework_TestCase { @@ -34,19 +38,26 @@ class ConfigTest extends \PHPUnit_Framework_TestCase /** * @var \Magento\Framework\App\Cache\StateInterface|\PHPUnit_Framework_MockObject_MockObject */ - protected $stateMock; + protected $cacheStateMock; /** * @var \Magento\Framework\Validator\UniversalFactory|\PHPUnit_Framework_MockObject_MockObject */ protected $universalFactoryMock; + /** + * @var SerializerInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $serializerMock; + + /** + * @var Type|\PHPUnit_Framework_MockObject_MockObject + */ + private $typeMock; + protected function setUp() { - $this->cacheMock = $this->getMockBuilder(\Magento\Framework\App\CacheInterface::class) - ->disableOriginalConstructor() - ->setMethods(['load', 'getFrontend', 'save', 'remove', 'clean']) - ->getMock(); + $this->cacheMock = $this->getMock(\Magento\Framework\App\CacheInterface::class); $this->typeFactoryMock = $this->getMockBuilder(\Magento\Eav\Model\Entity\TypeFactory::class) ->setMethods(['create']) ->disableOriginalConstructor() @@ -56,35 +67,44 @@ class ConfigTest extends \PHPUnit_Framework_TestCase ->setMethods(['create']) ->disableOriginalConstructor() ->getMock(); - $this->stateMock = $this->getMockBuilder(\Magento\Framework\App\Cache\StateInterface::class) - ->setMethods(['isEnabled', 'setEnabled', 'persist']) - ->disableOriginalConstructor() - ->getMock(); + $this->cacheStateMock = $this->getMock(\Magento\Framework\App\Cache\StateInterface::class); $this->universalFactoryMock = $this->getMockBuilder(\Magento\Framework\Validator\UniversalFactory::class) ->setMethods(['create']) ->disableOriginalConstructor() ->getMock(); + $this->serializerMock = $this->getMock(SerializerInterface::class); + + $this->typeMock = $this->getMock(Type::class, [], [], '', false); + $this->config = new Config( $this->cacheMock, $this->typeFactoryMock, $this->collectionFactoryMock, - $this->stateMock, - $this->universalFactoryMock + $this->cacheStateMock, + $this->universalFactoryMock, + $this->serializerMock ); } /** * @param boolean $cacheEnabled * @param int $loadCalls - * @param string $cachedValue + * @param int $cachedValue + * @param int $unserializeCalls * @dataProvider getAttributeCacheDataProvider * @return void */ - public function testGetAttributeCache($cacheEnabled, $loadCalls, $cachedValue) + public function testGetAttributeCache($cacheEnabled, $loadCalls, $unserializeCalls, $cachedValue) { + $attributeData = [ + [ + 'attribute_code' => 'attribute_code_1', + 'attribute_id' => 1 + ] + ]; $attributeCollectionMock = $this->getMockBuilder( - \Magento\Eav\Model\ResourceModel\Entity\Attribute\Collection::class + Collection::class )->disableOriginalConstructor() ->setMethods(['getData', 'setEntityTypeFilter']) ->getMock(); @@ -96,29 +116,40 @@ class ConfigTest extends \PHPUnit_Framework_TestCase ->expects($this->any()) ->method('getData') ->willReturn([]); - $entityAttributeMock = $this->getMockBuilder(\Magento\Eav\Model\Entity\Attribute::class) + $entityAttributeMock = $this->getMockBuilder(Attribute::class) ->setMethods(['setData']) ->disableOriginalConstructor() ->getMock(); $factoryCalls = [ - [\Magento\Eav\Model\ResourceModel\Entity\Attribute\Collection::class, [], $attributeCollectionMock], - [\Magento\Eav\Model\Entity\Attribute::class, [], $entityAttributeMock], + [ + Collection::class, + [], + $attributeCollectionMock + ], + [ + Attribute::class, + [], + $entityAttributeMock + ], ]; - $this->stateMock + $this->cacheStateMock ->expects($this->atLeastOnce()) ->method('isEnabled') - ->with(\Magento\Eav\Model\Cache\Type::TYPE_IDENTIFIER) + ->with(Cache::TYPE_IDENTIFIER) ->willReturn($cacheEnabled); $this->cacheMock ->expects($this->exactly($loadCalls)) ->method('load') ->with(Config::ATTRIBUTES_CACHE_ID) ->willReturn($cachedValue); + $this->serializerMock + ->expects($this->exactly($unserializeCalls)) + ->method('unserialize') + ->with($cachedValue) + ->willReturn($attributeData); - $collectionStub = new DataObject([ - ['entity_type_code' => 'type_code_1', 'entity_type_id' => 1], - ]); + $collectionStub = new DataObject([$attributeData]); $this->collectionFactoryMock ->expects($this->any()) ->method('create') @@ -134,7 +165,7 @@ class ConfigTest extends \PHPUnit_Framework_TestCase ->method('create') ->will($this->returnValueMap($factoryCalls)); - $entityType = $this->getMockBuilder(\Magento\Eav\Model\Entity\Type::class) + $entityType = $this->getMockBuilder(Type::class) ->setMethods(['getEntity', 'setData', 'getData']) ->disableOriginalConstructor() ->getMock(); @@ -151,38 +182,145 @@ class ConfigTest extends \PHPUnit_Framework_TestCase 'cache-disabled' => [ false, 0, + 0, false, ], 'cache-miss' => [ true, 1, + 0, false, ], 'cached' => [ true, 1, - serialize( - [ - ['attribute_code' => 'attribute_code_1', 'attribute_id' => 1], - ] - ), + 1, + 'attribute serialzied data', ], ]; } public function testClear() { - $this->cacheMock - ->expects($this->once()) + $this->cacheMock->expects($this->once()) ->method('clean') ->with( $this->equalTo( [ - \Magento\Eav\Model\Cache\Type::CACHE_TAG, - \Magento\Eav\Model\Entity\Attribute::CACHE_TAG, + Cache::CACHE_TAG, + Attribute::CACHE_TAG, ] ) ); $this->config->clear(); } + + public function testGetEntityTypeInstanceOfTypePassed() + { + $this->assertEquals( + $this->typeMock, + $this->config->getEntityType($this->typeMock) + ); + } + + public function testGetEntityTypeCacheExists() + { + $entityTypeCode = 'catalog_product'; + $data = [ + $entityTypeCode => [ + 'entity_type_id' => 1 + ] + ]; + $serializedData = 'serialized data'; + $this->cacheStateMock->expects($this->once()) + ->method('isEnabled') + ->with(Cache::TYPE_IDENTIFIER) + ->willReturn(true); + $this->cacheMock->expects($this->once()) + ->method('load') + ->with(Config::ENTITIES_CACHE_ID) + ->willReturn($serializedData); + $this->serializerMock->expects($this->once()) + ->method('unserialize') + ->with($serializedData) + ->willReturn($data); + $this->typeMock->expects($this->exactly(2)) + ->method('getId') + ->willReturn($data[$entityTypeCode]['entity_type_id']); + $this->typeMock->expects($this->once()) + ->method('getEntityTypeCode') + ->willReturn($entityTypeCode); + $this->typeFactoryMock->expects($this->once()) + ->method('create') + ->with(['data' => $data[$entityTypeCode]]) + ->willReturn($this->typeMock); + $this->assertInstanceOf( + Type::class, + $this->config->getEntityType($entityTypeCode) + ); + } + + public function testGetEntityTypeCacheDoesNotExist() + { + $entityTypeCode = 'catalog_product'; + $collectionData = [ + [ + 'entity_type_id' => 1, + 'entity_type_code' => $entityTypeCode + ] + ]; + $data = [ + $entityTypeCode => [ + 'entity_type_id' => 1, + 'entity_type_code' => $entityTypeCode, + 'attribute_model' => Attribute::class + ] + ]; + $serializedData = 'serialized data'; + $this->cacheStateMock->expects($this->once()) + ->method('isEnabled') + ->with(Cache::TYPE_IDENTIFIER) + ->willReturn(true); + $this->cacheMock->expects($this->once()) + ->method('load') + ->with(Config::ENTITIES_CACHE_ID) + ->willReturn(false); + $this->serializerMock->expects($this->never()) + ->method('unserialize'); + $attributeCollectionMock = $this->getMock(Collection::class, [], [], '', false); + $this->collectionFactoryMock->expects($this->once()) + ->method('create') + ->willReturn($attributeCollectionMock); + $attributeCollectionMock->expects($this->once()) + ->method('getData') + ->willReturn($collectionData); + $this->serializerMock->expects($this->once()) + ->method('serialize') + ->with($data) + ->willReturn($serializedData); + $this->cacheMock->expects($this->once()) + ->method('save') + ->with( + $serializedData, + Config::ENTITIES_CACHE_ID, + [ + Cache::CACHE_TAG, + Attribute::CACHE_TAG + ] + ); + $this->typeMock->expects($this->exactly(2)) + ->method('getId') + ->willReturn($data[$entityTypeCode]['entity_type_id']); + $this->typeMock->expects($this->once()) + ->method('getEntityTypeCode') + ->willReturn($entityTypeCode); + $this->typeFactoryMock->expects($this->once()) + ->method('create') + ->with(['data' => $data[$entityTypeCode]]) + ->willReturn($this->typeMock); + $this->assertInstanceOf( + Type::class, + $this->config->getEntityType($entityTypeCode) + ); + } } diff --git a/app/code/Magento/Eav/Test/Unit/Model/Entity/Attribute/ConfigTest.php b/app/code/Magento/Eav/Test/Unit/Model/Entity/Attribute/ConfigTest.php index 78dbc6bed34c31e5025cb366c2200457e4303b1d..5ae74a16b27a90b0bbf53b3ab13ad2a4cf398efe 100644 --- a/app/code/Magento/Eav/Test/Unit/Model/Entity/Attribute/ConfigTest.php +++ b/app/code/Magento/Eav/Test/Unit/Model/Entity/Attribute/ConfigTest.php @@ -32,7 +32,7 @@ class ConfigTest extends \PHPUnit_Framework_TestCase protected $_cacheId; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Eav\Model\Entity\Attribute|\PHPUnit_Framework_MockObject_MockObject */ protected $_attribute; @@ -54,20 +54,20 @@ class ConfigTest extends \PHPUnit_Framework_TestCase ); $this->_cacheMock = $this->getMock(\Magento\Framework\App\Cache\Type\Config::class, [], [], '', false); $this->_cacheId = 'eav_attributes'; - $this->_cacheMock->expects( - $this->once() - )->method( - 'load' - )->with( - $this->equalTo($this->_cacheId) - )->will( - $this->returnValue(serialize([])) - ); + $this->_cacheMock->expects($this->once()) + ->method('load') + ->with($this->_cacheId) + ->willReturn(''); + + $serializerMock = $this->getMock(\Magento\Framework\Serialize\SerializerInterface::class); + $serializerMock->method('unserialize') + ->willReturn([]); $this->_model = new \Magento\Eav\Model\Entity\Attribute\Config( $this->_readerMock, $this->_cacheMock, - $this->_cacheId + $this->_cacheId, + $serializerMock ); } diff --git a/app/code/Magento/Eav/Test/Unit/Model/ResourceModel/Entity/Attribute/SetTest.php b/app/code/Magento/Eav/Test/Unit/Model/ResourceModel/Entity/Attribute/SetTest.php index a380b14595eb24afb563dfccb94f867de55e5eff..e00a8ee97648c0768c7dac4c10359e1378856674 100644 --- a/app/code/Magento/Eav/Test/Unit/Model/ResourceModel/Entity/Attribute/SetTest.php +++ b/app/code/Magento/Eav/Test/Unit/Model/ResourceModel/Entity/Attribute/SetTest.php @@ -1,14 +1,14 @@ <?php /** - * * Copyright © 2016 Magento. All rights reserved. * See COPYING.txt for license details. */ - namespace Magento\Eav\Test\Unit\Model\ResourceModel\Entity\Attribute; use Magento\Eav\Model\ResourceModel\Entity\Attribute\Set; - +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; +use Magento\Framework\Serialize\SerializerInterface; + /** * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ @@ -49,11 +49,17 @@ class SetTest extends \PHPUnit_Framework_TestCase */ protected $relationProcessor; + /** + * @var SerializerInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $serializerMock; + /** * {@inheritdoc} */ protected function setUp() { + $objectManager = new ObjectManager($this); $this->resourceMock = $this->getMockBuilder(\Magento\Framework\App\ResourceConnection::class) ->disableOriginalConstructor() ->setMethods(['getConnection', 'getTableName']) @@ -81,31 +87,28 @@ class SetTest extends \PHPUnit_Framework_TestCase ->setMethods(['isCacheEnabled', 'getEntityType', 'getCache']) ->disableOriginalConstructor() ->getMock(); - $this->model = $this->getMock( + + $this->serializerMock = $this->getMock(SerializerInterface::class); + + $attributeGroupFactoryMock = $this->getMock( + \Magento\Eav\Model\ResourceModel\Entity\Attribute\GroupFactory::class, + [], + [], + '', + false + ); + + $this->model = $objectManager->getObject( \Magento\Eav\Model\ResourceModel\Entity\Attribute\Set::class, [ - 'beginTransaction', - 'getMainTable', - 'getIdFieldName', - '_afterDelete', - 'commit', - 'rollBack', - '__wakeup' - ], - [ - $contextMock, - $this->getMock( - \Magento\Eav\Model\ResourceModel\Entity\Attribute\GroupFactory::class, - [], - [], - '', - false - ), - $this->eavConfigMock - ], - '', - true + 'context' => $contextMock, + 'attrGroupFactory' => $attributeGroupFactoryMock, + 'eavConfig' => $this->eavConfigMock + ] ); + + $objectManager->setBackwardCompatibleProperty($this->model, 'serializer', $this->serializerMock); + $this->typeMock = $this->getMock(\Magento\Eav\Model\Entity\Type::class, [], [], '', false); $this->objectMock = $this->getMock( \Magento\Framework\Model\AbstractModel::class, @@ -123,7 +126,6 @@ class SetTest extends \PHPUnit_Framework_TestCase '', false ); - } /** @@ -182,6 +184,22 @@ class SetTest extends \PHPUnit_Framework_TestCase */ public function testGetSetInfoCacheMiss() { + $serializedData = 'serialized data'; + $setElement = [ + 10000 => [ + 'group_id' => 10, + 'group_sort' => 100, + 'sort' => 1000 + ] + ]; + $setData = [ + 1 => $setElement, + 2 => [], + 3 => [] + ]; + $cached = [ + 1 => $setElement + ]; $cacheMock = $this->getMockBuilder(\Magento\Framework\App\CacheInterface::class) ->disableOriginalConstructor() ->setMethods(['load', 'save', 'getFrontend', 'remove', 'clean']) @@ -192,21 +210,15 @@ class SetTest extends \PHPUnit_Framework_TestCase ->method('load') ->with($cacheKey) ->willReturn(false); + $this->serializerMock->expects($this->once()) + ->method('serialize') + ->with($cached) + ->willReturn($serializedData); $cacheMock ->expects($this->once()) ->method('save') ->with( - serialize( - [ - 1 => [ - 10000 => [ - 'group_id' => 10, - 'group_sort' => 100, - 'sort' => 1000 - ] - ] - ] - ), + $serializedData, $cacheKey, [\Magento\Eav\Model\Cache\Type::CACHE_TAG, \Magento\Eav\Model\Entity\Attribute::CACHE_TAG] ); @@ -242,17 +254,7 @@ class SetTest extends \PHPUnit_Framework_TestCase $this->resourceMock->expects($this->any())->method('getConnection')->willReturn($connectionMock); $this->resourceMock->expects($this->any())->method('getTableName')->willReturn('_TABLE_'); $this->assertEquals( - [ - 1 => [ - 10000 => [ - 'group_id' => 10, - 'group_sort' => 100, - 'sort' => 1000 - ] - ], - 2 => [], - 3 => [] - ], + $setData, $this->model->getSetInfo([1, 2, 3], 1) ); } @@ -262,42 +264,41 @@ class SetTest extends \PHPUnit_Framework_TestCase */ public function testGetSetInfoCacheHit() { - $cached = [ - 1 => [ - 10000 => [ - 'group_id' => 10, - 'group_sort' => 100, - 'sort' => 1000 - ] + $setElement = [ + 10000 => [ + 'group_id' => 10, + 'group_sort' => 100, + 'sort' => 1000 ] ]; - + $setData = [ + 1 => $setElement, + 2 => [], + 3 => [] + ]; + $cached = [ + 1 => $setElement + ]; + $serializedData = 'serialized data'; $this->resourceMock->expects($this->never())->method('getConnection'); $this->eavConfigMock->expects($this->any())->method('isCacheEnabled')->willReturn(true); $cacheMock = $this->getMockBuilder(\Magento\Framework\App\CacheInterface::class) ->disableOriginalConstructor() ->setMethods(['load', 'save', 'getFrontend', 'remove', 'clean']) ->getMock(); - $cacheMock - ->expects($this->once()) + $cacheMock->expects($this->once()) ->method('load') ->with(Set::ATTRIBUTES_CACHE_ID . 1) - ->willReturn(serialize($cached)); + ->willReturn($serializedData); + $this->serializerMock->expects($this->once()) + ->method('unserialize') + ->with($serializedData) + ->willReturn($cached); $this->eavConfigMock->expects($this->any())->method('getCache')->willReturn($cacheMock); $this->assertEquals( - [ - 1 => [ - 10000 => [ - 'group_id' => 10, - 'group_sort' => 100, - 'sort' => 1000 - ] - ], - 2 => [], - 3 => [] - ], + $setData, $this->model->getSetInfo([1, 2, 3], 1) ); } diff --git a/app/code/Magento/Eav/Test/Unit/Plugin/Model/ResourceModel/Entity/AttributeTest.php b/app/code/Magento/Eav/Test/Unit/Plugin/Model/ResourceModel/Entity/AttributeTest.php index 7d4561259cf88f1fdaf4a5bb53ac2d2eac7408f7..3fa739d4096a8eedb0b2aaaa69b6c0f1adf93c30 100644 --- a/app/code/Magento/Eav/Test/Unit/Plugin/Model/ResourceModel/Entity/AttributeTest.php +++ b/app/code/Magento/Eav/Test/Unit/Plugin/Model/ResourceModel/Entity/AttributeTest.php @@ -3,111 +3,166 @@ * Copyright © 2016 Magento. All rights reserved. * See COPYING.txt for license details. */ - -// @codingStandardsIgnoreFile - namespace Magento\Eav\Test\Unit\Plugin\Model\ResourceModel\Entity; use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; +use Magento\Framework\Serialize\SerializerInterface; +use Magento\Framework\App\CacheInterface; +use Magento\Framework\App\Cache\StateInterface; +use Magento\Eav\Model\ResourceModel\Entity\Attribute as AttributeResource; +use Magento\Eav\Plugin\Model\ResourceModel\Entity\Attribute as AttributeResourcePlugin; +use Magento\Eav\Model\Cache\Type; +use Magento\Eav\Model\Entity\Attribute; class AttributeTest extends \PHPUnit_Framework_TestCase { - /** @var \Magento\Framework\App\CacheInterface|\PHPUnit_Framework_MockObject_MockObject */ - protected $cache; + /** + * @var CacheInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $cacheMock; - /** @var \Magento\Framework\App\Cache\StateInterface|\PHPUnit_Framework_MockObject_MockObject */ - protected $cacheState; + /** + * @var StateInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $cacheStateMock; + + /** + * @var SerializerInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $serializerMock; + + /** + * @var AttributeResource|\PHPUnit_Framework_MockObject_MockObject + */ + private $attributeResourceMock; - /** @var \Magento\Eav\Model\ResourceModel\Entity\Attribute|\PHPUnit_Framework_MockObject_MockObject */ - protected $subject; + /** + * @var AttributeResourcePlugin + */ + private $attributeResourcePlugin; protected function setUp() { - $this->cache = $this->getMock(\Magento\Framework\App\CacheInterface::class); - $this->cacheState = $this->getMock(\Magento\Framework\App\Cache\StateInterface::class); - $this->subject = $this->getMock(\Magento\Eav\Model\ResourceModel\Entity\Attribute::class, [], [], '', false); + $objectManager = new ObjectManager($this); + $this->cacheMock = $this->getMock(CacheInterface::class); + $this->cacheStateMock = $this->getMock(StateInterface::class); + $this->attributeResourceMock = $this->getMock(AttributeResource::class, [], [], '', false); + $this->serializerMock = $this->getMock(SerializerInterface::class); + $this->attributeResourcePlugin = $objectManager->getObject( + AttributeResourcePlugin::class, + [ + 'cache' => $this->cacheMock, + 'cacheState' => $this->cacheStateMock, + 'serializer' => $this->serializerMock + ] + ); } - public function testGetStoreLabelsByAttributeIdOnCacheDisabled() + public function testAroundGetStoreLabelsByAttributeIdCacheIsDisabled() { - $this->cache->expects($this->never())->method('load'); + $attributeId = 1; + $this->cacheMock->expects($this->never()) + ->method('load'); + $this->cacheStateMock->expects($this->exactly(2)) + ->method('isEnabled') + ->with(Type::TYPE_IDENTIFIER) + ->willReturn(false); - $this->assertEquals( - 'attributeId', - $this->getAttribute(false)->aroundGetStoreLabelsByAttributeId( - $this->subject, - $this->mockPluginProceed('attributeId'), - 'attributeId' - ) + $isProceedCalled = false; + // @SuppressWarnings(PHPMD.UnusedFormalParameter) + $proceed = function ($attributeId) use (&$isProceedCalled) { + $isProceedCalled = true; + }; + + $this->attributeResourcePlugin->aroundGetStoreLabelsByAttributeId( + $this->attributeResourceMock, + $proceed, + $attributeId ); + $this->assertTrue($isProceedCalled); } - public function testGetStoreLabelsByAttributeIdFromCache() + public function testAroundGetStoreLabelsByAttributeIdCacheExists() { $attributeId = 1; - $attributes = ['k' => 'v']; - $cacheId = \Magento\Eav\Plugin\Model\ResourceModel\Entity\Attribute::STORE_LABEL_ATTRIBUTE . $attributeId; - $this->cache->expects($this->any())->method('load')->with($cacheId)->willReturn(serialize($attributes)); + $attributes = ['foo' => 'bar']; + $serializedAttributes = 'serialized attributes'; + $cacheId = AttributeResourcePlugin::STORE_LABEL_ATTRIBUTE . $attributeId; + $this->cacheStateMock->expects($this->once()) + ->method('isEnabled') + ->with(Type::TYPE_IDENTIFIER) + ->willReturn(true); + $this->cacheMock->expects($this->once()) + ->method('load') + ->with($cacheId) + ->willReturn($serializedAttributes); + $this->serializerMock->expects($this->once()) + ->method('unserialize') + ->with($serializedAttributes) + ->willReturn($attributes); + + $isProceedCalled = false; + // @SuppressWarnings(PHPMD.UnusedFormalParameter) + $proceed = function ($attributeId) use (&$isProceedCalled) { + $isProceedCalled = true; + }; $this->assertEquals( $attributes, - $this->getAttribute(true)->aroundGetStoreLabelsByAttributeId( - $this->subject, - $this->mockPluginProceed(), + $this->attributeResourcePlugin->aroundGetStoreLabelsByAttributeId( + $this->attributeResourceMock, + $proceed, $attributeId ) ); + $this->assertFalse($isProceedCalled); } - public function testGetStoreLabelsByAttributeIdWithCacheSave() + public function testAroundGetStoreLabelsByAttributeIdCacheDoesNotExist() { $attributeId = 1; - $cacheId = \Magento\Eav\Plugin\Model\ResourceModel\Entity\Attribute::STORE_LABEL_ATTRIBUTE . $attributeId; - $this->cache->expects($this->any())->method('load')->with($cacheId)->willReturn(false); - $this->cache->expects($this->any())->method('save')->with( - serialize([$attributeId]), - $cacheId, - [ - \Magento\Eav\Model\Cache\Type::CACHE_TAG, - \Magento\Eav\Model\Entity\Attribute::CACHE_TAG - ] - ); + $attributes = ['foo' => 'bar']; + $serializedAttributes = 'serialized attributes'; + $cacheId = AttributeResourcePlugin::STORE_LABEL_ATTRIBUTE . $attributeId; + $this->cacheStateMock->expects($this->exactly(2)) + ->method('isEnabled') + ->with(Type::TYPE_IDENTIFIER) + ->willReturn(true); + $this->cacheMock->expects($this->once()) + ->method('load') + ->with($cacheId) + ->willReturn(false); + $this->serializerMock->expects($this->never()) + ->method('unserialize') + ->with($serializedAttributes) + ->willReturn($attributes); + $this->serializerMock->expects($this->once()) + ->method('serialize') + ->with($attributes) + ->willReturn($serializedAttributes); + $this->cacheMock->expects($this->once()) + ->method('save') + ->with( + $serializedAttributes, + $cacheId, + [ + Type::CACHE_TAG, + Attribute::CACHE_TAG + ] + ); + + // @SuppressWarnings(PHPMD.UnusedFormalParameter) + $proceed = function ($attributeId) use ($attributes) { + return $attributes; + }; $this->assertEquals( - [$attributeId], - $this->getAttribute(true)->aroundGetStoreLabelsByAttributeId( - $this->subject, - $this->mockPluginProceed([$attributeId]), + $attributes, + $this->attributeResourcePlugin->aroundGetStoreLabelsByAttributeId( + $this->attributeResourceMock, + $proceed, $attributeId ) ); } - - /** - * @param bool $cacheEnabledFlag - * @return \Magento\Eav\Plugin\Model\ResourceModel\Entity\Attribute - */ - protected function getAttribute($cacheEnabledFlag) - { - $this->cacheState->expects($this->any())->method('isEnabled') - ->with(\Magento\Eav\Model\Cache\Type::TYPE_IDENTIFIER)->willReturn($cacheEnabledFlag); - return (new ObjectManager($this))->getObject( - \Magento\Eav\Plugin\Model\ResourceModel\Entity\Attribute::class, - [ - 'cache' => $this->cache, - 'cacheState' => $this->cacheState - ] - ); - } - - /** - * @param mixed $returnValue - * @return callable - */ - protected function mockPluginProceed($returnValue = null) - { - return function () use ($returnValue) { - return $returnValue; - }; - } } diff --git a/app/code/Magento/Email/Model/Template/Config/Data.php b/app/code/Magento/Email/Model/Template/Config/Data.php index c7f4054bf311efbf55add66d4794981a42a1e459..1f6a4beb166e0da25283b8b29efff85c3b24ba58 100644 --- a/app/code/Magento/Email/Model/Template/Config/Data.php +++ b/app/code/Magento/Email/Model/Template/Config/Data.php @@ -1,22 +1,31 @@ <?php /** - * Email templates configuration data container. Provides email templates configuration data. - * * Copyright © 2016 Magento. All rights reserved. * See COPYING.txt for license details. */ namespace Magento\Email\Model\Template\Config; +use Magento\Framework\Serialize\SerializerInterface; + +/** + * Provides email templates configuration + */ class Data extends \Magento\Framework\Config\Data { /** + * Constructor + * * @param \Magento\Email\Model\Template\Config\Reader $reader * @param \Magento\Framework\Config\CacheInterface $cache + * @param string|null $cacheId + * @param SerializerInterface|null $serializer */ public function __construct( \Magento\Email\Model\Template\Config\Reader $reader, - \Magento\Framework\Config\CacheInterface $cache + \Magento\Framework\Config\CacheInterface $cache, + $cacheId = 'email_templates', + SerializerInterface $serializer = null ) { - parent::__construct($reader, $cache, 'email_templates'); + parent::__construct($reader, $cache, $cacheId, $serializer); } } 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/GroupedProduct/Model/Product/Type/Grouped.php b/app/code/Magento/GroupedProduct/Model/Product/Type/Grouped.php index 02ff894df7c1fb1ed6ec7b6af07f019cece1b8cb..74a7e8112aa0ddb528b46168a16df15310fd227c 100644 --- a/app/code/Magento/GroupedProduct/Model/Product/Type/Grouped.php +++ b/app/code/Magento/GroupedProduct/Model/Product/Type/Grouped.php @@ -202,7 +202,7 @@ class Grouped extends \Magento\Catalog\Model\Product\Type\AbstractType $collection = $this->getAssociatedProductCollection( $product )->addAttributeToSelect( - ['name', 'price', 'special_price', 'special_from_date', 'special_to_date'] + ['name', 'price', 'special_price', 'special_from_date', 'special_to_date', 'tax_class_id'] )->addFilterByRequiredOptions()->setPositionOrder()->addStoreFilter( $this->getStoreFilter($product) )->addAttributeToFilter( diff --git a/app/code/Magento/ImportExport/Model/Export/Config.php b/app/code/Magento/ImportExport/Model/Export/Config.php index 267a7e6c7a9e1ef161aff935377848e19faf72c2..2d7b2c7a3af253e7ef7d80d13de45a95007f6c5a 100644 --- a/app/code/Magento/ImportExport/Model/Export/Config.php +++ b/app/code/Magento/ImportExport/Model/Export/Config.php @@ -5,19 +5,28 @@ */ namespace Magento\ImportExport\Model\Export; +use Magento\Framework\Serialize\SerializerInterface; + +/** + * Provides export configuration + */ class Config extends \Magento\Framework\Config\Data implements \Magento\ImportExport\Model\Export\ConfigInterface { /** - * @param \Magento\ImportExport\Model\Export\Config\Reader $reader + * Constructor + * + * @param Config\Reader $reader * @param \Magento\Framework\Config\CacheInterface $cache - * @param string $cacheId + * @param string|null $cacheId + * @param SerializerInterface|null $serializer */ public function __construct( \Magento\ImportExport\Model\Export\Config\Reader $reader, \Magento\Framework\Config\CacheInterface $cache, - $cacheId = 'export_config_cache' + $cacheId = 'export_config_cache', + SerializerInterface $serializer = null ) { - parent::__construct($reader, $cache, $cacheId); + parent::__construct($reader, $cache, $cacheId, $serializer); } /** diff --git a/app/code/Magento/ImportExport/Model/Import/Config.php b/app/code/Magento/ImportExport/Model/Import/Config.php index 0652dd03d9ff43944ef9e7cb10fa1671c7048987..a1ec492da3e9630d0166d52f6eae28a564897c12 100644 --- a/app/code/Magento/ImportExport/Model/Import/Config.php +++ b/app/code/Magento/ImportExport/Model/Import/Config.php @@ -5,19 +5,28 @@ */ namespace Magento\ImportExport\Model\Import; +use Magento\Framework\Serialize\SerializerInterface; + +/** + * Provides import configuration + */ class Config extends \Magento\Framework\Config\Data implements \Magento\ImportExport\Model\Import\ConfigInterface { /** - * @param \Magento\ImportExport\Model\Import\Config\Reader $reader + * Constructor + * + * @param Config\Reader $reader * @param \Magento\Framework\Config\CacheInterface $cache - * @param string $cacheId + * @param string|null $cacheId + * @param SerializerInterface|null $serializer */ public function __construct( \Magento\ImportExport\Model\Import\Config\Reader $reader, \Magento\Framework\Config\CacheInterface $cache, - $cacheId = 'import_config_cache' + $cacheId = 'import_config_cache', + SerializerInterface $serializer = null ) { - parent::__construct($reader, $cache, $cacheId); + parent::__construct($reader, $cache, $cacheId, $serializer); } /** diff --git a/app/code/Magento/ImportExport/Test/Unit/Model/Export/ConfigTest.php b/app/code/Magento/ImportExport/Test/Unit/Model/Export/ConfigTest.php index 797c9f7a1ae32a8464114e3f144bfc7b679fb54e..0b1e542f85b9deb9dc3c24a7cb0497ba4d9d5168 100644 --- a/app/code/Magento/ImportExport/Test/Unit/Model/Export/ConfigTest.php +++ b/app/code/Magento/ImportExport/Test/Unit/Model/Export/ConfigTest.php @@ -8,35 +8,41 @@ namespace Magento\ImportExport\Test\Unit\Model\Export; class ConfigTest extends \PHPUnit_Framework_TestCase { /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var \Magento\ImportExport\Model\Export\Config\Reader|\PHPUnit_Framework_MockObject_MockObject */ - protected $_readerMock; + private $readerMock; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\Config\CacheInterface|\PHPUnit_Framework_MockObject_MockObject */ - protected $_configScopeMock; + private $cacheMock; + + /** + * @var \Magento\Framework\Serialize\SerializerInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $serializerMock; /** * @var string */ - protected $_cacheId = 'some_id'; + private $cacheId = 'some_id'; /** * @var \Magento\ImportExport\Model\Export\Config */ - protected $_model; + private $model; protected function setUp() { - $this->_readerMock = $this->getMock( + $this->readerMock = $this->getMock( \Magento\ImportExport\Model\Export\Config\Reader::class, [], [], '', false ); - $this->_configScopeMock = $this->getMock(\Magento\Framework\Config\CacheInterface::class); + $this->cacheMock = $this->getMock(\Magento\Framework\Config\CacheInterface::class); + $this->serializerMock = $this->getMock(\Magento\Framework\Serialize\SerializerInterface::class); } /** @@ -46,22 +52,23 @@ class ConfigTest extends \PHPUnit_Framework_TestCase */ public function testGetEntities($value, $expected) { - $this->_configScopeMock->expects( + $this->cacheMock->expects( $this->any() )->method( 'load' )->with( - $this->_cacheId + $this->cacheId )->will( $this->returnValue(false) ); - $this->_readerMock->expects($this->any())->method('read')->will($this->returnValue($value)); - $this->_model = new \Magento\ImportExport\Model\Export\Config( - $this->_readerMock, - $this->_configScopeMock, - $this->_cacheId + $this->readerMock->expects($this->any())->method('read')->will($this->returnValue($value)); + $this->model = new \Magento\ImportExport\Model\Export\Config( + $this->readerMock, + $this->cacheMock, + $this->cacheId, + $this->serializerMock ); - $this->assertEquals($expected, $this->_model->getEntities('entities')); + $this->assertEquals($expected, $this->model->getEntities('entities')); } public function getEntitiesDataProvider() @@ -80,22 +87,23 @@ class ConfigTest extends \PHPUnit_Framework_TestCase */ public function testGetEntityTypes($configData, $entity, $expectedResult) { - $this->_configScopeMock->expects( + $this->cacheMock->expects( $this->any() )->method( 'load' )->with( - $this->_cacheId + $this->cacheId )->will( $this->returnValue(false) ); - $this->_readerMock->expects($this->any())->method('read')->will($this->returnValue($configData)); - $this->_model = new \Magento\ImportExport\Model\Export\Config( - $this->_readerMock, - $this->_configScopeMock, - $this->_cacheId + $this->readerMock->expects($this->any())->method('read')->will($this->returnValue($configData)); + $this->model = new \Magento\ImportExport\Model\Export\Config( + $this->readerMock, + $this->cacheMock, + $this->cacheId, + $this->serializerMock ); - $this->assertEquals($expectedResult, $this->_model->getEntityTypes($entity)); + $this->assertEquals($expectedResult, $this->model->getEntityTypes($entity)); } public function getEntityTypesDataProvider() @@ -133,22 +141,23 @@ class ConfigTest extends \PHPUnit_Framework_TestCase */ public function testGetFileFormats($value, $expected) { - $this->_configScopeMock->expects( + $this->cacheMock->expects( $this->any() )->method( 'load' )->with( - $this->_cacheId + $this->cacheId )->will( $this->returnValue(false) ); - $this->_readerMock->expects($this->any())->method('read')->will($this->returnValue($value)); - $this->_model = new \Magento\ImportExport\Model\Export\Config( - $this->_readerMock, - $this->_configScopeMock, - $this->_cacheId + $this->readerMock->expects($this->any())->method('read')->will($this->returnValue($value)); + $this->model = new \Magento\ImportExport\Model\Export\Config( + $this->readerMock, + $this->cacheMock, + $this->cacheId, + $this->serializerMock ); - $this->assertEquals($expected, $this->_model->getFileFormats('fileFormats')); + $this->assertEquals($expected, $this->model->getFileFormats('fileFormats')); } public function getFileFormatsDataProvider() diff --git a/app/code/Magento/ImportExport/Test/Unit/Model/Import/ConfigTest.php b/app/code/Magento/ImportExport/Test/Unit/Model/Import/ConfigTest.php index 1530c0b4a4d00d00944b6f57c41e1b5410ee9d16..60cd1f50238a46f746ad9e8107f7fd612d4f593b 100644 --- a/app/code/Magento/ImportExport/Test/Unit/Model/Import/ConfigTest.php +++ b/app/code/Magento/ImportExport/Test/Unit/Model/Import/ConfigTest.php @@ -8,35 +8,41 @@ namespace Magento\ImportExport\Test\Unit\Model\Import; class ConfigTest extends \PHPUnit_Framework_TestCase { /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var \Magento\ImportExport\Model\Import\Config\Reader|\PHPUnit_Framework_MockObject_MockObject */ - protected $_readerMock; + protected $readerMock; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\Config\CacheInterface|\PHPUnit_Framework_MockObject_MockObject */ - protected $_configScopeMock; + protected $cacheMock; + + /** + * @var \Magento\Framework\Serialize\SerializerInterface + */ + private $serializerMock; /** * @var string */ - protected $_cacheId = 'some_id'; + protected $cacheId = 'some_id'; /** * @var \Magento\ImportExport\Model\Import\Config */ - protected $_model; + protected $model; protected function setUp() { - $this->_readerMock = $this->getMock( + $this->readerMock = $this->getMock( \Magento\ImportExport\Model\Import\Config\Reader::class, [], [], '', false ); - $this->_configScopeMock = $this->getMock(\Magento\Framework\Config\CacheInterface::class); + $this->cacheMock = $this->getMock(\Magento\Framework\Config\CacheInterface::class); + $this->serializerMock = $this->getMock(\Magento\Framework\Serialize\SerializerInterface::class); } /** @@ -46,22 +52,23 @@ class ConfigTest extends \PHPUnit_Framework_TestCase */ public function testGetEntities($value, $expected) { - $this->_configScopeMock->expects( + $this->cacheMock->expects( $this->any() )->method( 'load' )->with( - $this->_cacheId + $this->cacheId )->will( $this->returnValue(false) ); - $this->_readerMock->expects($this->any())->method('read')->will($this->returnValue($value)); - $this->_model = new \Magento\ImportExport\Model\Import\Config( - $this->_readerMock, - $this->_configScopeMock, - $this->_cacheId + $this->readerMock->expects($this->any())->method('read')->will($this->returnValue($value)); + $this->model = new \Magento\ImportExport\Model\Import\Config( + $this->readerMock, + $this->cacheMock, + $this->cacheId, + $this->serializerMock ); - $this->assertEquals($expected, $this->_model->getEntities('entities')); + $this->assertEquals($expected, $this->model->getEntities('entities')); } public function getEntitiesDataProvider() @@ -80,22 +87,23 @@ class ConfigTest extends \PHPUnit_Framework_TestCase */ public function testGetEntityTypes($configData, $entity, $expectedResult) { - $this->_configScopeMock->expects( + $this->cacheMock->expects( $this->any() )->method( 'load' )->with( - $this->_cacheId + $this->cacheId )->will( $this->returnValue(false) ); - $this->_readerMock->expects($this->any())->method('read')->will($this->returnValue($configData)); - $this->_model = new \Magento\ImportExport\Model\Import\Config( - $this->_readerMock, - $this->_configScopeMock, - $this->_cacheId + $this->readerMock->expects($this->any())->method('read')->will($this->returnValue($configData)); + $this->model = new \Magento\ImportExport\Model\Import\Config( + $this->readerMock, + $this->cacheMock, + $this->cacheId, + $this->serializerMock ); - $this->assertEquals($expectedResult, $this->_model->getEntityTypes($entity)); + $this->assertEquals($expectedResult, $this->model->getEntityTypes($entity)); } public function getEntityTypesDataProvider() diff --git a/app/code/Magento/Indexer/Model/Config/Data.php b/app/code/Magento/Indexer/Model/Config/Data.php index 68a390a8c06b761b710b0ab950b56528a4228d22..3cedaa51ef4bb4952799321d5032e90c154b4feb 100644 --- a/app/code/Magento/Indexer/Model/Config/Data.php +++ b/app/code/Magento/Indexer/Model/Config/Data.php @@ -5,6 +5,12 @@ */ namespace Magento\Indexer\Model\Config; +use Magento\Framework\Serialize\SerializerInterface; +use Magento\Framework\App\ObjectManager; + +/** + * Provides indexer configuration + */ class Data extends \Magento\Framework\Config\Data { /** @@ -13,22 +19,26 @@ class Data extends \Magento\Framework\Config\Data protected $stateCollection; /** + * Constructor + * * @param \Magento\Framework\Indexer\Config\Reader $reader * @param \Magento\Framework\Config\CacheInterface $cache * @param \Magento\Indexer\Model\ResourceModel\Indexer\State\Collection $stateCollection - * @param string $cacheId + * @param string|null $cacheId + * @param SerializerInterface|null $serializer */ public function __construct( \Magento\Framework\Indexer\Config\Reader $reader, \Magento\Framework\Config\CacheInterface $cache, \Magento\Indexer\Model\ResourceModel\Indexer\State\Collection $stateCollection, - $cacheId = 'indexer_config' + $cacheId = 'indexer_config', + SerializerInterface $serializer = null ) { $this->stateCollection = $stateCollection; $isCacheExists = $cache->test($cacheId); - parent::__construct($reader, $cache, $cacheId); + parent::__construct($reader, $cache, $cacheId, $serializer); if (!$isCacheExists) { $this->deleteNonexistentStates(); diff --git a/app/code/Magento/Indexer/Test/Unit/Model/Config/DataTest.php b/app/code/Magento/Indexer/Test/Unit/Model/Config/DataTest.php index 5e0f7c314cf31d2189a0540b66d87b983f8dd0e9..e16c21b8f112592e759cca7489a685ae59aa5dbe 100644 --- a/app/code/Magento/Indexer/Test/Unit/Model/Config/DataTest.php +++ b/app/code/Magento/Indexer/Test/Unit/Model/Config/DataTest.php @@ -37,6 +37,11 @@ class DataTest extends \PHPUnit_Framework_TestCase */ protected $indexers = ['indexer1' => [], 'indexer3' => []]; + /** + * @var \Magento\Framework\Serialize\SerializerInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $serializerMock; + protected function setUp() { $this->reader = $this->getMock(\Magento\Framework\Indexer\Config\Reader::class, ['read'], [], '', false); @@ -56,20 +61,22 @@ class DataTest extends \PHPUnit_Framework_TestCase '', false ); + $this->serializerMock = $this->getMock(\Magento\Framework\Serialize\SerializerInterface::class); } public function testConstructorWithCache() { + $serializedData = 'serialized data'; $this->cache->expects($this->once())->method('test')->with($this->cacheId)->will($this->returnValue(true)); - $this->cache->expects( - $this->once() - )->method( - 'load' - )->with( - $this->cacheId - )->will( - $this->returnValue(serialize($this->indexers)) - ); + $this->cache->expects($this->once()) + ->method('load') + ->with($this->cacheId) + ->willReturn($serializedData); + + $this->serializerMock->expects($this->once()) + ->method('unserialize') + ->with($serializedData) + ->willReturn($this->indexers); $this->stateCollection->expects($this->never())->method('getItems'); @@ -77,7 +84,8 @@ class DataTest extends \PHPUnit_Framework_TestCase $this->reader, $this->cache, $this->stateCollection, - $this->cacheId + $this->cacheId, + $this->serializerMock ); } @@ -116,7 +124,8 @@ class DataTest extends \PHPUnit_Framework_TestCase $this->reader, $this->cache, $this->stateCollection, - $this->cacheId + $this->cacheId, + $this->serializerMock ); } } diff --git a/app/code/Magento/Indexer/view/adminhtml/layout/indexer_indexer_list_grid.xml b/app/code/Magento/Indexer/view/adminhtml/layout/indexer_indexer_list_grid.xml index 6def568e9cbbd83fec74955430834f7538418ab9..63ef028238393bbbbcebaeff4c50caa1e94b44db 100644 --- a/app/code/Magento/Indexer/view/adminhtml/layout/indexer_indexer_list_grid.xml +++ b/app/code/Magento/Indexer/view/adminhtml/layout/indexer_indexer_list_grid.xml @@ -46,6 +46,7 @@ <argument name="index" xsi:type="string">title</argument> <argument name="sortable" xsi:type="string">0</argument> <argument name="column_css_class" xsi:type="string">indexer-title</argument> + <argument name="translate" xsi:type="boolean">true</argument> </arguments> </block> <block class="Magento\Backend\Block\Widget\Grid\Column" as="indexer_description"> @@ -54,6 +55,7 @@ <argument name="index" xsi:type="string">description</argument> <argument name="sortable" xsi:type="string">0</argument> <argument name="column_css_class" xsi:type="string">indexer-description</argument> + <argument name="translate" xsi:type="boolean">true</argument> </arguments> </block> <block class="Magento\Backend\Block\Widget\Grid\Column" as="indexer_mode"> diff --git a/app/code/Magento/Multishipping/Block/Checkout/Billing/Items.php b/app/code/Magento/Multishipping/Block/Checkout/Billing/Items.php index 5a3e581d5375bb983baac8516b63788331388da9..3d2ca91d3ba6c0b687a6361858ce13269967861e 100644 --- a/app/code/Magento/Multishipping/Block/Checkout/Billing/Items.php +++ b/app/code/Magento/Multishipping/Block/Checkout/Billing/Items.php @@ -68,7 +68,7 @@ class Items extends \Magento\Sales\Block\Items\AbstractItems */ public function getVirtualProductEditUrl() { - return $this->getUrl('*/cart'); + return $this->getUrl('checkout/cart'); } /** diff --git a/app/code/Magento/Multishipping/Block/Checkout/Overview.php b/app/code/Magento/Multishipping/Block/Checkout/Overview.php index 0031b6416d333eb32eb032ead7267ca4d8f9da9c..299e85d6f13c31a4633d9886f4565866def62802 100644 --- a/app/code/Magento/Multishipping/Block/Checkout/Overview.php +++ b/app/code/Magento/Multishipping/Block/Checkout/Overview.php @@ -297,7 +297,7 @@ class Overview extends \Magento\Sales\Block\Items\AbstractItems */ public function getVirtualProductEditUrl() { - return $this->getUrl('*/cart'); + return $this->getUrl('checkout/cart'); } /** diff --git a/app/code/Magento/Multishipping/Test/Unit/Block/Checkout/Billing/ItemsTest.php b/app/code/Magento/Multishipping/Test/Unit/Block/Checkout/Billing/ItemsTest.php new file mode 100644 index 0000000000000000000000000000000000000000..056ac173621743ac162ba744d83a60d097cf12fc --- /dev/null +++ b/app/code/Magento/Multishipping/Test/Unit/Block/Checkout/Billing/ItemsTest.php @@ -0,0 +1,40 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Multishipping\Test\Unit\Block\Checkout\Billing; + + +class ItemsTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var \Magento\Multishipping\Block\Checkout\Billing\Items + */ + private $model; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + private $urlBuilderMock; + + protected function setUp() + { + $objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); + $this->urlBuilderMock = $this->getMock(\Magento\Framework\UrlInterface::class); + $this->model = $objectManager->getObject( + \Magento\Multishipping\Block\Checkout\Billing\Items::class, + [ + 'urlBuilder' => $this->urlBuilderMock + ] + ); + } + + public function testGetVirtualProductEditUrl() + { + $url = 'http://example.com'; + $this->urlBuilderMock->expects($this->once())->method('getUrl')->with('checkout/cart', [])->willReturn($url); + $this->assertEquals($url, $this->model->getVirtualProductEditUrl()); + } +} diff --git a/app/code/Magento/Multishipping/Test/Unit/Block/Checkout/OverviewTest.php b/app/code/Magento/Multishipping/Test/Unit/Block/Checkout/OverviewTest.php index fc2169f38e4af88559b112931ac0952ecd82f5d0..b583ad258595b7101fb8683df6c9932a20ee1b3f 100644 --- a/app/code/Magento/Multishipping/Test/Unit/Block/Checkout/OverviewTest.php +++ b/app/code/Magento/Multishipping/Test/Unit/Block/Checkout/OverviewTest.php @@ -52,6 +52,11 @@ class OverviewTest extends \PHPUnit_Framework_TestCase */ protected $quoteMock; + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + private $urlBuilderMock; + protected function setUp() { $objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); @@ -83,13 +88,15 @@ class OverviewTest extends \PHPUnit_Framework_TestCase $this->checkoutMock = $this->getMock(\Magento\Multishipping\Model\Checkout\Type\Multishipping::class, [], [], '', false); $this->quoteMock = $this->getMock(\Magento\Quote\Model\Quote::class, [], [], '', false); + $this->urlBuilderMock = $this->getMock(\Magento\Framework\UrlInterface::class); $this->model = $objectManager->getObject( \Magento\Multishipping\Block\Checkout\Overview::class, [ 'priceCurrency' => $this->priceCurrencyMock, 'totalsCollector' => $this->totalsCollectorMock, 'totalsReader' => $this->totalsReaderMock, - 'multishipping' => $this->checkoutMock + 'multishipping' => $this->checkoutMock, + 'urlBuilder' => $this->urlBuilderMock ] ); } @@ -189,4 +196,11 @@ class OverviewTest extends \PHPUnit_Framework_TestCase ->willReturn([$totalMock]); return $totalMock; } + + public function testGetVirtualProductEditUrl() + { + $url = 'http://example.com'; + $this->urlBuilderMock->expects($this->once())->method('getUrl')->with('checkout/cart', [])->willReturn($url); + $this->assertEquals($url, $this->model->getVirtualProductEditUrl()); + } } diff --git a/app/code/Magento/NewRelicReporting/etc/di.xml b/app/code/Magento/NewRelicReporting/etc/di.xml index caabf89be1871b05d55040d34f3b4b0e5b7a9120..6e3a24be91982e9f14b54228144157165094b1a5 100644 --- a/app/code/Magento/NewRelicReporting/etc/di.xml +++ b/app/code/Magento/NewRelicReporting/etc/di.xml @@ -12,4 +12,14 @@ <argument name="fullModuleList" xsi:type="object">Magento\Framework\Module\FullModuleList</argument> </arguments> </type> + <type name="Magento\Config\Model\Config\Export\ExcludeList"> + <arguments> + <argument name="configs" xsi:type="array"> + <item name="newrelicreporting/general/account_id" xsi:type="string">1</item> + <item name="newrelicreporting/general/app_id" xsi:type="string">1</item> + <item name="newrelicreporting/general/api" xsi:type="string">1</item> + <item name="newrelicreporting/general/insights_insert_key" xsi:type="string">1</item> + </argument> + </arguments> + </type> </config> diff --git a/app/code/Magento/Newsletter/Model/ResourceModel/Queue.php b/app/code/Magento/Newsletter/Model/ResourceModel/Queue.php index 12375a5a6ca07404fbcf813c56dc76f3a404c5d3..b25677846622bf175fb6c80ae632132d2fb43e2d 100644 --- a/app/code/Magento/Newsletter/Model/ResourceModel/Queue.php +++ b/app/code/Magento/Newsletter/Model/ResourceModel/Queue.php @@ -80,13 +80,13 @@ class Queue extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb $subscriberIds ); - $usedIds = $connection->fetchCol($select); + $usedIds = array_flip($connection->fetchCol($select)); + $subscriberIds = array_flip($subscriberIds); + $newIds = array_diff_key($subscriberIds, $usedIds); + $connection->beginTransaction(); try { - foreach ($subscriberIds as $subscriberId) { - if (in_array($subscriberId, $usedIds)) { - continue; - } + foreach (array_keys($newIds) as $subscriberId) { $data = []; $data['queue_id'] = $queue->getId(); $data['subscriber_id'] = $subscriberId; diff --git a/app/code/Magento/OfflineShipping/Model/Quote/Address/FreeShipping.php b/app/code/Magento/OfflineShipping/Model/Quote/Address/FreeShipping.php index d2febaccb2fdf3644774f89626e6224bf6e89415..cf9eed3e84d26860792c4d3751e138ad84863eb8 100644 --- a/app/code/Magento/OfflineShipping/Model/Quote/Address/FreeShipping.php +++ b/app/code/Magento/OfflineShipping/Model/Quote/Address/FreeShipping.php @@ -5,8 +5,6 @@ */ namespace Magento\OfflineShipping\Model\Quote\Address; -use Magento\Quote\Model\Quote\Address; - class FreeShipping implements \Magento\Quote\Model\Quote\Address\FreeShippingInterface { /** @@ -48,7 +46,8 @@ class FreeShipping implements \Magento\Quote\Model\Quote\Address\FreeShippingInt $quote->getCustomerGroupId(), $quote->getCouponCode() ); - + $shippingAddress = $quote->getShippingAddress(); + $shippingAddress->setFreeShipping(0); /** @var \Magento\Quote\Api\Data\CartItemInterface $item */ foreach ($items as $item) { if ($item->getNoDiscount()) { @@ -66,10 +65,14 @@ class FreeShipping implements \Magento\Quote\Model\Quote\Address\FreeShippingInt $itemFreeShipping = (bool)$item->getFreeShipping(); $addressFreeShipping = $addressFreeShipping && $itemFreeShipping; + if ($addressFreeShipping && !$item->getAddress()->getFreeShipping()) { + $item->getAddress()->setFreeShipping(true); + } + /** Parent free shipping we apply to all children*/ $this->applyToChildren($item, $itemFreeShipping); } - return $addressFreeShipping; + return (bool)$shippingAddress->getFreeShipping(); } /** diff --git a/app/code/Magento/OfflineShipping/Test/Unit/Model/Quote/Address/FreeShippingTest.php b/app/code/Magento/OfflineShipping/Test/Unit/Model/Quote/Address/FreeShippingTest.php new file mode 100644 index 0000000000000000000000000000000000000000..27f3c375c91c5a70de74c3ed620838ec358144db --- /dev/null +++ b/app/code/Magento/OfflineShipping/Test/Unit/Model/Quote/Address/FreeShippingTest.php @@ -0,0 +1,111 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\OfflineShipping\Test\Unit\Model\Quote\Address; + +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper; + +class FreeShippingTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var \Magento\OfflineShipping\Model\Quote\Address\FreeShipping + */ + private $model; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Store\Model\StoreManagerInterface + */ + private $storeManagerMock; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\OfflineShipping\Model\SalesRule\Calculator + */ + private $calculatorMock; + + protected function setUp() + { + $this->storeManagerMock = $this->getMock(\Magento\Store\Model\StoreManagerInterface::class); + $this->calculatorMock = $this->getMock( + \Magento\OfflineShipping\Model\SalesRule\Calculator::class, + [], + [], + '', + false + ); + + $this->model = new \Magento\OfflineShipping\Model\Quote\Address\FreeShipping( + $this->storeManagerMock, + $this->calculatorMock + ); + } + + public function testIsFreeShippingIfNoItems() + { + $quoteMock = $this->getMock(\Magento\Quote\Model\Quote::class, [], [], '', false); + $this->assertFalse($this->model->isFreeShipping($quoteMock, [])); + } + + public function testIsFreeShipping() + { + $storeId = 100; + $websiteId = 200; + $customerGroupId = 300; + $objectManagerMock = new ObjectManagerHelper($this); + $quoteMock = $this->getMock( + \Magento\Quote\Model\Quote::class, + ['getShippingAddress', 'getStoreId', 'getCustomerGroupId', 'getCouponCode'], + [], + '', + false + ); + $itemMock = $this->getMock( + \Magento\Quote\Model\Quote\Item::class, + [ + 'getNoDiscount', + 'getParentItemId', + 'getFreeShipping', + 'getAddress', + 'isChildrenCalculated', + 'getHasChildren', + 'getChildren' + ], + [], + '', + false + ); + + $quoteMock->expects($this->once())->method('getStoreId')->willReturn($storeId); + $storeMock = $this->getMock(\Magento\Store\Api\Data\StoreInterface::class); + $storeMock->expects($this->once())->method('getWebsiteId')->willReturn($websiteId); + $this->storeManagerMock->expects($this->once())->method('getStore')->with($storeId)->willReturn($storeMock); + + $quoteMock->expects($this->once())->method('getCustomerGroupId')->willReturn($customerGroupId); + $quoteMock->expects($this->once())->method('getCouponCode')->willReturn(null); + + $this->calculatorMock->expects($this->once()) + ->method('init') + ->with($websiteId, $customerGroupId, null) + ->willReturnSelf(); + + $itemMock->expects($this->once())->method('getNoDiscount')->willReturn(false); + $itemMock->expects($this->once())->method('getParentItemId')->willReturn(false); + $this->calculatorMock->expects($this->exactly(2))->method('processFreeShipping')->willReturnSelf(); + $itemMock->expects($this->once())->method('getFreeShipping')->willReturn(true); + + $addressMock = $objectManagerMock->getObject(\Magento\Quote\Model\Quote\Address::class); + $quoteMock->expects($this->once())->method('getShippingAddress')->willReturn($addressMock); + $itemMock->expects($this->exactly(2))->method('getAddress')->willReturn($addressMock); + + $itemMock->expects($this->once())->method('getHasChildren')->willReturn(true); + $itemMock->expects($this->once())->method('isChildrenCalculated')->willReturn(true); + + $childMock = $this->getMock(\Magento\Quote\Model\Quote\Item::class, ['setFreeShipping'], [], '', false); + $childMock->expects($this->once())->method('setFreeShipping')->with(true)->willReturnSelf(); + $itemMock->expects($this->once())->method('getChildren')->willReturn([$childMock]); + + $this->assertTrue($this->model->isFreeShipping($quoteMock, [$itemMock])); + } +} diff --git a/app/code/Magento/Payment/Plugin/PaymentConfigurationProcess.php b/app/code/Magento/Payment/Plugin/PaymentConfigurationProcess.php new file mode 100644 index 0000000000000000000000000000000000000000..5b107b74295b3a842c00429543b00e0466b1d530 --- /dev/null +++ b/app/code/Magento/Payment/Plugin/PaymentConfigurationProcess.php @@ -0,0 +1,73 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Payment\Plugin; + +/** + * Class PaymentConfigurationProcess + * + * Removes inactive payment methods and group from checkout configuration. + */ +class PaymentConfigurationProcess +{ + /** + * @var \Magento\Payment\Api\PaymentMethodListInterface + */ + private $paymentMethodList; + + /** + * @var \Magento\Store\Model\StoreManagerInterface + */ + private $storeManager; + + /** + * @param \Magento\Payment\Api\PaymentMethodListInterface $paymentMethodList + * @param \Magento\Store\Model\StoreManagerInterface $storeManager + */ + public function __construct( + \Magento\Payment\Api\PaymentMethodListInterface $paymentMethodList, + \Magento\Store\Model\StoreManagerInterface $storeManager + ) { + $this->paymentMethodList = $paymentMethodList; + $this->storeManager = $storeManager; + } + + /** + * Checkout LayoutProcessor before process plugin. + * + * @param \Magento\Checkout\Block\Checkout\LayoutProcessor $processor + * @param array $jsLayout + * @return array + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + */ + public function beforeProcess(\Magento\Checkout\Block\Checkout\LayoutProcessor $processor, $jsLayout) + { + $configuration = &$jsLayout['components']['checkout']['children']['steps']['children']['billing-step'] + ['children']['payment']['children']['renders']['children']; + + if (!isset($configuration)) { + return [$jsLayout]; + } + + $storeId = $this->storeManager->getStore()->getId(); + $activePaymentMethodList = $this->paymentMethodList->getActiveList($storeId); + $getCodeFunc = function ($method) { + return $method->getCode(); + }; + $activePaymentMethodCodes = array_map($getCodeFunc, $activePaymentMethodList); + + foreach ($configuration as $paymentGroup => $groupConfig) { + $notActivePaymentMethodCodes = array_diff(array_keys($groupConfig['methods']), $activePaymentMethodCodes); + foreach ($notActivePaymentMethodCodes as $notActivePaymentMethodCode) { + unset($configuration[$paymentGroup]['methods'][$notActivePaymentMethodCode]); + } + if (empty($configuration[$paymentGroup]['methods'])) { + unset($configuration[$paymentGroup]); + } + } + + return [$jsLayout]; + } +} diff --git a/app/code/Magento/Payment/Test/Unit/Plugin/PaymentConfigurationProcessTest.php b/app/code/Magento/Payment/Test/Unit/Plugin/PaymentConfigurationProcessTest.php new file mode 100644 index 0000000000000000000000000000000000000000..3e49c8718e6044de36cc6a1018d052dc48ed7485 --- /dev/null +++ b/app/code/Magento/Payment/Test/Unit/Plugin/PaymentConfigurationProcessTest.php @@ -0,0 +1,146 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Payment\Test\Unit\Plugin; + +/** + * Class PaymentConfigurationProcessTest. + */ +class PaymentConfigurationProcessTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var \Magento\Store\Model\StoreManagerInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $storeManager; + + /** + * @var \Magento\Store\Api\Data\StoreInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $store; + + /** + * @var \Magento\Payment\Api\PaymentMethodListInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $paymentMethodList; + + /** + * @var \Magento\Checkout\Block\Checkout\LayoutProcessor|\PHPUnit_Framework_MockObject_MockObject + */ + private $layoutProcessor; + + /** + * @var \Magento\Payment\Plugin\PaymentConfigurationProcess + */ + private $plugin; + + /** + * Set up + */ + protected function setUp() + { + $this->storeManager = $this + ->getMockBuilder(\Magento\Store\Model\StoreManagerInterface::class) + ->disableOriginalConstructor() + ->setMethods(['getStore']) + ->getMockForAbstractClass(); + $this->store = $this + ->getMockBuilder(\Magento\Store\Api\Data\StoreInterface::class) + ->disableOriginalConstructor() + ->setMethods(['getId']) + ->getMockForAbstractClass(); + $this->paymentMethodList = $this + ->getMockBuilder(\Magento\Payment\Api\PaymentMethodListInterface::class) + ->disableOriginalConstructor() + ->setMethods(['getActiveList']) + ->getMockForAbstractClass(); + $this->layoutProcessor = $this + ->getMockBuilder(\Magento\Checkout\Block\Checkout\LayoutProcessor::class) + ->disableOriginalConstructor() + ->setMethods(['process']) + ->getMockForAbstractClass(); + + $objectManagerHelper = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); + $this->plugin = $objectManagerHelper->getObject( + \Magento\Payment\Plugin\PaymentConfigurationProcess::class, + [ + 'paymentMethodList' => $this->paymentMethodList, + 'storeManager' => $this->storeManager + ] + ); + } + + /** + * @param array $jsLayout + * @param array $activePaymentList + * @param array $expectedResult + * @dataProvider beforeProcessDataProvider + */ + public function testBeforeProcess($jsLayout, $activePaymentList, $expectedResult) + { + $this->store->expects($this->once())->method('getId')->willReturn(1); + $this->storeManager->expects($this->once())->method('getStore')->willReturn($this->store); + $this->paymentMethodList->expects($this->once()) + ->method('getActiveList') + ->with(1) + ->willReturn($activePaymentList); + + $result = $this->plugin->beforeProcess($this->layoutProcessor, $jsLayout); + $this->assertEquals($result[0], $expectedResult); + } + + /** + * Data provider for BeforeProcess. + * + * @return array + */ + public function beforeProcessDataProvider() + { + $jsLayout['components']['checkout']['children']['steps']['children']['billing-step'] + ['children']['payment']['children']['renders']['children'] = [ + 'braintree' => [ + 'methods' => [ + 'braintree_paypal' => [], + 'braintree' => [] + ] + ], + 'paypal-payments' => [ + 'methods' => [ + 'payflowpro' => [], + 'payflow_link' => [] + ] + ] + ]; + $result1['components']['checkout']['children']['steps']['children']['billing-step'] + ['children']['payment']['children']['renders']['children'] = []; + $result2['components']['checkout']['children']['steps']['children']['billing-step'] + ['children']['payment']['children']['renders']['children'] = [ + 'braintree' => [ + 'methods' => [ + 'braintree' => [], + 'braintree_paypal' => [] + ] + ] + ]; + + $braintreePaymentMethod = $this + ->getMockBuilder(\Magento\Payment\Api\Data\PaymentMethodInterface::class) + ->disableOriginalConstructor() + ->setMethods(['getCode']) + ->getMockForAbstractClass(); + $braintreePaypalPaymentMethod = $this + ->getMockBuilder(\Magento\Payment\Api\Data\PaymentMethodInterface::class) + ->disableOriginalConstructor() + ->setMethods(['getCode']) + ->getMockForAbstractClass(); + + $braintreePaymentMethod->expects($this->any())->method('getCode')->willReturn('braintree'); + $braintreePaypalPaymentMethod->expects($this->any())->method('getCode')->willReturn('braintree_paypal'); + + return [ + [$jsLayout, [], $result1], + [$jsLayout, [$braintreePaymentMethod, $braintreePaypalPaymentMethod], $result2] + ]; + } +} diff --git a/app/code/Magento/Payment/etc/frontend/di.xml b/app/code/Magento/Payment/etc/frontend/di.xml index 4ff3c013b676523fe20a3deb49f32758c01e604e..471a7ce9e2de585609eb490ada35248c4ee59be3 100644 --- a/app/code/Magento/Payment/etc/frontend/di.xml +++ b/app/code/Magento/Payment/etc/frontend/di.xml @@ -19,4 +19,7 @@ </argument> </arguments> </type> + <type name="Magento\Checkout\Block\Checkout\LayoutProcessor"> + <plugin name="ProcessPaymentConfiguration" type="Magento\Payment\Plugin\PaymentConfigurationProcess"/> + </type> </config> \ No newline at end of file diff --git a/app/code/Magento/Paypal/Model/Express/Checkout.php b/app/code/Magento/Paypal/Model/Express/Checkout.php index 0f96b14124d042e86adbad3e944b2bdc97ee2e1a..893eda8cc6020882763056e78f844ab19166c1a6 100644 --- a/app/code/Magento/Paypal/Model/Express/Checkout.php +++ b/app/code/Magento/Paypal/Model/Express/Checkout.php @@ -7,7 +7,9 @@ namespace Magento\Paypal\Model\Express; use Magento\Customer\Api\Data\CustomerInterface as CustomerDataObject; use Magento\Customer\Model\AccountManagement; +use Magento\Framework\App\ObjectManager; use Magento\Paypal\Model\Config as PaypalConfig; +use Magento\Sales\Api\OrderRepositoryInterface; use Magento\Sales\Model\Order\Email\Sender\OrderSender; use Magento\Quote\Model\Quote\Address; use Magento\Framework\DataObject; @@ -268,6 +270,11 @@ class Checkout */ protected $totalsCollector; + /** + * @var OrderRepositoryInterface + */ + private $orderRepository; + /** * @param \Psr\Log\LoggerInterface $logger * @param \Magento\Customer\Model\Url $customerUrl @@ -789,7 +796,8 @@ class Checkout $this->ignoreAddressValidation(); $this->_quote->collectTotals(); - $order = $this->quoteManagement->submit($this->_quote); + $orderId = $this->quoteManagement->placeOrder($this->_quote->getId()); + $order = $this->getOrderRepository()->get($orderId); if (!$order) { return; @@ -1157,4 +1165,20 @@ class Checkout ->setCustomerGroupId(\Magento\Customer\Model\Group::NOT_LOGGED_IN_ID); return $this; } + + /** + * Returns order repository instance + * + * @return OrderRepositoryInterface + * @deprecated + */ + private function getOrderRepository() + { + if ($this->orderRepository === null) { + $this->orderRepository = ObjectManager::getInstance() + ->get(OrderRepositoryInterface::class); + } + + return $this->orderRepository; + } } diff --git a/app/code/Magento/Paypal/etc/di.xml b/app/code/Magento/Paypal/etc/di.xml index c5cbdbdc51331c95a269581a97a8ee3a94c25e0f..940876451fd591984937faeae1deef5ac1e4ea60 100644 --- a/app/code/Magento/Paypal/etc/di.xml +++ b/app/code/Magento/Paypal/etc/di.xml @@ -182,4 +182,32 @@ <argument name="paymentTokenFactory" xsi:type="object">Magento\Vault\Model\CreditCardTokenFactory</argument> </arguments> </type> + <type name="Magento\Config\Model\Config\Export\ExcludeList"> + <arguments> + <argument name="configs" xsi:type="array"> + <item name="paypal/general/business_account" xsi:type="string">1</item> + <item name="paypal/wpp/api_password" xsi:type="string">1</item> + <item name="paypal/wpp/api_signature" xsi:type="string">1</item> + <item name="paypal/wpp/api_username" xsi:type="string">1</item> + <item name="paypal/wpp/api_cert" xsi:type="string">1</item> + <item name="paypal/wpp/proxy_host" xsi:type="string">1</item> + <item name="paypal/wpp/proxy_port" xsi:type="string">1</item> + <item name="payment/paypal_express/merchant_id" xsi:type="string">1</item> + <item name="payment/paypal_express_bml/publisher_id" xsi:type="string">1</item> + <item name="paypal/fetch_reports/ftp_password" xsi:type="string">1</item> + <item name="paypal/fetch_reports/ftp_login" xsi:type="string">1</item> + <item name="paypal/fetch_reports/ftp_path" xsi:type="string">1</item> + <item name="paypal/fetch_reports/ftp_ip" xsi:type="string">1</item> + <item name="payment/payflow_advanced/user" xsi:type="string">1</item> + <item name="payment/payflow_advanced/pwd" xsi:type="string">1</item> + <item name="payment/payflow_link/user" xsi:type="string">1</item> + <item name="payment/payflow_link/pwd" xsi:type="string">1</item> + <item name="payment/payflowpro/user" xsi:type="string">1</item> + <item name="payment/payflowpro/pwd" xsi:type="string">1</item> + <item name="payment/payflowpro/partner" xsi:type="string">1</item> + <item name="payment/payflowpro/proxy_host" xsi:type="string">1</item> + <item name="payment/payflowpro/proxy_port" xsi:type="string">1</item> + </argument> + </arguments> + </type> </config> diff --git a/app/code/Magento/Persistent/Model/Observer.php b/app/code/Magento/Persistent/Model/Observer.php index 283d7bb45a5e832b0f4450a7633f6d27056d85ca..392d88a29a58137c04209a91107a4a4cc2f7001d 100644 --- a/app/code/Magento/Persistent/Model/Observer.php +++ b/app/code/Magento/Persistent/Model/Observer.php @@ -121,6 +121,13 @@ class Observer public function emulateTopLinks($block) { $this->_applyAccountLinksPersistentData(); - $block->removeLinkByUrl($this->_url->getUrl('customer/account/login')); + /** @var \Magento\Framework\View\Element\Html\Link[] $links */ + $links = $block->getLinks(); + $removeLink = $this->_url->getUrl('customer/account/login'); + foreach ($links as $link) { + if ($link->getHref() == $removeLink) { + $this->_layout->unsetChild($block->getNameInLayout(), $link->getNameInLayout()); + } + } } } diff --git a/app/code/Magento/ProductAlert/composer.json b/app/code/Magento/ProductAlert/composer.json index 9c63c6958a465852ea3148cab659102880b07630..4ed6a998b084eb25a93ec939ebe20c70c6a4e5c2 100644 --- a/app/code/Magento/ProductAlert/composer.json +++ b/app/code/Magento/ProductAlert/composer.json @@ -9,6 +9,9 @@ "magento/module-customer": "100.2.*", "magento/framework": "100.2.*" }, + "suggest": { + "magento/module-config": "100.2.*" + }, "type": "magento2-module", "version": "100.2.0-dev", "license": [ diff --git a/app/code/Magento/ProductAlert/etc/di.xml b/app/code/Magento/ProductAlert/etc/di.xml index 734b0f6695778bc38744f185da7b58eb0faf50a1..d5c81adce46f0c66f10d5b60226f0525e3fd4c54 100644 --- a/app/code/Magento/ProductAlert/etc/di.xml +++ b/app/code/Magento/ProductAlert/etc/di.xml @@ -13,4 +13,12 @@ </argument> </arguments> </type> + + <type name="Magento\Config\Model\Config\Export\ExcludeList"> + <arguments> + <argument name="configs" xsi:type="array"> + <item name="catalog/productalert_cron/error_email" xsi:type="string">1</item> + </argument> + </arguments> + </type> </config> diff --git a/app/code/Magento/ProductVideo/composer.json b/app/code/Magento/ProductVideo/composer.json index 08d21e4c2abbfb167aed2ca24c0ba012d6b2e8c8..726104c084677dfcb69e3721adfe63f4d71a7ecd 100644 --- a/app/code/Magento/ProductVideo/composer.json +++ b/app/code/Magento/ProductVideo/composer.json @@ -12,7 +12,8 @@ "magento/magento-composer-installer": "*" }, "suggest": { - "magento/module-customer": "100.2.*" + "magento/module-customer": "100.2.*", + "magento/module-config": "100.2.*" }, "type": "magento2-module", "version": "100.2.0-dev", diff --git a/app/code/Magento/ProductVideo/etc/di.xml b/app/code/Magento/ProductVideo/etc/di.xml index 7242a9d48ce1e3c0da66a3f4d5953cda705132cd..9aad01caaf72b65bc1a49951cb84c2f28a2de5e0 100644 --- a/app/code/Magento/ProductVideo/etc/di.xml +++ b/app/code/Magento/ProductVideo/etc/di.xml @@ -46,4 +46,11 @@ <type name="Magento\Catalog\Model\ResourceModel\Product\Gallery"> <plugin name="external_video_media_resource_backend" type="Magento\ProductVideo\Model\Plugin\ExternalVideoResourceBackend" /> </type> + <type name="Magento\Config\Model\Config\Export\ExcludeList"> + <arguments> + <argument name="configs" xsi:type="array"> + <item name="catalog/product_video/youtube_api_key" xsi:type="string">1</item> + </argument> + </arguments> + </type> </config> diff --git a/app/code/Magento/Quote/Model/Product/Plugin/RemoveQuoteItems.php b/app/code/Magento/Quote/Model/Product/Plugin/RemoveQuoteItems.php index 49d9be6bcf8ff748b00f67166856185b23a15f53..76af26e3c89cc651691f05f19a9689bedf823b1f 100644 --- a/app/code/Magento/Quote/Model/Product/Plugin/RemoveQuoteItems.php +++ b/app/code/Magento/Quote/Model/Product/Plugin/RemoveQuoteItems.php @@ -5,6 +5,8 @@ */ namespace Magento\Quote\Model\Product\Plugin; +use Magento\Catalog\Model\ResourceModel\Product as ProductResource; + class RemoveQuoteItems { /** @@ -21,19 +23,17 @@ class RemoveQuoteItems } /** - * @param \Magento\Catalog\Model\ResourceModel\Product $subject - * @param \Closure $proceed + * @param ProductResource $subject + * @param ProductResource $result * @param \Magento\Catalog\Api\Data\ProductInterface $product - * @return mixed + * @return ProductResource * @SuppressWarnings(PHPMD.UnusedFormalParameter) - * TODO: reimplement with after plugin */ - public function aroundDelete( - \Magento\Catalog\Model\ResourceModel\Product $subject, - \Closure $proceed, + public function afterDelete( + ProductResource $subject, + ProductResource $result, \Magento\Catalog\Api\Data\ProductInterface $product ) { - $result = $proceed($product); $this->quoteItemsCleaner->execute($product); return $result; } diff --git a/app/code/Magento/Quote/Test/Unit/Model/Product/Plugin/RemoveQuoteItemsTest.php b/app/code/Magento/Quote/Test/Unit/Model/Product/Plugin/RemoveQuoteItemsTest.php index 083722f3a1bb3d9044284f7f65ac1b1239b2d0c5..deb6aab3a980a54baf4c69289833d068a78c8d4d 100644 --- a/app/code/Magento/Quote/Test/Unit/Model/Product/Plugin/RemoveQuoteItemsTest.php +++ b/app/code/Magento/Quote/Test/Unit/Model/Product/Plugin/RemoveQuoteItemsTest.php @@ -23,16 +23,13 @@ class RemoveQuoteItemsTest extends \PHPUnit_Framework_TestCase $this->model = new \Magento\Quote\Model\Product\Plugin\RemoveQuoteItems($this->quoteItemsCleanerMock); } - public function testAroundDelete() + public function testAfterDelete() { $productResourceMock = $this->getMock(\Magento\Catalog\Model\ResourceModel\Product::class, [], [], '', false); $productMock = $this->getMock(\Magento\Catalog\Api\Data\ProductInterface::class); - $closure = function () use ($productResourceMock) { - return $productResourceMock; - }; $this->quoteItemsCleanerMock->expects($this->once())->method('execute')->with($productMock); - $result = $this->model->aroundDelete($productResourceMock, $closure, $productMock); + $result = $this->model->afterDelete($productResourceMock, $productResourceMock, $productMock); $this->assertEquals($result, $productResourceMock); } } diff --git a/app/code/Magento/Quote/Test/Unit/Model/Quote/Item/RepositoryTest.php b/app/code/Magento/Quote/Test/Unit/Model/Quote/Item/RepositoryTest.php index dae3d56aa04b093c76d33f671606e2acfedb57af..c6e5241282cd0e9212ad342b0d48ee6da006ed51 100644 --- a/app/code/Magento/Quote/Test/Unit/Model/Quote/Item/RepositoryTest.php +++ b/app/code/Magento/Quote/Test/Unit/Model/Quote/Item/RepositoryTest.php @@ -12,6 +12,11 @@ namespace Magento\Quote\Test\Unit\Model\Quote\Item; */ class RepositoryTest extends \PHPUnit_Framework_TestCase { + /** + * @var \Magento\Framework\TestFramework\Unit\Helper\ObjectManager + */ + private $objectManager; + /** * @var \Magento\Quote\Api\CartItemRepositoryInterface */ @@ -68,6 +73,7 @@ class RepositoryTest extends \PHPUnit_Framework_TestCase */ protected function setUp() { + $this->objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); $this->quoteRepositoryMock = $this->getMock(\Magento\Quote\Api\CartRepositoryInterface::class); $this->productRepositoryMock = $this->getMock(\Magento\Catalog\Api\ProductRepositoryInterface::class); $this->itemDataFactoryMock = @@ -100,12 +106,6 @@ class RepositoryTest extends \PHPUnit_Framework_TestCase '', false ); - $this->prepareObjectManager([ - [ - \Magento\Quote\Model\Quote\Item\CartItemOptionsProcessor::class, - $this->optionsProcessorMock - ] - ]); $this->repository = new \Magento\Quote\Model\Quote\Item\Repository( $this->quoteRepositoryMock, @@ -113,6 +113,11 @@ class RepositoryTest extends \PHPUnit_Framework_TestCase $this->itemDataFactoryMock, ['custom_options' => $this->customOptionProcessor] ); + $this->objectManager->setBackwardCompatibleProperty( + $this->repository, + 'cartItemOptionsProcessor', + $this->optionsProcessorMock + ); } /** @@ -246,20 +251,4 @@ class RepositoryTest extends \PHPUnit_Framework_TestCase $this->assertTrue($this->repository->deleteById($cartId, $itemId)); } - - /** - * @param array $map - */ - private function prepareObjectManager($map) - { - $objectManagerMock = $this->getMock(\Magento\Framework\ObjectManagerInterface::class); - $objectManagerMock->expects($this->any())->method('getInstance')->willReturnSelf(); - $objectManagerMock->expects($this->any()) - ->method('get') - ->will($this->returnValueMap($map)); - $reflectionClass = new \ReflectionClass(\Magento\Framework\App\ObjectManager::class); - $reflectionProperty = $reflectionClass->getProperty('_instance'); - $reflectionProperty->setAccessible(true); - $reflectionProperty->setValue($objectManagerMock); - } } diff --git a/app/code/Magento/Quote/Test/Unit/Model/ShippingAddressManagementTest.php b/app/code/Magento/Quote/Test/Unit/Model/ShippingAddressManagementTest.php index abae7bae110e6521fbf7b708270eb32cb6792c69..d8e65de847457e243a02d9535196e4c42f0499f8 100644 --- a/app/code/Magento/Quote/Test/Unit/Model/ShippingAddressManagementTest.php +++ b/app/code/Magento/Quote/Test/Unit/Model/ShippingAddressManagementTest.php @@ -104,12 +104,6 @@ class ShippingAddressManagementTest extends \PHPUnit_Framework_TestCase '', false ); - $this->prepareObjectManager([ - [ - \Magento\Quote\Model\Quote\Validator\MinimumOrderAmount\ValidationMessage::class, - $this->amountErrorMessageMock - ] - ]); $this->service = $this->objectManager->getObject( \Magento\Quote\Model\ShippingAddressManagement::class, @@ -122,6 +116,11 @@ class ShippingAddressManagementTest extends \PHPUnit_Framework_TestCase 'addressRepository' => $this->addressRepository ] ); + $this->objectManager->setBackwardCompatibleProperty( + $this->service, + 'minimumAmountErrorMessage', + $this->amountErrorMessageMock + ); } /** @@ -375,20 +374,4 @@ class ShippingAddressManagementTest extends \PHPUnit_Framework_TestCase $this->service->get('cartId'); } - - /** - * @param $map - */ - private function prepareObjectManager($map) - { - $objectManagerMock = $this->getMock(\Magento\Framework\ObjectManagerInterface::class); - $objectManagerMock->expects($this->any())->method('getInstance')->willReturnSelf(); - $objectManagerMock->expects($this->any()) - ->method('get') - ->will($this->returnValueMap($map)); - $reflectionClass = new \ReflectionClass(\Magento\Framework\App\ObjectManager::class); - $reflectionProperty = $reflectionClass->getProperty('_instance'); - $reflectionProperty->setAccessible(true); - $reflectionProperty->setValue($objectManagerMock); - } } diff --git a/app/code/Magento/Review/Model/ResourceModel/Review/Product/Collection.php b/app/code/Magento/Review/Model/ResourceModel/Review/Product/Collection.php index f4945508fe722c9308002cbc2b49a4123eacde77..f066bb53b51accc86b7a0141423334aa417739a1 100644 --- a/app/code/Magento/Review/Model/ResourceModel/Review/Product/Collection.php +++ b/app/code/Magento/Review/Model/ResourceModel/Review/Product/Collection.php @@ -7,6 +7,8 @@ namespace Magento\Review\Model\ResourceModel\Review\Product; use Magento\Eav\Model\Entity\Attribute\AbstractAttribute; use Magento\Framework\DB\Select; +use Magento\Framework\EntityManager\MetadataPool; +use Magento\Catalog\Model\ResourceModel\Product\Collection\ProductLimitationFactory; /** * Review Product Collection @@ -59,7 +61,8 @@ class Collection extends \Magento\Catalog\Model\ResourceModel\Product\Collection protected $_voteFactory; /** - * Collection constructor. + * Collection constructor + * * @param \Magento\Framework\Data\Collection\EntityFactory $entityFactory * @param \Psr\Log\LoggerInterface $logger * @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy @@ -81,7 +84,9 @@ class Collection extends \Magento\Catalog\Model\ResourceModel\Product\Collection * @param \Magento\Customer\Api\GroupManagementInterface $groupManagement * @param \Magento\Review\Model\RatingFactory $ratingFactory * @param \Magento\Review\Model\Rating\Option\VoteFactory $voteFactory - * @param mixed $connection + * @param \Magento\Framework\DB\Adapter\AdapterInterface|null $connection + * @param ProductLimitationFactory|null $productLimitationFactory + * @param MetadataPool|null $metadataPool * * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ @@ -107,7 +112,9 @@ class Collection extends \Magento\Catalog\Model\ResourceModel\Product\Collection \Magento\Customer\Api\GroupManagementInterface $groupManagement, \Magento\Review\Model\RatingFactory $ratingFactory, \Magento\Review\Model\Rating\Option\VoteFactory $voteFactory, - \Magento\Framework\DB\Adapter\AdapterInterface $connection = null + \Magento\Framework\DB\Adapter\AdapterInterface $connection = null, + ProductLimitationFactory $productLimitationFactory = null, + MetadataPool $metadataPool = null ) { $this->_ratingFactory = $ratingFactory; $this->_voteFactory = $voteFactory; @@ -131,7 +138,9 @@ class Collection extends \Magento\Catalog\Model\ResourceModel\Product\Collection $customerSession, $dateTime, $groupManagement, - $connection + $connection, + $productLimitationFactory, + $metadataPool ); } diff --git a/app/code/Magento/Review/Test/Unit/Model/ResourceModel/Review/Product/CollectionTest.php b/app/code/Magento/Review/Test/Unit/Model/ResourceModel/Review/Product/CollectionTest.php index b1a1b9a69c7ff9905954385d7d685b87f9e2d273..8c51535a7f6ab9e40c1186315d9302eba760cc23 100644 --- a/app/code/Magento/Review/Test/Unit/Model/ResourceModel/Review/Product/CollectionTest.php +++ b/app/code/Magento/Review/Test/Unit/Model/ResourceModel/Review/Product/CollectionTest.php @@ -5,11 +5,18 @@ */ namespace Magento\Review\Test\Unit\Model\ResourceModel\Review\Product; +use Magento\Catalog\Model\ResourceModel\Product\Collection\ProductLimitationFactory; + /** * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class CollectionTest extends \PHPUnit_Framework_TestCase { + /** + * @var \Magento\Framework\TestFramework\Unit\Helper\ObjectManager + */ + private $objectManager; + /** * @var \Magento\Review\Model\ResourceModel\Review\Product\Collection */ @@ -74,16 +81,23 @@ class CollectionTest extends \PHPUnit_Framework_TestCase false ); $fetchStrategy->expects($this->any())->method('fetchAll')->will($this->returnValue([])); - $this->model = (new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this)) - ->getObject( - \Magento\Review\Model\ResourceModel\Review\Product\Collection::class, - [ - 'universalFactory' => $universalFactory, - 'storeManager' => $storeManager, - 'eavConfig' => $eavConfig, - 'fetchStrategy' => $fetchStrategy - ] - ); + $productLimitationMock = $this->getMock( + \Magento\Catalog\Model\ResourceModel\Product\Collection\ProductLimitation::class + ); + $productLimitationFactoryMock = $this->getMock(ProductLimitationFactory::class, ['create']); + $productLimitationFactoryMock->method('create') + ->willReturn($productLimitationMock); + $this->objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); + $this->model = $this->objectManager->getObject( + \Magento\Review\Model\ResourceModel\Review\Product\Collection::class, + [ + 'universalFactory' => $universalFactory, + 'storeManager' => $storeManager, + 'eavConfig' => $eavConfig, + 'fetchStrategy' => $fetchStrategy, + 'productLimitationFactory' => $productLimitationFactoryMock + ] + ); } /** diff --git a/app/code/Magento/Review/etc/di.xml b/app/code/Magento/Review/etc/di.xml index d42d3e3330c670bce2c036cf8b100842f10a0a48..13f7d0b84bc505bb1fd66c9e16e36e75367219e2 100644 --- a/app/code/Magento/Review/etc/di.xml +++ b/app/code/Magento/Review/etc/di.xml @@ -26,4 +26,9 @@ <argument name="urlModel" xsi:type="object">Magento\Framework\Url</argument> </arguments> </type> + <type name="Magento\Review\Model\ResourceModel\Rating\Option"> + <arguments> + <argument name="customerSession" xsi:type="object">Magento\Customer\Model\Session\Proxy</argument> + </arguments> + </type> </config> diff --git a/app/code/Magento/Review/view/frontend/templates/review.phtml b/app/code/Magento/Review/view/frontend/templates/review.phtml index c3f64511b151226854c3a569740e939e58d87d44..c332a1b4c874cae00c9e93103073e6a3a2910a2b 100644 --- a/app/code/Magento/Review/view/frontend/templates/review.phtml +++ b/app/code/Magento/Review/view/frontend/templates/review.phtml @@ -13,7 +13,8 @@ { "*": { "Magento_Review/js/process-reviews": { - "productReviewUrl": "<?php echo $block->escapeJs($block->escapeUrl($block->getProductReviewUrl())); ?>" + "productReviewUrl": "<?php echo $block->escapeJs($block->escapeUrl($block->getProductReviewUrl())); ?>", + "reviewsTabSelector": "#tab-label-reviews" } } } diff --git a/app/code/Magento/Review/view/frontend/web/js/process-reviews.js b/app/code/Magento/Review/view/frontend/web/js/process-reviews.js index 124b59becf1cbc569b191f5e61b274fba0e7494f..8ba22caf292319e1c259d198cbea92b989084f3d 100644 --- a/app/code/Magento/Review/view/frontend/web/js/process-reviews.js +++ b/app/code/Magento/Review/view/frontend/web/js/process-reviews.js @@ -11,7 +11,9 @@ define([ $.ajax({ url: url, cache: true, - dataType: 'html' + dataType: 'html', + showLoader: true, + loaderContext: $('.product.data.items') }).done(function (data) { $('#product-review-container').html(data); $('[data-role="product-review"] .pages a').each(function (index, element) { @@ -30,7 +32,17 @@ define([ } return function (config, element) { - processReviews(config.productReviewUrl); + var reviewTab = $(config.reviewsTabSelector); + var requiredReviewTabRole = 'tab'; + + if (reviewTab.attr('role') === requiredReviewTabRole && reviewTab.hasClass('active')) { + processReviews(config.productReviewUrl); + } else { + reviewTab.one('beforeOpen', function () { + processReviews(config.productReviewUrl); + }); + } + $(function () { $('.product-info-main .reviews-actions a').click(function (event) { event.preventDefault(); diff --git a/app/code/Magento/Rss/Model/Rss.php b/app/code/Magento/Rss/Model/Rss.php index 0f228cb9a21c2f6c8ca64a2692f309bbfaced855..af716613bd2612cce965c386e1bb8eac107a4222 100644 --- a/app/code/Magento/Rss/Model/Rss.php +++ b/app/code/Magento/Rss/Model/Rss.php @@ -5,13 +5,10 @@ */ namespace Magento\Rss\Model; +use Magento\Framework\App\ObjectManager; use Magento\Framework\App\Rss\DataProviderInterface; +use Magento\Framework\Serialize\SerializerInterface; -/** - * Auth session model - * - * @author Magento Core Team <core@magentocommerce.com> - */ class Rss { /** @@ -25,11 +22,22 @@ class Rss protected $cache; /** + * @var SerializerInterface + */ + private $serializer; + + /** + * Rss constructor + * * @param \Magento\Framework\App\CacheInterface $cache + * @param SerializerInterface|null $serializer */ - public function __construct(\Magento\Framework\App\CacheInterface $cache) - { + public function __construct( + \Magento\Framework\App\CacheInterface $cache, + SerializerInterface $serializer = null + ) { $this->cache = $cache; + $this->serializer = $serializer ?: ObjectManager::getInstance()->get(SerializerInterface::class); } /** @@ -46,14 +54,14 @@ class Rss } if ($cache) { - return unserialize($cache); + return $this->serializer->unserialize($cache); } $data = $this->dataProvider->getRssData(); if ($this->dataProvider->getCacheKey() && $this->dataProvider->getCacheLifetime()) { $this->cache->save( - serialize($data), + $this->serializer->serialize($data), $this->dataProvider->getCacheKey(), ['rss'], $this->dataProvider->getCacheLifetime() diff --git a/app/code/Magento/Rss/Test/Unit/Model/RssTest.php b/app/code/Magento/Rss/Test/Unit/Model/RssTest.php index 7a12c4818e71a16a7ffc1b4f41cff78cb547798f..0c5eb303935ff37c084fb0e27803e2ef40a17f95 100644 --- a/app/code/Magento/Rss/Test/Unit/Model/RssTest.php +++ b/app/code/Magento/Rss/Test/Unit/Model/RssTest.php @@ -6,6 +6,7 @@ namespace Magento\Rss\Test\Unit\Model; +use Magento\Framework\Serialize\SerializerInterface; use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper; class RssTest extends \PHPUnit_Framework_TestCase @@ -40,17 +41,23 @@ class RssTest extends \PHPUnit_Framework_TestCase /** * @var \Magento\Framework\App\CacheInterface|\PHPUnit_Framework_MockObject_MockObject */ - protected $cacheInterface; + private $cacheMock; + + /** + * @var SerializerInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $serializerMock; protected function setUp() { - $this->cacheInterface = $this->getMock(\Magento\Framework\App\CacheInterface::class); - + $this->cacheMock = $this->getMock(\Magento\Framework\App\CacheInterface::class); + $this->serializerMock = $this->getMock(SerializerInterface::class); $this->objectManagerHelper = new ObjectManagerHelper($this); $this->rss = $this->objectManagerHelper->getObject( \Magento\Rss\Model\Rss::class, [ - 'cache' => $this->cacheInterface + 'cache' => $this->cacheMock, + 'serializer' => $this->serializerMock ] ); } @@ -64,8 +71,18 @@ class RssTest extends \PHPUnit_Framework_TestCase $this->rss->setDataProvider($dataProvider); - $this->cacheInterface->expects($this->once())->method('load')->will($this->returnValue(false)); - $this->cacheInterface->expects($this->once())->method('save')->will($this->returnValue(true)); + $this->cacheMock->expects($this->once()) + ->method('load') + ->with('cache_key') + ->will($this->returnValue(false)); + $this->cacheMock->expects($this->once()) + ->method('save') + ->with('serializedData') + ->will($this->returnValue(true)); + $this->serializerMock->expects($this->once()) + ->method('serialize') + ->with($this->feedData) + ->willReturn('serializedData'); $this->assertEquals($this->feedData, $this->rss->getFeeds()); } @@ -79,9 +96,15 @@ class RssTest extends \PHPUnit_Framework_TestCase $this->rss->setDataProvider($dataProvider); - $this->cacheInterface->expects($this->once())->method('load') - ->will($this->returnValue(serialize($this->feedData))); - $this->cacheInterface->expects($this->never())->method('save'); + $this->cacheMock->expects($this->once()) + ->method('load') + ->with('cache_key') + ->will($this->returnValue('serializedData')); + $this->serializerMock->expects($this->once()) + ->method('unserialize') + ->with('serializedData') + ->willReturn($this->feedData); + $this->cacheMock->expects($this->never())->method('save'); $this->assertEquals($this->feedData, $this->rss->getFeeds()); } diff --git a/app/code/Magento/Rule/Model/AbstractModel.php b/app/code/Magento/Rule/Model/AbstractModel.php index 45f0c092c4aece714653feec67abdaf36b2def0c..73e3db2c8a35895c8943284a62377d1a4e03d592 100644 --- a/app/code/Magento/Rule/Model/AbstractModel.php +++ b/app/code/Magento/Rule/Model/AbstractModel.php @@ -3,9 +3,11 @@ * Copyright © 2016 Magento. All rights reserved. * See COPYING.txt for license details. */ - namespace Magento\Rule\Model; +use Magento\Framework\Api\AttributeValueFactory; +use Magento\Framework\Api\ExtensionAttributesFactory; + /** * Abstract Rule entity data model * @SuppressWarnings(PHPMD.CouplingBetweenObjects) @@ -76,7 +78,7 @@ abstract class AbstractModel extends \Magento\Framework\Model\AbstractExtensible protected $_localeDate; /** - * AbstractModel constructor. + * AbstractModel constructor * * @param \Magento\Framework\Model\Context $context * @param \Magento\Framework\Registry $registry @@ -85,6 +87,8 @@ abstract class AbstractModel extends \Magento\Framework\Model\AbstractExtensible * @param \Magento\Framework\Model\ResourceModel\AbstractResource|null $resource * @param \Magento\Framework\Data\Collection\AbstractDb|null $resourceCollection * @param array $data + * @param ExtensionAttributesFactory|null $extensionFactory + * @param AttributeValueFactory|null $customAttributeFactory */ public function __construct( \Magento\Framework\Model\Context $context, @@ -93,15 +97,17 @@ abstract class AbstractModel extends \Magento\Framework\Model\AbstractExtensible \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate, \Magento\Framework\Model\ResourceModel\AbstractResource $resource = null, \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, - array $data = [] + array $data = [], + ExtensionAttributesFactory $extensionFactory = null, + AttributeValueFactory $customAttributeFactory = null ) { $this->_formFactory = $formFactory; $this->_localeDate = $localeDate; parent::__construct( $context, $registry, - $this->getExtensionFactory(), - $this->getCustomAttributeFactory(), + $extensionFactory ?: $this->getExtensionFactory(), + $customAttributeFactory ?: $this->getCustomAttributeFactory(), $resource, $resourceCollection, $data diff --git a/app/code/Magento/Sales/Block/Status/Grid/Column/State.php b/app/code/Magento/Sales/Block/Status/Grid/Column/State.php index cd049799e7b497b5b657bd03122a2dcf4e2986ab..ae9ea20fd35fd110e796d87564409cadcd8fe57e 100644 --- a/app/code/Magento/Sales/Block/Status/Grid/Column/State.php +++ b/app/code/Magento/Sales/Block/Status/Grid/Column/State.php @@ -49,8 +49,9 @@ class State extends \Magento\Backend\Block\Widget\Grid\Column */ public function decorateState($value, $row, $column, $isExport) { + $status = $row->getStatus(); if ($value) { - $cell = $value . '[' . $this->_config->getStateLabel($value) . ']'; + $cell = $value . '[' . $this->_config->getStateLabelByStateAndStatus($value, $status) . ']'; } else { $cell = $value; } diff --git a/app/code/Magento/Sales/Model/Config/Data.php b/app/code/Magento/Sales/Model/Config/Data.php index 6d3d3a2ac123459bb1734a8f0456c98442e216c2..b6a1b43012f9e8ba55c4440d78cde41a0d6e2dfc 100644 --- a/app/code/Magento/Sales/Model/Config/Data.php +++ b/app/code/Magento/Sales/Model/Config/Data.php @@ -3,24 +3,29 @@ * Copyright © 2016 Magento. All rights reserved. * See COPYING.txt for license details. */ +namespace Magento\Sales\Model\Config; + +use Magento\Framework\Serialize\SerializerInterface; /** - * Sales configuration data container + * Provides sales configuration */ -namespace Magento\Sales\Model\Config; - class Data extends \Magento\Framework\Config\Data { /** - * @param \Magento\Sales\Model\Config\Reader $reader + * Constructor + * + * @param Reader $reader * @param \Magento\Framework\Config\CacheInterface $cache - * @param string $cacheId + * @param string|null $cacheId + * @param SerializerInterface|null $serializer */ public function __construct( \Magento\Sales\Model\Config\Reader $reader, \Magento\Framework\Config\CacheInterface $cache, - $cacheId = 'sales_totals_config_cache' + $cacheId = 'sales_totals_config_cache', + SerializerInterface $serializer = null ) { - parent::__construct($reader, $cache, $cacheId); + parent::__construct($reader, $cache, $cacheId, $serializer); } } diff --git a/app/code/Magento/Sales/Model/Order/Config.php b/app/code/Magento/Sales/Model/Order/Config.php index 8c6f2e55f55acfa9ea8b0c26e25efac97f330f30..535e2975ee13da8458cba83666ba49abb942a89a 100644 --- a/app/code/Magento/Sales/Model/Order/Config.php +++ b/app/code/Magento/Sales/Model/Order/Config.php @@ -256,4 +256,22 @@ class Config } return $this->statuses[(bool) $visibility]; } + + /** + * Retrieve label by state and status + * + * @param string $state + * @param string $status + * @return \Magento\Framework\Phrase|string + */ + public function getStateLabelByStateAndStatus($state, $status) + { + foreach ($this->_getCollection() as $item) { + if ($item->getData('state') == $state && $item->getData('status') == $status) { + $label = $item->getData('label'); + return __($label); + } + } + return $state; + } } diff --git a/app/code/Magento/Sales/Setup/UpgradeSchema.php b/app/code/Magento/Sales/Setup/UpgradeSchema.php index d35825242fb291a41961eb882ad93f7d24c58ee9..288e8085a0dab51947905ed0254e69c8479e79ff 100644 --- a/app/code/Magento/Sales/Setup/UpgradeSchema.php +++ b/app/code/Magento/Sales/Setup/UpgradeSchema.php @@ -76,8 +76,9 @@ class UpgradeSchema implements UpgradeSchemaInterface 'sales_shipment_grid', ]; foreach ($tables as $table) { - $setup->getConnection()->modifyColumn( - $setup->getTable($table), + $salesConnection = $setup->getConnection(self::$connectionName); + $salesConnection->modifyColumn( + $installer->getTable($table, self::$connectionName), 'customer_group_id', ['type' => 'integer'] ); diff --git a/app/code/Magento/Sales/Test/Unit/Block/Status/Grid/Column/StateTest.php b/app/code/Magento/Sales/Test/Unit/Block/Status/Grid/Column/StateTest.php new file mode 100644 index 0000000000000000000000000000000000000000..59e7accb583d051a62821276a3c6521c8abb54f2 --- /dev/null +++ b/app/code/Magento/Sales/Test/Unit/Block/Status/Grid/Column/StateTest.php @@ -0,0 +1,91 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Sales\Test\Unit\Block\Status\Grid\Column; + +class StateTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var \Magento\Sales\Block\Status\Grid\Column\State + */ + private $stateColumn; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + private $orderStatusCollectionFactoryMock; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + private $configMock; + + protected function setUp() + { + $helper = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); + $this->orderStatusCollectionFactoryMock = $this->getMock( + \Magento\Sales\Model\ResourceModel\Order\Status\CollectionFactory::class, + ['create'], + [], + '', + false, + false + ); + $this->configMock = $helper->getObject( + \Magento\Sales\Model\Order\Config::class, + [ + 'orderStatusCollectionFactory' => $this->orderStatusCollectionFactoryMock + ] + ); + $this->stateColumn = $helper + ->getObject( + \Magento\Sales\Block\Status\Grid\Column\State::class, + [ + 'config' => $this->configMock, + ] + ); + } + + public function testDecorateState() + { + $rowMock = $this->getMock(\Magento\Sales\Model\Order\Status::class, [], [], '', false); + $rowMock->expects($this->any())->method('getStatus')->willReturn('fraud'); + $columnMock = $this->getMock(\Magento\Backend\Block\Widget\Grid\Column::class, [], [], '', false); + $statuses = [ + new \Magento\Framework\DataObject( + [ + 'status' => 'fraud', + 'state' => 'processing', + 'label' => 'Suspected Fraud', + ] + ), + new \Magento\Framework\DataObject( + [ + 'status' => 'processing', + 'state' => 'processing', + 'label' => 'Processing', + ] + ) + ]; + $collectionMock = $this->getMock( + \Magento\Sales\Model\ResourceModel\Order\Status\Collection::class, + ['create', 'joinStates'], + [], + '', + false, + false + ); + $this->orderStatusCollectionFactoryMock->expects($this->once()) + ->method('create') + ->will($this->returnValue($collectionMock)); + $collectionMock->expects($this->once()) + ->method('joinStates') + ->will($this->returnValue($statuses)); + + $result = $this->stateColumn->decorateState('processing', $rowMock, $columnMock, false); + $this->assertSame('processing[processing]', $result); + } +} diff --git a/app/code/Magento/Sales/Test/Unit/Model/Config/DataTest.php b/app/code/Magento/Sales/Test/Unit/Model/Config/DataTest.php index 722fdb2b9495fd86413eeda76a8abc041a0722dc..0c342ff115eaff8d761c8b1ac7c395b724daefb2 100644 --- a/app/code/Magento/Sales/Test/Unit/Model/Config/DataTest.php +++ b/app/code/Magento/Sales/Test/Unit/Model/Config/DataTest.php @@ -7,31 +7,56 @@ namespace Magento\Sales\Test\Unit\Model\Config; class DataTest extends \PHPUnit_Framework_TestCase { + /** + * @var \Magento\Framework\TestFramework\Unit\Helper\ObjectManager + */ + private $objectManager; + /** * @var \PHPUnit_Framework_MockObject_MockObject */ - protected $_readerMock; + private $_readerMock; /** * @var \PHPUnit_Framework_MockObject_MockObject */ - protected $_cacheMock; + private $_cacheMock; + + /** + * @var \Magento\Framework\Serialize\SerializerInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $serializerMock; protected function setUp() { + $this->objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); $this->_readerMock = $this->getMockBuilder( \Magento\Sales\Model\Config\Reader::class )->disableOriginalConstructor()->getMock(); $this->_cacheMock = $this->getMockBuilder( \Magento\Framework\App\Cache\Type\Config::class )->disableOriginalConstructor()->getMock(); + $this->serializerMock = $this->getMock(\Magento\Framework\Serialize\SerializerInterface::class); } public function testGet() { $expected = ['someData' => ['someValue', 'someKey' => 'someValue']]; - $this->_cacheMock->expects($this->any())->method('load')->will($this->returnValue(serialize($expected))); - $configData = new \Magento\Sales\Model\Config\Data($this->_readerMock, $this->_cacheMock); + $this->_cacheMock->expects($this->once()) + ->method('load'); + + $this->serializerMock->expects($this->once()) + ->method('unserialize') + ->willReturn($expected); + + $configData = $this->objectManager->getObject( + \Magento\Sales\Model\Config\Data::class, + [ + 'reader' => $this->_readerMock, + 'cache' => $this->_cacheMock, + 'serializer' => $this->serializerMock, + ] + ); $this->assertEquals($expected, $configData->get()); } diff --git a/app/code/Magento/Sales/Test/Unit/Model/Order/ConfigTest.php b/app/code/Magento/Sales/Test/Unit/Model/Order/ConfigTest.php index 1f29235efaef29a790daccd7cf16447d9254adac..7ee4f745cde8f75de23147c956ca0bf039ab2e3a 100644 --- a/app/code/Magento/Sales/Test/Unit/Model/Order/ConfigTest.php +++ b/app/code/Magento/Sales/Test/Unit/Model/Order/ConfigTest.php @@ -5,8 +5,6 @@ */ namespace Magento\Sales\Test\Unit\Model\Order; -use \Magento\Sales\Model\Order\Config; - /** * Class ConfigTest */ @@ -95,4 +93,40 @@ class ConfigTest extends \PHPUnit_Framework_TestCase $result = $this->salesConfig->getInvisibleOnFrontStatuses(); $this->assertSame($expectedResult, $result); } + + public function testGetStateLabelByStateAndStatus() + { + $statuses = [ + new \Magento\Framework\DataObject( + [ + 'status' => 'fraud', + 'state' => 'processing', + 'label' => 'Suspected Fraud', + ] + ), + new \Magento\Framework\DataObject( + [ + 'status' => 'processing', + 'state' => 'processing', + 'label' => 'Processing', + ] + ) + ]; + $collectionMock = $this->getMock( + \Magento\Sales\Model\ResourceModel\Order\Status\Collection::class, + ['create', 'joinStates'], + [], + '', + false, + false + ); + $this->orderStatusCollectionFactoryMock->expects($this->once()) + ->method('create') + ->will($this->returnValue($collectionMock)); + $collectionMock->expects($this->once()) + ->method('joinStates') + ->will($this->returnValue($statuses)); + $result = $this->salesConfig->getStateLabelByStateAndStatus('processing', 'fraud'); + $this->assertSame('Suspected Fraud', $result->getText()); + } } diff --git a/app/code/Magento/Sales/etc/di.xml b/app/code/Magento/Sales/etc/di.xml index 4e2487d9dcada2eaf224f8cc30f65fc8fa4a4fc8..eb392fc83d8580e0cea6803a43c5f1a44f27fd58 100644 --- a/app/code/Magento/Sales/etc/di.xml +++ b/app/code/Magento/Sales/etc/di.xml @@ -956,4 +956,18 @@ <type name="Magento\Sales\Model\ResourceModel\Order\Handler\Address"> <plugin name="addressUpdate" type="Magento\Sales\Model\Order\Invoice\Plugin\AddressUpdate"/> </type> + <type name="Magento\Config\Model\Config\Export\ExcludeList"> + <arguments> + <argument name="configs" xsi:type="array"> + <item name="sales_email/order/copy_to" xsi:type="string">1</item> + <item name="sales_email/order_comment/copy_to" xsi:type="string">1</item> + <item name="sales_email/invoice/copy_to" xsi:type="string">1</item> + <item name="sales_email/invoice_comment/copy_to" xsi:type="string">1</item> + <item name="sales_email/shipment/copy_to" xsi:type="string">1</item> + <item name="sales_email/shipment_comment/copy_to" xsi:type="string">1</item> + <item name="sales_email/creditmemo/copy_to" xsi:type="string">1</item> + <item name="sales_email/creditmemo_comment/copy_to" xsi:type="string">1</item> + </argument> + </arguments> + </type> </config> diff --git a/app/code/Magento/Sales/view/adminhtml/ui_component/sales_order_grid.xml b/app/code/Magento/Sales/view/adminhtml/ui_component/sales_order_grid.xml index e0a5471b1e45ee1f6ba9bd8c05d0145656a642ea..0dc555c93d94d3db64e102f24b2fa4e6f45e278f 100644 --- a/app/code/Magento/Sales/view/adminhtml/ui_component/sales_order_grid.xml +++ b/app/code/Magento/Sales/view/adminhtml/ui_component/sales_order_grid.xml @@ -322,7 +322,7 @@ </item> </argument> </column> - <column name="total_refunded" class="Magento\Sales\Ui\Component\Listing\Column\Price"> + <column name="total_refunded" class="Magento\Sales\Ui\Component\Listing\Column\PurchasedPrice"> <argument name="data" xsi:type="array"> <item name="config" xsi:type="array"> <item name="filter" xsi:type="string">textRange</item> diff --git a/app/code/Magento/SalesRule/Model/ResourceModel/Rule.php b/app/code/Magento/SalesRule/Model/ResourceModel/Rule.php index 78cc3e1c39c275055811fb38db1474634c2b0386..0398508eccf3ef621afb1a0b1cb0f0753128bd14 100644 --- a/app/code/Magento/SalesRule/Model/ResourceModel/Rule.php +++ b/app/code/Magento/SalesRule/Model/ResourceModel/Rule.php @@ -5,12 +5,11 @@ */ namespace Magento\SalesRule\Model\ResourceModel; +use Magento\Framework\App\ObjectManager; use \Magento\SalesRule\Model\Rule as SalesRule; use Magento\Framework\Model\AbstractModel; -use Magento\Framework\DB\Select; use Magento\Rule\Model\ResourceModel\AbstractResource; use Magento\Framework\EntityManager\EntityManager; -use Magento\SalesRule\Api\Data\RuleInterface; /** * Sales Rule resource model @@ -56,16 +55,21 @@ class Rule extends AbstractResource * @param \Magento\Framework\Stdlib\StringUtils $string * @param \Magento\SalesRule\Model\ResourceModel\Coupon $resourceCoupon * @param string $connectionName + * @param \Magento\Framework\DataObject|null $associatedEntityMapInstance */ public function __construct( \Magento\Framework\Model\ResourceModel\Db\Context $context, \Magento\Framework\Stdlib\StringUtils $string, \Magento\SalesRule\Model\ResourceModel\Coupon $resourceCoupon, - $connectionName = null + $connectionName = null, + \Magento\Framework\DataObject $associatedEntityMapInstance = null ) { $this->string = $string; $this->_resourceCoupon = $resourceCoupon; - $this->_associatedEntitiesMap = $this->getAssociatedEntitiesMap(); + $associatedEntitiesMapInstance = $associatedEntityMapInstance ?: ObjectManager::getInstance()->get( + \Magento\SalesRule\Model\ResourceModel\Rule\AssociatedEntityMap::class + ); + $this->_associatedEntitiesMap = $associatedEntitiesMapInstance->getData(); parent::__construct($context, $connectionName); } @@ -380,20 +384,6 @@ class Rule extends AbstractResource return $this; } - /** - * @return array - * @deprecated - */ - private function getAssociatedEntitiesMap() - { - if (!$this->_associatedEntitiesMap) { - $this->_associatedEntitiesMap = \Magento\Framework\App\ObjectManager::getInstance() - ->get(\Magento\SalesRule\Model\ResourceModel\Rule\AssociatedEntityMap::class) - ->getData(); - } - return $this->_associatedEntitiesMap; - } - /** * @return \Magento\Framework\EntityManager\EntityManager * @deprecated diff --git a/app/code/Magento/SalesRule/Model/Rule.php b/app/code/Magento/SalesRule/Model/Rule.php index 3253c040ac9f90398cf7388870fca5598980309a..033c0ebd5be90b523bed4da381aa059ba8d7d3a9 100644 --- a/app/code/Magento/SalesRule/Model/Rule.php +++ b/app/code/Magento/SalesRule/Model/Rule.php @@ -5,6 +5,8 @@ */ namespace Magento\SalesRule\Model; +use Magento\Framework\Api\AttributeValueFactory; +use Magento\Framework\Api\ExtensionAttributesFactory; use Magento\Quote\Model\Quote\Address; /** @@ -171,6 +173,8 @@ class Rule extends \Magento\Rule\Model\AbstractModel protected $_storeManager; /** + * Rule constructor + * * @param \Magento\Framework\Model\Context $context * @param \Magento\Framework\Registry $registry * @param \Magento\Framework\Data\FormFactory $formFactory @@ -184,6 +188,9 @@ class Rule extends \Magento\Rule\Model\AbstractModel * @param \Magento\Framework\Model\ResourceModel\AbstractResource|null $resource * @param \Magento\Framework\Data\Collection\AbstractDb|null $resourceCollection * @param array $data + * @param ExtensionAttributesFactory|null $extensionFactory + * @param AttributeValueFactory|null $customAttributeFactory + * * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( @@ -199,7 +206,9 @@ class Rule extends \Magento\Rule\Model\AbstractModel \Magento\Store\Model\StoreManagerInterface $storeManager, \Magento\Framework\Model\ResourceModel\AbstractResource $resource = null, \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, - array $data = [] + array $data = [], + ExtensionAttributesFactory $extensionFactory = null, + AttributeValueFactory $customAttributeFactory = null ) { $this->_couponFactory = $couponFactory; $this->_codegenFactory = $codegenFactory; @@ -214,7 +223,9 @@ class Rule extends \Magento\Rule\Model\AbstractModel $localeDate, $resource, $resourceCollection, - $data + $data, + $extensionFactory, + $customAttributeFactory ); } diff --git a/app/code/Magento/SalesRule/Test/Unit/Model/ResourceModel/RuleTest.php b/app/code/Magento/SalesRule/Test/Unit/Model/ResourceModel/RuleTest.php index 5c60007543916f163f5e13ea8c83bf1a0e178be7..763e77f94f7a277c592a294c426b4f1478e51248 100644 --- a/app/code/Magento/SalesRule/Test/Unit/Model/ResourceModel/RuleTest.php +++ b/app/code/Magento/SalesRule/Test/Unit/Model/ResourceModel/RuleTest.php @@ -3,16 +3,18 @@ * Copyright © 2016 Magento. All rights reserved. * See COPYING.txt for license details. */ - namespace Magento\SalesRule\Test\Unit\Model\ResourceModel; -use Magento\SalesRule\Api\Data\RuleInterface; - /** * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class RuleTest extends \PHPUnit_Framework_TestCase { + /** + * @var \Magento\Framework\TestFramework\Unit\Helper\ObjectManager + */ + private $objectManager; + /** * @var \Magento\SalesRule\Model\ResourceModel\Rule */ @@ -60,7 +62,7 @@ class RuleTest extends \PHPUnit_Framework_TestCase protected function setUp() { - $objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); + $this->objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); $this->rule = $this->getMockBuilder(\Magento\SalesRule\Model\Rule::class) ->disableOriginalConstructor() ->getMock(); @@ -117,7 +119,13 @@ class RuleTest extends \PHPUnit_Framework_TestCase ->disableOriginalConstructor() ->getMock(); - $associatedEntitiesMap = $this->getMock(\Magento\Framework\DataObject::class, [], [], '', false); + $associatedEntitiesMap = $this->getMock( + \Magento\Framework\DataObject::class, + ['getData'], + [], + '', + false + ); $associatedEntitiesMap->expects($this->once()) ->method('getData') ->willReturn( @@ -135,19 +143,13 @@ class RuleTest extends \PHPUnit_Framework_TestCase ] ); - $this->prepareObjectManager([ - [ - \Magento\SalesRule\Model\ResourceModel\Rule\AssociatedEntityMap::class, - $associatedEntitiesMap - ], - ]); - - $this->model = $objectManager->getObject( + $this->model = $this->objectManager->getObject( \Magento\SalesRule\Model\ResourceModel\Rule::class, [ 'context' => $context, 'connectionName' => $connectionName, 'entityManager' => $this->entityManager, + 'associatedEntityMapInstance' => $associatedEntitiesMap ] ); } @@ -184,20 +186,4 @@ class RuleTest extends \PHPUnit_Framework_TestCase ->with($this->rule); $this->assertEquals($this->model->delete($this->rule), $this->model); } - - /** - * @param $map - */ - private function prepareObjectManager($map) - { - $objectManagerMock = $this->getMock(\Magento\Framework\ObjectManagerInterface::class); - $objectManagerMock->expects($this->any())->method('getInstance')->willReturnSelf(); - $objectManagerMock->expects($this->any()) - ->method('get') - ->will($this->returnValueMap($map)); - $reflectionClass = new \ReflectionClass(\Magento\Framework\App\ObjectManager::class); - $reflectionProperty = $reflectionClass->getProperty('_instance'); - $reflectionProperty->setAccessible(true); - $reflectionProperty->setValue($objectManagerMock); - } } diff --git a/app/code/Magento/SalesRule/Test/Unit/Model/RuleTest.php b/app/code/Magento/SalesRule/Test/Unit/Model/RuleTest.php index f3d16c188fdf9dec8d2404d52fd01047a5deed6f..48cd2ab7c4850450d5c62986619877531fc382b4 100644 --- a/app/code/Magento/SalesRule/Test/Unit/Model/RuleTest.php +++ b/app/code/Magento/SalesRule/Test/Unit/Model/RuleTest.php @@ -3,7 +3,6 @@ * Copyright © 2016 Magento. All rights reserved. * See COPYING.txt for license details. */ - namespace Magento\SalesRule\Test\Unit\Model; class RuleTest extends \PHPUnit_Framework_TestCase @@ -57,17 +56,6 @@ class RuleTest extends \PHPUnit_Framework_TestCase ->setMethods(['create']) ->getMock(); - $this->prepareObjectManager([ - [ - \Magento\Framework\Api\ExtensionAttributesFactory::class, - $this->getMock(\Magento\Framework\Api\ExtensionAttributesFactory::class, [], [], '', false) - ], - [ - \Magento\Framework\Api\AttributeValueFactory::class, - $this->getMock(\Magento\Framework\Api\AttributeValueFactory::class, [], [], '', false) - ], - ]); - $this->model = $objectManager->getObject( \Magento\SalesRule\Model\Rule::class, [ @@ -179,20 +167,4 @@ class RuleTest extends \PHPUnit_Framework_TestCase $expectedResult = 'form_namerule_actions_fieldset_100'; $this->assertEquals($expectedResult, $this->model->getActionsFieldSetId($formName)); } - - /** - * @param $map - */ - private function prepareObjectManager($map) - { - $objectManagerMock = $this->getMock(\Magento\Framework\ObjectManagerInterface::class); - $objectManagerMock->expects($this->any())->method('getInstance')->willReturnSelf(); - $objectManagerMock->expects($this->any()) - ->method('get') - ->will($this->returnValueMap($map)); - $reflectionClass = new \ReflectionClass(\Magento\Framework\App\ObjectManager::class); - $reflectionProperty = $reflectionClass->getProperty('_instance'); - $reflectionProperty->setAccessible(true); - $reflectionProperty->setValue($objectManagerMock); - } } diff --git a/app/code/Magento/Search/Model/SearchEngine/Config/Data.php b/app/code/Magento/Search/Model/SearchEngine/Config/Data.php index 18a3b620eee18d1905d9c0cc533d358e05044c53..d128a9d50025d8f69437284ba2d42a5ae5f022ff 100644 --- a/app/code/Magento/Search/Model/SearchEngine/Config/Data.php +++ b/app/code/Magento/Search/Model/SearchEngine/Config/Data.php @@ -5,6 +5,11 @@ */ namespace Magento\Search\Model\SearchEngine\Config; +use Magento\Framework\Serialize\SerializerInterface; + +/** + * Provides search engine configuration + */ class Data extends \Magento\Framework\Config\Data { /** @@ -12,13 +17,15 @@ class Data extends \Magento\Framework\Config\Data * * @param \Magento\Framework\Search\SearchEngine\Config\Reader $reader * @param \Magento\Framework\Config\CacheInterface $cache - * @param string $cacheId + * @param string|null $cacheId + * @param SerializerInterface|null $serializer */ public function __construct( \Magento\Framework\Search\SearchEngine\Config\Reader $reader, \Magento\Framework\Config\CacheInterface $cache, - $cacheId = 'search_engine_config_cache' + $cacheId = 'search_engine_config_cache', + SerializerInterface $serializer = null ) { - parent::__construct($reader, $cache, $cacheId); + parent::__construct($reader, $cache, $cacheId, $serializer); } } diff --git a/app/code/Magento/Shipping/composer.json b/app/code/Magento/Shipping/composer.json index 03f51bbd95e0ff5f65b88e565cfbe77102a44760..6f3f5c3925fa5431446d0c40ccf1e4bf902afede 100644 --- a/app/code/Magento/Shipping/composer.json +++ b/app/code/Magento/Shipping/composer.json @@ -21,7 +21,8 @@ }, "suggest": { "magento/module-fedex": "100.2.*", - "magento/module-ups": "100.2.*" + "magento/module-ups": "100.2.*", + "magento/module-config": "100.2.*" }, "type": "magento2-module", "version": "100.2.0-dev", diff --git a/app/code/Magento/Shipping/etc/di.xml b/app/code/Magento/Shipping/etc/di.xml index 1fe0657bf1337a1712c2aef7b614db6a45ea853f..44e138d6c9ac6f5c102727458edfe4d34fe4a9c5 100644 --- a/app/code/Magento/Shipping/etc/di.xml +++ b/app/code/Magento/Shipping/etc/di.xml @@ -9,4 +9,16 @@ <preference for="Magento\Quote\Model\Quote\Address\RateCollectorInterface" type="Magento\Shipping\Model\Shipping" /> <preference for="Magento\Shipping\Model\CarrierFactoryInterface" type="Magento\Shipping\Model\CarrierFactory" /> <preference for="Magento\Shipping\Model\Carrier\Source\GenericInterface" type="\Magento\Shipping\Model\Carrier\Source\GenericDefault" /> + <type name="Magento\Config\Model\Config\Export\ExcludeList"> + <arguments> + <argument name="configs" xsi:type="array"> + <item name="shipping/origin/country_id" xsi:type="string">1</item> + <item name="shipping/origin/region_id" xsi:type="string">1</item> + <item name="shipping/origin/postcode" xsi:type="string">1</item> + <item name="shipping/origin/city" xsi:type="string">1</item> + <item name="shipping/origin/street_line1" xsi:type="string">1</item> + <item name="shipping/origin/street_line2" xsi:type="string">1</item> + </argument> + </arguments> + </type> </config> diff --git a/app/code/Magento/Sitemap/composer.json b/app/code/Magento/Sitemap/composer.json index 9f556178fc2cccfd070c272a89164e438f1d33e8..307691a67d2e24617f381803d8a3f96a2c010d1b 100644 --- a/app/code/Magento/Sitemap/composer.json +++ b/app/code/Magento/Sitemap/composer.json @@ -12,6 +12,9 @@ "magento/module-media-storage": "100.2.*", "magento/framework": "100.2.*" }, + "suggest": { + "magento/module-config": "100.2.*" + }, "type": "magento2-module", "version": "100.2.0-dev", "license": [ diff --git a/app/code/Magento/Sitemap/etc/di.xml b/app/code/Magento/Sitemap/etc/di.xml index 7ce1fdee7b5b6a1de7947da82c2a1b93bf470bfc..dfe34a25fb7ba37766ae0247194df1cc85bdee28 100644 --- a/app/code/Magento/Sitemap/etc/di.xml +++ b/app/code/Magento/Sitemap/etc/di.xml @@ -11,4 +11,11 @@ <argument name="resource" xsi:type="object">Magento\Sitemap\Model\ResourceModel\Sitemap</argument> </arguments> </type> + <type name="Magento\Config\Model\Config\Export\ExcludeList"> + <arguments> + <argument name="configs" xsi:type="array"> + <item name="sitemap/generate/error_email" xsi:type="string">1</item> + </argument> + </arguments> + </type> </config> 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..f64f2fe84a8cd9a496c0c85f8135e3274cd75f2f 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 @@ -150,7 +152,7 @@ class StoreManager implements public function getStore($storeId = null) { if (!isset($storeId) || '' === $storeId || $storeId === true) { - if (!$this->currentStoreId) { + if (null === $this->currentStoreId) { \Magento\Framework\Profiler::start('store.resolve'); $this->currentStoreId = $this->storeResolver->getCurrentStoreId(); \Magento\Framework\Profiler::stop('store.resolve'); @@ -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/StoreResolver.php b/app/code/Magento/Store/Model/StoreResolver.php index a19d75d9f47e06364afe9d2aa1dd3dab950e2a60..cfb57849f25a83fd8c1f971e1b9bbf7870c2765c 100644 --- a/app/code/Magento/Store/Model/StoreResolver.php +++ b/app/code/Magento/Store/Model/StoreResolver.php @@ -5,8 +5,7 @@ */ namespace Magento\Store\Model; -use Magento\Framework\Exception\NoSuchEntityException; -use Magento\Store\Api\StoreCookieManagerInterface; +use Magento\Framework\Serialize\SerializerInterface; class StoreResolver implements \Magento\Store\Api\StoreResolverInterface { @@ -21,7 +20,7 @@ class StoreResolver implements \Magento\Store\Api\StoreResolverInterface protected $storeRepository; /** - * @var StoreCookieManagerInterface + * @var \Magento\Store\Api\StoreCookieManagerInterface */ protected $storeCookieManager; @@ -31,7 +30,7 @@ class StoreResolver implements \Magento\Store\Api\StoreResolverInterface protected $cache; /** - * @var StoreResolver\ReaderList + * @var \Magento\Store\Model\StoreResolver\ReaderList */ protected $readerList; @@ -50,21 +49,26 @@ class StoreResolver implements \Magento\Store\Api\StoreResolverInterface */ protected $request; + /** + * @var \Magento\Framework\Serialize\SerializerInterface + */ + private $serializer; + /** * @param \Magento\Store\Api\StoreRepositoryInterface $storeRepository - * @param StoreCookieManagerInterface $storeCookieManager + * @param \Magento\Store\Api\StoreCookieManagerInterface $storeCookieManager * @param \Magento\Framework\App\RequestInterface $request * @param \Magento\Framework\Cache\FrontendInterface $cache - * @param StoreResolver\ReaderList $readerList + * @param \Magento\Store\Model\StoreResolver\ReaderList $readerList * @param string $runMode * @param null $scopeCode */ public function __construct( \Magento\Store\Api\StoreRepositoryInterface $storeRepository, - StoreCookieManagerInterface $storeCookieManager, + \Magento\Store\Api\StoreCookieManagerInterface $storeCookieManager, \Magento\Framework\App\RequestInterface $request, \Magento\Framework\Cache\FrontendInterface $cache, - StoreResolver\ReaderList $readerList, + \Magento\Store\Model\StoreResolver\ReaderList $readerList, $runMode = ScopeInterface::SCOPE_STORE, $scopeCode = null ) { @@ -94,7 +98,7 @@ class StoreResolver implements \Magento\Store\Api\StoreResolverInterface if ($storeCode) { try { $store = $this->getRequestedStoreByCode($storeCode); - } catch (NoSuchEntityException $e) { + } catch (\Magento\Framework\Exception\NoSuchEntityException $e) { $store = $this->getDefaultStoreById($defaultStoreId); } @@ -117,10 +121,10 @@ class StoreResolver implements \Magento\Store\Api\StoreResolverInterface $cacheKey = 'resolved_stores_' . md5($this->runMode . $this->scopeCode); $cacheData = $this->cache->load($cacheKey); if ($cacheData) { - $storesData = unserialize($cacheData); + $storesData = $this->getSerializer()->unserialize($cacheData); } else { $storesData = $this->readStoresData(); - $this->cache->save(serialize($storesData), $cacheKey, [self::CACHE_TAG]); + $this->cache->save($this->getSerializer()->serialize($storesData), $cacheKey, [self::CACHE_TAG]); } return $storesData; } @@ -141,14 +145,14 @@ class StoreResolver implements \Magento\Store\Api\StoreResolverInterface * * @param string $storeCode * @return \Magento\Store\Api\Data\StoreInterface - * @throws NoSuchEntityException + * @throws \Magento\Framework\Exception\NoSuchEntityException */ protected function getRequestedStoreByCode($storeCode) { try { $store = $this->storeRepository->getActiveStoreByCode($storeCode); } catch (StoreIsInactiveException $e) { - throw new NoSuchEntityException(__('Requested store is inactive')); + throw new \Magento\Framework\Exception\NoSuchEntityException(__('Requested store is inactive')); } return $store; @@ -159,16 +163,31 @@ class StoreResolver implements \Magento\Store\Api\StoreResolverInterface * * @param int $id * @return \Magento\Store\Api\Data\StoreInterface - * @throws NoSuchEntityException + * @throws \Magento\Framework\Exception\NoSuchEntityException */ protected function getDefaultStoreById($id) { try { $store = $this->storeRepository->getActiveStoreById($id); } catch (StoreIsInactiveException $e) { - throw new NoSuchEntityException(__('Default store is inactive')); + throw new \Magento\Framework\Exception\NoSuchEntityException(__('Default store is inactive')); } return $store; } + + /** + * Get serializer + * + * @return \Magento\Framework\Serialize\SerializerInterface + * @deprecated + */ + private function getSerializer() + { + if ($this->serializer === null) { + $this->serializer = \Magento\Framework\App\ObjectManager::getInstance() + ->get(SerializerInterface::class); + } + return $this->serializer; + } } 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/Swatches/Helper/Data.php b/app/code/Magento/Swatches/Helper/Data.php index a973a822c4101671faa0fe57925a0e9b0c5b2f2a..d80aaaf73ccf016bc1d571254cfc90a7f0452c3d 100644 --- a/app/code/Magento/Swatches/Helper/Data.php +++ b/app/code/Magento/Swatches/Helper/Data.php @@ -328,12 +328,10 @@ class Data private function getAllSizeImages(ModelProduct $product, $imageFile) { return [ - 'large' => $this->imageHelper->init($product, 'product_page_image_large') - ->constrainOnly(true)->keepAspectRatio(true)->keepFrame(false) + 'large' => $this->imageHelper->init($product, 'product_page_image_large_no_frame') ->setImageFile($imageFile) ->getUrl(), - 'medium' => $this->imageHelper->init($product, 'product_page_image_medium') - ->constrainOnly(true)->keepAspectRatio(true)->keepFrame(false) + 'medium' => $this->imageHelper->init($product, 'product_page_image_medium_no_frame') ->setImageFile($imageFile) ->getUrl(), 'small' => $this->imageHelper->init($product, 'product_page_image_small') diff --git a/app/code/Magento/Swatches/Test/Unit/Helper/DataTest.php b/app/code/Magento/Swatches/Test/Unit/Helper/DataTest.php index e5f2f887836eff5ad73ca95602d4d7aec411150e..10f26acfc2594499adb80cd6df5bfee1fc277f88 100644 --- a/app/code/Magento/Swatches/Test/Unit/Helper/DataTest.php +++ b/app/code/Magento/Swatches/Test/Unit/Helper/DataTest.php @@ -340,8 +340,8 @@ class DataTest extends \PHPUnit_Framework_TestCase $this->imageHelperMock->expects($this->any()) ->method('init') ->willReturnMap([ - [$this->productMock, 'product_page_image_large', [], $this->imageHelperMock], - [$this->productMock, 'product_page_image_medium', [], $this->imageHelperMock], + [$this->productMock, 'product_page_image_large_no_frame', [], $this->imageHelperMock], + [$this->productMock, 'product_page_image_medium_no_frame', [], $this->imageHelperMock], [$this->productMock, 'product_page_image_small', [], $this->imageHelperMock], ]); @@ -349,15 +349,6 @@ class DataTest extends \PHPUnit_Framework_TestCase ->method('setImageFile') ->with($image) ->willReturnSelf(); - $this->imageHelperMock->expects($this->any()) - ->method('constrainOnly') - ->willReturnSelf(); - $this->imageHelperMock->expects($this->any()) - ->method('keepAspectRatio') - ->willReturnSelf(); - $this->imageHelperMock->expects($this->any()) - ->method('keepFrame') - ->willReturnSelf(); $this->imageHelperMock->expects($this->any()) ->method('getUrl') ->willReturn('http://full_path_to_image/magento1.png'); diff --git a/app/code/Magento/Swatches/view/frontend/web/js/swatch-renderer.js b/app/code/Magento/Swatches/view/frontend/web/js/swatch-renderer.js index 8af48829df438261aaed469c88245fc50a349853..cd9794dc1757d4cfa5f092209ad8515557e42a4a 100644 --- a/app/code/Magento/Swatches/view/frontend/web/js/swatch-renderer.js +++ b/app/code/Magento/Swatches/view/frontend/web/js/swatch-renderer.js @@ -6,11 +6,14 @@ define([ 'jquery', 'underscore', + 'mage/template', 'mage/smart-keyboard-handler', + 'mage/translate', + 'priceUtils', 'jquery/ui', 'jquery/jquery.parsequery', 'mage/validation/validation' -], function ($, _, keyboardHandler) { +], function ($, _, mageTemplate, keyboardHandler, $t, priceUtils) { 'use strict'; /** @@ -254,7 +257,16 @@ define([ gallerySwitchStrategy: 'replace', // whether swatches are rendered in product list or on product page - inProductList: false + inProductList: false, + + // sly-old-price block selector + slyOldPriceSelector: '.sly-old-price', + + // tier prise selectors start + tierPriceTemplateSelector: '#tier-prices-template', + tierPriceBlockSelector: '[data-role="tier-price-block"]', + tierPriceTemplate: '' + // tier prise selectors end }, /** @@ -279,6 +291,7 @@ define([ } else { console.log('SwatchRenderer: No input data received'); } + this.options.tierPriceTemplate = $(this.options.tierPriceTemplateSelector).html(); }, /** @@ -809,7 +822,8 @@ define([ $product = $widget.element.parents($widget.options.selectorProduct), $productPrice = $product.find(this.options.selectorProductPrice), options = _.object(_.keys($widget.optionsMap), {}), - result; + result, + tierPriceHtml; $widget.element.find('.' + $widget.options.classes.attributeClass + '[option-selected]').each(function () { var attributeId = $(this).attr('attribute-id'); @@ -825,6 +839,29 @@ define([ 'prices': $widget._getPrices(result, $productPrice.priceBox('option').prices) } ); + + if (result.oldPrice.amount !== result.finalPrice.amount) { + $(this.options.slyOldPriceSelector).show(); + } else { + $(this.options.slyOldPriceSelector).hide(); + } + + if (result.tierPrices.length) { + if (this.options.tierPriceTemplate) { + tierPriceHtml = mageTemplate( + this.options.tierPriceTemplate, + { + 'tierPrices': result.tierPrices, + '$t': $t, + 'currencyFormat': this.options.jsonConfig.currencyFormat, + 'priceUtils': priceUtils + } + ); + $(this.options.tierPriceBlockSelector).html(tierPriceHtml).show(); + } + } else { + $(this.options.tierPriceBlockSelector).hide(); + } }, /** diff --git a/app/code/Magento/Tax/Model/Sales/Total/Quote/CommonTaxCollector.php b/app/code/Magento/Tax/Model/Sales/Total/Quote/CommonTaxCollector.php index 07b9c558043b0ddee1c3b99f63fa0b2f8aa27490..c2c53a3d7754ab080bb9fa818d3cb8d65eac2531 100644 --- a/app/code/Magento/Tax/Model/Sales/Total/Quote/CommonTaxCollector.php +++ b/app/code/Magento/Tax/Model/Sales/Total/Quote/CommonTaxCollector.php @@ -535,6 +535,7 @@ class CommonTaxCollector extends AbstractTotal $total->setSubtotalInclTax($subtotalInclTax); $total->setBaseSubtotalTotalInclTax($baseSubtotalInclTax); $total->setBaseSubtotalInclTax($baseSubtotalInclTax); + $shippingAssignment->getShipping()->getAddress()->setBaseSubtotalTotalInclTax($baseSubtotalInclTax);; return $this; } diff --git a/app/code/Magento/Theme/Model/Design.php b/app/code/Magento/Theme/Model/Design.php index 39527afc0250d77e0e9ac6d8f9a2941e76e07398..55941cfbcacb6003ef1f03a5a834c1272d40dda8 100644 --- a/app/code/Magento/Theme/Model/Design.php +++ b/app/code/Magento/Theme/Model/Design.php @@ -6,9 +6,11 @@ namespace Magento\Theme\Model; use Magento\Framework\App\DesignInterface; +use Magento\Framework\App\ObjectManager; use Magento\Framework\Model\AbstractModel; use Magento\Framework\Model\ResourceModel\AbstractResource; use Magento\Framework\DataObject\IdentityInterface; +use Magento\Framework\Serialize\SerializerInterface; /** * Design settings change model @@ -55,6 +57,11 @@ class Design extends AbstractModel implements IdentityInterface, DesignInterface */ protected $_dateTime; + /** + * @var SerializerInterface + */ + private $serializer; + /** * @param \Magento\Framework\Model\Context $context * @param \Magento\Framework\Registry $registry @@ -63,6 +70,7 @@ class Design extends AbstractModel implements IdentityInterface, DesignInterface * @param AbstractResource $resource * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data + * @param SerializerInterface $serializer */ public function __construct( \Magento\Framework\Model\Context $context, @@ -71,10 +79,12 @@ class Design extends AbstractModel implements IdentityInterface, DesignInterface \Magento\Framework\Stdlib\DateTime $dateTime, AbstractResource $resource = null, \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, - array $data = [] + array $data = [], + SerializerInterface $serializer = null ) { $this->_localeDate = $localeDate; $this->_dateTime = $dateTime; + $this->serializer = $serializer ?: ObjectManager::getInstance()->get(SerializerInterface::class); parent::__construct($context, $registry, $resource, $resourceCollection, $data); } @@ -108,9 +118,9 @@ class Design extends AbstractModel implements IdentityInterface, DesignInterface if (!$result) { $result = []; } - $this->_cacheManager->save(serialize($result), $changeCacheId, [self::CACHE_TAG], 86400); + $this->_cacheManager->save($this->serializer->serialize($result), $changeCacheId, [self::CACHE_TAG], 86400); } else { - $result = unserialize($result); + $result = $this->serializer->unserialize($result); } if ($result) { diff --git a/app/code/Magento/Theme/Model/Design/Backend/File.php b/app/code/Magento/Theme/Model/Design/Backend/File.php index e788c6892f4c89e20f89b454f7a6061f30d08b0b..0d93352f041ac6af29abb16e4ffcb7d837ad5634 100644 --- a/app/code/Magento/Theme/Model/Design/Backend/File.php +++ b/app/code/Magento/Theme/Model/Design/Backend/File.php @@ -9,8 +9,10 @@ use Magento\Config\Model\Config\Backend\File\RequestData\RequestDataInterface; use Magento\Config\Model\Config\Backend\File as BackendFile; use Magento\Framework\App\Cache\TypeListInterface; use Magento\Framework\App\Config\ScopeConfigInterface; +use Magento\Framework\App\ObjectManager; use Magento\Framework\Data\Collection\AbstractDb; use Magento\Framework\Exception\LocalizedException; +use Magento\Framework\File\Mime; use Magento\Framework\Filesystem; use Magento\Framework\Model\Context; use Magento\Framework\Model\ResourceModel\AbstractResource; @@ -29,6 +31,11 @@ class File extends BackendFile */ protected $urlBuilder; + /** + * @var Mime + */ + private $mime; + /** * @param Context $context * @param Registry $registry @@ -125,7 +132,9 @@ class File extends BackendFile 'url' => $url, 'file' => $value, 'size' => is_array($stat) ? $stat['size'] : 0, - 'exists' => true + 'name' => basename($value), + 'type' => $this->getMimeType($fileName), + 'exists' => true, ] ]; } @@ -192,4 +201,33 @@ class File extends BackendFile { return 'tmp/' . FileProcessor::FILE_DIR . '/' . $filename; } + + /** + * Retrieve MIME type of requested file + * + * @param string $fileName + * @return string + */ + private function getMimeType($fileName) + { + $absoluteFilePath = $this->_mediaDirectory->getAbsolutePath($fileName); + + $result = $this->getMime()->getMimeType($absoluteFilePath); + return $result; + } + + /** + * Get Mime instance + * + * @return Mime + * + * @deprecated + */ + private function getMime() + { + if ($this->mime === null) { + $this->mime = ObjectManager::getInstance()->get(Mime::class); + } + return $this->mime; + } } diff --git a/app/code/Magento/Theme/Model/Design/Config/DataProvider.php b/app/code/Magento/Theme/Model/Design/Config/DataProvider.php index c433b02fab240d736637bf41b571c2eb75d193bc..977295c1f80c466899284f0e8e18c373a6007445 100644 --- a/app/code/Magento/Theme/Model/Design/Config/DataProvider.php +++ b/app/code/Magento/Theme/Model/Design/Config/DataProvider.php @@ -5,9 +5,13 @@ */ namespace Magento\Theme\Model\Design\Config; +use Magento\Framework\App\Config\ScopeCodeResolver; +use Magento\Framework\App\ObjectManager; use Magento\Theme\Model\ResourceModel\Design\Config\Collection; use Magento\Theme\Model\ResourceModel\Design\Config\CollectionFactory; use Magento\Ui\DataProvider\AbstractDataProvider; +use Magento\Config\Model\Config\Reader\Source\Deployed\SettingChecker; +use Magento\Framework\App\RequestInterface; class DataProvider extends AbstractDataProvider { @@ -31,6 +35,21 @@ class DataProvider extends AbstractDataProvider */ private $metadataLoader; + /** + * @var SettingChecker + */ + private $settingChecker; + + /** + * @var RequestInterface + */ + private $request; + + /** + * @var ScopeCodeResolver + */ + private $scopeCodeResolver; + /** * @param string $name * @param string $primaryFieldName @@ -78,4 +97,84 @@ class DataProvider extends AbstractDataProvider $this->loadedData = $this->dataLoader->getData(); return $this->loadedData; } + + /** + * {@inheritdoc} + */ + public function getMeta() + { + $meta = parent::getMeta(); + if (!isset($meta['other_settings']['children'])) { + return $meta; + } + + $request = $this->getRequest()->getParams(); + if (!isset($request['scope'])) { + return $meta; + } + + $scope = $request['scope']; + $scopeCode = $this->getScopeCodeResolver()->resolve( + $scope, + isset($request['scope_id']) ? $request['scope_id'] : null + ); + + foreach ($meta['other_settings']['children'] as $settingGroupName => &$settingGroup) { + foreach ($settingGroup['children'] as $fieldName => &$field) { + $path = sprintf( + 'design/%s/%s', + $settingGroupName, + preg_replace('/^' . $settingGroupName . '_/', '', $fieldName) + ); + $isReadOnly = $this->getSettingChecker()->isReadOnly( + $path, + $scope, + $scopeCode + ); + + if ($isReadOnly) { + $field['arguments']['data']['config']['disabled'] = true; + $field['arguments']['data']['config']['is_disable_inheritance'] = true; + } + } + } + + return $meta; + } + + /** + * @deprecated + * @return ScopeCodeResolver + */ + private function getScopeCodeResolver() + { + if ($this->scopeCodeResolver === null) { + $this->scopeCodeResolver = ObjectManager::getInstance()->get(ScopeCodeResolver::class); + } + return $this->scopeCodeResolver; + } + + /** + * @deprecated + * @return SettingChecker + */ + private function getSettingChecker() + { + if ($this->settingChecker === null) { + $this->settingChecker = ObjectManager::getInstance()->get(SettingChecker::class); + } + return $this->settingChecker; + } + + /** + * @deprecated + * @return RequestInterface + */ + private function getRequest() + { + if ($this->request === null) { + $this->request = ObjectManager::getInstance()->get(RequestInterface::class); + } + return $this->request; + } } diff --git a/app/code/Magento/Theme/Model/Design/Config/FileUploader/FileProcessor.php b/app/code/Magento/Theme/Model/Design/Config/FileUploader/FileProcessor.php index 5a132b0250079123694a23addaea3935d53cb685..786a1820aa5b3f53bbb55aa5f3e0693be2b1776f 100644 --- a/app/code/Magento/Theme/Model/Design/Config/FileUploader/FileProcessor.php +++ b/app/code/Magento/Theme/Model/Design/Config/FileUploader/FileProcessor.php @@ -135,7 +135,6 @@ class FileProcessor */ protected function save($fileId, $destination) { - $result = ['file' => '', 'size' => '']; /** @var File $backendModel */ $backendModel = $this->getBackendModel($fileId); $uploader = $this->uploaderFactory->create(['fileId' => $fileId]); @@ -143,7 +142,9 @@ class FileProcessor $uploader->setFilesDispersion(false); $uploader->setAllowedExtensions($backendModel->getAllowedExtensions()); $uploader->addValidateCallback('size', $backendModel, 'validateMaxSize'); - return array_intersect_key($uploader->save($destination), $result); + + $result = $uploader->save($destination); + return $result; } /** 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/Design/Backend/FileTest.php b/app/code/Magento/Theme/Test/Unit/Model/Design/Backend/FileTest.php index 7dd8b636210fc6ca6ab86398e2ceb12bd590529f..7038edebac0204ee945e67bbd6e0db2d7b5bbac0 100644 --- a/app/code/Magento/Theme/Test/Unit/Model/Design/Backend/FileTest.php +++ b/app/code/Magento/Theme/Test/Unit/Model/Design/Backend/FileTest.php @@ -23,6 +23,11 @@ class FileTest extends \PHPUnit_Framework_TestCase /** @var File */ protected $fileBackend; + /** + * @var \Magento\Framework\File\Mime|\PHPUnit_Framework_MockObject_MockObject + */ + private $mime; + public function setUp() { $context = $this->getMockObject(\Magento\Framework\Model\Context::class); @@ -46,6 +51,10 @@ class FileTest extends \PHPUnit_Framework_TestCase $this->urlBuilder = $this->getMockBuilder(\Magento\Framework\UrlInterface::class) ->getMockForAbstractClass(); + $this->mime = $this->getMockBuilder(\Magento\Framework\File\Mime::class) + ->disableOriginalConstructor() + ->getMock(); + $this->fileBackend = new File( $context, $registry, @@ -56,6 +65,13 @@ class FileTest extends \PHPUnit_Framework_TestCase $filesystem, $this->urlBuilder ); + + $objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); + $objectManager->setBackwardCompatibleProperty( + $this->fileBackend, + 'mime', + $this->mime + ); } public function tearDown() @@ -91,6 +107,10 @@ class FileTest extends \PHPUnit_Framework_TestCase public function testAfterLoad() { $value = 'filename.jpg'; + $mime = 'image/jpg'; + + $absoluteFilePath = '/absolute_path/' . $value; + $this->fileBackend->setValue($value); $this->fileBackend->setFieldConfig( [ @@ -109,6 +129,11 @@ class FileTest extends \PHPUnit_Framework_TestCase ->method('isExist') ->with('value/' . $value) ->willReturn(true); + $this->mediaDirectory->expects($this->once()) + ->method('getAbsolutePath') + ->with('value/' . $value) + ->willReturn($absoluteFilePath); + $this->urlBuilder->expects($this->once()) ->method('getBaseUrl') ->with(['_type' => UrlInterface::URL_TYPE_MEDIA]) @@ -122,6 +147,11 @@ class FileTest extends \PHPUnit_Framework_TestCase ->with('value/' . $value) ->willReturn(['size' => 234234]); + $this->mime->expects($this->once()) + ->method('getMimeType') + ->with($absoluteFilePath) + ->willReturn($mime); + $this->fileBackend->afterLoad(); $this->assertEquals( [ @@ -130,6 +160,8 @@ class FileTest extends \PHPUnit_Framework_TestCase 'file' => $value, 'size' => 234234, 'exists' => true, + 'name' => $value, + 'type' => $mime, ] ], $this->fileBackend->getValue() diff --git a/app/code/Magento/Theme/Test/Unit/Model/Design/Config/DataProviderTest.php b/app/code/Magento/Theme/Test/Unit/Model/Design/Config/DataProviderTest.php index 3ba61da79b5ca00073a14e11e7ab14c46b7af031..a5db6156efea32c56009620d9a8f2110f070bfe1 100644 --- a/app/code/Magento/Theme/Test/Unit/Model/Design/Config/DataProviderTest.php +++ b/app/code/Magento/Theme/Test/Unit/Model/Design/Config/DataProviderTest.php @@ -5,11 +5,18 @@ */ namespace Magento\Theme\Test\Unit\Model\Design\Config; +use Magento\Config\Model\Config\Reader\Source\Deployed\SettingChecker; +use Magento\Framework\App\Config\ScopeCodeResolver; +use Magento\Framework\App\RequestInterface; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; use Magento\Theme\Model\Design\Config\DataLoader; use Magento\Theme\Model\Design\Config\DataProvider; use Magento\Theme\Model\Design\Config\MetadataLoader; use Magento\Theme\Model\ResourceModel\Design\Config\Collection; +/** + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ class DataProviderTest extends \PHPUnit_Framework_TestCase { /** @@ -32,8 +39,29 @@ class DataProviderTest extends \PHPUnit_Framework_TestCase */ protected $collection; + /** + * @var ObjectManager + */ + private $objectManager; + + /** + * @var RequestInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $requestMock; + + /** + * @var ScopeCodeResolver|\PHPUnit_Framework_MockObject_MockObject + */ + private $scopeCodeResolverMock; + + /** + * @var SettingChecker|\PHPUnit_Framework_MockObject_MockObject + */ + private $settingCheckerMock; + protected function setUp() { + $this->objectManager = new ObjectManager($this); $this->dataLoader = $this->getMockBuilder(\Magento\Theme\Model\Design\Config\DataProvider\DataLoader::class) ->disableOriginalConstructor() ->getMock(); @@ -56,6 +84,16 @@ class DataProviderTest extends \PHPUnit_Framework_TestCase ->method('create') ->willReturn($this->collection); + $this->requestMock = $this->getMockBuilder(RequestInterface::class) + ->disableOriginalConstructor() + ->getMock(); + $this->scopeCodeResolverMock = $this->getMockBuilder(ScopeCodeResolver::class) + ->disableOriginalConstructor() + ->getMock(); + $this->settingCheckerMock = $this->getMockBuilder(SettingChecker::class) + ->disableOriginalConstructor() + ->getMock(); + $this->model = new DataProvider( 'scope', 'scope', @@ -64,6 +102,21 @@ class DataProviderTest extends \PHPUnit_Framework_TestCase $this->metadataLoader, $collectionFactory ); + $this->objectManager->setBackwardCompatibleProperty( + $this->model, + 'request', + $this->requestMock + ); + $this->objectManager->setBackwardCompatibleProperty( + $this->model, + 'scopeCodeResolver', + $this->scopeCodeResolverMock + ); + $this->objectManager->setBackwardCompatibleProperty( + $this->model, + 'settingChecker', + $this->settingCheckerMock + ); } public function testGetData() @@ -78,4 +131,119 @@ class DataProviderTest extends \PHPUnit_Framework_TestCase $this->assertEquals($data, $this->model->getData()); } + + /** + * @param array $inputMeta + * @param array $expectedMeta + * @param array $request + * @dataProvider getMetaDataProvider + */ + public function testGetMeta(array $inputMeta, array $expectedMeta, array $request) + { + $this->requestMock->expects($this->any()) + ->method('getParams') + ->willReturn($request); + $this->scopeCodeResolverMock->expects($this->any()) + ->method('resolve') + ->with('stores', 1) + ->willReturn('default'); + $this->settingCheckerMock->expects($this->any()) + ->method('isReadOnly') + ->withConsecutive( + ['design/head/welcome', 'stores', 'default'], + ['design/head/logo', 'stores', 'default'], + ['design/head/head', 'stores', 'default'] + ) + ->willReturnOnConsecutiveCalls( + true, + false, + true + ); + + $this->objectManager->setBackwardCompatibleProperty( + $this->model, + 'meta', + $inputMeta + ); + + $this->assertSame($expectedMeta, $this->model->getMeta()); + } + + /** + * @return array + */ + public function getMetaDataProvider() + { + return [ + [ + [ + 'option1' + ], + [ + 'option1' + ], + [ + 'scope' => 'default' + ] + ], + [ + [ + 'other_settings' => [ + 'children' => [ + 'head' => [ + 'children' => [ + 'head_welcome' => [ + + ], + 'head_logo' => [ + + ], + 'head_head' => [ + + ] + ] + ] + ] + ] + ], + [ + 'other_settings' => [ + 'children' => [ + 'head' => [ + 'children' => [ + 'head_welcome' => [ + 'arguments' => [ + 'data' => [ + 'config' => [ + 'disabled' => true, + 'is_disable_inheritance' => true, + ] + ] + ] + ], + 'head_logo' => [ + + ], + 'head_head' => [ + 'arguments' => [ + 'data' => [ + 'config' => [ + 'disabled' => true, + 'is_disable_inheritance' => true, + ] + ] + ] + ] + ] + ] + ] + ] + ], + [ + 'scope' => 'stores', + 'scope_id' => 1 + ] + ] + ]; + } } diff --git a/app/code/Magento/Theme/Test/Unit/Model/Design/Config/FileUploader/FileProcessorTest.php b/app/code/Magento/Theme/Test/Unit/Model/Design/Config/FileUploader/FileProcessorTest.php index 1cd1072ce69f12110936e4a518990dd854713fd7..61e510ec25cea949a28042c69331d02861891d7b 100644 --- a/app/code/Magento/Theme/Test/Unit/Model/Design/Config/FileUploader/FileProcessorTest.php +++ b/app/code/Magento/Theme/Test/Unit/Model/Design/Config/FileUploader/FileProcessorTest.php @@ -135,11 +135,18 @@ class FileProcessorTest extends \PHPUnit_Framework_TestCase $this->uploader->expects($this->once()) ->method('save') ->with('absolute/path/to/tmp/media') - ->willReturn(['file' => 'file.jpg', 'size' => '234234']); + ->willReturn([ + 'file' => 'file.jpg', + 'size' => '234234', + 'type' => 'image/jpg', + 'name' => 'file.jpg', + ]); $this->assertEquals( [ 'file' => 'file.jpg', + 'name' => 'file.jpg', 'size' => '234234', + 'type' => 'image/jpg', 'url' => 'http://magento2.com/pub/media/tmp/' . FileProcessor::FILE_DIR . '/file.jpg' ], $this->fileProcessor->saveToTmp($fieldCode) diff --git a/app/code/Magento/Theme/Test/Unit/Model/DesignTest.php b/app/code/Magento/Theme/Test/Unit/Model/DesignTest.php index dc11a4c46eda53a9fad92048f1c65d583ddcb607..67f86575a8afdb4143d5ebc5a213b472553bc463 100644 --- a/app/code/Magento/Theme/Test/Unit/Model/DesignTest.php +++ b/app/code/Magento/Theme/Test/Unit/Model/DesignTest.php @@ -9,6 +9,7 @@ */ namespace Magento\Theme\Test\Unit\Model; +use Magento\Framework\Serialize\SerializerInterface; use Magento\Theme\Model\Design; class DesignTest extends \PHPUnit_Framework_TestCase @@ -23,11 +24,6 @@ class DesignTest extends \PHPUnit_Framework_TestCase */ protected $cacheManager; - /** - * @var \Magento\Framework\Registry|\PHPUnit_Framework_MockObject_MockObject - */ - protected $registry; - /** * @var \Magento\Framework\Stdlib\DateTime\TimezoneInterface|\PHPUnit_Framework_MockObject_MockObject */ @@ -44,18 +40,15 @@ class DesignTest extends \PHPUnit_Framework_TestCase protected $resource; /** - * @var \Magento\Framework\Data\Collection\AbstractDb|\PHPUnit_Framework_MockObject_MockObject + * @var SerializerInterface|\PHPUnit_Framework_MockObject_MockObject */ - protected $resourceCollection; + private $serializerMock; protected function setUp() { $context = $this->getMockBuilder(\Magento\Framework\Model\Context::class) ->disableOriginalConstructor() ->getMock(); - $this->registry = $this->getMockBuilder( - \Magento\Framework\Registry::class - )->disableOriginalConstructor()->getMock(); $this->localeDate = $this->getMockBuilder( \Magento\Framework\Stdlib\DateTime\TimezoneInterface::class )->getMock(); @@ -65,25 +58,24 @@ class DesignTest extends \PHPUnit_Framework_TestCase $this->resource = $this->getMockBuilder(\Magento\Theme\Model\ResourceModel\Design::class) ->disableOriginalConstructor() ->getMock(); - $this->resourceCollection = $this->getMockBuilder(\Magento\Theme\Model\ResourceModel\Design\Collection::class) - ->disableOriginalConstructor() - ->getMock(); $this->cacheManager = $this->getMockBuilder(\Magento\Framework\App\CacheInterface::class)->getMock(); $context->expects($this->any()) ->method('getCacheManager') ->willReturn($this->cacheManager); - /** - * @var $context \Magento\Framework\Model\Context - */ - $this->model = new Design( - $context, - $this->registry, - $this->localeDate, - $this->dateTime, - $this->resource, - $this->resourceCollection + $this->serializerMock = $this->getMock(SerializerInterface::class); + + $objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); + $this->model = $objectManager->getObject( + Design::class, + [ + 'context' => $context, + 'localeDate' => $this->localeDate, + 'dateTime' => $this->dateTime, + 'resource' => $this->resource, + 'serializer' => $this->serializerMock, + ] ); } @@ -119,9 +111,12 @@ class DesignTest extends \PHPUnit_Framework_TestCase ->method('loadChange') ->with($storeId, $date) ->willReturn(false); + $this->serializerMock->expects($this->once()) + ->method('serialize') + ->willReturn('serializedData'); $this->cacheManager->expects($this->once()) ->method('save') - ->with(serialize([]), $cacheId, [Design::CACHE_TAG], 86400) + ->with('serializedData', $cacheId, [Design::CACHE_TAG], 86400) ->willReturnSelf(); $this->assertInstanceOf(get_class($this->model), $this->model->loadChange($storeId)); @@ -151,9 +146,16 @@ class DesignTest extends \PHPUnit_Framework_TestCase $this->cacheManager->expects($this->once()) ->method('load') ->with($cacheId) - ->willReturn(serialize(['test' => 'data'])); - - $this->assertInstanceOf(get_class($this->model), $this->model->loadChange($storeId)); + ->willReturn('serializedData'); + $data = ['test' => 'data']; + $this->serializerMock->expects($this->once()) + ->method('unserialize') + ->with('serializedData') + ->willReturn($data); + + $change = $this->model->loadChange($storeId); + $this->assertInstanceOf(get_class($this->model), $change); + $this->assertEquals($data, $change->getData()); } /** 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/Ui/Component/Form/Element/DataType/Date.php b/app/code/Magento/Ui/Component/Form/Element/DataType/Date.php index e9c0c8d7685166001b524af995d62bf6b3c84011..fd319e97b6ab7e87c88f4c899b0c1b49e41f86ab 100644 --- a/app/code/Magento/Ui/Component/Form/Element/DataType/Date.php +++ b/app/code/Magento/Ui/Component/Form/Element/DataType/Date.php @@ -60,6 +60,7 @@ class Date extends AbstractDataType public function prepare() { $config = $this->getData('config'); + if (!isset($config['storeTimeZone'])) { $storeTimeZone = $this->localeDate->getConfigTimezone(); $config['storeTimeZone'] = $storeTimeZone; @@ -67,7 +68,7 @@ class Date extends AbstractDataType // Set date format pattern by current locale $localeDateFormat = $this->localeDate->getDateFormat(); $config['options']['dateFormat'] = $localeDateFormat; - $config['outputDateFormat'] = $localeDateFormat; + $config['options']['storeLocale'] = $this->locale; $this->setData('config', $config); parent::prepare(); } diff --git a/app/code/Magento/Ui/Component/MassAction/Filter.php b/app/code/Magento/Ui/Component/MassAction/Filter.php index c24b77198030d7ebe1889ed3586b01becf6677ad..c23466ef0844e5237e2ae577cada08dd19086390 100644 --- a/app/code/Magento/Ui/Component/MassAction/Filter.php +++ b/app/code/Magento/Ui/Component/MassAction/Filter.php @@ -11,6 +11,7 @@ use Magento\Framework\View\Element\UiComponentFactory; use Magento\Framework\App\RequestInterface; use Magento\Framework\View\Element\UiComponentInterface; use Magento\Framework\Data\Collection\AbstractDb; +use Magento\Framework\View\Element\UiComponent\DataProvider\DataProviderInterface; /** * Class Filter @@ -43,6 +44,11 @@ class Filter */ protected $filterBuilder; + /** + * @var DataProviderInterface + */ + private $dataProvider; + /** * @param UiComponentFactory $factory * @param RequestInterface $request @@ -74,23 +80,33 @@ class Filter } /** + * Adds filters to collection using DataProvider filter results + * * @param AbstractDb $collection * @return AbstractDb * @throws LocalizedException */ public function getCollection(AbstractDb $collection) { - $component = $this->getComponent(); - $this->prepareComponent($component); - $dataProvider = $component->getContext()->getDataProvider(); - $dataProvider->setLimit(0, false); - $ids = []; - foreach ($dataProvider->getSearchResult()->getItems() as $document) { - $ids[] = $document->getId(); - } + $selected = $this->request->getParam(static::SELECTED_PARAM); + $excluded = $this->request->getParam(static::EXCLUDED_PARAM); - $collection->addFieldToFilter($collection->getIdFieldName(), ['in' => $ids]); - return $this->applySelection($collection); + $isExcludedIdsValid = (is_array($excluded) && !empty($excluded)); + $isSelectedIdsValid = (is_array($selected) && !empty($selected)); + + if ('false' !== $excluded) { + if (!$isExcludedIdsValid && !$isSelectedIdsValid) { + throw new LocalizedException(__('Please select item(s).')); + } + } + $idsArray = $this->getFilterIds(); + if (!empty($idsArray)) { + $collection->addFieldToFilter( + $collection->getIdFieldName(), + ['in' => $idsArray] + ); + } + return $collection; } /** @@ -106,9 +122,7 @@ class Filter if ('false' === $excluded) { return; } - $component = $this->getComponent(); - $this->prepareComponent($component); - $dataProvider = $component->getContext()->getDataProvider(); + $dataProvider = $this->getDataProvider(); try { if (is_array($excluded) && !empty($excluded)) { $this->filterBuilder->setConditionType('nin') @@ -127,6 +141,8 @@ class Filter } /** + * Applies selection to collection from POST parameters + * * @param AbstractDb $collection * @return AbstractDb * @throws LocalizedException @@ -169,7 +185,7 @@ class Filter } /** - * Returns RefererUrl + * Returns Referrer Url * * @return string|null */ @@ -178,4 +194,33 @@ class Filter $data = $this->getComponent()->getContext()->getDataProvider()->getConfigData(); return (isset($data['referer_url'])) ? $data['referer_url'] : null; } + + /** + * Get data provider + * + * @return DataProviderInterface + */ + private function getDataProvider() + { + if (!$this->dataProvider) { + $component = $this->getComponent(); + $this->prepareComponent($component); + $this->dataProvider = $component->getContext()->getDataProvider(); + } + return $this->dataProvider; + } + + /** + * Get filter ids as array + * + * @return int[] + */ + private function getFilterIds() + { + $this->applySelectionOnTargetProvider(); + if ($this->getDataProvider()->getSearchResult()) { + return $this->getDataProvider()->getSearchResult()->getAllIds(); + } + return []; + } } diff --git a/app/code/Magento/Ui/Test/Unit/Component/Form/Element/DataType/DateTest.php b/app/code/Magento/Ui/Test/Unit/Component/Form/Element/DataType/DateTest.php index 7a9df1a7df0a42cf40e98b2c7b0f115d78d5301a..e922b1460b3e0727a841ee034cdf62d570dbc628 100644 --- a/app/code/Magento/Ui/Test/Unit/Component/Form/Element/DataType/DateTest.php +++ b/app/code/Magento/Ui/Test/Unit/Component/Form/Element/DataType/DateTest.php @@ -70,9 +70,6 @@ class DateTest extends \PHPUnit_Framework_TestCase $this->assertArrayHasKey('options', $config); $this->assertArrayHasKey('dateFormat', $config['options']); $this->assertEquals($localeDateFormat, $config['options']['dateFormat']); - - $this->assertArrayHasKey('outputDateFormat', $config); - $this->assertEquals($localeDateFormat, $config['outputDateFormat']); } public function testPrepareWithoutTimeOffset() @@ -112,8 +109,6 @@ class DateTest extends \PHPUnit_Framework_TestCase $this->assertArrayHasKey('dateFormat', $config['options']); $this->assertEquals($localeDateFormat, $config['options']['dateFormat']); - $this->assertArrayHasKey('outputDateFormat', $config); - $this->assertEquals($localeDateFormat, $config['outputDateFormat']); } /** @@ -121,6 +116,7 @@ class DateTest extends \PHPUnit_Framework_TestCase */ public function testPrepare() { + $this->localeResolverMock->expects($this->any())->method('getLocale')->willReturn('de-DE'); $this->date = $this->objectManagerHelper->getObject( Date::class, [ @@ -133,5 +129,6 @@ class DateTest extends \PHPUnit_Framework_TestCase $this->date->prepare(); $configArray = $this->date->getData('config'); $this->assertEquals('America/Chicago', $configArray['storeTimeZone']); + $this->assertEquals('de-DE', $configArray['options']['storeLocale']); } } diff --git a/app/code/Magento/Ui/Test/Unit/Component/MassAction/FilterTest.php b/app/code/Magento/Ui/Test/Unit/Component/MassAction/FilterTest.php new file mode 100644 index 0000000000000000000000000000000000000000..604febecde041df3e62aeae3cf135bb5e57e5398 --- /dev/null +++ b/app/code/Magento/Ui/Test/Unit/Component/MassAction/FilterTest.php @@ -0,0 +1,289 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Ui\Test\Unit\Component\MassAction; + +use Magento\Ui\Component\MassAction\Filter; +use Magento\Framework\Api\Filter as ApiFilter; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; +use Magento\Framework\Data\Collection\AbstractDb; +use Magento\Framework\Api\FilterBuilder; +use Magento\Framework\View\Element\UiComponentFactory; +use Magento\Framework\App\RequestInterface; +use Magento\Framework\View\Element\UiComponentInterface; +use Magento\Framework\Api\Search\SearchResultInterface; +use Magento\Framework\View\Element\UiComponent\DataProvider\DataProviderInterface; +use Magento\Framework\View\Element\UiComponent\ContextInterface; + +class FilterTest extends \PHPUnit_Framework_TestCase +{ + /** + *\PHPUnit_Framework_MockObject_MockObject + */ + private $requestMock; + + /** + * \PHPUnit_Framework_MockObject_MockObject + */ + private $uiComponentFactoryMock; + + /** + * \PHPUnit_Framework_MockObject_MockObject + */ + private $filterBuilderMock; + + /** @var \Magento\Ui\Component\MassAction\Filter */ + private $filter; + + /** + * @var \Magento\Framework\TestFramework\Unit\Helper\ObjectManager + */ + private $objectManager; + + /** + *\PHPUnit_Framework_MockObject_MockObject + */ + private $dataProviderMock; + + /** + *\PHPUnit_Framework_MockObject_MockObject + */ + private $abstractDbMock; + + /** + * \PHPUnit_Framework_MockObject_MockObject + */ + private $searchResultMock; + + /** + * \PHPUnit_Framework_MockObject_MockObject + */ + private $uiComponentMock; + + /** + * Set up + */ + protected function setUp() + { + $this->objectManager = new ObjectManager($this); + $this->uiComponentFactoryMock = $this->getMock(UiComponentFactory::class, [], [], '', false); + $this->filterBuilderMock = $this->getMock(FilterBuilder::class, [], [], '', false); + $this->requestMock = $this->getMock(RequestInterface::class); + $this->dataProviderMock = $this->getMock(DataProviderInterface::class); + $this->uiComponentMock = $this->getMock(UiComponentInterface::class); + $this->abstractDbMock = $this->getMock(AbstractDb::class, [], [], '', false); + $contextMock = $this->getMock(ContextInterface::class); + $this->searchResultMock = $this->getMock(SearchResultInterface::class); + $uiComponentMockTwo = $this->getMock(UiComponentInterface::class); + $this->filter = $this->objectManager->getObject( + Filter::class, + [ + 'factory' => $this->uiComponentFactoryMock, + 'request' => $this->requestMock, + 'filterBuilder' => $this->filterBuilderMock + ] + ); + $this->uiComponentFactoryMock->expects($this->any()) + ->method('create') + ->willReturn($this->uiComponentMock); + $this->uiComponentMock->expects($this->any()) + ->method('getChildComponents') + ->willReturn([$uiComponentMockTwo]); + $uiComponentMockTwo->expects($this->any()) + ->method('getChildComponents') + ->willReturn([]); + $this->uiComponentMock->expects($this->any()) + ->method('getContext') + ->willReturn($contextMock); + $contextMock->expects($this->any()) + ->method('getDataProvider') + ->willReturn($this->dataProviderMock); + $this->dataProviderMock->expects($this->any()) + ->method('setLimit'); + $this->dataProviderMock->expects($this->any()) + ->method('searchResultMock') + ->willReturn($this->searchResultMock); + $this->searchResultMock->expects($this->any()) + ->method('getAllIds') + ->willReturn([]); + } + + /** + * Run test for applySelectionOnTargetProvider method + * + * @param int[]|bool $selectedIds + * @param int[]|bool $excludedIds + * @param int $filterExpected + * @param string $conditionExpected + * @dataProvider applySelectionOnTargetProviderDataProvider + */ + public function testApplySelectionOnTargetProvider($selectedIds, $excludedIds, $filterExpected, $conditionExpected) + { + $this->setUpApplySelection($selectedIds, $excludedIds, $filterExpected, $conditionExpected); + $this->filter->applySelectionOnTargetProvider(); + } + + /** + * Data provider for testApplySelectionOnTargetProvider + */ + public function applySelectionOnTargetProviderDataProvider() + { + return [ + [[1, 2, 3], 'false' , 0, 'in'], + [[1, 2, 3], [1, 2, 3] , 1, 'nin'], + ['false', [1, 2, 3] , 1, 'nin'], + ['false', 'false' , 0, ''] + ]; + } + + /** + * @throws \Exception + * @expectedException \Magento\Framework\Exception\LocalizedException + */ + public function testApplySelectionOnTargetProviderException() + { + $filterMock = $this->getMock(ApiFilter::class, [], [], '', false); + $this->filterBuilderMock->expects($this->any()) + ->method('setConditionType') + ->willReturn($this->filterBuilderMock); + $this->filterBuilderMock->expects($this->any()) + ->method('create') + ->willReturn($filterMock); + $this->filterBuilderMock->expects($this->any()) + ->method('setField') + ->willReturn($this->filterBuilderMock); + $this->requestMock->expects($this->at(0)) + ->method('getParam') + ->with(Filter::SELECTED_PARAM) + ->willReturn([1]); + $this->requestMock->expects($this->at(1)) + ->method('getParam') + ->with(Filter::EXCLUDED_PARAM) + ->willReturn([]); + $this->dataProviderMock->expects($this->any()) + ->method('addFilter') + ->with($filterMock) + ->willThrowException(new \Exception('exception')); + $this->filter->applySelectionOnTargetProvider(); + } + + /** + * Run test for getCollection method + * + * @param int[]|bool $selectedIds + * @param int[]|bool $excludedIds + * @param int $filterExpected + * @param string $conditionExpected + * @dataProvider applySelectionOnTargetProviderDataProvider + */ + public function testGetCollection($selectedIds, $excludedIds, $filterExpected, $conditionExpected) + { + $this->setUpApplySelection($selectedIds, $excludedIds, $filterExpected, $conditionExpected); + $this->requestMock->expects($this->at(4)) + ->method('getParam') + ->with('namespace') + ->willReturn(''); + $this->requestMock->expects($this->at(2)) + ->method('getParam') + ->with(Filter::SELECTED_PARAM) + ->willReturn($selectedIds); + $this->requestMock->expects($this->at(3)) + ->method('getParam') + ->with(Filter::EXCLUDED_PARAM) + ->willReturn($excludedIds); + $this->assertEquals($this->abstractDbMock, $this->filter->getCollection($this->abstractDbMock)); + } + + /** + * This tests the method prepareComponent() + */ + public function testPrepareComponent() + { + $this->filter->prepareComponent($this->uiComponentMock); + } + + /** + * This tests the method getComponent() + */ + public function testGetComponent() + { + $this->requestMock->expects($this->at(0)) + ->method('getParam') + ->with('namespace') + ->willReturn(''); + $this->assertEquals($this->uiComponentMock, $this->filter->getComponent()); + } + + /** + * This tests the method getComponentRefererUrl() + */ + public function testGetComponentRefererUrlIsNotNull() + { + $returnArray = [ + 'referer_url' => 'referer_url' + ]; + $this->dataProviderMock->expects($this->once()) + ->method('getConfigData') + ->willReturn($returnArray); + $this->assertEquals('referer_url', $this->filter->getComponentRefererUrl()); + } + + /** + * This tests the method getComponentRefererUrl() + */ + public function testGetComponentRefererUrlIsNull() + { + $this->assertNull($this->filter->getComponentRefererUrl()); + } + + /** + * Apply mocks for current parameters from datasource + * + * @param int[]|bool $selectedIds + * @param int[]|bool $excludedIds + * @param int $filterExpected + * @param string $conditionExpected + */ + private function setUpApplySelection($selectedIds, $excludedIds, $filterExpected, $conditionExpected) + { + $filterMock = $this->getMock(ApiFilter::class, [], [], '', false); + $this->requestMock->expects($this->at(0)) + ->method('getParam') + ->with(Filter::SELECTED_PARAM) + ->willReturn($selectedIds); + $this->requestMock->expects($this->at(1)) + ->method('getParam') + ->with(Filter::EXCLUDED_PARAM) + ->willReturn($excludedIds); + $this->dataProviderMock->expects($this->exactly($filterExpected)) + ->method('addFilter') + ->with($filterMock); + $this->filterBuilderMock->expects($this->exactly($filterExpected)) + ->method('setConditionType') + ->with($conditionExpected) + ->willReturnSelf(); + $this->filterBuilderMock->expects($this->any()) + ->method('setField') + ->willReturnSelf(); + $this->filterBuilderMock->expects($this->any()) + ->method('value') + ->willReturnSelf(); + $this->filterBuilderMock->expects($this->any()) + ->method('create') + ->willReturn($filterMock); + $this->filterBuilderMock->expects($this->any()) + ->method('setConditionType') + ->willReturnSelf(); + $this->filterBuilderMock->expects($this->any()) + ->method('setField') + ->willReturnSelf(); + $this->filterBuilderMock->expects($this->any()) + ->method('value') + ->willReturnSelf(); + $this->filterBuilderMock->expects($this->any()) + ->method('create') + ->willReturn($filterMock); + } +} diff --git a/app/code/Magento/Ui/view/base/web/js/form/element/country.js b/app/code/Magento/Ui/view/base/web/js/form/element/country.js index c72d02c595bb8d8d4185f8bc9969cfa3a3bc5940..cd611a04a1569d45f7edb0668f0fee75833e396d 100644 --- a/app/code/Magento/Ui/view/base/web/js/form/element/country.js +++ b/app/code/Magento/Ui/view/base/web/js/form/element/country.js @@ -42,6 +42,7 @@ define([ }); this.setOptions(result); + this.reset(); } }); }); diff --git a/app/code/Magento/Ui/view/base/web/js/form/element/date.js b/app/code/Magento/Ui/view/base/web/js/form/element/date.js index fde7faa72ed7c9307e0b2781b7301d421efe2fc0..202cfe93069b02bad6ff888a51b9661a54109e54 100644 --- a/app/code/Magento/Ui/view/base/web/js/form/element/date.js +++ b/app/code/Magento/Ui/view/base/web/js/form/element/date.js @@ -1,5 +1,5 @@ /** - * Copyright © 2015 Magento. All rights reserved. + * Copyright © 2016 Magento. All rights reserved. * See COPYING.txt for license details. */ define([ @@ -53,6 +53,12 @@ define([ pickerDefaultDateFormat: 'MM/dd/y', // ICU Date Format pickerDefaultTimeFormat: 'h:mm a', // ICU Time Format + /** + * Moment compatible format used for moment conversion + * of date from datePicker + */ + momentFormat: 'MM/DD/YYYY', + elementTmpl: 'ui/form/element/date', listens: { @@ -142,7 +148,7 @@ define([ formattedValue = moment(shiftedValue).format('YYYY-MM-DD HH:mm'); value = moment.tz(formattedValue, this.storeTimeZone).tz('UTC').toISOString(); } else { - value = moment(shiftedValue, this.pickerDateTimeFormat); + value = moment(shiftedValue, this.momentFormat); value = value.format(this.outputDateFormat); } } else { @@ -160,19 +166,21 @@ define([ */ prepareDateTimeFormats: function () { this.pickerDateTimeFormat = this.options.dateFormat; + this.momentFormat = this.options.dateFormat ? + utils.convertToMomentFormat(this.options.dateFormat) : this.momentFormat; if (this.options.showsTime) { this.pickerDateTimeFormat += ' ' + this.options.timeFormat; } - this.pickerDateTimeFormat = utils.normalizeDate(this.pickerDateTimeFormat); + this.pickerDateTimeFormat = utils.convertToMomentFormat(this.pickerDateTimeFormat); if (this.dateFormat) { this.inputDateFormat = this.dateFormat; } - this.inputDateFormat = utils.normalizeDate(this.inputDateFormat); - this.outputDateFormat = utils.normalizeDate(this.outputDateFormat); + this.inputDateFormat = utils.convertToMomentFormat(this.inputDateFormat); + this.outputDateFormat = utils.convertToMomentFormat(this.outputDateFormat); this.validationParams.dateFormat = this.outputDateFormat; } diff --git a/app/code/Magento/Ui/view/base/web/js/form/element/file-uploader.js b/app/code/Magento/Ui/view/base/web/js/form/element/file-uploader.js index 32ebd40f75346afb4d2d06cd6f9c4db16950fd4a..a695102bfdfa69e68bf664847c3cb31f4d563cb5 100644 --- a/app/code/Magento/Ui/view/base/web/js/form/element/file-uploader.js +++ b/app/code/Magento/Ui/view/base/web/js/form/element/file-uploader.js @@ -18,6 +18,7 @@ define([ value: [], maxFileSize: false, isMultipleFiles: false, + placeholderType: 'document', // 'image', 'video' allowedExtensions: false, previewTmpl: 'ui/form/element/uploader/preview', dropZone: '[data-role=drop-zone]', @@ -158,6 +159,8 @@ define([ * @returns {Object} Modified file object. */ processFile: function (file) { + file.previewType = this.getFilePreviewType(file); + this.observe.call(file, true, [ 'previewWidth', 'previewHeight' @@ -235,6 +238,24 @@ define([ return validator('validate-file-type', file.name, this.allowedExtensions); }, + /** + * Get simplified file type. + * + * @param {Object} file - File to be checked. + * @returns {String} + */ + getFilePreviewType: function (file) { + var type; + + if (!file.type) { + return 'document'; + } + + type = file.type.split('/')[0]; + + return type !== 'image' && type !== 'video' ? 'document' : type; + }, + /** * Checks if size of provided file exceeds * defined in configuration size limits. diff --git a/app/code/Magento/Ui/view/base/web/js/form/element/select.js b/app/code/Magento/Ui/view/base/web/js/form/element/select.js index 1887639c8d0313fe466aadb89b3cdaf7adc6bd81..4567bba1d017aec81e53dc668b35b4bf696c49d3 100644 --- a/app/code/Magento/Ui/view/base/web/js/form/element/select.js +++ b/app/code/Magento/Ui/view/base/web/js/form/element/select.js @@ -105,7 +105,9 @@ define([ return Abstract.extend({ defaults: { customName: '${ $.parentName }.${ $.index }_input', - elementTmpl: 'ui/form/element/select' + elementTmpl: 'ui/form/element/select', + caption: '', + options: [] }, /** @@ -127,28 +129,6 @@ define([ return this; }, - /** - * Parses options and merges the result with instance - * - * @param {Object} config - * @returns {Object} Chainable. - */ - initConfig: function (config) { - var options = config.options, - captionValue = config.captionValue || '', - result = parseOptions(options, captionValue); - - if (config.caption) { - delete result.caption; - } - - _.extend(config, result); - - this._super(); - - return this; - }, - /** * Calls 'initObservable' of parent, initializes 'options' and 'initialOptions' * properties, calls 'setOptions' passing options to it @@ -160,7 +140,7 @@ define([ this.initialOptions = this.options; - this.observe('options') + this.observe('options caption') .setOptions(this.options()); return this; @@ -209,7 +189,7 @@ define([ return option && option.value; } - if (!this.caption) { + if (!this.caption()) { return findFirst(this.options); } }, @@ -254,14 +234,20 @@ define([ * @returns {Object} Chainable */ setOptions: function (data) { - var isVisible; + var captionValue = this.captionValue || '', + result = parseOptions(data, captionValue), + isVisible; + + this.indexedOptions = indexOptions(result.options); - this.indexedOptions = indexOptions(data); + this.options(result.options); - this.options(data); + if (!this.caption()) { + this.caption(result.caption); + } if (this.customEntry) { - isVisible = !!data.length; + isVisible = !!result.options.length; this.setVisible(isVisible); this.toggleInput(!isVisible); @@ -301,7 +287,7 @@ define([ * @returns {Object} Chainable. */ clear: function () { - var value = this.caption ? '' : findFirst(this.options); + var value = this.caption() ? '' : findFirst(this.options); this.value(value); diff --git a/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/datepicker.js b/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/datepicker.js index 77d3a069ccef76bbcacad28459820b3359b025e7..4f52aa431632c11115864b22bdc819b9385b20a3 100644 --- a/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/datepicker.js +++ b/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/datepicker.js @@ -53,7 +53,7 @@ define([ 'setDate', moment( observable(), - utils.normalizeDate( + utils.convertToMomentFormat( options.dateFormat + (options.showsTime ? ' ' + options.timeFormat : '') ) ).toDate() diff --git a/app/code/Magento/Ui/view/base/web/templates/form/element/uploader/preview.html b/app/code/Magento/Ui/view/base/web/templates/form/element/uploader/preview.html index 91c2eb1bcd0dce2c7aba7e195a2364015f2470c9..45493b83d8f58222dd39a683a6db0effaa7d2464 100644 --- a/app/code/Magento/Ui/view/base/web/templates/form/element/uploader/preview.html +++ b/app/code/Magento/Ui/view/base/web/templates/form/element/uploader/preview.html @@ -6,9 +6,11 @@ --> <div class="file-uploader-summary"> <div class="file-uploader-preview"> - <a attr="href: $parent.getFilePreview($file)" target="_blank"> + <a class="preview-link" + css="'preview-' + $file.previewType" + attr="href: $parent.getFilePreview($file), title: $file.name" target="_blank"> <img - class="preview-image" + if="$file.previewType === 'image'" tabindex="0" event="load: $parent.onPreviewLoad.bind($parent)" attr=" @@ -29,8 +31,11 @@ </div> <div class="file-uploader-filename" text="$file.name"/> + <div class="file-uploader-meta"> - <text args="$file.previewWidth"/>x<text args="$file.previewHeight"/>, + <span if="$file.previewType === 'image'"> + <text args="$file.previewWidth"/>x<text args="$file.previewHeight"/>, + </span> <text args="$parent.formatSize($file.size)"/> </div> </div> diff --git a/app/code/Magento/Ui/view/base/web/templates/form/element/uploader/uploader.html b/app/code/Magento/Ui/view/base/web/templates/form/element/uploader/uploader.html index ab309026c9ffeb3a8e56816c19994b33d34d4116..f0f80efdb16d61745aa3624519c371634eba6130 100644 --- a/app/code/Magento/Ui/view/base/web/templates/form/element/uploader/uploader.html +++ b/app/code/Magento/Ui/view/base/web/templates/form/element/uploader/uploader.html @@ -4,6 +4,7 @@ * See COPYING.txt for license details. */ --> + <div class="admin__field" visible="visible" css="$data.additionalClasses"> <label class="admin__field-label" if="$data.label" attr="for: uid"> <span translate="label" attr="'data-config-scope': $data.scopeLabel"/> @@ -28,6 +29,15 @@ <label class="admin__field-error" if="error" attr="for: uid" text="error"/> <each args="data: value, as: '$file'" render="$parent.getPreviewTmpl($file)"/> + + <div if="isMultipleFiles" class="file-uploader-summary"> + <label attr="for: uid" + class="file-uploader-placeholder" + css="'placeholder-' + placeholderType"> + <span class="file-uploader-placeholder-text" + translate="'Click here or drag and drop to add files.'"/> + </label> + </div> </div> <render args="$data.service.template" if="$data.hasService()"/> </div> diff --git a/app/code/Magento/Ups/composer.json b/app/code/Magento/Ups/composer.json index c20dd28ba88876a70c04ea49038b94f82d3d9b06..e3cf2bce1813a0d6625f0b5dce2ac4cf0d8b5640 100644 --- a/app/code/Magento/Ups/composer.json +++ b/app/code/Magento/Ups/composer.json @@ -12,6 +12,9 @@ "magento/module-quote": "100.2.*", "magento/framework": "100.2.*" }, + "suggest": { + "magento/module-config": "100.2.*" + }, "type": "magento2-module", "version": "100.2.0-dev", "license": [ diff --git a/app/code/Magento/Ups/etc/di.xml b/app/code/Magento/Ups/etc/di.xml new file mode 100644 index 0000000000000000000000000000000000000000..324349a82994fdadec4d4db33cdb66f28029b137 --- /dev/null +++ b/app/code/Magento/Ups/etc/di.xml @@ -0,0 +1,21 @@ +<?xml version="1.0"?> +<!-- +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd"> + <type name="Magento\Config\Model\Config\Export\ExcludeList"> + <arguments> + <argument name="configs" xsi:type="array"> + <item name="carriers/ups/username" xsi:type="string">1</item> + <item name="carriers/ups/password" xsi:type="string">1</item> + <item name="carriers/ups/access_license_number" xsi:type="string">1</item> + <item name="carriers/ups/tracking_xml_url" xsi:type="string">1</item> + <item name="carriers/ups/gateway_xml_url" xsi:type="string">1</item> + <item name="carriers/ups/shipper_number" xsi:type="string">1</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/code/Magento/Usps/Model/Carrier.php b/app/code/Magento/Usps/Model/Carrier.php index b2345a86bff4d6349035950373d1e7975076f513..d79d7747de8af69192f16f530a600cfe12dab355 100644 --- a/app/code/Magento/Usps/Model/Carrier.php +++ b/app/code/Magento/Usps/Model/Carrier.php @@ -1901,27 +1901,30 @@ class Carrier extends AbstractCarrierOnline implements \Magento\Shipping\Model\C $response = $client->request()->getBody(); $response = $this->parseXml($response); - if ($response === false || $response->getName() == 'Error') { - $debugData['result'] = [ - 'error' => $response->Description, - 'code' => $response->Number, - 'xml' => $response->asXML(), - ]; - $this->_debug($debugData); - $result->setErrors($debugData['result']['error']); - } else { - if ($recipientUSCountry && $service == 'Priority Express') { - $labelContent = base64_decode((string)$response->EMLabel); - $trackingNumber = (string)$response->EMConfirmationNumber; - } elseif ($recipientUSCountry) { - $labelContent = base64_decode((string)$response->SignatureConfirmationLabel); - $trackingNumber = (string)$response->SignatureConfirmationNumber; + + if($response !== false) { + if ($response->getName() == 'Error') { + $debugData['result'] = [ + 'error' => $response->Description, + 'code' => $response->Number, + 'xml' => $response->asXML(), + ]; + $this->_debug($debugData); + $result->setErrors($debugData['result']['error']); } else { - $labelContent = base64_decode((string)$response->LabelImage); - $trackingNumber = (string)$response->BarcodeNumber; + if ($recipientUSCountry && $service == 'Priority Express') { + $labelContent = base64_decode((string)$response->EMLabel); + $trackingNumber = (string)$response->EMConfirmationNumber; + } elseif ($recipientUSCountry) { + $labelContent = base64_decode((string)$response->SignatureConfirmationLabel); + $trackingNumber = (string)$response->SignatureConfirmationNumber; + } else { + $labelContent = base64_decode((string)$response->LabelImage); + $trackingNumber = (string)$response->BarcodeNumber; + } + $result->setShippingLabelContent($labelContent); + $result->setTrackingNumber($trackingNumber); } - $result->setShippingLabelContent($labelContent); - $result->setTrackingNumber($trackingNumber); } $result->setGatewayResponse($response); diff --git a/app/code/Magento/Usps/etc/di.xml b/app/code/Magento/Usps/etc/di.xml new file mode 100644 index 0000000000000000000000000000000000000000..450a24ad8b9f734ec85d1640ea1df8bf75e12225 --- /dev/null +++ b/app/code/Magento/Usps/etc/di.xml @@ -0,0 +1,19 @@ +<?xml version="1.0"?> +<!-- +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd"> + <type name="Magento\Config\Model\Config\Export\ExcludeList"> + <arguments> + <argument name="configs" xsi:type="array"> + <item name="carriers/usps/userid" xsi:type="string">1</item> + <item name="carriers/usps/password" xsi:type="string">1</item> + <item name="carriers/usps/gateway_url" xsi:type="string">1</item> + <item name="carriers/usps/gateway_secure_url" xsi:type="string">1</item> + </argument> + </arguments> + </type> +</config> diff --git a/app/code/Magento/Vault/Plugin/PaymentVaultConfigurationProcess.php b/app/code/Magento/Vault/Plugin/PaymentVaultConfigurationProcess.php new file mode 100644 index 0000000000000000000000000000000000000000..db38ccbed417a95870a9da916a64e36b4281353d --- /dev/null +++ b/app/code/Magento/Vault/Plugin/PaymentVaultConfigurationProcess.php @@ -0,0 +1,93 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Vault\Plugin; + +/** + * Class PaymentVaultConfigurationProcess + * + * Checks if vault group have active vaults. + */ +class PaymentVaultConfigurationProcess +{ + /** + * @var \Magento\Vault\Api\PaymentMethodListInterface + */ + private $vaultPaymentList; + + /** + * @var \Magento\Vault\Api\PaymentMethodListInterface + */ + private $paymentMethodList; + + /** + * @var \Magento\Store\Model\StoreManagerInterface + */ + private $storeManager; + + /** + * @param \Magento\Vault\Api\PaymentMethodListInterface $vaultPaymentList + * @param \Magento\Payment\Api\PaymentMethodListInterface $paymentMethodList + * @param \Magento\Store\Model\StoreManagerInterface $storeManager + */ + public function __construct( + \Magento\Vault\Api\PaymentMethodListInterface $vaultPaymentList, + \Magento\Payment\Api\PaymentMethodListInterface $paymentMethodList, + \Magento\Store\Model\StoreManagerInterface $storeManager + ) { + $this->vaultPaymentList = $vaultPaymentList; + $this->paymentMethodList = $paymentMethodList; + $this->storeManager = $storeManager; + } + + /** + * Checkout LayoutProcessor before process plugin. + * + * @param \Magento\Checkout\Block\Checkout\LayoutProcessor $processor + * @param array $jsLayout + * @return array + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + */ + public function beforeProcess(\Magento\Checkout\Block\Checkout\LayoutProcessor $processor, $jsLayout) + { + $configuration = &$jsLayout['components']['checkout']['children']['steps']['children']['billing-step'] + ['children']['payment']['children']['renders']['children']; + + if (!isset($configuration)) { + return [$jsLayout]; + } + + $storeId = $this->storeManager->getStore()->getId(); + $activePaymentMethodList = $this->paymentMethodList->getActiveList($storeId); + $activeVaultList = $this->vaultPaymentList->getActiveList($storeId); + $getCodeFunc = function ($method) { + return $method->getCode(); + }; + $getProviderCodeFunc = function ($method) { + return $method->getProviderCode(); + }; + $activePaymentMethodCodes = array_map($getCodeFunc, $activePaymentMethodList); + $activeVaultProviderCodes = array_map($getProviderCodeFunc, $activeVaultList); + $activePaymentMethodCodes = array_merge( + $activePaymentMethodCodes, + $activeVaultProviderCodes + ); + + foreach ($configuration as $paymentGroup => $groupConfig) { + $notActivePaymentMethodCodes = array_diff(array_keys($groupConfig['methods']), $activePaymentMethodCodes); + foreach ($notActivePaymentMethodCodes as $notActivePaymentMethodCode) { + unset($configuration[$paymentGroup]['methods'][$notActivePaymentMethodCode]); + } + if ($paymentGroup === 'vault' && !empty($activeVaultProviderCodes)) { + continue; + } + if (empty($configuration[$paymentGroup]['methods'])) { + unset($configuration[$paymentGroup]); + } + } + + return [$jsLayout]; + } +} diff --git a/app/code/Magento/Vault/Setup/UpgradeData.php b/app/code/Magento/Vault/Setup/UpgradeData.php index 757b5f4d3167cb00254e8f2ef20fad3addc1cb27..1c3f113ba9831de6123cbf0c0af361a0f520a1fb 100644 --- a/app/code/Magento/Vault/Setup/UpgradeData.php +++ b/app/code/Magento/Vault/Setup/UpgradeData.php @@ -20,9 +20,11 @@ use Magento\Vault\Model\CreditCardTokenFactory; class UpgradeData implements UpgradeDataInterface { /** - * @var AdapterInterface + * Predefined name for sales connection + * + * @var string */ - private $connection; + private static $salesConnectionName = 'sales'; /** * @inheritdoc @@ -30,12 +32,11 @@ class UpgradeData implements UpgradeDataInterface public function upgrade(ModuleDataSetupInterface $setup, ModuleContextInterface $context) { $setup->startSetup(); - $connection = $this->getConnection(); // data update for Vault module < 2.0.1 if (version_compare($context->getVersion(), '2.0.1', '<')) { // update sets credit card as default token type - $connection->update($setup->getTable(InstallSchema::PAYMENT_TOKEN_TABLE), [ + $setup->getConnection()->update($setup->getTable(InstallSchema::PAYMENT_TOKEN_TABLE), [ PaymentTokenInterface::TYPE => CreditCardTokenFactory::TOKEN_TYPE_CREDIT_CARD ], PaymentTokenInterface::TYPE . ' = ""'); } @@ -43,12 +44,13 @@ class UpgradeData implements UpgradeDataInterface // data update for Vault module < 2.0.2 if (version_compare($context->getVersion(), '2.0.2', '<')) { // update converts additional info with token metadata to single dimensional array - $select = $connection->select() + $salesConnection = $setup->getConnection(self::$salesConnectionName); + $select = $salesConnection->select() ->from($setup->getTable('sales_order_payment'), 'entity_id') ->columns(['additional_information']) ->where('additional_information LIKE ?', '%token_metadata%'); - $items = $connection->fetchAll($select); + $items = $salesConnection->fetchAll($select); foreach ($items as $item) { $additionalInfo = unserialize($item['additional_information']); $additionalInfo[PaymentTokenInterface::CUSTOMER_ID] = @@ -57,7 +59,7 @@ class UpgradeData implements UpgradeDataInterface $additionalInfo['token_metadata'][PaymentTokenInterface::PUBLIC_HASH]; unset($additionalInfo['token_metadata']); - $connection->update( + $salesConnection->update( $setup->getTable('sales_order_payment'), ['additional_information' => serialize($additionalInfo)], ['entity_id = ?' => $item['entity_id']] @@ -67,23 +69,4 @@ class UpgradeData implements UpgradeDataInterface $setup->endSetup(); } - - /** - * Tries to get connection for scalable sales DB, otherwise returns default connection - * @return AdapterInterface - */ - private function getConnection() - { - if ($this->connection === null) { - /** @var ResourceConnection $conn */ - $conn = ObjectManager::getInstance()->get(ResourceConnection::class); - try { - $this->connection = $conn->getConnectionByName('sales'); - } catch (\DomainException $e) { - $this->connection = $conn->getConnection(); - } - } - - return $this->connection; - } } diff --git a/app/code/Magento/Vault/Test/Unit/Plugin/PaymentVaultConfigurationProcessTest.php b/app/code/Magento/Vault/Test/Unit/Plugin/PaymentVaultConfigurationProcessTest.php new file mode 100644 index 0000000000000000000000000000000000000000..7e7a3fd0aebdfcd8054a7276dcce04ec5f49dcb8 --- /dev/null +++ b/app/code/Magento/Vault/Test/Unit/Plugin/PaymentVaultConfigurationProcessTest.php @@ -0,0 +1,158 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Vault\Test\Unit\Plugin; + +/** + * Class PaymentVaultConfigurationProcessTest. + */ +class PaymentVaultConfigurationProcessTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var \Magento\Store\Model\StoreManagerInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $storeManager; + + /** + * @var \Magento\Store\Api\Data\StoreInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $store; + + /** + * @var \Magento\Vault\Api\PaymentMethodListInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $vaultList; + + /** + * @var \Magento\Payment\Api\PaymentMethodListInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $paymentMethodList; + + /** + * @var \Magento\Checkout\Block\Checkout\LayoutProcessor|\PHPUnit_Framework_MockObject_MockObject + */ + private $layoutProcessor; + + /** + * @var \Magento\Vault\Plugin\PaymentVaultConfigurationProcess + */ + private $plugin; + + /** + * Set up + */ + protected function setUp() + { + $this->storeManager = $this + ->getMockBuilder(\Magento\Store\Model\StoreManagerInterface::class) + ->disableOriginalConstructor() + ->setMethods(['getStore']) + ->getMockForAbstractClass(); + $this->store = $this + ->getMockBuilder(\Magento\Store\Api\Data\StoreInterface::class) + ->disableOriginalConstructor() + ->setMethods(['getId']) + ->getMockForAbstractClass(); + $this->vaultList = $this + ->getMockBuilder(\Magento\Vault\Api\PaymentMethodListInterface::class) + ->disableOriginalConstructor() + ->setMethods(['getActiveList']) + ->getMockForAbstractClass(); + $this->paymentMethodList = $this + ->getMockBuilder(\Magento\Payment\Api\PaymentMethodListInterface::class) + ->disableOriginalConstructor() + ->setMethods(['getActiveList']) + ->getMockForAbstractClass(); + $this->layoutProcessor = $this + ->getMockBuilder(\Magento\Checkout\Block\Checkout\LayoutProcessor::class) + ->disableOriginalConstructor() + ->setMethods(['process']) + ->getMockForAbstractClass(); + + $objectManagerHelper = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); + $this->plugin = $objectManagerHelper->getObject( + \Magento\Vault\Plugin\PaymentVaultConfigurationProcess::class, + [ + 'vaultPaymentList' => $this->vaultList, + 'paymentMethodList' => $this->paymentMethodList, + 'storeManager' => $this->storeManager + ] + ); + } + + /** + * @param array $jsLayout + * @param array $activeVaultList + * @param array $activePaymentList + * @param array $expectedResult + * @dataProvider beforeProcessDataProvider + */ + public function testBeforeProcess($jsLayout, $activeVaultList, $activePaymentList, $expectedResult) + { + $this->store->expects($this->once())->method('getId')->willReturn(1); + $this->storeManager->expects($this->once())->method('getStore')->willReturn($this->store); + $this->vaultList->expects($this->once())->method('getActiveList')->with(1)->willReturn($activeVaultList); + $this->paymentMethodList->expects($this->once()) + ->method('getActiveList') + ->with(1) + ->willReturn($activePaymentList); + $result = $this->plugin->beforeProcess($this->layoutProcessor, $jsLayout); + $this->assertEquals($result[0], $expectedResult); + } + + /** + * Data provider for BeforeProcess. + * + * @return array + */ + public function beforeProcessDataProvider() + { + $jsLayout['components']['checkout']['children']['steps']['children']['billing-step'] + ['children']['payment']['children']['renders']['children'] = [ + 'vault' => [ + 'methods' => [] + ], + 'braintree' => [ + 'methods' => [ + 'braintree_paypal' => [], + 'braintree' => [] + ] + ], + 'paypal-payments' => [ + 'methods' => [ + 'payflowpro' => [], + 'payflow_link' => [] + ] + ] + ]; + $result1['components']['checkout']['children']['steps']['children']['billing-step'] + ['children']['payment']['children']['renders']['children'] = []; + $result2['components']['checkout']['children']['steps']['children']['billing-step'] + ['children']['payment']['children']['renders']['children'] = [ + 'vault' => [ + 'methods' => [] + ], + 'braintree' => [ + 'methods' => [ + 'braintree_paypal' => [] + ] + ] + ]; + + $vaultPaymentMethod = $this + ->getMockBuilder(\Magento\Vault\Api\PaymentMethodListInterface::class) + ->disableOriginalConstructor() + ->setMethods(['getCode', 'getProviderCode']) + ->getMockForAbstractClass(); + + $vaultPaymentMethod->expects($this->any())->method('getCode')->willReturn('braintree_paypal_vault'); + $vaultPaymentMethod->expects($this->any())->method('getProviderCode')->willReturn('braintree_paypal'); + + return [ + [$jsLayout, [], [], $result1], + [$jsLayout, [$vaultPaymentMethod], [$vaultPaymentMethod], $result2] + ]; + } +} diff --git a/app/code/Magento/Vault/etc/frontend/di.xml b/app/code/Magento/Vault/etc/frontend/di.xml index d7f699faff53c6e48c6d3d854b265ded269e4dcc..0af0e4cd32217f952d3c49fc7424e99bc8a1ffe0 100644 --- a/app/code/Magento/Vault/etc/frontend/di.xml +++ b/app/code/Magento/Vault/etc/frontend/di.xml @@ -19,4 +19,8 @@ <argument name="session" xsi:type="object">Magento\Customer\Model\Session</argument> </arguments> </type> + <type name="Magento\Checkout\Block\Checkout\LayoutProcessor"> + <plugin name="ProcessPaymentVaultConfiguration" type="Magento\Vault\Plugin\PaymentVaultConfigurationProcess"/> + <plugin name="ProcessPaymentConfiguration" disabled="true"/> + </type> </config> diff --git a/app/code/Magento/Vault/view/adminhtml/web/js/vault.js b/app/code/Magento/Vault/view/adminhtml/web/js/vault.js index 560e65c007f8ab22c2b5b1e76bac0c9062e2af78..66c17801ec02edb262434bc807988bed1bece940 100644 --- a/app/code/Magento/Vault/view/adminhtml/web/js/vault.js +++ b/app/code/Magento/Vault/view/adminhtml/web/js/vault.js @@ -33,8 +33,8 @@ define([ .observe(['active']); // re-init payment method events - self.$selector.off('changePaymentMethod.' + this.code) - .on('changePaymentMethod.' + this.code, this.changePaymentMethod.bind(this)); + self.$selector.off('changePaymentMethod.' + this.getCode()) + .on('changePaymentMethod.' + this.getCode(), this.changePaymentMethod.bind(this)); if (this.active()) { $('#' + this.fieldset + ' input:radio:first').trigger('click'); @@ -50,7 +50,7 @@ define([ * @returns {exports.changePaymentMethod} */ changePaymentMethod: function (event, method) { - this.active(method === this.code); + this.active(method === this.getCode()); return this; }, @@ -61,13 +61,21 @@ define([ */ onActiveChange: function (isActive) { if (!isActive) { - this.$selector.trigger('setVaultNotActive'); + this.$selector.trigger('setVaultNotActive.' + this.getCode()); return; } $('#' + this.fieldset + ' input:radio:first').trigger('click'); - window.order.addExcludedPaymentMethod(this.code); + window.order.addExcludedPaymentMethod(this.getCode()); + }, + + /** + * Get payment method code + * @returns {String} + */ + getCode: function () { + return this.code; } }); }); diff --git a/app/code/Magento/Webapi/Test/Unit/Model/DataObjectProcessorTest.php b/app/code/Magento/Webapi/Test/Unit/Model/DataObjectProcessorTest.php index 4ab16098163328f1b49abe6b478b3fb06ae51adb..0565832932a3fcd9bcfacf491759a27370bbc1dd 100644 --- a/app/code/Magento/Webapi/Test/Unit/Model/DataObjectProcessorTest.php +++ b/app/code/Magento/Webapi/Test/Unit/Model/DataObjectProcessorTest.php @@ -6,6 +6,8 @@ namespace Magento\Webapi\Test\Unit\Model; +use Magento\Framework\Serialize\SerializerInterface; +use Magento\Framework\Reflection\DataObjectProcessor; use Magento\Webapi\Model\Config as ModelConfig; class DataObjectProcessorTest extends \PHPUnit_Framework_TestCase @@ -30,6 +32,17 @@ class DataObjectProcessorTest extends \PHPUnit_Framework_TestCase 'typeProcessor' => $objectManager->getObject(\Magento\Framework\Reflection\TypeProcessor::class), ] ); + $serializerMock = $this->getMock(SerializerInterface::class); + $serializerMock->method('serialize') + ->willReturn('serializedData'); + $serializerMock->method('unserialize') + ->willReturn(['unserializedData']); + + $objectManager->setBackwardCompatibleProperty( + $methodsMapProcessor, + 'serializer', + $serializerMock + ); $this->dataObjectProcessor = $objectManager->getObject( \Magento\Framework\Reflection\DataObjectProcessor::class, [ diff --git a/app/design/adminhtml/Magento/backend/Magento_Catalog/web/css/source/_module.less b/app/design/adminhtml/Magento/backend/Magento_Catalog/web/css/source/_module.less index 304f895a85b969dfe95acd4e3dddb0607940432f..77a769d8f5a36cc4788031b5efa4d57c85481106 100644 --- a/app/design/adminhtml/Magento/backend/Magento_Catalog/web/css/source/_module.less +++ b/app/design/adminhtml/Magento/backend/Magento_Catalog/web/css/source/_module.less @@ -78,3 +78,19 @@ margin-top: -@indent__base; } } + +// +// Advanced Price panel +// --------------------------------------------- + +.admin__control-fields { + .control-grouped { + .lib-vendor-prefix-display(inline-flex); + .lib-vendor-prefix-flex-direction(row); + + .admin__field + .admin__field { + margin-left: @indent__s; + margin-top: 0; + } + } +} diff --git a/app/design/adminhtml/Magento/backend/web/css/source/components/_file-uploader.less b/app/design/adminhtml/Magento/backend/web/css/source/components/_file-uploader.less index 7637e64d830d1ea3f7b8a36404bf8c14b661d656..e0639704f4583f1fb7dee0cd1bc0af73687ecaa1 100644 --- a/app/design/adminhtml/Magento/backend/web/css/source/components/_file-uploader.less +++ b/app/design/adminhtml/Magento/backend/web/css/source/components/_file-uploader.less @@ -15,6 +15,17 @@ @file-uploader-preview__background-color: @color-white; @file-uploader-preview-focus__color: @color-blue2; +@file-uploader-document-icon__color: @color-gray80; +@file-uploader-document-icon__size: 7rem; +@file-uploader-document-icon__z-index: @data-grid-file-uploader-image__z-index + 1; + +@file-uploader-video-icon__color: @color-gray80; +@file-uploader-video-icon__size: 4rem; +@file-uploader-video-icon__z-index: @data-grid-file-uploader-image__z-index + 1; + +@file-uploader-placeholder-icon__color: @color-gray80; +@file-uploader-placeholder-icon__z-index: @data-grid-file-uploader-image__z-index + 1; + @file-uploader-delete-icon__color: @color-brownie; @file-uploader-delete-icon__hover__color: @color-brownie-vanilla; @file-uploader-delete-icon__font-size: 2rem; @@ -48,7 +59,6 @@ // --------------------------------------------- .file-uploader-area { - margin-bottom: @indent__xs; position: relative; input[type='file'] { @@ -66,6 +76,11 @@ } } +.file-uploader-summary { + display: inline-block; + vertical-align: top; +} + .file-uploader-button { cursor: pointer; display: inline-block; @@ -89,17 +104,6 @@ } .file-uploader-preview { - background: @file-uploader-preview__background-color; - border: 1px solid @file-uploader-preview__border-color; - box-sizing: border-box; - cursor: pointer; - height: @file-uploader-preview__height; - line-height: 1; - margin-bottom: @indent__s; - overflow: hidden; - position: relative; - width: @file-uploader-preview__width; - .action-remove { &:extend(.abs-action-reset all); .lib-icon-font ( @@ -123,12 +127,18 @@ } &:hover { - .preview-image { + .preview-image img, + .preview-link:before { opacity: @file-uploader-preview__opacity; } } - .preview-image { + .preview-link { + display: block; + height: 100%; + } + + .preview-image img { bottom: 0; left: 0; margin: auto; @@ -139,6 +149,59 @@ top: 0; z-index: 1; } + + .preview-video { + .lib-icon-font( + @icon-video__content, + @_icon-font: @icons-admin__font-name, + @_icon-font-size: @file-uploader-video-icon__size, + @_icon-font-color: @file-uploader-video-icon__color, + @_icon-font-color-hover: @file-uploader-video-icon__color + ); + + &:before { + left: 0; + margin-top: -@file-uploader-video-icon__size / 2; + position: absolute; + right: 0; + top: 50%; + z-index: @file-uploader-video-icon__z-index; + } + } + + .preview-document { + .lib-icon-font( + @icon-document__content, + @_icon-font: @icons-admin__font-name, + @_icon-font-size: @file-uploader-document-icon__size, + @_icon-font-color: @file-uploader-document-icon__color, + @_icon-font-color-hover: @file-uploader-document-icon__color + ); + + &:before { + left: 0; + margin-top: -@file-uploader-document-icon__size / 2; + position: absolute; + right: 0; + top: 50%; + z-index: @file-uploader-document-icon__z-index; + } + } +} + +.file-uploader-preview, +.file-uploader-placeholder { + background: @file-uploader-preview__background-color; + border: 1px solid @file-uploader-preview__border-color; + box-sizing: border-box; + cursor: pointer; + display: block; + height: @file-uploader-preview__height; + line-height: 1; + margin: @indent__s @indent__m @indent__s 0; + overflow: hidden; + position: relative; + width: @file-uploader-preview__width; } .file-uploader { @@ -154,6 +217,8 @@ } .file-uploader-filename { + .lib-text-overflow(); + max-width: @file-uploader-preview__width; word-break: break-all; &:first-child { @@ -176,6 +241,76 @@ } } +// Placeholder for multiple uploader +.file-uploader-placeholder { + &.placeholder-document { + .lib-icon-font( + @icon-document__content, + @_icon-font: @icons-admin__font-name, + @_icon-font-size: 5rem, + @_icon-font-color: @file-uploader-placeholder-icon__color, + @_icon-font-color-hover: @file-uploader-placeholder-icon__color + ); + + &:before { + left: 0; + position: absolute; + right: 0; + top: 20px; + z-index: @file-uploader-placeholder-icon__z-index; + } + } + + &.placeholder-image { + .lib-icon-font( + @icon-camera__content, + @_icon-font: @icons-admin__font-name, + @_icon-font-size: 5rem, + @_icon-font-color: @file-uploader-placeholder-icon__color, + @_icon-font-color-hover: @file-uploader-placeholder-icon__color + ); + + &:before { + left: 0; + position: absolute; + right: 0; + top: 20px; + z-index: @file-uploader-placeholder-icon__z-index; + } + } + + &.placeholder-video { + .lib-icon-font( + @icon-video__content, + @_icon-font: @icons-admin__font-name, + @_icon-font-size: 3rem, + @_icon-font-color: @file-uploader-placeholder-icon__color, + @_icon-font-color-hover: @file-uploader-placeholder-icon__color + ); + + &:before { + left: 0; + position: absolute; + right: 0; + top: 30px; + z-index: @file-uploader-placeholder-icon__z-index; + } + } +} + +.file-uploader-placeholder-text { + bottom: 0; + color: @color-blue-dodger; + font-size: 1.1rem; + left: 0; + line-height: @line-height__base; + margin-bottom: 15%; + padding: 0 @indent__base; + position: absolute; + right: 0; + text-align: center; +} + // // Grid image uploader // --------------------------------------------- diff --git a/app/design/adminhtml/Magento/backend/web/css/source/variables/_icons.less b/app/design/adminhtml/Magento/backend/web/css/source/variables/_icons.less index 53433d3c75703f626e9ef86e721988b92e3836a4..ec1d4709213f3e1ea59ed53eda33fbc4f3741998 100644 --- a/app/design/adminhtml/Magento/backend/web/css/source/variables/_icons.less +++ b/app/design/adminhtml/Magento/backend/web/css/source/variables/_icons.less @@ -80,3 +80,4 @@ @icon-clip__content: '\e643'; @icon-module__content: '\e647'; @icon-alert-round__content: '\e648'; +@icon-document__content: '\e649'; diff --git a/app/design/adminhtml/Magento/backend/web/fonts/admin-icons/admin-icons.eot b/app/design/adminhtml/Magento/backend/web/fonts/admin-icons/admin-icons.eot index 5bc0bee548c35b205925ca3b46c99706d05c8d66..9587f3997440e0dd93da7e02e72423d2655e3533 100755 Binary files a/app/design/adminhtml/Magento/backend/web/fonts/admin-icons/admin-icons.eot and b/app/design/adminhtml/Magento/backend/web/fonts/admin-icons/admin-icons.eot differ diff --git a/app/design/adminhtml/Magento/backend/web/fonts/admin-icons/admin-icons.svg b/app/design/adminhtml/Magento/backend/web/fonts/admin-icons/admin-icons.svg index 4478010abc66d68dbfbae79368128878031350d4..2904f02b748e481e18d92eb7c347c17e18bb37ba 100755 --- a/app/design/adminhtml/Magento/backend/web/fonts/admin-icons/admin-icons.svg +++ b/app/design/adminhtml/Magento/backend/web/fonts/admin-icons/admin-icons.svg @@ -1 +1 @@ -<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" ><svg xmlns="http://www.w3.org/2000/svg"><defs><font id="icomoon" horiz-adv-x="1024"><font-face units-per-em="1024" ascent="960" descent="-64" /><missing-glyph horiz-adv-x="1024" /><glyph unicode=" " horiz-adv-x="512" d="" /><glyph unicode="" glyph-name="account" horiz-adv-x="1090" d="M709.921 801.306c8.139-32.295 8.927-34.974 8.192-68.162-0.263-12.813-7.772-71.943-5.724-90.112 1.628-14.966 5.461-16.174 11.448-28.514 10.398-21.425 6.984-51.095 2.941-72.678-2.206-11.868-6.827-28.725-13.916-38.387-7.667-10.66-23.211-10.713-30.142-23.158-9.872-17.854-4.306-43.008-10.503-62.385-7.142-21.898-25.101-23.421-26.466-52.145 8.822-1.155 17.592-2.468 26.466-3.623 8.822-18.59 25.049-55.874 41.59-67.059 13.863-3.728 27.727-7.457 41.59-11.185 48.627-19.64 102.558-43.061 151.237-63.33 44.373-18.432 97.411-24.996 113.48-70.84 0-31.035 2.941-104.501 2.153-145.25h-965.553c-0.893 40.697 2.153 114.215 2.153 145.25 15.964 45.844 69.002 52.408 113.375 70.84 48.679 20.27 102.61 43.691 151.237 63.33 13.811 3.728 27.674 7.457 41.59 11.185 16.489 11.185 32.715 48.522 41.538 67.059l19.692 4.621c-4.464 24.576-19.85 26.466-26.256 43.743-2.521 26.099-5.041 52.145-7.509 78.192 0.053-1.155-18.117 3.361-20.48 4.779-25.731 15.806-26.204 80.24-28.725 107.021-1.103 12.183 16.174 22.265 11.343 44.636-28.094 131.44 12.183 192.88 75.881 213.307 44.216 17.749 126.871 50.465 203.855 3.728l19.167-17.487 30.93-5.251c15.491-8.77 25.416-38.124 25.416-38.124z" /><glyph unicode="" glyph-name="arrowdown" horiz-adv-x="1085" d="M529.203 73.86l-468.465 628.209h936.931l-468.465-628.209z" /><glyph unicode="" glyph-name="cms" horiz-adv-x="1034" d="M976.793-22.006h-910.388v910.388h910.388v-910.388zM912.622 824.211h-782.046v-782.088h782.046v782.088zM221.432 137.2h152.876v372.033h-152.876v-372.033zM466.323 139.766h350.932v366.53h-350.932v-366.53zM221.432 599.511h595.865v147.125h-595.865v-147.125z" /><glyph unicode="" glyph-name="customers" horiz-adv-x="489" d="M264.319 651.169c75.685 0 136.98 61.259 136.98 136.944 0 75.649-61.295 136.98-136.98 136.98s-137.017-61.331-137.017-136.98c0-75.649 61.331-136.944 137.017-136.944zM448.929 589.149c-28.962 28.926-63.325 46.252-187.655 46.252s-157.859-18.776-185.335-46.252c-27.44-27.44-18.196-320.43-18.196-320.43l60.824 144.411 38.241-430.334 110.23 220.278 102.907-220.278 36.393 430.334 60.824-144.411c-0.036 0 10.693 291.468-18.233 320.43z" /><glyph unicode="" glyph-name="dashboard" horiz-adv-x="1376" d="M680.975 886.272c-337.523 0-610.976-273.515-611.038-610.976 0.122-37.72 1.039-251.812 1.039-251.812h1219.997c0 0 0.978 239.219 1.039 251.812-0.183 337.523-273.637 610.976-611.038 610.976zM737.708 762.169c31.117-3.607 61.379-10.271 90.418-19.624l-19.93-61.685c-25.004 8.070-51.169 13.939-78.191 16.995l7.703 64.313zM270.091 286.85h-64.864c0 31.423 3.118 62.235 8.803 92.007l63.702-12.349c-5.135-25.799-7.642-52.392-7.642-79.658zM305.855 455.581l-59.178 26.288c12.655 28.489 28 55.449 45.79 80.636l52.942-37.475c-15.284-21.825-28.611-45.056-39.554-69.449zM407.46 594.845l-43.405 48.113c22.925 20.541 47.807 39.187 74.462 54.96l33.318-55.571c-22.987-13.755-44.567-29.65-64.374-47.501zM536.943 742.545c29.039 9.292 59.178 16.017 90.418 19.624l7.581-64.313c-26.838-3.057-53.003-8.926-78.13-16.995l-19.869 61.685zM761.673 158.468l-152.897-27.205-38.881 150.452 395.172 404.22-203.394-527.467zM1019.476 525.029l52.942 37.414c17.79-25.187 33.257-52.148 45.851-80.636l-59.178-26.288c-10.943 24.454-24.209 47.685-39.615 69.51zM1094.916 286.85c0 27.266-2.69 53.859-7.703 79.658l63.702 12.349c5.808-29.834 8.803-60.645 8.803-92.007h-64.802zM646.006 189.341c26.777-17.056 62.174-9.415 79.291 17.24 17.118 26.593 9.292 62.051-17.301 79.108-26.655 17.24-62.051 9.354-79.23-17.362-17.118-26.349-9.476-61.99 17.24-78.986z" /><glyph unicode="" glyph-name="filter" d="M24.097 846.535h972.827v-111.922l-410.504-412.792v-238.366l-171.447-87.505v325.871l-390.875 415.877v108.837z" /><glyph unicode="" glyph-name="logo" horiz-adv-x="903" d="M454.495 911.101l-402.697-240.513v-457.026l104.632-60.727v457.049l298.157 178.728 299.698-179.142-0.138-455.922 103.528 60.013v457.026l-403.18 240.513zM507.766 629.72v-534.344l-53.271-32.124-53.34 32.262v533.792l-138.090-83.853v-456.934l191.453-115.516 193.087 116.322v456.451l-139.839 83.945z" /><glyph unicode="" glyph-name="notification-02" horiz-adv-x="989" d="M870.821 228.163c-64.195 65.89-78.231 188.772-91.738 283.159-20.074 139.937-24.259 297.089-226.008 317.693v25.318c0 25.424-39.195 46.028-64.937 46.028s-62.024-20.551-62.024-46.028v-25.371c-200.054-20.816-206.993-177.914-226.855-317.693-13.453-94.439-27.331-217.268-91.049-283.264-12.818-13.348-16.473-32.998-9.11-49.947 7.362-16.843 24.153-27.913 42.797-27.913h695.343c18.75 0 35.593 11.070 42.903 28.019s3.655 36.653-9.322 50zM489.569-3.883c51.060 0 92.373 40.837 92.373 91.367h-184.694c-0.053-50.53 41.314-91.367 92.32-91.367z" /><glyph unicode="" glyph-name="product" horiz-adv-x="954" d="M252.137 806.772l-160.070-92.393 378.042-218.205 160.023 92.393-377.996 218.205zM845.638 712.937l-377.996 218.252-145.222-83.828 377.996-218.205 145.222 83.782zM502.784 433.85v-433.664l376.832 217.507v433.711l-376.832-217.553zM55.668 217.74l376.785-217.507v436.503l-376.785 217.46v-436.457z" /><glyph unicode="" glyph-name="promotions" horiz-adv-x="1170" d="M59.153 425.818l164.053-38.141v303.902l-164.053-38.141v-227.621zM1122.198 900.847l-837.712-194.959v-335.978l140.328-376.832 151.712 57.45-104.049 279.113 649.668-151.18v722.385z" /><glyph unicode="" glyph-name="reports" horiz-adv-x="991" d="M736.707-21.234h207.134v322.703h-207.134v-322.703zM399.646-21.234h207.134v946.793h-207.134v-946.793zM62.673-21.19h207.134v634.704h-207.134v-634.704z" /><glyph unicode="" glyph-name="sales" horiz-adv-x="659" d="M426.502 347.483c-15.866 13.512-42.796 25.753-80.79 36.723v-198.774c11.535 1.459 23.729 4.331 36.299 8.851 12.618 4.426 23.87 10.829 33.804 19.068 9.981 8.427 18.173 18.55 24.529 30.649 6.638 12.006 9.651 26.365 9.651 42.89 0.047 26.836-7.721 47.222-23.493 60.593zM576.736 223.144c-7.109-23.117-19.774-45.762-38.135-67.749-18.503-22.175-43.079-41.855-74.010-58.992-30.885-17.373-70.432-27.683-118.878-31.12v-88.088h-57.014v88.088c-72.080 5.603-128.483 29.237-169.113 71.374-40.536 42.090-63.935 104.095-70.432 185.544h136.251c-0.753-39.359 8.992-70.479 28.86-93.266 20.15-22.74 44.774-37.335 74.434-43.455v216.523c-3.060 1.318-7.486 2.919-12.994 4.567-5.508 1.789-11.393 3.343-17.938 4.708-23.776 6.827-47.175 15.019-70.291 24.294-23.493 9.369-44.114 21.704-62.523 37.335-18.456 15.584-33.098 34.84-43.879 57.956-11.111 23.211-16.478 51.977-16.478 86.487 0 35.31 6.168 66.336 18.785 93.313 12.665 26.836 29.143 49.529 49.858 67.702 20.621 18.314 44.303 32.58 71.468 42.419 27.071 10.122 55.037 16.149 83.992 18.314v79.66h57.014v-79.66c29.143-3.531 56.308-10.169 81.638-20.292 25.423-10.028 47.787-23.729 67.137-41.478 19.585-17.514 35.357-39.453 47.457-65.771 12.288-26.13 19.35-57.109 21.28-93.172h-137.287c-0.518 27.636-8.616 51.082-23.917 70.432-15.725 19.303-34.275 29.002-56.308 29.002v-183.331c7.862-2.072 15.631-4.143 23.729-6.12 8.098-2.072 16.525-4.567 25.565-7.297 47.645-13.983 84.415-31.12 110.168-51.318 25.8-20.292 44.726-41.666 56.92-63.653 12.335-22.175 19.633-44.256 21.704-66.336 2.448-22.081 3.531-41.713 3.531-59.039 0.047-15.207-3.531-34.416-10.593-57.579zM228.905 696.585c-8.38-7.156-15.113-16.196-19.962-26.883-4.802-10.781-7.062-23.352-7.062-37.759 0-22.834 6.733-40.536 20.103-52.824 13.653-12.618 35.734-22.552 66.713-30.131v168.831c-10.829 0-21.516-1.695-31.826-5.226-10.216-3.437-19.633-8.851-27.966-16.007z" /><glyph unicode="" glyph-name="search" horiz-adv-x="1109" d="M555.139 938.358c-218.775 71.601-457.062-40.29-532.231-250.028-75.227-209.681 41.211-437.665 259.928-509.208 218.717-71.601 457.004 40.348 532.231 250.028s-41.211 437.665-259.928 509.208zM320.076 282.955c-158.915 52.089-243.467 217.681-188.903 369.978 54.679 152.296 227.754 233.625 386.669 181.593s243.409-217.624 188.788-369.92c-54.622-152.296-227.696-233.567-386.554-181.65zM638.482 274.206l358.927-349.602 24.807 69.241 24.865 69.241-310.348 302.29z" /><glyph unicode="" glyph-name="stores" horiz-adv-x="1280" d="M1098.281 874.55c19.777 3.723 34.901 21.232 34.901 42.347-0.058 23.791-19.196 43.103-42.812 43.103h-900.508c-23.675 0-42.754-19.312-42.754-43.103 0-21.057 15.007-38.566 34.843-42.347l-181.951-354.421v-68.988c0-30.946 32.516-56.016 72.594-56.016 13.437 0 26.001 2.908 36.821 7.795v-466.919h1061.286v466.919c10.878-4.944 23.326-7.795 36.879-7.795 40.078 0 72.594 25.071 72.594 56.016v68.988l-181.893 354.421zM214.758 395.125c-38.217 0-69.221 25.071-69.221 56.016v6.457h-0.349v62.531l137.162 353.665h109.648l-107.961-353.665v-68.988c0 0 0 0 0 0 0-30.946-31.004-56.016-69.279-56.016zM498.447 395.125c-38.217 0-69.221 25.071-69.221 56.016v68.988l57.354 353.665h109.241l-28.095-353.665v-68.93c-0.058-31.004-31.004-56.075-69.279-56.075zM782.077 395.125c-38.217 0-69.162 25.071-69.162 56.016v68.988l-28.154 353.665h108.892l57.296-353.665v-68.988c0-0.931 0.175-1.92 0.233-2.792-1.803-29.666-32.051-53.224-69.104-53.224zM1134.637 451.141c0-30.946-31.004-56.016-69.221-56.016s-69.162 25.071-69.162 56.016v68.988l-108.019 353.665h109.59l137.22-353.665v-62.473h-0.349v-6.515h-0.058z" /><glyph unicode="" glyph-name="views" horiz-adv-x="1890" d="M944.97 630.958c-97.861 0-177.522-79.581-177.522-177.443 0-97.94 79.66-177.679 177.522-177.679 98.019 0 177.679 79.739 177.679 177.679 0 97.861-79.66 177.443-177.679 177.443zM944.97 960c-470.712 0-944.97-512-944.97-512s474.258-512 944.97-512c470.949 0 945.128 512 945.128 512s-474.179 512-945.128 512zM944.97 91.144c-200.057 0-362.292 162.078-362.292 362.45 0 200.057 162.236 362.292 362.292 362.292 200.214 0 362.45-162.236 362.45-362.292 0-200.451-162.236-362.45-362.45-362.45z" /><glyph unicode="" glyph-name="system-config" d="M1020.032 394.445v116.045l-16.41 5.376-124.237 40.525-33.152 80.102 63.718 134.784-82.048 82.125-15.411-7.808-116.531-59.213-80.077 33.178-50.278 140.442h-116.096l-45.875-140.698-80-33.126-134.963 63.744-82.022-82.074 7.834-15.334 59.162-116.608-33.126-80.026-140.518-50.253v-116.147l16.435-5.325 124.288-40.576 33.075-80-63.693-134.886 82.048-82.099 131.942 66.97 80.026-33.152 50.304-140.39h116.096l5.35 16.41 40.55 124.237 80.077 33.178 134.886-63.718 82.074 82.074-7.834 15.386-59.213 116.582 33.203 80.026 140.416 50.253zM510.003 287.411c-89.754 0-162.509 72.832-162.509 162.611 0 89.754 72.755 162.483 162.509 162.483 89.83 0 162.509-72.73 162.509-162.483 0.026-89.805-72.653-162.611-162.509-162.611z" /><glyph unicode="" glyph-name="home" d="M509.978 905.574l-509.978-509.926 95.949-95.949 414.106 413.978 413.875-413.978 95.949 95.898-509.901 509.978zM146.253 271.437v-335.437h259.917v304.819h207.514v-304.819h259.917v335.488l-363.622 363.597-363.725-363.648z" /><glyph unicode="" glyph-name="lego" d="M0 223.59l498.278-287.59v421.402l-498.278 287.667v-421.478zM894.464 735.514v-44.262c0-32.819-62.797-59.418-140.365-59.418-77.466 0-140.262 26.598-140.262 59.418v73.216h0.435c4.71-30.925 65.408-55.475 139.853-55.475 77.568 0 140.365 26.624 140.365 59.29 0 32.845-62.797 59.366-140.365 59.366-6.195 0-12.262-0.205-18.202-0.563l-90.317 52.147v-55.706c0-32.819-62.72-59.392-140.262-59.392-48.691 0-91.597 10.496-116.813 26.47-3.584 3.712-7.987 7.245-13.312 10.598-6.579 6.861-10.24 14.387-10.24 22.323v53.939l-87.322-50.381c-6.272 0.307-12.646 0.614-19.123 0.614-77.491 0-140.314-26.522-140.314-59.366 0-32.691 62.822-59.29 140.314-59.29 74.445 0 135.219 24.525 139.93 55.475h0.384v-73.216c0-32.819-62.746-59.418-140.314-59.418-77.491 0-140.314 26.598-140.314 59.418v43.622l-108.083-62.31 499.994-288.563 496.691 286.694-112.358 64.768zM646.784 551.987c0-32.794-62.874-59.315-140.365-59.315s-140.339 26.522-140.339 59.315v73.267h0.41c4.762-30.95 65.459-55.475 139.93-55.475s135.142 24.525 139.904 55.475h0.486v-73.267zM525.645 353.766v-417.766l498.355 287.718v417.766l-498.355-287.718zM505.318 841.344c77.542 0 140.262 26.547 140.262 59.315s-62.72 59.315-140.262 59.315c-77.491 0-140.339-26.573-140.339-59.315-0.026-32.768 62.822-59.315 140.339-59.315z" /><glyph unicode="" glyph-name="tool" d="M287.002 478.336c0.205-0.23 0.461-0.486 0.691-0.717l103.347-103.373 36.045 36.045-56.55 56.499 90.266 90.189 11.904-1.28c3.046-0.307 6.093-0.538 9.19-0.538 6.246 0 12.314 0.768 18.253 2.125l-66.381 66.381c-1.357 1.382-2.765 2.611-4.173 3.814 20.454 73.6 1.766 155.725-56.038 213.555-57.421 57.421-138.803 76.237-211.968 56.525l123.955-123.981-32.563-121.446-121.395-32.589-124.032 124.006c-19.712-73.19-0.896-154.573 56.525-212.019 60.262-60.288 147.021-77.952 222.925-53.197zM653.235 404.198c-1.997-8.909-2.509-18.202-1.459-27.546l1.306-11.93-90.189-90.189-56.55 56.55-36.070-36.122 327.219-327.194c20.198-20.173 46.618-30.259 73.062-30.259s52.915 10.086 73.037 30.259c40.346 40.32 40.346 105.728 0 146.074l-290.355 290.355zM905.907 1.638l-51.866-13.875-42.112 42.112 13.901 51.891 51.866 13.926 42.112-42.138-13.901-51.917zM506.701 365.901l56.576-56.576 64.128 64.154c-3.482 31.334 6.707 63.821 30.669 87.808 24.013 23.962 56.474 34.176 87.808 30.72l280.397 280.346-157.056 157.056-280.448-280.397c3.482-31.258-6.682-63.821-30.669-87.782-24.013-23.987-56.525-34.176-87.808-30.643l-64.102-64.205 56.499-56.422-277.043-277.12-10.138 10.138-53.248-42.829-89.421-141.312 22.835-22.835 141.312 89.421 42.803 53.222-10.138 10.138 277.043 277.12z" /><glyph unicode="" glyph-name="upgrade" d="M1023.932 454.895c-3.717 282.692-236.1 508.826-518.793 505.003-282.658-3.775-508.826-236.066-505.071-518.827 3.772-282.556 236.1-508.826 518.793-505.003 282.658 3.768 508.826 236.066 505.071 518.827zM623.991 478.696v-298.633h-223.983v298.633h-186.621l298.633 298.633 298.667-298.633h-186.679z" /><glyph unicode="" glyph-name="expand-close" d="M512.794 960c-283.187 0-512.794-229.581-512.794-512.794 0-283.187 229.606-512.794 512.794-512.794s512.794 229.632 512.794 512.794c0 283.213-229.581 512.794-512.794 512.794zM512.794-11.213c-253.158 0-458.394 205.261-458.394 458.368 0 253.158 205.261 458.394 458.394 458.394 253.184 0 458.394-205.235 458.394-458.394 0.026-253.107-205.21-458.368-458.394-458.368zM760.013 334.387l30.387 38.4-265.6 206.413-20.787 1.613-259.226-208.026 28.826-39.987 236.8 177.613z" /><glyph unicode="" glyph-name="expand-open" d="M512.794 960c-283.187 0-512.794-229.581-512.794-512.794 0-283.187 229.606-512.794 512.794-512.794s512.794 229.606 512.794 512.794c0 283.213-229.581 512.794-512.794 512.794zM512.794-11.213c-253.158 0-458.394 205.261-458.394 458.394 0 253.158 205.261 458.394 458.394 458.394 253.184 0 458.394-205.235 458.394-458.394 0.026-253.133-205.21-458.394-458.394-458.394zM265.6 505.6l-30.387-38.4 265.574-206.387 20.813-1.613 259.2 208-28.8 39.987-236.8-177.587z" /><glyph unicode="" glyph-name="gripper" d="M259.2 960h214.323v-214.323h-214.323v214.323zM259.2 690.125h214.323v-214.349h-214.323v214.349zM259.2 420.224h214.323v-214.349h-214.323v214.349zM259.2 150.349h214.323v-214.349h-214.323v214.349zM549.325 960h214.323v-214.323h-214.323v214.323zM549.325 690.125h214.323v-214.349h-214.323v214.349zM549.325 420.224h214.323v-214.349h-214.323v214.349zM549.325 150.349h214.323v-214.349h-214.323v214.349z" /><glyph unicode="" glyph-name="forward" d="M860.058 774.938v-272l-430.029 269.158-1.894-253.491-424.371 249.754-3.763-647.834 426.24 241.28-5.606-239.437 439.424 252.16v-259.635h163.942v660.045z" /><glyph unicode="" glyph-name="backward" d="M163.942 114.893v271.974l430.029-269.133 1.894 253.491 424.397-249.754 3.738 647.834-426.24-241.28 5.606 239.437-439.424-252.16v259.635h-163.942v-660.045z" /><glyph unicode="" glyph-name="info" d="M505.704 919.002c-260.096-3.489-468.158-217.202-464.706-477.336 3.489-259.982 217.202-468.12 477.298-464.631s468.158 217.202 464.706 477.336c-3.413 260.058-217.202 468.12-477.298 464.631zM557.928 762.027c47.863 0 62.009-27.762 62.009-59.544 0-39.671-31.782-76.383-86.016-76.383-45.359 0-66.901 22.831-65.65 60.53 0 31.782 26.624 75.435 89.657 75.435zM435.162 153.619c-32.73 0-56.661 19.873-33.792 107.217l37.547 154.814c6.485 24.841 7.585 34.778 0 34.778-9.785 0-52.262-17.143-77.407-34.057l-16.346 26.776c79.607 66.446 171.16 105.472 210.375 105.472 32.73 0 38.153-38.722 21.807-98.266l-43.008-162.816c-7.585-28.786-4.286-38.722 3.262-38.722 9.785 0 41.984 11.871 73.614 36.75l18.47-24.841c-77.369-77.369-161.792-107.179-194.56-107.179z" /><glyph unicode="" glyph-name="lock" d="M591.986 511.981h-16.005v192.019c0 105.851-86.13 192.019-192.019 192.019h-128c-105.851 0-192.019-86.13-192.019-192.019v-192.019h-16.005c-26.396 0-48.014-21.618-48.014-48.014v-479.991c0-26.396 21.618-48.014 48.014-48.014h544.009c26.396 0 48.014 21.618 48.014 48.014v479.991c0 26.396-21.618 48.014-48.014 48.014zM384 64h-128l27.838 139.188c-16.801 11.529-27.838 30.872-27.838 52.793 0 35.347 28.672 64.019 64.019 64.019s64.019-28.672 64.019-64.019c0-21.921-11.036-41.263-27.838-52.793l27.838-139.188zM448.019 511.981h-256v192.019c0 35.271 28.71 64.019 64.019 64.019h128c35.271 0 64.019-28.71 64.019-64.019v-192.019z" /><glyph unicode="" glyph-name="loop" d="M870.4 642.56h-194.56v-143.36h153.6v-215.040h-634.88v215.040h215.040v-112.64l204.8 184.32-204.8 184.32v-112.64h-256c-56.51 0-102.4-45.815-102.4-102.4v-296.96c0-56.51 45.89-102.4 102.4-102.4h716.8c56.585 0 102.4 45.89 102.4 102.4v296.96c0 56.585-45.815 102.4-102.4 102.4z" /><glyph unicode="" glyph-name="plus" d="M991.991 576h-351.991v351.991c0 17.673-14.336 32.009-32.009 32.009h-192.019c-17.673 0-32.009-14.336-32.009-32.009v-351.991h-351.991c-17.673 0-32.009-14.336-32.009-32.009v-192.019c0-17.673 14.336-32.009 32.009-32.009h351.991v-351.991c0-17.673 14.336-32.009 32.009-32.009h192.019c17.673 0 32.009 14.336 32.009 32.009v351.991h351.991c17.673 0 32.009 14.336 32.009 32.009v192.019c0 17.673-14.336 32.009-32.009 32.009z" /><glyph unicode="" glyph-name="recover" d="M505.704 919.002c-260.096-3.489-468.158-217.126-464.706-477.298 3.489-260.21 217.202-468.158 477.298-464.744 260.134 3.489 468.233 217.202 464.706 477.298-3.489 260.21-217.202 468.233-477.298 464.744zM506.577 857.6c70.163 0.986 136.382-15.853 194.56-46.118l-63.374-105.662c-38.002 18.47-80.631 28.937-125.762 28.937-45.056 0-87.723-10.43-125.687-28.975l-63.336 105.624c54.993 28.672 117.343 45.321 183.599 46.232zM254.255 322.313l-105.586-63.298c-28.672 54.955-45.321 117.305-46.194 183.486-0.986 70.201 15.853 136.457 46.118 194.56l105.624-63.45c-18.546-37.926-28.975-80.555-28.975-125.649 0-45.056 10.43-87.723 28.975-125.687zM517.461 38.438c-70.163-0.986-136.457 15.853-194.56 46.118l63.374 105.662c38.002-18.546 80.631-28.975 125.687-28.975 45.094 0 87.761 10.392 125.687 28.937l63.336-105.586c-54.993-28.634-117.305-45.246-183.561-46.194zM512 222.758c-124.397 0-225.242 100.883-225.242 225.242 0 124.397 100.883 225.28 225.242 225.28 124.473 0 225.28-100.883 225.28-225.28s-100.807-225.242-225.28-225.242zM769.745 322.313c18.546 38.002 28.975 80.631 28.975 125.687 0 45.094-10.43 87.723-28.975 125.687l105.586 63.374c28.672-54.993 45.359-117.305 46.232-183.561 0.91-70.201-15.929-136.457-46.194-194.56l-105.624 63.336z" /><glyph unicode="" glyph-name="refresh" horiz-adv-x="1176" d="M906.126 824.187v0c-91.174 75.89-202.487 113.171-312.548 113.057-127.014 0.038-253.611-49.683-348.16-145.636l-95.004 79.265-1.593-305.342 300.184 56.282-99.442 82.944c67.546 64.247 155.269 97.204 244.015 97.28 79.948-0.038 159.782-26.7 226.114-81.806 84.347-70.125 127.659-170.629 127.772-272.46-0.038-14.715-0.948-29.431-2.769-44.070l137.519 26.283c0.19 5.954 0.303 11.871 0.303 17.787 0.152 140.098-60.151 279.78-176.431 376.415zM839.035 193.024c-67.736-65.498-156.255-99.025-245.912-99.1-79.986 0.038-159.82 26.738-226.114 81.806-84.347 70.125-127.697 170.629-127.772 272.498 0 16.839 1.252 33.716 3.679 50.366l-138.164-25.941c-0.379-8.116-0.683-16.346-0.683-24.462-0.114-140.174 60.226-279.817 176.545-376.491 91.136-75.852 202.411-113.057 312.51-112.981h0.341c127.924 0 255.241 50.441 349.943 147.759l90.795-75.207 0.569 305.38-299.956-57.344 104.183-86.281z" /><glyph unicode="" glyph-name="remove-small" horiz-adv-x="1176" d="M593.351 938.268c-270.753 0-490.268-219.477-490.268-490.231s219.515-490.268 490.268-490.268 490.231 219.515 490.231 490.268c0 270.753-219.477 490.231-490.231 490.231zM828.947 276.347l-72.363-72.363-162.095 162.133-164.902-164.902-73.121 73.121 164.902 164.902-161.678 161.678 72.363 72.325 161.602-161.678 165.774 165.736 73.121-73.083-165.774-165.736 162.171-162.133z" /><glyph unicode="" glyph-name="retweet" d="M254.976 284.16v267.264h103.424l-179.2 203.776-179.2-203.776h103.424v-308.224c0-56.51 45.815-102.4 102.4-102.4h459.776l-131.186 143.36h-279.438zM920.538 344.576v308.224c0 56.51-45.89 102.4-102.4 102.4h-459.738l131.11-143.36h279.514v-267.264h-103.424l179.2-203.776 179.2 203.776h-103.462z" /><glyph unicode="" glyph-name="unlocked" d="M768 895.981h-128c-105.851 0-192.019-86.13-192.019-192.019v-192.019h-400.005c-26.396 0-48.014-21.618-48.014-48.014v-479.991c0-26.396 21.618-48.014 48.014-48.014h544.009c26.396 0 48.014 21.618 48.014 48.014v479.991c0 26.396-21.618 48.014-48.014 48.014h-16.005v192.019c0 35.271 28.71 64.019 64.019 64.019h128c35.271 0 64.019-28.71 64.019-64.019v-192.019h128v192.019c0 105.851-86.13 192.019-192.019 192.019zM384 64h-128l27.838 139.188c-16.801 11.529-27.838 30.872-27.838 52.793 0 35.347 28.672 64.019 64.019 64.019s64.019-28.672 64.019-64.019c0-21.921-11.036-41.263-27.838-52.793l27.838-139.188z" /><glyph unicode="" glyph-name="warning" horiz-adv-x="1176" d="M593.351 960l-593.351-1023.962h1186.74l-593.351 1023.962zM653.236 60.549h-125.421v121.211h125.421v-121.211zM622.175 231.671h-62.502l-34.816 288.313v156.748h131.3v-156.748l-33.982-288.313z" /><glyph unicode="" glyph-name="arrow-left" d="M0 448l512-512v320.019h512v384h-512v320.019z" /><glyph unicode="" glyph-name="arrow-right" d="M1024 448l-512 512v-320.019h-512v-384h512v-320.019z" /><glyph unicode="" glyph-name="back-arrow" d="M402.735 813.265l-320.019-320.019c-24.993-24.993-24.993-65.498 0-90.491l320.019-320.019c24.993-24.993 65.498-24.993 90.491 0s24.993 65.498 0 90.491l-210.754 210.754h613.49c35.347 0 64.019 28.634 64.019 64.019s-28.672 64.019-64.019 64.019h-613.49l210.754 210.754c12.478 12.478 18.735 28.862 18.735 45.246s-6.258 32.768-18.735 45.246c-24.993 24.993-65.498 24.993-90.491 0z" /><glyph unicode="" glyph-name="calendar" horiz-adv-x="1176" d="M507.259 381.478h-102.059v-101.717h102.059v101.717zM650.885 245.286h-101.945v-101.717h101.945v101.717zM507.259 245.286h-102.059v-101.717h102.059v101.717zM507.259 517.67h-102.059v-101.679h102.059v101.679zM843.131 715.909c23.4 0 42.287 18.887 42.287 42.174v145.408c0 23.324-18.887 42.174-42.287 42.174s-42.325-18.849-42.325-42.174v-145.408c0.038-23.324 18.925-42.174 42.325-42.174zM343.419 715.909c23.362 0 42.249 18.887 42.249 42.174v145.408c0 23.324-18.887 42.174-42.249 42.174-23.4 0-42.325-18.849-42.325-42.174v-145.408c0-23.324 18.925-42.174 42.325-42.174zM363.444 381.478h-102.059v-101.717h102.059v101.717zM363.444 245.286h-102.059v-101.717h102.059v101.717zM650.885 381.478h-101.945v-101.717h101.945v101.717zM938.325 381.478h-102.059v-101.717h102.059v101.717zM938.325 517.67h-102.059v-101.679h102.059v101.679zM899.337 875.615v-46.914c17.598-15.474 28.71-38.153 28.71-63.412 0-46.801-37.964-84.764-84.916-84.764s-84.954 37.964-84.954 84.764c0 25.259 11.15 47.938 28.71 63.412v46.914h-387.262v-46.914c17.56-15.474 28.71-38.153 28.71-63.412 0-46.801-38.002-84.764-84.916-84.764s-84.954 37.964-84.954 84.764c0 25.259 11.15 47.938 28.71 63.412v46.914h-192.322v-925.279h997.035v925.279h-192.512zM999.234 44.696h-809.832v589.938h809.832v-589.938zM650.885 517.67h-101.945v-101.679h101.945v101.679zM794.624 517.67h-101.983v-101.679h101.983v101.679zM794.624 245.286h-101.983v-101.717h101.983v101.717zM794.624 381.478h-101.983v-101.717h101.983v101.717z" /><glyph unicode="" glyph-name="caret-down" d="M132.21 673.242c-13.881 13.729-36.295 13.729-50.138 0-13.805-13.653-13.805-35.878 0-49.607l404.897-400.877c13.881-13.729 36.257-13.729 50.138 0l404.897 400.877c13.805 13.729 13.881 35.878 0 49.607s-36.371 13.729-50.138 0.038l-379.866-365.606-379.79 365.568z" /><glyph unicode="" glyph-name="caret-left" d="M737.242 68.21c13.729-13.881 13.729-36.257 0-50.138s-35.878-13.881-49.607 0l-400.877 404.821c-13.729 13.881-13.729 36.295 0 50.138l400.877 404.897c13.729 13.881 35.878 13.881 49.607 0s13.729-36.257 0-50.138l-365.568-379.79 365.568-379.79z" /><glyph unicode="" glyph-name="caret-right" d="M286.72 68.21c-13.729-13.881-13.729-36.257 0-50.138s35.878-13.881 49.607 0l400.877 404.821c13.729 13.881 13.729 36.295 0 50.138l-400.915 404.897c-13.729 13.881-35.878 13.881-49.607 0s-13.729-36.257 0-50.138l365.568-379.79-365.568-379.79z" /><glyph unicode="" glyph-name="caret-up" d="M891.79 222.758c13.881-13.729 36.295-13.729 50.138 0 13.881 13.729 13.881 35.878 0 49.607l-404.897 400.877c-13.805 13.729-36.257 13.729-50.062 0l-404.897-400.877c-13.805-13.729-13.881-35.878 0-49.607s36.257-13.729 50.138 0l379.79 365.606 379.79-365.606z" /><glyph unicode="" glyph-name="ccw" d="M574.767 867.84c-227.593 0-412.672-182.386-418.247-409.335h-125.8l188.378-209.92 188.302 209.92h-146.242c5.537 168.998 143.777 304.393 313.609 304.393 173.397 0 313.913-140.971 313.913-314.899s-140.478-314.861-313.913-314.861c-69.48 0-133.689 22.718-185.685 61.099l-71.983-76.99c70.997-55.751 160.465-89.050 257.707-89.050 231.159 0 418.551 187.961 418.551 419.84-0.038 231.879-187.43 419.84-418.551 419.84z" /><glyph unicode="" glyph-name="check-mage" horiz-adv-x="1176" d="M996.617 833.214l-513.555-513.555-256.796 256.834-128.379-128.417 385.214-385.252 641.896 642.010z" /><glyph unicode="" glyph-name="clock" d="M512 919.040c-260.134 0-471.040-210.944-471.040-471.040 0-260.134 210.906-471.040 471.040-471.040s471.040 210.906 471.040 471.040c0 260.134-210.906 471.040-471.040 471.040zM512 79.36c-203.624 0-368.64 165.054-368.64 368.64s165.016 368.64 368.64 368.64 368.64-165.054 368.64-368.64-165.016-368.64-368.64-368.64zM547.84 714.24h-71.68v-281.069l174.345-174.345 50.669 50.707-153.335 153.335z" /><glyph unicode="" glyph-name="close-mage" horiz-adv-x="1176" d="M1094.391 882.29l-77.71 77.71-423.329-423.347-423.33 423.347-77.71-77.672 423.35-423.368-423.312-423.329 77.672-77.71 423.338 423.338 423.283-423.3 77.671 77.71-423.263 423.281z" /><glyph unicode="" glyph-name="delete" horiz-adv-x="1176" d="M337.541-61.004h513.024l64.512 645.916h-639.128l61.592-645.916zM737.394 805.831v116.508c0 19.191-15.398 34.702-34.361 34.702h-217.847c-19.001 0-34.361-15.55-34.361-34.702v-114.574c-73.576-8.382-150.149-24.614-226.494-52.338v-106.989h738.001v109.833c0 0-90.074 31.403-224.977 47.559zM668.937 812.241c-47.749 3.224-99.252 4.096-153.297 0.986v61.44c0 9.519 7.623 17.332 17.143 17.332h118.936c9.519 0 17.218-7.813 17.218-17.332v-62.426z" /><glyph unicode="" glyph-name="edit" horiz-adv-x="1176" d="M928.503 933.111l-111.502-112.109 156.065-156.9 111.502 112.071-156.065 156.937zM215.002 215.59l156.065-156.9 535.211 538.093-156.065 156.9-535.211-538.093zM103.917-47.161l188.985 49.873-139.302 140.098-49.683-190.009z" /><glyph unicode="" glyph-name="error" d="M1014.67 137.349c0 0 0 0 0 0l-310.651 310.651 310.651 310.651c0 0 0 0 0 0 3.337 3.337 5.765 7.244 7.32 11.416 4.248 11.378 1.82 24.69-7.32 33.83l-146.735 146.735c-9.14 9.14-22.452 11.567-33.83 7.32-4.172-1.555-8.078-3.982-11.416-7.32 0 0 0 0 0 0l-310.651-310.651-310.651 310.651c0 0 0 0 0 0-3.337 3.337-7.244 5.765-11.416 7.32-11.378 4.248-24.69 1.82-33.83-7.32l-146.735-146.735c-9.14-9.14-11.567-22.452-7.32-33.83 1.555-4.172 3.982-8.078 7.32-11.416 0 0 0 0 0 0l310.651-310.651-310.651-310.651c0 0 0 0 0 0-3.337-3.337-5.765-7.244-7.32-11.416-4.248-11.378-1.82-24.69 7.32-33.83l146.735-146.735c9.14-9.14 22.452-11.567 33.83-7.32 4.172 1.555 8.078 3.982 11.416 7.32 0 0 0 0 0 0l310.651 310.651 310.651-310.651c0 0 0 0 0 0 3.337-3.337 7.244-5.765 11.416-7.32 11.378-4.248 24.69-1.82 33.83 7.32l146.735 146.735c9.14 9.14 11.567 22.452 7.32 33.83-1.555 4.172-3.982 8.078-7.32 11.416z" /><glyph unicode="" glyph-name="help" horiz-adv-x="1176" d="M593.351 937.434c-270.336 0-489.434-219.098-489.434-489.358s219.098-489.434 489.434-489.434 489.434 219.136 489.434 489.434-219.136 489.358-489.434 489.358zM635.752 133.404c-11.985-11.719-26.396-17.636-43.16-17.636-8.154 0-15.967 1.517-23.4 4.589-7.358 3.034-13.843 7.168-19.456 12.174-5.613 5.158-10.126 11.226-13.388 18.356-3.337 7.13-4.968 14.753-4.968 22.945 0 16.308 5.992 30.303 17.977 42.060 11.947 11.681 26.396 17.598 43.198 17.598 16.308 0 30.606-5.689 42.78-16.801 12.25-11.188 18.318-24.993 18.318-41.339-0.038-16.384-5.992-30.303-17.939-41.984zM778.923 577.327c-3.982-13.767-9.747-26.396-17.18-37.774-7.471-11.454-16.498-22.49-27.079-33.071s-22.49-21.618-35.65-33.033c-11.454-9.785-20.783-18.318-27.913-25.79-7.168-7.396-12.895-14.867-17.218-22.338-4.286-7.433-7.282-15.398-9.026-24.007-1.707-8.609-2.617-49.721-2.617-62.35v-22.338h-101.376v32.616c0 13.729 0.986 56.661 3.034 67.584s5.158 21.125 9.481 30.872 10.012 19.228 17.18 28.369c7.168 9.14 16.232 18.887 27.079 29.203l38.647 36.902c10.847 9.747 20.177 20.632 27.951 32.616 7.737 12.060 11.529 26.7 11.529 43.88 0 22.3-6.978 41.036-21.011 56.206-14.071 15.17-33.944 22.793-59.695 22.793-13.16 0-25.069-2.389-35.65-7.282-10.619-4.817-19.797-11.454-27.496-19.759-7.737-8.344-13.577-17.901-17.598-28.786-3.982-10.847-6.334-21.997-6.865-33.527l-105.624 9.444c3.413 27.496 10.733 51.959 21.921 73.463 11.112 21.466 25.562 39.595 43.311 54.575 17.711 14.829 38.078 26.169 61.023 33.944 22.869 7.699 47.521 11.605 73.842 11.605 24.614 0 47.976-3.603 70.049-10.771 21.959-7.168 41.491-17.711 58.406-31.782 16.839-14.033 30.227-31.365 39.936-51.959 9.709-20.632 14.564-44.411 14.564-71.263 0-18.356-2.010-34.475-5.992-48.166z" /><glyph unicode="" glyph-name="history" d="M574.805 867.84c-227.631 0-412.71-182.386-418.247-409.335h-125.838l188.378-209.958 188.302 209.958h-146.242c5.537 168.998 143.777 304.393 313.647 304.393 173.359 0 313.875-140.971 313.875-314.899s-140.478-314.861-313.875-314.861c-69.518 0-133.727 22.718-185.761 61.099l-71.983-76.99c71.073-55.751 160.503-89.050 257.745-89.050 231.121 0 418.513 187.961 418.513 419.84-0.038 231.879-187.43 419.84-418.513 419.84zM537.6 673.28v-240.109l153.865-153.865 50.669 50.669-132.855 132.855v210.413h-71.68z" /><glyph unicode="" glyph-name="export" d="M383.462 382.49h255.693v213.043h127.795l-255.642 255.667-255.642-255.667h127.795zM852.173 382.49v-170.394h-681.754v170.394h-170.419v-340.89h1022.618v340.89z" /><glyph unicode="" glyph-name="import" d="M639.155 851.2h-255.693v-213.043h-127.795l255.667-255.667 255.616 255.667h-127.795zM852.173 382.49v-170.394h-681.754v170.394h-170.419v-340.89h1022.618v340.89z" /><glyph unicode="" glyph-name="dot" d="M505.139 959.915c-282.658-3.775-508.826-236.066-505.071-518.827 3.772-282.556 236.1-508.826 518.793-505.003 282.658 3.768 508.826 236.066 505.071 518.827-3.717 282.658-236.1 508.826-518.793 505.003z" /><glyph unicode="" glyph-name="not-installed" d="M510.413 960c-281.907 0-510.413-228.582-510.413-510.413 0-281.933 228.506-510.464 510.413-510.464s510.387 228.557 510.387 510.464c0 281.83-228.48 510.413-510.387 510.413zM865.843 449.587c0-69.99-20.506-135.27-55.578-190.285l-490.163 490.163c55.091 35.021 120.32 55.475 190.31 55.475 195.942 0 355.43-159.411 355.43-355.354zM154.957 449.587c0 69.939 20.506 135.245 55.578 190.31l490.189-490.189c-55.066-35.072-120.371-55.501-190.31-55.501-195.942-0.026-355.456 159.437-355.456 355.379z" /><glyph unicode="" glyph-name="disabled" d="M511.77 960c-282.778 0-512.102-229.222-512.102-512.179 0-282.829 229.325-512.102 512.102-512.102 282.931-0.026 512.23 229.248 512.23 512.102 0 282.957-229.299 512.179-512.23 512.179zM143.718 540.032h736.205v-184.269h-736.205v184.269z" /><glyph unicode="" glyph-name="menu-item" horiz-adv-x="903" d="M857.675 670.587l-403.18 240.514-402.726-240.514v-457.026l403.18-240.515 402.726 240.514v457.027zM454.857 95.535l-298.427 178.383v335.966l298.157 178.729 298.428-178.383v-335.966l-298.158-178.729z" /><glyph unicode="" glyph-name="tag" d="M904.192 959.973l-307.234-0.116-596.89-596.958 426.906-426.906 596.958 596.958-0.113 305.596-119.603 121.426zM858.679 646.663c-39.997-40.001-104.854-40.001-144.794 0-40.001 40.001-40.001 104.796 0 144.794 39.939 40.001 104.796 40.001 144.794 0 39.997-39.997 39.997-104.793 0-144.794z" /><glyph unicode="" glyph-name="camera" d="M982.767 728.098h-250.095l-59.255 121.364c0 0-11.827 25.201-42.11 25.201-23.375 0-169.366 0-235.25 0-32.969 0-44.001-25.027-44.001-25.027l-57.484-121.539h-253.406c-22.74 0-41.131-18.459-41.131-41.267v-624.333c0-22.743 18.401-41.199 41.131-41.199h941.636c22.74 0 41.199 18.459 41.199 41.199v624.299c0 22.798-18.456 41.267-41.199 41.267zM512 136.090c-138.793 0-251.597 113.015-251.597 251.931 0 138.912 112.845 251.87 251.597 251.87 138.68 0 251.597-112.981 251.597-251.87 0-138.909-112.913-251.931-251.597-251.931zM512 539.068c-83.255 0-150.972-67.714-150.972-150.972 0-83.197 67.71-150.903 150.972-150.903 83.258 0 150.903 67.714 150.903 150.903 0 83.255-67.652 150.972-150.903 150.972z" /><glyph unicode="" glyph-name="grid" d="M0.010 959.628h279.074v-279.074h-279.074zM372.77 959.628h279.074v-279.074h-279.074zM744.892 959.628h279.074v-279.074h-279.074zM0.010 587.503h279.074v-279.074h-279.074zM372.77 587.503h279.074v-279.074h-279.074zM744.892 587.503h279.074v-279.074h-279.074zM0.010 215.415h279.074v-279.074h-279.074zM372.77 215.415h279.074v-279.074h-279.074zM744.892 215.415h279.074v-279.074h-279.074z" /><glyph unicode="" glyph-name="list-menu" d="M0.010 771.516h1023.966v-136.509h-1023.966zM0.010 517.53h1023.966v-136.506h-1023.966zM0.010 260.983h1023.966v-136.513h-1023.966z" /><glyph unicode="" glyph-name="cart" d="M771.001 183.263c-55.445 0-100.448-44.754-100.448-100.2s44.879-100.324 100.448-100.324 100.448 44.879 100.448 100.324-45.003 100.2-100.448 100.2zM771.001 41.293c-23.123 0-41.77 18.648-41.77 41.771s18.647 41.77 41.77 41.77c23.247 0 41.895-18.648 41.895-41.77s-18.648-41.771-41.895-41.771zM469.532 183.263c-55.445 0-100.449-44.754-100.449-100.2s45.003-100.324 100.449-100.324c55.445 0 100.448 44.879 100.448 100.324s-45.003 100.2-100.448 100.2zM469.532 41.293c-23.123 0-41.771 18.648-41.771 41.771s18.648 41.77 41.771 41.77 41.77-18.648 41.77-41.77-18.648-41.771-41.77-41.771zM823.587 465.588c-130.036 0-238.441 91.622-264.547 213.825h-207.237l-136.749 198.162v1.865h-207.237v-83.541h169.942l78.693-117.729 83.417-412.857h581.183l49.23 243.786c-42.268-27.474-92.616-43.511-146.694-43.511zM1023.862 710.244v45.376l-55.073 18.026-12.929 31.204 24.863 52.71-31.95 32.074-5.967-2.984-45.5-23.123-31.328 12.929-19.642 54.948h-45.376l-2.114-6.464-15.912-48.608-31.203-12.929-52.835 24.863-32.074-31.95 3.108-5.967 23.247-45.624-13.053-31.328-54.948-19.766v-45.376l6.34-2.113 48.732-15.788 12.929-31.204-24.863-52.71 32.074-32.074 6.092 3.108 45.376 22.999 31.328-12.929 19.642-54.824h45.376l2.113 6.464 15.913 48.359 31.203 12.929 52.71-24.988 32.198 32.074-3.108 6.092-23.247 45.624 12.929 31.203 54.948 19.766zM824.582 668.473c-35.057 0-63.65 28.469-63.65 63.526 0 35.182 28.469 63.526 63.65 63.526s63.526-28.469 63.526-63.526c-0.124-35.182-28.469-63.526-63.526-63.526z" /><glyph unicode="" glyph-name="screen" horiz-adv-x="1159" d="M723.661 70.399c-2.404 10.843-4.034 21.47-5.282 31.583h-277.528c-2.458-20.233-6.917-43.087-14.646-64.305-7.79-21.277-18.796-40.54-33.824-54.15-15.028-13.552-33.689-22.104-59.788-22.158v-25.369h494.020v25.369c-26.142 0.058-44.737 8.61-59.838 22.158-22.44 20.307-35.961 53.91-43.114 86.873zM1126.214 960h-1093.209c-18.22 0-33.005-15.024-33.005-33.596v-731.259c0-18.576 14.785-33.623 33.005-33.623h1093.209c18.224 0 33.067 15.051 33.067 33.623v731.259c0 18.572-14.843 33.596-33.067 33.596zM1079.193 243.078h-999.234v635.394h999.234v-635.394z" /><glyph unicode="" glyph-name="video" horiz-adv-x="2041" d="M2041.366 958.898v-1021.449h-175.926l-411.263 409.297v204.59l411.263 407.568h175.926zM1305.997-29.076c0-19.377-15.608-34.924-34.856-34.924h-1236.279c-19.255 0-34.863 15.547-34.863 34.924v954.275c0 19.248 15.608 34.801 34.863 34.801h1236.279c19.248 0 34.856-15.553 34.856-34.801v-954.275z" /><glyph unicode="" glyph-name="revert" horiz-adv-x="1404" d="M1042.226 660.151h-598.393v299.849l-443.833-384.316 443.833-384.403v299.859h598.393c106.478 0 192.801-86.318 192.801-192.801s-86.318-192.796-192.801-192.796v-0.483l-452.707-0.005c-46.695-0.005-84.53-37.845-84.53-84.535 0-46.68 37.84-84.525 84.535-84.525 0.377 0 0.744 0.053 1.121 0.058h451.581c199.964 0 362.044 162.085 362.044 362.039 0 199.964-162.080 362.059-362.044 362.059z" /><glyph unicode="" glyph-name="clip" d="M939.616 811.616c112.512-112.448 112.512-294.816 0-407.264l-350.944-350.976c-12.512-12.544-32.736-12.544-45.248 0-12.576 12.512-12.576 32.704 0 45.248l346.432 346.464c87.488 87.488 87.488 229.248-0.064 316.768-87.36 87.488-229.248 87.488-316.736 0l-462.304-456.864c-62.496-62.464-62.496-163.776 0-226.24 62.496-62.496 163.744-62.496 226.24 0l466.88 461.344c37.44 37.44 37.44 98.336 0 135.776-37.44 37.408-98.304 37.408-135.744 0l-351.008-351.008c-12.512-12.512-32.736-12.512-45.248 0-12.512 12.544-12.512 32.736 0 45.28l350.976 350.976c62.432 62.464 163.744 62.464 226.24 0 62.496-62.496 62.496-163.776 0-226.272l-466.88-461.376c-87.296-87.328-229.408-87.328-316.736 0s-87.328 229.472 0 316.8l466.88 461.344c112.448 112.512 294.816 112.512 407.264 0z" /><glyph unicode="" glyph-name="module" horiz-adv-x="883" d="M793.271 737.4l-192.695 83.055v-80.482c-2.517-31.926-83.182-57.618-182.582-57.618-99.309 0-180.126 25.692-182.398 57.618h-0.318l-0.465 80.482-197.709-83.055 381.218-167.697 374.95 167.697zM265.959 841.886l-1.104-0.428c32.596-16.331 89.086-27.124 153.551-27.124 64.726 0 121.621 10.94 153.996 27.355l-1.168 0.512c18.811 9.3 29.664 20.34 29.664 32.264 0 32.713-81.606 59.114-182.492 59.114-100.759 0-182.806-26.401-182.806-59.114-0.003-12.007 11.295-23.218 30.36-32.579zM418.418 497.564l-418.418 191.009v-563.335l418.321-189.238 418.321 189.238v563.733l-418.224-191.407z" /><glyph unicode="" glyph-name="alert-round" d="M1023.959 454.912c-3.717 282.665-236.121 508.842-518.817 505.040-282.689-3.772-508.866-236.091-505.094-518.868 3.772-282.58 236.121-508.842 518.813-505.040 282.689 3.772 508.866 236.067 505.098 518.868zM580.086 55.641h-136.149v136.163h136.149v-136.163zM597.168 666.258l-44.103-388.928h-83.113l-43.099 388.928v171.575h170.318v-171.575z" /></font></defs></svg> \ No newline at end of file +<svg xmlns="http://www.w3.org/2000/svg"><metadata>Generated by IcoMoon</metadata><defs><font id="icomoon" horiz-adv-x="1024"><font-face units-per-em="1024" ascent="960" descent="-64"/><missing-glyph horiz-adv-x="1024"/><glyph unicode=" " horiz-adv-x="512" d=""/><glyph unicode="" glyph-name="account" horiz-adv-x="1090" d="M709.921 801.306c8.139-32.295 8.927-34.974 8.192-68.162-0.263-12.813-7.772-71.943-5.724-90.112 1.628-14.966 5.461-16.174 11.448-28.514 10.398-21.425 6.984-51.095 2.941-72.678-2.206-11.868-6.827-28.725-13.916-38.387-7.667-10.66-23.211-10.713-30.142-23.158-9.872-17.854-4.306-43.008-10.503-62.385-7.142-21.898-25.101-23.421-26.466-52.145 8.822-1.155 17.592-2.468 26.466-3.623 8.822-18.59 25.049-55.874 41.59-67.059 13.863-3.728 27.727-7.457 41.59-11.185 48.627-19.64 102.558-43.061 151.237-63.33 44.373-18.432 97.411-24.996 113.48-70.84 0-31.035 2.941-104.501 2.153-145.25h-965.553c-0.893 40.697 2.153 114.215 2.153 145.25 15.964 45.844 69.002 52.408 113.375 70.84 48.679 20.27 102.61 43.691 151.237 63.33 13.811 3.728 27.674 7.457 41.59 11.185 16.489 11.185 32.715 48.522 41.538 67.059l19.692 4.621c-4.464 24.576-19.85 26.466-26.256 43.743-2.521 26.099-5.041 52.145-7.509 78.192 0.053-1.155-18.117 3.361-20.48 4.779-25.731 15.806-26.204 80.24-28.725 107.021-1.103 12.183 16.174 22.265 11.343 44.636-28.094 131.44 12.183 192.88 75.881 213.307 44.216 17.749 126.871 50.465 203.855 3.728l19.167-17.487 30.93-5.251c15.491-8.77 25.416-38.124 25.416-38.124z"/><glyph unicode="" glyph-name="arrowdown" horiz-adv-x="1085" d="M529.203 73.86l-468.465 628.209h936.931l-468.465-628.209z"/><glyph unicode="" glyph-name="cms" horiz-adv-x="1034" d="M976.793-22.006h-910.388v910.388h910.388v-910.388zM912.622 824.211h-782.046v-782.088h782.046v782.088zM221.432 137.2h152.876v372.033h-152.876v-372.033zM466.323 139.766h350.932v366.53h-350.932v-366.53zM221.432 599.511h595.865v147.125h-595.865v-147.125z"/><glyph unicode="" glyph-name="customers" horiz-adv-x="489" d="M264.319 651.169c75.685 0 136.98 61.259 136.98 136.944 0 75.649-61.295 136.98-136.98 136.98s-137.017-61.331-137.017-136.98c0-75.649 61.331-136.944 137.017-136.944zM448.929 589.149c-28.962 28.926-63.325 46.252-187.655 46.252s-157.859-18.776-185.335-46.252c-27.44-27.44-18.196-320.43-18.196-320.43l60.824 144.411 38.241-430.334 110.23 220.278 102.907-220.278 36.393 430.334 60.824-144.411c-0.036 0 10.693 291.468-18.233 320.43z"/><glyph unicode="" glyph-name="dashboard" horiz-adv-x="1376" d="M680.975 886.272c-337.523 0-610.976-273.515-611.038-610.976 0.122-37.72 1.039-251.812 1.039-251.812h1219.997c0 0 0.978 239.219 1.039 251.812-0.183 337.523-273.637 610.976-611.038 610.976zM737.708 762.169c31.117-3.607 61.379-10.271 90.418-19.624l-19.93-61.685c-25.004 8.070-51.169 13.939-78.191 16.995l7.703 64.313zM270.091 286.85h-64.864c0 31.423 3.118 62.235 8.803 92.007l63.702-12.349c-5.135-25.799-7.642-52.392-7.642-79.658zM305.855 455.581l-59.178 26.288c12.655 28.489 28 55.449 45.79 80.636l52.942-37.475c-15.284-21.825-28.611-45.056-39.554-69.449zM407.46 594.845l-43.405 48.113c22.925 20.541 47.807 39.187 74.462 54.96l33.318-55.571c-22.987-13.755-44.567-29.65-64.374-47.501zM536.943 742.545c29.039 9.292 59.178 16.017 90.418 19.624l7.581-64.313c-26.838-3.057-53.003-8.926-78.13-16.995l-19.869 61.685zM761.673 158.468l-152.897-27.205-38.881 150.452 395.172 404.22-203.394-527.467zM1019.476 525.029l52.942 37.414c17.79-25.187 33.257-52.148 45.851-80.636l-59.178-26.288c-10.943 24.454-24.209 47.685-39.615 69.51zM1094.916 286.85c0 27.266-2.69 53.859-7.703 79.658l63.702 12.349c5.808-29.834 8.803-60.645 8.803-92.007h-64.802zM646.006 189.341c26.777-17.056 62.174-9.415 79.291 17.24 17.118 26.593 9.292 62.051-17.301 79.108-26.655 17.24-62.051 9.354-79.23-17.362-17.118-26.349-9.476-61.99 17.24-78.986z"/><glyph unicode="" glyph-name="filter" d="M24.097 846.535h972.827v-111.922l-410.504-412.792v-238.366l-171.447-87.505v325.871l-390.875 415.877v108.837z"/><glyph unicode="" glyph-name="logo" horiz-adv-x="903" d="M454.495 911.101l-402.697-240.513v-457.026l104.632-60.727v457.049l298.157 178.728 299.698-179.142-0.138-455.922 103.528 60.013v457.026l-403.18 240.513zM507.766 629.72v-534.344l-53.271-32.124-53.34 32.262v533.792l-138.090-83.853v-456.934l191.453-115.516 193.087 116.322v456.451l-139.839 83.945z"/><glyph unicode="" glyph-name="notification-02" horiz-adv-x="989" d="M870.821 228.163c-64.195 65.89-78.231 188.772-91.738 283.159-20.074 139.937-24.259 297.089-226.008 317.693v25.318c0 25.424-39.195 46.028-64.937 46.028s-62.024-20.551-62.024-46.028v-25.371c-200.054-20.816-206.993-177.914-226.855-317.693-13.453-94.439-27.331-217.268-91.049-283.264-12.818-13.348-16.473-32.998-9.11-49.947 7.362-16.843 24.153-27.913 42.797-27.913h695.343c18.75 0 35.593 11.070 42.903 28.019s3.655 36.653-9.322 50zM489.569-3.883c51.060 0 92.373 40.837 92.373 91.367h-184.694c-0.053-50.53 41.314-91.367 92.32-91.367z"/><glyph unicode="" glyph-name="product" horiz-adv-x="954" d="M252.137 806.772l-160.070-92.393 378.042-218.205 160.023 92.393-377.996 218.205zM845.638 712.937l-377.996 218.252-145.222-83.828 377.996-218.205 145.222 83.782zM502.784 433.85v-433.664l376.832 217.507v433.711l-376.832-217.553zM55.668 217.74l376.785-217.507v436.503l-376.785 217.46v-436.457z"/><glyph unicode="" glyph-name="promotions" horiz-adv-x="1170" d="M59.153 425.818l164.053-38.141v303.902l-164.053-38.141v-227.621zM1122.198 900.847l-837.712-194.959v-335.978l140.328-376.832 151.712 57.45-104.049 279.113 649.668-151.18v722.385z"/><glyph unicode="" glyph-name="reports" horiz-adv-x="991" d="M736.707-21.234h207.134v322.703h-207.134v-322.703zM399.646-21.234h207.134v946.793h-207.134v-946.793zM62.673-21.19h207.134v634.704h-207.134v-634.704z"/><glyph unicode="" glyph-name="sales" horiz-adv-x="659" d="M426.502 347.483c-15.866 13.512-42.796 25.753-80.79 36.723v-198.774c11.535 1.459 23.729 4.331 36.299 8.851 12.618 4.426 23.87 10.829 33.804 19.068 9.981 8.427 18.173 18.55 24.529 30.649 6.638 12.006 9.651 26.365 9.651 42.89 0.047 26.836-7.721 47.222-23.493 60.593zM576.736 223.144c-7.109-23.117-19.774-45.762-38.135-67.749-18.503-22.175-43.079-41.855-74.010-58.992-30.885-17.373-70.432-27.683-118.878-31.12v-88.088h-57.014v88.088c-72.080 5.603-128.483 29.237-169.113 71.374-40.536 42.090-63.935 104.095-70.432 185.544h136.251c-0.753-39.359 8.992-70.479 28.86-93.266 20.15-22.74 44.774-37.335 74.434-43.455v216.523c-3.060 1.318-7.486 2.919-12.994 4.567-5.508 1.789-11.393 3.343-17.938 4.708-23.776 6.827-47.175 15.019-70.291 24.294-23.493 9.369-44.114 21.704-62.523 37.335-18.456 15.584-33.098 34.84-43.879 57.956-11.111 23.211-16.478 51.977-16.478 86.487 0 35.31 6.168 66.336 18.785 93.313 12.665 26.836 29.143 49.529 49.858 67.702 20.621 18.314 44.303 32.58 71.468 42.419 27.071 10.122 55.037 16.149 83.992 18.314v79.66h57.014v-79.66c29.143-3.531 56.308-10.169 81.638-20.292 25.423-10.028 47.787-23.729 67.137-41.478 19.585-17.514 35.357-39.453 47.457-65.771 12.288-26.13 19.35-57.109 21.28-93.172h-137.287c-0.518 27.636-8.616 51.082-23.917 70.432-15.725 19.303-34.275 29.002-56.308 29.002v-183.331c7.862-2.072 15.631-4.143 23.729-6.12 8.098-2.072 16.525-4.567 25.565-7.297 47.645-13.983 84.415-31.12 110.168-51.318 25.8-20.292 44.726-41.666 56.92-63.653 12.335-22.175 19.633-44.256 21.704-66.336 2.448-22.081 3.531-41.713 3.531-59.039 0.047-15.207-3.531-34.416-10.593-57.579zM228.905 696.585c-8.38-7.156-15.113-16.196-19.962-26.883-4.802-10.781-7.062-23.352-7.062-37.759 0-22.834 6.733-40.536 20.103-52.824 13.653-12.618 35.734-22.552 66.713-30.131v168.831c-10.829 0-21.516-1.695-31.826-5.226-10.216-3.437-19.633-8.851-27.966-16.007z"/><glyph unicode="" glyph-name="search" horiz-adv-x="1109" d="M555.139 938.358c-218.775 71.601-457.062-40.29-532.231-250.028-75.227-209.681 41.211-437.665 259.928-509.208 218.717-71.601 457.004 40.348 532.231 250.028s-41.211 437.665-259.928 509.208zM320.076 282.955c-158.915 52.089-243.467 217.681-188.903 369.978 54.679 152.296 227.754 233.625 386.669 181.593s243.409-217.624 188.788-369.92c-54.622-152.296-227.696-233.567-386.554-181.65zM638.482 274.206l358.927-349.602 24.807 69.241 24.865 69.241-310.348 302.29z"/><glyph unicode="" glyph-name="stores" horiz-adv-x="1280" d="M1098.281 874.55c19.777 3.723 34.901 21.232 34.901 42.347-0.058 23.791-19.196 43.103-42.812 43.103h-900.508c-23.675 0-42.754-19.312-42.754-43.103 0-21.057 15.007-38.566 34.843-42.347l-181.951-354.421v-68.988c0-30.946 32.516-56.016 72.594-56.016 13.437 0 26.001 2.908 36.821 7.795v-466.919h1061.286v466.919c10.878-4.944 23.326-7.795 36.879-7.795 40.078 0 72.594 25.071 72.594 56.016v68.988l-181.893 354.421zM214.758 395.125c-38.217 0-69.221 25.071-69.221 56.016v6.457h-0.349v62.531l137.162 353.665h109.648l-107.961-353.665v-68.988c0 0 0 0 0 0 0-30.946-31.004-56.016-69.279-56.016zM498.447 395.125c-38.217 0-69.221 25.071-69.221 56.016v68.988l57.354 353.665h109.241l-28.095-353.665v-68.93c-0.058-31.004-31.004-56.075-69.279-56.075zM782.077 395.125c-38.217 0-69.162 25.071-69.162 56.016v68.988l-28.154 353.665h108.892l57.296-353.665v-68.988c0-0.931 0.175-1.92 0.233-2.792-1.803-29.666-32.051-53.224-69.104-53.224zM1134.637 451.141c0-30.946-31.004-56.016-69.221-56.016s-69.162 25.071-69.162 56.016v68.988l-108.019 353.665h109.59l137.22-353.665v-62.473h-0.349v-6.515h-0.058z"/><glyph unicode="" glyph-name="views" horiz-adv-x="1890" d="M944.97 630.958c-97.861 0-177.522-79.581-177.522-177.443 0-97.94 79.66-177.679 177.522-177.679 98.019 0 177.679 79.739 177.679 177.679 0 97.861-79.66 177.443-177.679 177.443zM944.97 960c-470.712 0-944.97-512-944.97-512s474.258-512 944.97-512c470.949 0 945.128 512 945.128 512s-474.179 512-945.128 512zM944.97 91.144c-200.057 0-362.292 162.078-362.292 362.45 0 200.057 162.236 362.292 362.292 362.292 200.214 0 362.45-162.236 362.45-362.292 0-200.451-162.236-362.45-362.45-362.45z"/><glyph unicode="" glyph-name="system-config" d="M1020.032 394.445v116.045l-16.41 5.376-124.237 40.525-33.152 80.102 63.718 134.784-82.048 82.125-15.411-7.808-116.531-59.213-80.077 33.178-50.278 140.442h-116.096l-45.875-140.698-80-33.126-134.963 63.744-82.022-82.074 7.834-15.334 59.162-116.608-33.126-80.026-140.518-50.253v-116.147l16.435-5.325 124.288-40.576 33.075-80-63.693-134.886 82.048-82.099 131.942 66.97 80.026-33.152 50.304-140.39h116.096l5.35 16.41 40.55 124.237 80.077 33.178 134.886-63.718 82.074 82.074-7.834 15.386-59.213 116.582 33.203 80.026 140.416 50.253zM510.003 287.411c-89.754 0-162.509 72.832-162.509 162.611 0 89.754 72.755 162.483 162.509 162.483 89.83 0 162.509-72.73 162.509-162.483 0.026-89.805-72.653-162.611-162.509-162.611z"/><glyph unicode="" glyph-name="home" d="M509.978 905.574l-509.978-509.926 95.949-95.949 414.106 413.978 413.875-413.978 95.949 95.898-509.901 509.978zM146.253 271.437v-335.437h259.917v304.819h207.514v-304.819h259.917v335.488l-363.622 363.597-363.725-363.648z"/><glyph unicode="" glyph-name="lego" d="M0 223.59l498.278-287.59v421.402l-498.278 287.667v-421.478zM894.464 735.514v-44.262c0-32.819-62.797-59.418-140.365-59.418-77.466 0-140.262 26.598-140.262 59.418v73.216h0.435c4.71-30.925 65.408-55.475 139.853-55.475 77.568 0 140.365 26.624 140.365 59.29 0 32.845-62.797 59.366-140.365 59.366-6.195 0-12.262-0.205-18.202-0.563l-90.317 52.147v-55.706c0-32.819-62.72-59.392-140.262-59.392-48.691 0-91.597 10.496-116.813 26.47-3.584 3.712-7.987 7.245-13.312 10.598-6.579 6.861-10.24 14.387-10.24 22.323v53.939l-87.322-50.381c-6.272 0.307-12.646 0.614-19.123 0.614-77.491 0-140.314-26.522-140.314-59.366 0-32.691 62.822-59.29 140.314-59.29 74.445 0 135.219 24.525 139.93 55.475h0.384v-73.216c0-32.819-62.746-59.418-140.314-59.418-77.491 0-140.314 26.598-140.314 59.418v43.622l-108.083-62.31 499.994-288.563 496.691 286.694-112.358 64.768zM646.784 551.987c0-32.794-62.874-59.315-140.365-59.315s-140.339 26.522-140.339 59.315v73.267h0.41c4.762-30.95 65.459-55.475 139.93-55.475s135.142 24.525 139.904 55.475h0.486v-73.267zM525.645 353.766v-417.766l498.355 287.718v417.766l-498.355-287.718zM505.318 841.344c77.542 0 140.262 26.547 140.262 59.315s-62.72 59.315-140.262 59.315c-77.491 0-140.339-26.573-140.339-59.315-0.026-32.768 62.822-59.315 140.339-59.315z"/><glyph unicode="" glyph-name="tool" d="M287.002 478.336c0.205-0.23 0.461-0.486 0.691-0.717l103.347-103.373 36.045 36.045-56.55 56.499 90.266 90.189 11.904-1.28c3.046-0.307 6.093-0.538 9.19-0.538 6.246 0 12.314 0.768 18.253 2.125l-66.381 66.381c-1.357 1.382-2.765 2.611-4.173 3.814 20.454 73.6 1.766 155.725-56.038 213.555-57.421 57.421-138.803 76.237-211.968 56.525l123.955-123.981-32.563-121.446-121.395-32.589-124.032 124.006c-19.712-73.19-0.896-154.573 56.525-212.019 60.262-60.288 147.021-77.952 222.925-53.197zM653.235 404.198c-1.997-8.909-2.509-18.202-1.459-27.546l1.306-11.93-90.189-90.189-56.55 56.55-36.070-36.122 327.219-327.194c20.198-20.173 46.618-30.259 73.062-30.259s52.915 10.086 73.037 30.259c40.346 40.32 40.346 105.728 0 146.074l-290.355 290.355zM905.907 1.638l-51.866-13.875-42.112 42.112 13.901 51.891 51.866 13.926 42.112-42.138-13.901-51.917zM506.701 365.901l56.576-56.576 64.128 64.154c-3.482 31.334 6.707 63.821 30.669 87.808 24.013 23.962 56.474 34.176 87.808 30.72l280.397 280.346-157.056 157.056-280.448-280.397c3.482-31.258-6.682-63.821-30.669-87.782-24.013-23.987-56.525-34.176-87.808-30.643l-64.102-64.205 56.499-56.422-277.043-277.12-10.138 10.138-53.248-42.829-89.421-141.312 22.835-22.835 141.312 89.421 42.803 53.222-10.138 10.138 277.043 277.12z"/><glyph unicode="" glyph-name="upgrade" d="M1023.932 454.895c-3.717 282.692-236.1 508.826-518.793 505.003-282.658-3.775-508.826-236.066-505.071-518.827 3.772-282.556 236.1-508.826 518.793-505.003 282.658 3.768 508.826 236.066 505.071 518.827zM623.991 478.696v-298.633h-223.983v298.633h-186.621l298.633 298.633 298.667-298.633h-186.679z"/><glyph unicode="" glyph-name="expand-close" d="M512.794 960c-283.187 0-512.794-229.581-512.794-512.794 0-283.187 229.606-512.794 512.794-512.794s512.794 229.632 512.794 512.794c0 283.213-229.581 512.794-512.794 512.794zM512.794-11.213c-253.158 0-458.394 205.261-458.394 458.368 0 253.158 205.261 458.394 458.394 458.394 253.184 0 458.394-205.235 458.394-458.394 0.026-253.107-205.21-458.368-458.394-458.368zM760.013 334.387l30.387 38.4-265.6 206.413-20.787 1.613-259.226-208.026 28.826-39.987 236.8 177.613z"/><glyph unicode="" glyph-name="expand-open" d="M512.794 960c-283.187 0-512.794-229.581-512.794-512.794 0-283.187 229.606-512.794 512.794-512.794s512.794 229.606 512.794 512.794c0 283.213-229.581 512.794-512.794 512.794zM512.794-11.213c-253.158 0-458.394 205.261-458.394 458.394 0 253.158 205.261 458.394 458.394 458.394 253.184 0 458.394-205.235 458.394-458.394 0.026-253.133-205.21-458.394-458.394-458.394zM265.6 505.6l-30.387-38.4 265.574-206.387 20.813-1.613 259.2 208-28.8 39.987-236.8-177.587z"/><glyph unicode="" glyph-name="gripper" d="M259.2 960h214.323v-214.323h-214.323v214.323zM259.2 690.125h214.323v-214.349h-214.323v214.349zM259.2 420.224h214.323v-214.349h-214.323v214.349zM259.2 150.349h214.323v-214.349h-214.323v214.349zM549.325 960h214.323v-214.323h-214.323v214.323zM549.325 690.125h214.323v-214.349h-214.323v214.349zM549.325 420.224h214.323v-214.349h-214.323v214.349zM549.325 150.349h214.323v-214.349h-214.323v214.349z"/><glyph unicode="" glyph-name="forward" d="M860.058 774.938v-272l-430.029 269.158-1.894-253.491-424.371 249.754-3.763-647.834 426.24 241.28-5.606-239.437 439.424 252.16v-259.635h163.942v660.045z"/><glyph unicode="" glyph-name="backward" d="M163.942 114.893v271.974l430.029-269.133 1.894 253.491 424.397-249.754 3.738 647.834-426.24-241.28 5.606 239.437-439.424-252.16v259.635h-163.942v-660.045z"/><glyph unicode="" glyph-name="info" d="M505.704 919.002c-260.096-3.489-468.158-217.202-464.706-477.336 3.489-259.982 217.202-468.12 477.298-464.631s468.158 217.202 464.706 477.336c-3.413 260.058-217.202 468.12-477.298 464.631zM557.928 762.027c47.863 0 62.009-27.762 62.009-59.544 0-39.671-31.782-76.383-86.016-76.383-45.359 0-66.901 22.831-65.65 60.53 0 31.782 26.624 75.435 89.657 75.435zM435.162 153.619c-32.73 0-56.661 19.873-33.792 107.217l37.547 154.814c6.485 24.841 7.585 34.778 0 34.778-9.785 0-52.262-17.143-77.407-34.057l-16.346 26.776c79.607 66.446 171.16 105.472 210.375 105.472 32.73 0 38.153-38.722 21.807-98.266l-43.008-162.816c-7.585-28.786-4.286-38.722 3.262-38.722 9.785 0 41.984 11.871 73.614 36.75l18.47-24.841c-77.369-77.369-161.792-107.179-194.56-107.179z"/><glyph unicode="" glyph-name="lock" d="M591.986 511.981h-16.005v192.019c0 105.851-86.13 192.019-192.019 192.019h-128c-105.851 0-192.019-86.13-192.019-192.019v-192.019h-16.005c-26.396 0-48.014-21.618-48.014-48.014v-479.991c0-26.396 21.618-48.014 48.014-48.014h544.009c26.396 0 48.014 21.618 48.014 48.014v479.991c0 26.396-21.618 48.014-48.014 48.014zM384 64h-128l27.838 139.188c-16.801 11.529-27.838 30.872-27.838 52.793 0 35.347 28.672 64.019 64.019 64.019s64.019-28.672 64.019-64.019c0-21.921-11.036-41.263-27.838-52.793l27.838-139.188zM448.019 511.981h-256v192.019c0 35.271 28.71 64.019 64.019 64.019h128c35.271 0 64.019-28.71 64.019-64.019v-192.019z"/><glyph unicode="" glyph-name="loop" d="M870.4 642.56h-194.56v-143.36h153.6v-215.040h-634.88v215.040h215.040v-112.64l204.8 184.32-204.8 184.32v-112.64h-256c-56.51 0-102.4-45.815-102.4-102.4v-296.96c0-56.51 45.89-102.4 102.4-102.4h716.8c56.585 0 102.4 45.89 102.4 102.4v296.96c0 56.585-45.815 102.4-102.4 102.4z"/><glyph unicode="" glyph-name="plus" d="M991.991 576h-351.991v351.991c0 17.673-14.336 32.009-32.009 32.009h-192.019c-17.673 0-32.009-14.336-32.009-32.009v-351.991h-351.991c-17.673 0-32.009-14.336-32.009-32.009v-192.019c0-17.673 14.336-32.009 32.009-32.009h351.991v-351.991c0-17.673 14.336-32.009 32.009-32.009h192.019c17.673 0 32.009 14.336 32.009 32.009v351.991h351.991c17.673 0 32.009 14.336 32.009 32.009v192.019c0 17.673-14.336 32.009-32.009 32.009z"/><glyph unicode="" glyph-name="recover" d="M505.704 919.002c-260.096-3.489-468.158-217.126-464.706-477.298 3.489-260.21 217.202-468.158 477.298-464.744 260.134 3.489 468.233 217.202 464.706 477.298-3.489 260.21-217.202 468.233-477.298 464.744zM506.577 857.6c70.163 0.986 136.382-15.853 194.56-46.118l-63.374-105.662c-38.002 18.47-80.631 28.937-125.762 28.937-45.056 0-87.723-10.43-125.687-28.975l-63.336 105.624c54.993 28.672 117.343 45.321 183.599 46.232zM254.255 322.313l-105.586-63.298c-28.672 54.955-45.321 117.305-46.194 183.486-0.986 70.201 15.853 136.457 46.118 194.56l105.624-63.45c-18.546-37.926-28.975-80.555-28.975-125.649 0-45.056 10.43-87.723 28.975-125.687zM517.461 38.438c-70.163-0.986-136.457 15.853-194.56 46.118l63.374 105.662c38.002-18.546 80.631-28.975 125.687-28.975 45.094 0 87.761 10.392 125.687 28.937l63.336-105.586c-54.993-28.634-117.305-45.246-183.561-46.194zM512 222.758c-124.397 0-225.242 100.883-225.242 225.242 0 124.397 100.883 225.28 225.242 225.28 124.473 0 225.28-100.883 225.28-225.28s-100.807-225.242-225.28-225.242zM769.745 322.313c18.546 38.002 28.975 80.631 28.975 125.687 0 45.094-10.43 87.723-28.975 125.687l105.586 63.374c28.672-54.993 45.359-117.305 46.232-183.561 0.91-70.201-15.929-136.457-46.194-194.56l-105.624 63.336z"/><glyph unicode="" glyph-name="refresh" horiz-adv-x="1176" d="M906.126 824.187v0c-91.174 75.89-202.487 113.171-312.548 113.057-127.014 0.038-253.611-49.683-348.16-145.636l-95.004 79.265-1.593-305.342 300.184 56.282-99.442 82.944c67.546 64.247 155.269 97.204 244.015 97.28 79.948-0.038 159.782-26.7 226.114-81.806 84.347-70.125 127.659-170.629 127.772-272.46-0.038-14.715-0.948-29.431-2.769-44.070l137.519 26.283c0.19 5.954 0.303 11.871 0.303 17.787 0.152 140.098-60.151 279.78-176.431 376.415zM839.035 193.024c-67.736-65.498-156.255-99.025-245.912-99.1-79.986 0.038-159.82 26.738-226.114 81.806-84.347 70.125-127.697 170.629-127.772 272.498 0 16.839 1.252 33.716 3.679 50.366l-138.164-25.941c-0.379-8.116-0.683-16.346-0.683-24.462-0.114-140.174 60.226-279.817 176.545-376.491 91.136-75.852 202.411-113.057 312.51-112.981h0.341c127.924 0 255.241 50.441 349.943 147.759l90.795-75.207 0.569 305.38-299.956-57.344 104.183-86.281z"/><glyph unicode="" glyph-name="remove-small" horiz-adv-x="1176" d="M593.351 938.268c-270.753 0-490.268-219.477-490.268-490.231s219.515-490.268 490.268-490.268 490.231 219.515 490.231 490.268c0 270.753-219.477 490.231-490.231 490.231zM828.947 276.347l-72.363-72.363-162.095 162.133-164.902-164.902-73.121 73.121 164.902 164.902-161.678 161.678 72.363 72.325 161.602-161.678 165.774 165.736 73.121-73.083-165.774-165.736 162.171-162.133z"/><glyph unicode="" glyph-name="retweet" d="M254.976 284.16v267.264h103.424l-179.2 203.776-179.2-203.776h103.424v-308.224c0-56.51 45.815-102.4 102.4-102.4h459.776l-131.186 143.36h-279.438zM920.538 344.576v308.224c0 56.51-45.89 102.4-102.4 102.4h-459.738l131.11-143.36h279.514v-267.264h-103.424l179.2-203.776 179.2 203.776h-103.462z"/><glyph unicode="" glyph-name="unlocked" d="M768 895.981h-128c-105.851 0-192.019-86.13-192.019-192.019v-192.019h-400.005c-26.396 0-48.014-21.618-48.014-48.014v-479.991c0-26.396 21.618-48.014 48.014-48.014h544.009c26.396 0 48.014 21.618 48.014 48.014v479.991c0 26.396-21.618 48.014-48.014 48.014h-16.005v192.019c0 35.271 28.71 64.019 64.019 64.019h128c35.271 0 64.019-28.71 64.019-64.019v-192.019h128v192.019c0 105.851-86.13 192.019-192.019 192.019zM384 64h-128l27.838 139.188c-16.801 11.529-27.838 30.872-27.838 52.793 0 35.347 28.672 64.019 64.019 64.019s64.019-28.672 64.019-64.019c0-21.921-11.036-41.263-27.838-52.793l27.838-139.188z"/><glyph unicode="" glyph-name="warning" horiz-adv-x="1176" d="M593.351 960l-593.351-1023.962h1186.74l-593.351 1023.962zM653.236 60.549h-125.421v121.211h125.421v-121.211zM622.175 231.671h-62.502l-34.816 288.313v156.748h131.3v-156.748l-33.982-288.313z"/><glyph unicode="" glyph-name="arrow-left" d="M0 448l512-512v320.019h512v384h-512v320.019z"/><glyph unicode="" glyph-name="arrow-right" d="M1024 448l-512 512v-320.019h-512v-384h512v-320.019z"/><glyph unicode="" glyph-name="back-arrow" d="M402.735 813.265l-320.019-320.019c-24.993-24.993-24.993-65.498 0-90.491l320.019-320.019c24.993-24.993 65.498-24.993 90.491 0s24.993 65.498 0 90.491l-210.754 210.754h613.49c35.347 0 64.019 28.634 64.019 64.019s-28.672 64.019-64.019 64.019h-613.49l210.754 210.754c12.478 12.478 18.735 28.862 18.735 45.246s-6.258 32.768-18.735 45.246c-24.993 24.993-65.498 24.993-90.491 0z"/><glyph unicode="" glyph-name="calendar" horiz-adv-x="1176" d="M507.259 381.478h-102.059v-101.717h102.059v101.717zM650.885 245.286h-101.945v-101.717h101.945v101.717zM507.259 245.286h-102.059v-101.717h102.059v101.717zM507.259 517.67h-102.059v-101.679h102.059v101.679zM843.131 715.909c23.4 0 42.287 18.887 42.287 42.174v145.408c0 23.324-18.887 42.174-42.287 42.174s-42.325-18.849-42.325-42.174v-145.408c0.038-23.324 18.925-42.174 42.325-42.174zM343.419 715.909c23.362 0 42.249 18.887 42.249 42.174v145.408c0 23.324-18.887 42.174-42.249 42.174-23.4 0-42.325-18.849-42.325-42.174v-145.408c0-23.324 18.925-42.174 42.325-42.174zM363.444 381.478h-102.059v-101.717h102.059v101.717zM363.444 245.286h-102.059v-101.717h102.059v101.717zM650.885 381.478h-101.945v-101.717h101.945v101.717zM938.325 381.478h-102.059v-101.717h102.059v101.717zM938.325 517.67h-102.059v-101.679h102.059v101.679zM899.337 875.615v-46.914c17.598-15.474 28.71-38.153 28.71-63.412 0-46.801-37.964-84.764-84.916-84.764s-84.954 37.964-84.954 84.764c0 25.259 11.15 47.938 28.71 63.412v46.914h-387.262v-46.914c17.56-15.474 28.71-38.153 28.71-63.412 0-46.801-38.002-84.764-84.916-84.764s-84.954 37.964-84.954 84.764c0 25.259 11.15 47.938 28.71 63.412v46.914h-192.322v-925.279h997.035v925.279h-192.512zM999.234 44.696h-809.832v589.938h809.832v-589.938zM650.885 517.67h-101.945v-101.679h101.945v101.679zM794.624 517.67h-101.983v-101.679h101.983v101.679zM794.624 245.286h-101.983v-101.717h101.983v101.717zM794.624 381.478h-101.983v-101.717h101.983v101.717z"/><glyph unicode="" glyph-name="caret-down" d="M132.21 673.242c-13.881 13.729-36.295 13.729-50.138 0-13.805-13.653-13.805-35.878 0-49.607l404.897-400.877c13.881-13.729 36.257-13.729 50.138 0l404.897 400.877c13.805 13.729 13.881 35.878 0 49.607s-36.371 13.729-50.138 0.038l-379.866-365.606-379.79 365.568z"/><glyph unicode="" glyph-name="caret-left" d="M737.242 68.21c13.729-13.881 13.729-36.257 0-50.138s-35.878-13.881-49.607 0l-400.877 404.821c-13.729 13.881-13.729 36.295 0 50.138l400.877 404.897c13.729 13.881 35.878 13.881 49.607 0s13.729-36.257 0-50.138l-365.568-379.79 365.568-379.79z"/><glyph unicode="" glyph-name="caret-right" d="M286.72 68.21c-13.729-13.881-13.729-36.257 0-50.138s35.878-13.881 49.607 0l400.877 404.821c13.729 13.881 13.729 36.295 0 50.138l-400.915 404.897c-13.729 13.881-35.878 13.881-49.607 0s-13.729-36.257 0-50.138l365.568-379.79-365.568-379.79z"/><glyph unicode="" glyph-name="caret-up" d="M891.79 222.758c13.881-13.729 36.295-13.729 50.138 0 13.881 13.729 13.881 35.878 0 49.607l-404.897 400.877c-13.805 13.729-36.257 13.729-50.062 0l-404.897-400.877c-13.805-13.729-13.881-35.878 0-49.607s36.257-13.729 50.138 0l379.79 365.606 379.79-365.606z"/><glyph unicode="" glyph-name="ccw" d="M574.767 867.84c-227.593 0-412.672-182.386-418.247-409.335h-125.8l188.378-209.92 188.302 209.92h-146.242c5.537 168.998 143.777 304.393 313.609 304.393 173.397 0 313.913-140.971 313.913-314.899s-140.478-314.861-313.913-314.861c-69.48 0-133.689 22.718-185.685 61.099l-71.983-76.99c70.997-55.751 160.465-89.050 257.707-89.050 231.159 0 418.551 187.961 418.551 419.84-0.038 231.879-187.43 419.84-418.551 419.84z"/><glyph unicode="" glyph-name="check-mage" horiz-adv-x="1176" d="M996.617 833.214l-513.555-513.555-256.796 256.834-128.379-128.417 385.214-385.252 641.896 642.010z"/><glyph unicode="" glyph-name="clock" d="M512 919.040c-260.134 0-471.040-210.944-471.040-471.040 0-260.134 210.906-471.040 471.040-471.040s471.040 210.906 471.040 471.040c0 260.134-210.906 471.040-471.040 471.040zM512 79.36c-203.624 0-368.64 165.054-368.64 368.64s165.016 368.64 368.64 368.64 368.64-165.054 368.64-368.64-165.016-368.64-368.64-368.64zM547.84 714.24h-71.68v-281.069l174.345-174.345 50.669 50.707-153.335 153.335z"/><glyph unicode="" glyph-name="close-mage" horiz-adv-x="1176" d="M1094.391 882.29l-77.71 77.71-423.329-423.347-423.33 423.347-77.71-77.672 423.35-423.368-423.312-423.329 77.672-77.71 423.338 423.338 423.283-423.3 77.671 77.71-423.263 423.281z"/><glyph unicode="" glyph-name="delete" horiz-adv-x="1176" d="M337.541-61.004h513.024l64.512 645.916h-639.128l61.592-645.916zM737.394 805.831v116.508c0 19.191-15.398 34.702-34.361 34.702h-217.847c-19.001 0-34.361-15.55-34.361-34.702v-114.574c-73.576-8.382-150.149-24.614-226.494-52.338v-106.989h738.001v109.833c0 0-90.074 31.403-224.977 47.559zM668.937 812.241c-47.749 3.224-99.252 4.096-153.297 0.986v61.44c0 9.519 7.623 17.332 17.143 17.332h118.936c9.519 0 17.218-7.813 17.218-17.332v-62.426z"/><glyph unicode="" glyph-name="edit" horiz-adv-x="1176" d="M928.503 933.111l-111.502-112.109 156.065-156.9 111.502 112.071-156.065 156.937zM215.002 215.59l156.065-156.9 535.211 538.093-156.065 156.9-535.211-538.093zM103.917-47.161l188.985 49.873-139.302 140.098-49.683-190.009z"/><glyph unicode="" glyph-name="error" d="M1014.67 137.349c0 0 0 0 0 0l-310.651 310.651 310.651 310.651c0 0 0 0 0 0 3.337 3.337 5.765 7.244 7.32 11.416 4.248 11.378 1.82 24.69-7.32 33.83l-146.735 146.735c-9.14 9.14-22.452 11.567-33.83 7.32-4.172-1.555-8.078-3.982-11.416-7.32 0 0 0 0 0 0l-310.651-310.651-310.651 310.651c0 0 0 0 0 0-3.337 3.337-7.244 5.765-11.416 7.32-11.378 4.248-24.69 1.82-33.83-7.32l-146.735-146.735c-9.14-9.14-11.567-22.452-7.32-33.83 1.555-4.172 3.982-8.078 7.32-11.416 0 0 0 0 0 0l310.651-310.651-310.651-310.651c0 0 0 0 0 0-3.337-3.337-5.765-7.244-7.32-11.416-4.248-11.378-1.82-24.69 7.32-33.83l146.735-146.735c9.14-9.14 22.452-11.567 33.83-7.32 4.172 1.555 8.078 3.982 11.416 7.32 0 0 0 0 0 0l310.651 310.651 310.651-310.651c0 0 0 0 0 0 3.337-3.337 7.244-5.765 11.416-7.32 11.378-4.248 24.69-1.82 33.83 7.32l146.735 146.735c9.14 9.14 11.567 22.452 7.32 33.83-1.555 4.172-3.982 8.078-7.32 11.416z"/><glyph unicode="" glyph-name="help" horiz-adv-x="1176" d="M593.351 937.434c-270.336 0-489.434-219.098-489.434-489.358s219.098-489.434 489.434-489.434 489.434 219.136 489.434 489.434-219.136 489.358-489.434 489.358zM635.752 133.404c-11.985-11.719-26.396-17.636-43.16-17.636-8.154 0-15.967 1.517-23.4 4.589-7.358 3.034-13.843 7.168-19.456 12.174-5.613 5.158-10.126 11.226-13.388 18.356-3.337 7.13-4.968 14.753-4.968 22.945 0 16.308 5.992 30.303 17.977 42.060 11.947 11.681 26.396 17.598 43.198 17.598 16.308 0 30.606-5.689 42.78-16.801 12.25-11.188 18.318-24.993 18.318-41.339-0.038-16.384-5.992-30.303-17.939-41.984zM778.923 577.327c-3.982-13.767-9.747-26.396-17.18-37.774-7.471-11.454-16.498-22.49-27.079-33.071s-22.49-21.618-35.65-33.033c-11.454-9.785-20.783-18.318-27.913-25.79-7.168-7.396-12.895-14.867-17.218-22.338-4.286-7.433-7.282-15.398-9.026-24.007-1.707-8.609-2.617-49.721-2.617-62.35v-22.338h-101.376v32.616c0 13.729 0.986 56.661 3.034 67.584s5.158 21.125 9.481 30.872 10.012 19.228 17.18 28.369c7.168 9.14 16.232 18.887 27.079 29.203l38.647 36.902c10.847 9.747 20.177 20.632 27.951 32.616 7.737 12.060 11.529 26.7 11.529 43.88 0 22.3-6.978 41.036-21.011 56.206-14.071 15.17-33.944 22.793-59.695 22.793-13.16 0-25.069-2.389-35.65-7.282-10.619-4.817-19.797-11.454-27.496-19.759-7.737-8.344-13.577-17.901-17.598-28.786-3.982-10.847-6.334-21.997-6.865-33.527l-105.624 9.444c3.413 27.496 10.733 51.959 21.921 73.463 11.112 21.466 25.562 39.595 43.311 54.575 17.711 14.829 38.078 26.169 61.023 33.944 22.869 7.699 47.521 11.605 73.842 11.605 24.614 0 47.976-3.603 70.049-10.771 21.959-7.168 41.491-17.711 58.406-31.782 16.839-14.033 30.227-31.365 39.936-51.959 9.709-20.632 14.564-44.411 14.564-71.263 0-18.356-2.010-34.475-5.992-48.166z"/><glyph unicode="" glyph-name="history" d="M574.805 867.84c-227.631 0-412.71-182.386-418.247-409.335h-125.838l188.378-209.958 188.302 209.958h-146.242c5.537 168.998 143.777 304.393 313.647 304.393 173.359 0 313.875-140.971 313.875-314.899s-140.478-314.861-313.875-314.861c-69.518 0-133.727 22.718-185.761 61.099l-71.983-76.99c71.073-55.751 160.503-89.050 257.745-89.050 231.121 0 418.513 187.961 418.513 419.84-0.038 231.879-187.43 419.84-418.513 419.84zM537.6 673.28v-240.109l153.865-153.865 50.669 50.669-132.855 132.855v210.413h-71.68z"/><glyph unicode="" glyph-name="export" d="M383.462 382.49h255.693v213.043h127.795l-255.642 255.667-255.642-255.667h127.795zM852.173 382.49v-170.394h-681.754v170.394h-170.419v-340.89h1022.618v340.89z"/><glyph unicode="" glyph-name="import" d="M639.155 851.2h-255.693v-213.043h-127.795l255.667-255.667 255.616 255.667h-127.795zM852.173 382.49v-170.394h-681.754v170.394h-170.419v-340.89h1022.618v340.89z"/><glyph unicode="" glyph-name="dot" d="M505.139 959.915c-282.658-3.775-508.826-236.066-505.071-518.827 3.772-282.556 236.1-508.826 518.793-505.003 282.658 3.768 508.826 236.066 505.071 518.827-3.717 282.658-236.1 508.826-518.793 505.003z"/><glyph unicode="" glyph-name="not-installed" d="M510.413 960c-281.907 0-510.413-228.582-510.413-510.413 0-281.933 228.506-510.464 510.413-510.464s510.387 228.557 510.387 510.464c0 281.83-228.48 510.413-510.387 510.413zM865.843 449.587c0-69.99-20.506-135.27-55.578-190.285l-490.163 490.163c55.091 35.021 120.32 55.475 190.31 55.475 195.942 0 355.43-159.411 355.43-355.354zM154.957 449.587c0 69.939 20.506 135.245 55.578 190.31l490.189-490.189c-55.066-35.072-120.371-55.501-190.31-55.501-195.942-0.026-355.456 159.437-355.456 355.379z"/><glyph unicode="" glyph-name="disabled" d="M511.77 960c-282.778 0-512.102-229.222-512.102-512.179 0-282.829 229.325-512.102 512.102-512.102 282.931-0.026 512.23 229.248 512.23 512.102 0 282.957-229.299 512.179-512.23 512.179zM143.718 540.032h736.205v-184.269h-736.205v184.269z"/><glyph unicode="" glyph-name="menu-item" horiz-adv-x="903" d="M857.675 670.587l-403.18 240.514-402.726-240.514v-457.026l403.18-240.515 402.726 240.514v457.027zM454.857 95.535l-298.427 178.383v335.966l298.157 178.729 298.428-178.383v-335.966l-298.158-178.729z"/><glyph unicode="" glyph-name="tag" d="M904.192 959.973l-307.234-0.116-596.89-596.958 426.906-426.906 596.958 596.958-0.113 305.596-119.603 121.426zM858.679 646.663c-39.997-40.001-104.854-40.001-144.794 0-40.001 40.001-40.001 104.796 0 144.794 39.939 40.001 104.796 40.001 144.794 0 39.997-39.997 39.997-104.793 0-144.794z"/><glyph unicode="" glyph-name="camera" d="M982.767 728.098h-250.095l-59.255 121.364c0 0-11.827 25.201-42.11 25.201-23.375 0-169.366 0-235.25 0-32.969 0-44.001-25.027-44.001-25.027l-57.484-121.539h-253.406c-22.74 0-41.131-18.459-41.131-41.267v-624.333c0-22.743 18.401-41.199 41.131-41.199h941.636c22.74 0 41.199 18.459 41.199 41.199v624.299c0 22.798-18.456 41.267-41.199 41.267zM512 136.090c-138.793 0-251.597 113.015-251.597 251.931 0 138.912 112.845 251.87 251.597 251.87 138.68 0 251.597-112.981 251.597-251.87 0-138.909-112.913-251.931-251.597-251.931zM512 539.068c-83.255 0-150.972-67.714-150.972-150.972 0-83.197 67.71-150.903 150.972-150.903 83.258 0 150.903 67.714 150.903 150.903 0 83.255-67.652 150.972-150.903 150.972z"/><glyph unicode="" glyph-name="grid" d="M0.010 959.628h279.074v-279.074h-279.074zM372.77 959.628h279.074v-279.074h-279.074zM744.892 959.628h279.074v-279.074h-279.074zM0.010 587.503h279.074v-279.074h-279.074zM372.77 587.503h279.074v-279.074h-279.074zM744.892 587.503h279.074v-279.074h-279.074zM0.010 215.415h279.074v-279.074h-279.074zM372.77 215.415h279.074v-279.074h-279.074zM744.892 215.415h279.074v-279.074h-279.074z"/><glyph unicode="" glyph-name="list-menu" d="M0.010 771.516h1023.966v-136.509h-1023.966zM0.010 517.53h1023.966v-136.506h-1023.966zM0.010 260.983h1023.966v-136.513h-1023.966z"/><glyph unicode="" glyph-name="cart" d="M771.001 183.263c-55.445 0-100.448-44.754-100.448-100.2s44.879-100.324 100.448-100.324 100.448 44.879 100.448 100.324-45.003 100.2-100.448 100.2zM771.001 41.293c-23.123 0-41.77 18.648-41.77 41.771s18.647 41.77 41.77 41.77c23.247 0 41.895-18.648 41.895-41.77s-18.648-41.771-41.895-41.771zM469.532 183.263c-55.445 0-100.449-44.754-100.449-100.2s45.003-100.324 100.449-100.324c55.445 0 100.448 44.879 100.448 100.324s-45.003 100.2-100.448 100.2zM469.532 41.293c-23.123 0-41.771 18.648-41.771 41.771s18.648 41.77 41.771 41.77 41.77-18.648 41.77-41.77-18.648-41.771-41.77-41.771zM823.587 465.588c-130.036 0-238.441 91.622-264.547 213.825h-207.237l-136.749 198.162v1.865h-207.237v-83.541h169.942l78.693-117.729 83.417-412.857h581.183l49.23 243.786c-42.268-27.474-92.616-43.511-146.694-43.511zM1023.862 710.244v45.376l-55.073 18.026-12.929 31.204 24.863 52.71-31.95 32.074-5.967-2.984-45.5-23.123-31.328 12.929-19.642 54.948h-45.376l-2.114-6.464-15.912-48.608-31.203-12.929-52.835 24.863-32.074-31.95 3.108-5.967 23.247-45.624-13.053-31.328-54.948-19.766v-45.376l6.34-2.113 48.732-15.788 12.929-31.204-24.863-52.71 32.074-32.074 6.092 3.108 45.376 22.999 31.328-12.929 19.642-54.824h45.376l2.113 6.464 15.913 48.359 31.203 12.929 52.71-24.988 32.198 32.074-3.108 6.092-23.247 45.624 12.929 31.203 54.948 19.766zM824.582 668.473c-35.057 0-63.65 28.469-63.65 63.526 0 35.182 28.469 63.526 63.65 63.526s63.526-28.469 63.526-63.526c-0.124-35.182-28.469-63.526-63.526-63.526z"/><glyph unicode="" glyph-name="screen" horiz-adv-x="1159" d="M723.661 70.399c-2.404 10.843-4.034 21.47-5.282 31.583h-277.528c-2.458-20.233-6.917-43.087-14.646-64.305-7.79-21.277-18.796-40.54-33.824-54.15-15.028-13.552-33.689-22.104-59.788-22.158v-25.369h494.020v25.369c-26.142 0.058-44.737 8.61-59.838 22.158-22.44 20.307-35.961 53.91-43.114 86.873zM1126.214 960h-1093.209c-18.22 0-33.005-15.024-33.005-33.596v-731.259c0-18.576 14.785-33.623 33.005-33.623h1093.209c18.224 0 33.067 15.051 33.067 33.623v731.259c0 18.572-14.843 33.596-33.067 33.596zM1079.193 243.078h-999.234v635.394h999.234v-635.394z"/><glyph unicode="" glyph-name="video" horiz-adv-x="2041" d="M2041.366 958.898v-1021.449h-175.926l-411.263 409.297v204.59l411.263 407.568h175.926zM1305.997-29.076c0-19.377-15.608-34.924-34.856-34.924h-1236.279c-19.255 0-34.863 15.547-34.863 34.924v954.275c0 19.248 15.608 34.801 34.863 34.801h1236.279c19.248 0 34.856-15.553 34.856-34.801v-954.275z"/><glyph unicode="" glyph-name="revert" horiz-adv-x="1404" d="M1042.226 660.151h-598.393v299.849l-443.833-384.316 443.833-384.403v299.859h598.393c106.478 0 192.801-86.318 192.801-192.801s-86.318-192.796-192.801-192.796v-0.483l-452.707-0.005c-46.695-0.005-84.53-37.845-84.53-84.535 0-46.68 37.84-84.525 84.535-84.525 0.377 0 0.744 0.053 1.121 0.058h451.581c199.964 0 362.044 162.085 362.044 362.039 0 199.964-162.080 362.059-362.044 362.059z"/><glyph unicode="" glyph-name="clip" d="M939.616 811.616c112.512-112.448 112.512-294.816 0-407.264l-350.944-350.976c-12.512-12.544-32.736-12.544-45.248 0-12.576 12.512-12.576 32.704 0 45.248l346.432 346.464c87.488 87.488 87.488 229.248-0.064 316.768-87.36 87.488-229.248 87.488-316.736 0l-462.304-456.864c-62.496-62.464-62.496-163.776 0-226.24 62.496-62.496 163.744-62.496 226.24 0l466.88 461.344c37.44 37.44 37.44 98.336 0 135.776-37.44 37.408-98.304 37.408-135.744 0l-351.008-351.008c-12.512-12.512-32.736-12.512-45.248 0-12.512 12.544-12.512 32.736 0 45.28l350.976 350.976c62.432 62.464 163.744 62.464 226.24 0 62.496-62.496 62.496-163.776 0-226.272l-466.88-461.376c-87.296-87.328-229.408-87.328-316.736 0s-87.328 229.472 0 316.8l466.88 461.344c112.448 112.512 294.816 112.512 407.264 0z"/><glyph unicode="" glyph-name="module" horiz-adv-x="883" d="M793.271 737.4l-192.695 83.055v-80.482c-2.517-31.926-83.182-57.618-182.582-57.618-99.309 0-180.126 25.692-182.398 57.618h-0.318l-0.465 80.482-197.709-83.055 381.218-167.697 374.95 167.697zM265.959 841.886l-1.104-0.428c32.596-16.331 89.086-27.124 153.551-27.124 64.726 0 121.621 10.94 153.996 27.355l-1.168 0.512c18.811 9.3 29.664 20.34 29.664 32.264 0 32.713-81.606 59.114-182.492 59.114-100.759 0-182.806-26.401-182.806-59.114-0.003-12.007 11.295-23.218 30.36-32.579zM418.418 497.564l-418.418 191.009v-563.335l418.321-189.238 418.321 189.238v563.733l-418.224-191.407z"/><glyph unicode="" glyph-name="alert-round" d="M1023.959 454.912c-3.717 282.665-236.121 508.842-518.817 505.040-282.689-3.772-508.866-236.091-505.094-518.868 3.772-282.58 236.121-508.842 518.813-505.040 282.689 3.772 508.866 236.067 505.098 518.868zM580.086 55.641h-136.149v136.163h136.149v-136.163zM597.168 666.258l-44.103-388.928h-83.113l-43.099 388.928v171.575h170.318v-171.575z"/><glyph unicode="" glyph-name="document" horiz-adv-x="793" d="M0 448v-512h793.43v771.052l-42.045 36.62c-23.735 19.666-46.114 39.332-50.183 43.401-4.069 3.391-16.275 14.241-27.126 23.735s-53.574 46.792-94.94 83.412l-75.952 65.78h-503.184v-512zM465.886 746.384c0.678-56.286 1.356-105.791 2.034-109.86 0-6.781 25.77-8.816 107.147-8.816h107.147v-287.534c-0.678-252.27-1.356-288.212-10.85-290.246-5.425-1.356-133.595-2.034-284.821-2.034l-274.649 0.678-1.356 392.646c-0.678 216.328-0.678 396.715 0.678 400.106 1.356 4.069 67.136 6.781 177.674 6.781h175.64l1.356-101.722z"/></font></defs></svg> \ No newline at end of file diff --git a/app/design/adminhtml/Magento/backend/web/fonts/admin-icons/admin-icons.ttf b/app/design/adminhtml/Magento/backend/web/fonts/admin-icons/admin-icons.ttf index bc3eddf307438029d440be39f85fe2bfe398afc8..2d896e8b3dba067a0b772b262be35c066160a7d8 100755 Binary files a/app/design/adminhtml/Magento/backend/web/fonts/admin-icons/admin-icons.ttf and b/app/design/adminhtml/Magento/backend/web/fonts/admin-icons/admin-icons.ttf differ diff --git a/app/design/adminhtml/Magento/backend/web/fonts/admin-icons/admin-icons.woff b/app/design/adminhtml/Magento/backend/web/fonts/admin-icons/admin-icons.woff index bd9560bf583279cb79ec485a741272b9a73e89bd..7cd73320aed862466a210b9d8455f19bca9b0cd9 100755 Binary files a/app/design/adminhtml/Magento/backend/web/fonts/admin-icons/admin-icons.woff and b/app/design/adminhtml/Magento/backend/web/fonts/admin-icons/admin-icons.woff differ diff --git a/app/design/adminhtml/Magento/backend/web/fonts/admin-icons/admin-icons.woff2 b/app/design/adminhtml/Magento/backend/web/fonts/admin-icons/admin-icons.woff2 index 25c1c88c0bff8958c62084729d9b618f97646fde..a26908a3b1e6992cf5a27638e38871b2eac07b13 100755 Binary files a/app/design/adminhtml/Magento/backend/web/fonts/admin-icons/admin-icons.woff2 and b/app/design/adminhtml/Magento/backend/web/fonts/admin-icons/admin-icons.woff2 differ diff --git a/app/design/adminhtml/Magento/backend/web/fonts/admin-icons/selection.json b/app/design/adminhtml/Magento/backend/web/fonts/admin-icons/selection.json index c1733d650bcd283ce794e7989a555bc0cb87f438..f639e5bb413f1976b46a371e28bb6a7ceec528cb 100755 --- a/app/design/adminhtml/Magento/backend/web/fonts/admin-icons/selection.json +++ b/app/design/adminhtml/Magento/backend/web/fonts/admin-icons/selection.json @@ -1,2326 +1,2356 @@ { - "IcoMoonType": "selection", - "icons": [ - { - "icon": { - "paths": [ - "M2041.366 1.102v1021.449h-175.926l-411.263-409.297v-204.59l411.263-407.568h175.926z", - "M1305.997 989.076c0 19.377-15.608 34.924-34.856 34.924h-1236.279c-19.255 0-34.863-15.547-34.863-34.924v-954.275c0-19.248 15.608-34.801 34.863-34.801h1236.279c19.248 0 34.856 15.553 34.856 34.801v954.275z" - ], - "width": 2041, - "attrs": [], - "isMulticolor": false, - "isMulticolor2": false, - "tags": [ - "video" - ], - "grid": 0 - }, - "attrs": [], - "properties": { - "order": 127, - "id": 0, - "prevSize": 32, - "code": 58945, - "name": "video" - }, - "setIdx": 0, - "setId": 7, - "iconIdx": 0 - }, - { - "icon": { - "paths": [ - "M723.661 889.601c-2.404-10.843-4.034-21.47-5.282-31.583h-277.528c-2.458 20.233-6.917 43.087-14.646 64.305-7.79 21.277-18.796 40.54-33.824 54.15-15.028 13.552-33.689 22.104-59.788 22.158v25.369h494.020v-25.369c-26.142-0.058-44.737-8.61-59.838-22.158-22.44-20.307-35.961-53.91-43.114-86.873zM1126.214 0h-1093.209c-18.22 0-33.005 15.024-33.005 33.596v731.259c0 18.576 14.785 33.623 33.005 33.623h1093.209c18.224 0 33.067-15.051 33.067-33.623v-731.259c0-18.572-14.843-33.596-33.067-33.596zM1079.193 716.922h-999.234v-635.394h999.234v635.394z" - ], - "width": 1159, - "attrs": [], - "isMulticolor": false, - "isMulticolor2": false, - "tags": [ - "screen" - ], - "grid": 0 - }, - "attrs": [], - "properties": { - "order": 72, - "id": 1, - "prevSize": 32, - "code": 58944, - "name": "screen" - }, - "setIdx": 0, - "setId": 7, - "iconIdx": 1 - }, - { - "icon": { - "paths": [ - "M771.001 776.737c-55.445 0-100.448 44.754-100.448 100.2s44.879 100.324 100.448 100.324 100.448-44.879 100.448-100.324-45.003-100.2-100.448-100.2zM771.001 918.707c-23.123 0-41.77-18.648-41.77-41.771s18.647-41.77 41.77-41.77c23.247 0 41.895 18.648 41.895 41.77s-18.648 41.771-41.895 41.771z", - "M469.532 776.737c-55.445 0-100.449 44.754-100.449 100.2s45.003 100.324 100.449 100.324c55.445 0 100.448-44.879 100.448-100.324s-45.003-100.2-100.448-100.2zM469.532 918.707c-23.123 0-41.771-18.648-41.771-41.771s18.648-41.77 41.771-41.77 41.77 18.648 41.77 41.77-18.648 41.771-41.77 41.771z", - "M823.587 494.412c-130.036 0-238.441-91.622-264.547-213.825h-207.237l-136.749-198.162v-1.865h-207.237v83.541h169.942l78.693 117.729 83.417 412.857h581.183l49.23-243.786c-42.268 27.474-92.616 43.511-146.694 43.511z", - "M1023.862 249.756v-45.376l-55.073-18.026-12.929-31.204 24.863-52.71-31.95-32.074-5.967 2.984-45.5 23.123-31.328-12.929-19.642-54.948h-45.376l-2.114 6.464-15.912 48.608-31.203 12.929-52.835-24.863-32.074 31.95 3.108 5.967 23.247 45.624-13.053 31.328-54.948 19.766v45.376l6.34 2.113 48.732 15.788 12.929 31.204-24.863 52.71 32.074 32.074 6.092-3.108 45.376-22.999 31.328 12.929 19.642 54.824h45.376l2.113-6.464 15.913-48.359 31.203-12.929 52.71 24.988 32.198-32.074-3.108-6.092-23.247-45.624 12.929-31.203 54.948-19.766zM824.582 291.527c-35.057 0-63.65-28.469-63.65-63.526 0-35.182 28.469-63.526 63.65-63.526s63.526 28.469 63.526 63.526c-0.124 35.182-28.469 63.526-63.526 63.526z" - ], - "attrs": [], - "isMulticolor": false, - "isMulticolor2": false, - "tags": [ - "cart" - ], - "grid": 0 - }, - "attrs": [], - "properties": { - "order": 71, - "id": 2, - "prevSize": 32, - "code": 58943, - "name": "cart" - }, - "setIdx": 0, - "setId": 7, - "iconIdx": 2 - }, - { - "icon": { - "paths": [ - "M0.010 188.484h1023.966v136.509h-1023.966z", - "M0.010 442.47h1023.966v136.506h-1023.966z", - "M0.010 699.017h1023.966v136.513h-1023.966z" - ], - "attrs": [ - {}, - {}, - {} - ], - "isMulticolor": false, - "isMulticolor2": false, - "tags": [ - "list-menu" - ], - "grid": 0 - }, - "attrs": [ - {}, - {}, - {} - ], - "properties": { - "order": 61, - "id": 3, - "prevSize": 32, - "code": 58942, - "name": "list-menu" - }, - "setIdx": 0, - "setId": 7, - "iconIdx": 3 - }, - { - "icon": { - "paths": [ - "M0.010 0.372h279.074v279.074h-279.074z", - "M372.77 0.372h279.074v279.074h-279.074z", - "M744.892 0.372h279.074v279.074h-279.074z", - "M0.010 372.497h279.074v279.074h-279.074z", - "M372.77 372.497h279.074v279.074h-279.074z", - "M744.892 372.497h279.074v279.074h-279.074z", - "M0.010 744.585h279.074v279.074h-279.074z", - "M372.77 744.585h279.074v279.074h-279.074z", - "M744.892 744.585h279.074v279.074h-279.074z" - ], - "attrs": [ - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {} - ], - "isMulticolor": false, - "isMulticolor2": false, - "tags": [ - "grid" - ], - "grid": 0 - }, - "attrs": [ - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {} - ], - "properties": { - "order": 112, - "id": 4, - "prevSize": 32, - "code": 58941, - "name": "grid" - }, - "setIdx": 0, - "setId": 7, - "iconIdx": 4 - }, - { - "icon": { - "paths": [ - "M982.767 231.902h-250.095l-59.255-121.364c0 0-11.827-25.201-42.11-25.201-23.375 0-169.366 0-235.25 0-32.969 0-44.001 25.027-44.001 25.027l-57.484 121.539h-253.406c-22.74 0-41.131 18.459-41.131 41.267v624.333c0 22.743 18.401 41.199 41.131 41.199h941.636c22.74 0 41.199-18.459 41.199-41.199v-624.299c0-22.798-18.456-41.267-41.199-41.267zM512 823.91c-138.793 0-251.597-113.015-251.597-251.931 0-138.912 112.845-251.87 251.597-251.87 138.68 0 251.597 112.981 251.597 251.87 0 138.909-112.913 251.931-251.597 251.931z", - "M512 420.932c-83.255 0-150.972 67.714-150.972 150.972 0 83.197 67.71 150.903 150.972 150.903 83.258 0 150.903-67.714 150.903-150.903 0-83.255-67.652-150.972-150.903-150.972z" - ], - "attrs": [ - {}, - {} - ], - "isMulticolor": false, - "isMulticolor2": false, - "tags": [ - "camera" - ], - "grid": 0 - }, - "attrs": [ - {}, - {} - ], - "properties": { - "order": 121, - "id": 5, - "prevSize": 32, - "code": 58940, - "name": "camera" - }, - "setIdx": 0, - "setId": 7, - "iconIdx": 5 - }, - { - "icon": { - "paths": [ - "M904.192 0.027l-307.234 0.116-596.89 596.958 426.906 426.906 596.958-596.958-0.113-305.596-119.603-121.426zM858.679 313.337c-39.997 40.001-104.854 40.001-144.794 0-40.001-40.001-40.001-104.796 0-144.794 39.939-40.001 104.796-40.001 144.794 0 39.997 39.997 39.997 104.793 0 144.794z" - ], - "attrs": [ - {} - ], - "isMulticolor": false, - "isMulticolor2": false, - "tags": [ - "tag" - ], - "grid": 0 - }, - "attrs": [ - {} - ], - "properties": { - "order": 111, - "id": 6, - "prevSize": 32, - "code": 58939, - "name": "tag" - }, - "setIdx": 0, - "setId": 7, - "iconIdx": 6 - }, - { - "icon": { - "paths": [ - "M1094.391 77.71l-77.71-77.71-423.329 423.347-423.33-423.347-77.71 77.672 423.35 423.368-423.312 423.329 77.672 77.71 423.338-423.338 423.283 423.3 77.671-77.71-423.263-423.281z" - ], - "width": 1176, - "attrs": [ - {} - ], - "isMulticolor": false, - "isMulticolor2": false, - "colorPermutations": { - "6868681": [ - { - "f": 0 - } - ] - }, - "tags": [ - "close-mage" - ], - "grid": 0 - }, - "attrs": [ - {} - ], - "properties": { - "order": 110, - "id": 7, - "prevSize": 32, - "code": 58927, - "name": "close-mage" - }, - "setIdx": 0, - "setId": 7, - "iconIdx": 7 - }, - { - "icon": { - "paths": [ - "M857.675 289.413l-403.18-240.514-402.726 240.514v457.026l403.18 240.515 402.726-240.514v-457.027zM454.857 864.465l-298.427-178.383v-335.966l298.157-178.729 298.428 178.383v335.966l-298.158 178.729z" - ], - "width": 903, - "attrs": [ - {} - ], - "isMulticolor": false, - "isMulticolor2": false, - "colorPermutations": { - "6868681": [ - { - "f": 0 - } - ] - }, - "tags": [ - "menu-item" - ], - "grid": 0 - }, - "attrs": [ - {} - ], - "properties": { - "order": 109, - "id": 8, - "prevSize": 32, - "code": 58938, - "name": "menu-item" - }, - "setIdx": 0, - "setId": 7, - "iconIdx": 8 - }, - { - "icon": { - "paths": [ - "M505.704 40.998c-260.096 3.489-468.158 217.202-464.706 477.336 3.489 259.982 217.202 468.12 477.298 464.631s468.158-217.202 464.706-477.336c-3.413-260.058-217.202-468.12-477.298-464.631zM557.928 197.973c47.863 0 62.009 27.762 62.009 59.544 0 39.671-31.782 76.383-86.016 76.383-45.359 0-66.901-22.831-65.65-60.53 0-31.782 26.624-75.435 89.657-75.435zM435.162 806.381c-32.73 0-56.661-19.873-33.792-107.217l37.547-154.814c6.485-24.841 7.585-34.778 0-34.778-9.785 0-52.262 17.143-77.407 34.057l-16.346-26.776c79.607-66.446 171.16-105.472 210.375-105.472 32.73 0 38.153 38.722 21.807 98.266l-43.008 162.816c-7.585 28.786-4.286 38.722 3.262 38.722 9.785 0 41.984-11.871 73.614-36.75l18.47 24.841c-77.369 77.369-161.792 107.179-194.56 107.179z" - ], - "attrs": [ - {} - ], - "isMulticolor": false, - "isMulticolor2": false, - "tags": [ - "info" - ], - "grid": 0 - }, - "attrs": [ - {} - ], - "properties": { - "order": 108, - "id": 9, - "prevSize": 32, - "code": 58906, - "name": "info" - }, - "setIdx": 0, - "setId": 7, - "iconIdx": 9 - }, - { - "icon": { - "paths": [ - "M591.986 448.019h-16.005v-192.019c0-105.851-86.13-192.019-192.019-192.019h-128c-105.851 0-192.019 86.13-192.019 192.019v192.019h-16.005c-26.396 0-48.014 21.618-48.014 48.014v479.991c0 26.396 21.618 48.014 48.014 48.014h544.009c26.396 0 48.014-21.618 48.014-48.014v-479.991c0-26.396-21.618-48.014-48.014-48.014zM384 896h-128l27.838-139.188c-16.801-11.529-27.838-30.872-27.838-52.793 0-35.347 28.672-64.019 64.019-64.019s64.019 28.672 64.019 64.019c0 21.921-11.036 41.263-27.838 52.793l27.838 139.188zM448.019 448.019h-256v-192.019c0-35.271 28.71-64.019 64.019-64.019h128c35.271 0 64.019 28.71 64.019 64.019v192.019z" - ], - "attrs": [ - {} - ], - "isMulticolor": false, - "isMulticolor2": false, - "tags": [ - "lock" - ], - "grid": 0 - }, - "attrs": [ - {} - ], - "properties": { - "order": 107, - "id": 10, - "prevSize": 32, - "code": 58907, - "name": "lock" - }, - "setIdx": 0, - "setId": 7, - "iconIdx": 10 - }, - { - "icon": { - "paths": [ - "M870.4 317.44h-194.56v143.36h153.6v215.040h-634.88v-215.040h215.040v112.64l204.8-184.32-204.8-184.32v112.64h-256c-56.51 0-102.4 45.815-102.4 102.4v296.96c0 56.51 45.89 102.4 102.4 102.4h716.8c56.585 0 102.4-45.89 102.4-102.4v-296.96c0-56.585-45.815-102.4-102.4-102.4z" - ], - "attrs": [ - {} - ], - "isMulticolor": false, - "isMulticolor2": false, - "tags": [ - "loop" - ], - "grid": 0 - }, - "attrs": [ - {} - ], - "properties": { - "order": 106, - "id": 11, - "prevSize": 32, - "code": 58908, - "name": "loop" - }, - "setIdx": 0, - "setId": 7, - "iconIdx": 11 - }, - { - "icon": { - "paths": [ - "M991.991 384h-351.991v-351.991c0-17.673-14.336-32.009-32.009-32.009h-192.019c-17.673 0-32.009 14.336-32.009 32.009v351.991h-351.991c-17.673 0-32.009 14.336-32.009 32.009v192.019c0 17.673 14.336 32.009 32.009 32.009h351.991v351.991c0 17.673 14.336 32.009 32.009 32.009h192.019c17.673 0 32.009-14.336 32.009-32.009v-351.991h351.991c17.673 0 32.009-14.336 32.009-32.009v-192.019c0-17.673-14.336-32.009-32.009-32.009z" - ], - "attrs": [ - {} - ], - "isMulticolor": false, - "isMulticolor2": false, - "tags": [ - "plus" - ], - "grid": 0 - }, - "attrs": [ - {} - ], - "properties": { - "order": 105, - "id": 12, - "prevSize": 32, - "code": 58909, - "name": "plus" - }, - "setIdx": 0, - "setId": 7, - "iconIdx": 12 - }, - { - "icon": { - "paths": [ - "M505.704 40.998c-260.096 3.489-468.158 217.126-464.706 477.298 3.489 260.21 217.202 468.158 477.298 464.744 260.134-3.489 468.233-217.202 464.706-477.298-3.489-260.21-217.202-468.233-477.298-464.744zM506.577 102.4c70.163-0.986 136.382 15.853 194.56 46.118l-63.374 105.662c-38.002-18.47-80.631-28.937-125.762-28.937-45.056 0-87.723 10.43-125.687 28.975l-63.336-105.624c54.993-28.672 117.343-45.321 183.599-46.232zM254.255 637.687l-105.586 63.298c-28.672-54.955-45.321-117.305-46.194-183.486-0.986-70.201 15.853-136.457 46.118-194.56l105.624 63.45c-18.546 37.926-28.975 80.555-28.975 125.649 0 45.056 10.43 87.723 28.975 125.687zM517.461 921.562c-70.163 0.986-136.457-15.853-194.56-46.118l63.374-105.662c38.002 18.546 80.631 28.975 125.687 28.975 45.094 0 87.761-10.392 125.687-28.937l63.336 105.586c-54.993 28.634-117.305 45.246-183.561 46.194zM512 737.242c-124.397 0-225.242-100.883-225.242-225.242 0-124.397 100.883-225.28 225.242-225.28 124.473 0 225.28 100.883 225.28 225.28s-100.807 225.242-225.28 225.242zM769.745 637.687c18.546-38.002 28.975-80.631 28.975-125.687 0-45.094-10.43-87.723-28.975-125.687l105.586-63.374c28.672 54.993 45.359 117.305 46.232 183.561 0.91 70.201-15.929 136.457-46.194 194.56l-105.624-63.336z" - ], - "attrs": [ - {} - ], - "isMulticolor": false, - "isMulticolor2": false, - "tags": [ - "recover" - ], - "grid": 0 - }, - "attrs": [ - {} - ], - "properties": { - "order": 104, - "id": 13, - "prevSize": 32, - "code": 58910, - "name": "recover" - }, - "setIdx": 0, - "setId": 7, - "iconIdx": 13 - }, - { - "icon": { - "paths": [ - "M906.126 135.813v0c-91.174-75.89-202.487-113.171-312.548-113.057-127.014-0.038-253.611 49.683-348.16 145.636l-95.004-79.265-1.593 305.342 300.184-56.282-99.442-82.944c67.546-64.247 155.269-97.204 244.015-97.28 79.948 0.038 159.782 26.7 226.114 81.806 84.347 70.125 127.659 170.629 127.772 272.46-0.038 14.715-0.948 29.431-2.769 44.070l137.519-26.283c0.19-5.954 0.303-11.871 0.303-17.787 0.152-140.098-60.151-279.78-176.431-376.415zM839.035 766.976c-67.736 65.498-156.255 99.025-245.912 99.1-79.986-0.038-159.82-26.738-226.114-81.806-84.347-70.125-127.697-170.629-127.772-272.498 0-16.839 1.252-33.716 3.679-50.366l-138.164 25.941c-0.379 8.116-0.683 16.346-0.683 24.462-0.114 140.174 60.226 279.817 176.545 376.491 91.136 75.852 202.411 113.057 312.51 112.981h0.341c127.924 0 255.241-50.441 349.943-147.759l90.795 75.207 0.569-305.38-299.956 57.344 104.183 86.281z" - ], - "width": 1176, - "attrs": [ - {} - ], - "isMulticolor": false, - "isMulticolor2": false, - "tags": [ - "refresh" - ], - "grid": 0 - }, - "attrs": [ - {} - ], - "properties": { - "order": 113, - "id": 14, - "prevSize": 32, - "code": 58911, - "name": "refresh" - }, - "setIdx": 0, - "setId": 7, - "iconIdx": 14 - }, - { - "icon": { - "paths": [ - "M593.351 21.732c-270.753 0-490.268 219.477-490.268 490.231s219.515 490.268 490.268 490.268 490.231-219.515 490.231-490.268c0-270.753-219.477-490.231-490.231-490.231zM828.947 683.653l-72.363 72.363-162.095-162.133-164.902 164.902-73.121-73.121 164.902-164.902-161.678-161.678 72.363-72.325 161.602 161.678 165.774-165.736 73.121 73.083-165.774 165.736 162.171 162.133z" - ], - "width": 1176, - "attrs": [ - {} - ], - "isMulticolor": false, - "isMulticolor2": false, - "tags": [ - "remove-small" - ], - "grid": 0 - }, - "attrs": [ - {} - ], - "properties": { - "order": 114, - "id": 15, - "prevSize": 32, - "code": 58912, - "name": "remove-small" - }, - "setIdx": 0, - "setId": 7, - "iconIdx": 15 - }, - { - "icon": { - "paths": [ - "M254.976 675.84v-267.264h103.424l-179.2-203.776-179.2 203.776h103.424v308.224c0 56.51 45.815 102.4 102.4 102.4h459.776l-131.186-143.36h-279.438zM920.538 615.424v-308.224c0-56.51-45.89-102.4-102.4-102.4h-459.738l131.11 143.36h279.514v267.264h-103.424l179.2 203.776 179.2-203.776h-103.462z" - ], - "attrs": [ - {} - ], - "isMulticolor": false, - "isMulticolor2": false, - "tags": [ - "retweet" - ], - "grid": 0 - }, - "attrs": [ - {} - ], - "properties": { - "order": 117, - "id": 16, - "prevSize": 32, - "code": 58913, - "name": "retweet" - }, - "setIdx": 0, - "setId": 7, - "iconIdx": 16 - }, - { - "icon": { - "paths": [ - "M768 64.019h-128c-105.851 0-192.019 86.13-192.019 192.019v192.019h-400.005c-26.396 0-48.014 21.618-48.014 48.014v479.991c0 26.396 21.618 48.014 48.014 48.014h544.009c26.396 0 48.014-21.618 48.014-48.014v-479.991c0-26.396-21.618-48.014-48.014-48.014h-16.005v-192.019c0-35.271 28.71-64.019 64.019-64.019h128c35.271 0 64.019 28.71 64.019 64.019v192.019h128v-192.019c0-105.851-86.13-192.019-192.019-192.019zM384 896h-128l27.838-139.188c-16.801-11.529-27.838-30.872-27.838-52.793 0-35.347 28.672-64.019 64.019-64.019s64.019 28.672 64.019 64.019c0 21.921-11.036 41.263-27.838 52.793l27.838 139.188z" - ], - "attrs": [ - {} - ], - "isMulticolor": false, - "isMulticolor2": false, - "tags": [ - "unlocked" - ], - "grid": 0 - }, - "attrs": [ - {} - ], - "properties": { - "order": 36, - "id": 17, - "prevSize": 32, - "code": 58914, - "name": "unlocked" - }, - "setIdx": 0, - "setId": 7, - "iconIdx": 17 - }, - { - "icon": { - "paths": [ - "M593.351 0l-593.351 1023.962h1186.74l-593.351-1023.962zM653.236 899.451h-125.421v-121.211h125.421v121.211zM622.175 728.329h-62.502l-34.816-288.313v-156.748h131.3v156.748l-33.982 288.313z" - ], - "width": 1176, - "attrs": [ - {} - ], - "isMulticolor": false, - "isMulticolor2": false, - "tags": [ - "warning" - ], - "grid": 0 - }, - "attrs": [ - {} - ], - "properties": { - "order": 37, - "id": 18, - "prevSize": 32, - "code": 58915, - "name": "warning" - }, - "setIdx": 0, - "setId": 7, - "iconIdx": 18 - }, - { - "icon": { - "paths": [ - "M0 512l512 512v-320.019h512v-384h-512v-320.019z" - ], - "attrs": [ - {} - ], - "isMulticolor": false, - "isMulticolor2": false, - "tags": [ - "arrow-left" - ], - "grid": 0 - }, - "attrs": [ - {} - ], - "properties": { - "order": 38, - "id": 19, - "prevSize": 32, - "code": 58916, - "name": "arrow-left" - }, - "setIdx": 0, - "setId": 7, - "iconIdx": 19 - }, - { - "icon": { - "paths": [ - "M1024 512l-512-512v320.019h-512v384h512v320.019z" - ], - "attrs": [ - {} - ], - "isMulticolor": false, - "isMulticolor2": false, - "tags": [ - "arrow-right" - ], - "grid": 0 - }, - "attrs": [ - {} - ], - "properties": { - "order": 39, - "id": 20, - "prevSize": 32, - "code": 58917, - "name": "arrow-right" - }, - "setIdx": 0, - "setId": 7, - "iconIdx": 20 - }, - { - "icon": { - "paths": [ - "M402.735 146.735l-320.019 320.019c-24.993 24.993-24.993 65.498 0 90.491l320.019 320.019c24.993 24.993 65.498 24.993 90.491 0s24.993-65.498 0-90.491l-210.754-210.754h613.49c35.347 0 64.019-28.634 64.019-64.019s-28.672-64.019-64.019-64.019h-613.49l210.754-210.754c12.478-12.478 18.735-28.862 18.735-45.246s-6.258-32.768-18.735-45.246c-24.993-24.993-65.498-24.993-90.491 0z" - ], - "attrs": [ - {} - ], - "isMulticolor": false, - "isMulticolor2": false, - "tags": [ - "back-arrow" - ], - "grid": 0 - }, - "attrs": [ - {} - ], - "properties": { - "order": 103, - "id": 21, - "prevSize": 32, - "code": 58918, - "name": "back-arrow" - }, - "setIdx": 0, - "setId": 7, - "iconIdx": 21 - }, - { - "icon": { - "paths": [ - "M507.259 578.522h-102.059v101.717h102.059v-101.717zM650.885 714.714h-101.945v101.717h101.945v-101.717zM507.259 714.714h-102.059v101.717h102.059v-101.717zM507.259 442.33h-102.059v101.679h102.059v-101.679zM843.131 244.091c23.4 0 42.287-18.887 42.287-42.174v-145.408c0-23.324-18.887-42.174-42.287-42.174s-42.325 18.849-42.325 42.174v145.408c0.038 23.324 18.925 42.174 42.325 42.174zM343.419 244.091c23.362 0 42.249-18.887 42.249-42.174v-145.408c0-23.324-18.887-42.174-42.249-42.174-23.4 0-42.325 18.849-42.325 42.174v145.408c0 23.324 18.925 42.174 42.325 42.174zM363.444 578.522h-102.059v101.717h102.059v-101.717zM363.444 714.714h-102.059v101.717h102.059v-101.717zM650.885 578.522h-101.945v101.717h101.945v-101.717zM938.325 578.522h-102.059v101.717h102.059v-101.717zM938.325 442.33h-102.059v101.679h102.059v-101.679zM899.337 84.385v46.914c17.598 15.474 28.71 38.153 28.71 63.412 0 46.801-37.964 84.764-84.916 84.764s-84.954-37.964-84.954-84.764c0-25.259 11.15-47.938 28.71-63.412v-46.914h-387.262v46.914c17.56 15.474 28.71 38.153 28.71 63.412 0 46.801-38.002 84.764-84.916 84.764s-84.954-37.964-84.954-84.764c0-25.259 11.15-47.938 28.71-63.412v-46.914h-192.322v925.279h997.035v-925.279h-192.512zM999.234 915.304h-809.832v-589.938h809.832v589.938zM650.885 442.33h-101.945v101.679h101.945v-101.679zM794.624 442.33h-101.983v101.679h101.983v-101.679zM794.624 714.714h-101.983v101.717h101.983v-101.717zM794.624 578.522h-101.983v101.717h101.983v-101.717z" - ], - "width": 1176, - "attrs": [ - {} - ], - "isMulticolor": false, - "isMulticolor2": false, - "tags": [ - "calendar" - ], - "grid": 0 - }, - "attrs": [ - {} - ], - "properties": { - "order": 102, - "id": 22, - "prevSize": 32, - "code": 58919, - "name": "calendar" - }, - "setIdx": 0, - "setId": 7, - "iconIdx": 22 - }, - { - "icon": { - "paths": [ - "M132.21 286.758c-13.881-13.729-36.295-13.729-50.138 0-13.805 13.653-13.805 35.878 0 49.607l404.897 400.877c13.881 13.729 36.257 13.729 50.138 0l404.897-400.877c13.805-13.729 13.881-35.878 0-49.607s-36.371-13.729-50.138-0.038l-379.866 365.606-379.79-365.568z" - ], - "attrs": [ - {} - ], - "isMulticolor": false, - "isMulticolor2": false, - "tags": [ - "caret-down" - ], - "grid": 0 - }, - "attrs": [ - {} - ], - "properties": { - "order": 101, - "id": 23, - "prevSize": 32, - "code": 58920, - "name": "caret-down" - }, - "setIdx": 0, - "setId": 7, - "iconIdx": 23 - }, - { - "icon": { - "paths": [ - "M737.242 891.79c13.729 13.881 13.729 36.257 0 50.138s-35.878 13.881-49.607 0l-400.877-404.821c-13.729-13.881-13.729-36.295 0-50.138l400.877-404.897c13.729-13.881 35.878-13.881 49.607 0s13.729 36.257 0 50.138l-365.568 379.79 365.568 379.79z" - ], - "attrs": [ - {} - ], - "isMulticolor": false, - "isMulticolor2": false, - "tags": [ - "caret-left" - ], - "grid": 0 - }, - "attrs": [ - {} - ], - "properties": { - "order": 100, - "id": 24, - "prevSize": 32, - "code": 58921, - "name": "caret-left" - }, - "setIdx": 0, - "setId": 7, - "iconIdx": 24 - }, - { - "icon": { - "paths": [ - "M286.72 891.79c-13.729 13.881-13.729 36.257 0 50.138s35.878 13.881 49.607 0l400.877-404.821c13.729-13.881 13.729-36.295 0-50.138l-400.915-404.897c-13.729-13.881-35.878-13.881-49.607 0s-13.729 36.257 0 50.138l365.568 379.79-365.568 379.79z" - ], - "attrs": [ - {} - ], - "isMulticolor": false, - "isMulticolor2": false, - "tags": [ - "caret-right" - ], - "grid": 0 - }, - "attrs": [ - {} - ], - "properties": { - "order": 99, - "id": 25, - "prevSize": 32, - "code": 58922, - "name": "caret-right" - }, - "setIdx": 0, - "setId": 7, - "iconIdx": 25 - }, - { - "icon": { - "paths": [ - "M891.79 737.242c13.881 13.729 36.295 13.729 50.138 0 13.881-13.729 13.881-35.878 0-49.607l-404.897-400.877c-13.805-13.729-36.257-13.729-50.062 0l-404.897 400.877c-13.805 13.729-13.881 35.878 0 49.607s36.257 13.729 50.138 0l379.79-365.606 379.79 365.606z" - ], - "attrs": [ - {} - ], - "isMulticolor": false, - "isMulticolor2": false, - "tags": [ - "caret-up" - ], - "grid": 0 - }, - "attrs": [ - {} - ], - "properties": { - "order": 98, - "id": 26, - "prevSize": 32, - "code": 58923, - "name": "caret-up" - }, - "setIdx": 0, - "setId": 7, - "iconIdx": 26 - }, - { - "icon": { - "paths": [ - "M574.767 92.16c-227.593 0-412.672 182.386-418.247 409.335h-125.8l188.378 209.92 188.302-209.92h-146.242c5.537-168.998 143.777-304.393 313.609-304.393 173.397 0 313.913 140.971 313.913 314.899s-140.478 314.861-313.913 314.861c-69.48 0-133.689-22.718-185.685-61.099l-71.983 76.99c70.997 55.751 160.465 89.050 257.707 89.050 231.159 0 418.551-187.961 418.551-419.84-0.038-231.879-187.43-419.84-418.551-419.84z" - ], - "attrs": [ - {} - ], - "isMulticolor": false, - "isMulticolor2": false, - "tags": [ - "ccw" - ], - "grid": 0 - }, - "attrs": [ - {} - ], - "properties": { - "order": 97, - "id": 27, - "prevSize": 32, - "code": 58924, - "name": "ccw" - }, - "setIdx": 0, - "setId": 7, - "iconIdx": 27 - }, - { - "icon": { - "paths": [ - "M996.617 126.786l-513.555 513.555-256.796-256.834-128.379 128.417 385.214 385.252 641.896-642.010z" - ], - "width": 1176, - "attrs": [ - {} - ], - "isMulticolor": false, - "isMulticolor2": false, - "tags": [ - "check-mage" - ], - "grid": 0 - }, - "attrs": [ - {} - ], - "properties": { - "order": 96, - "id": 28, - "prevSize": 32, - "code": 58925, - "name": "check-mage" - }, - "setIdx": 0, - "setId": 7, - "iconIdx": 28 - }, - { - "icon": { - "paths": [ - "M512 40.96c-260.134 0-471.040 210.944-471.040 471.040 0 260.134 210.906 471.040 471.040 471.040s471.040-210.906 471.040-471.040c0-260.134-210.906-471.040-471.040-471.040zM512 880.64c-203.624 0-368.64-165.054-368.64-368.64s165.016-368.64 368.64-368.64 368.64 165.054 368.64 368.64-165.016 368.64-368.64 368.64zM547.84 245.76h-71.68v281.069l174.345 174.345 50.669-50.707-153.335-153.335z" - ], - "attrs": [ - {} - ], - "isMulticolor": false, - "isMulticolor2": false, - "tags": [ - "clock" - ], - "grid": 0 - }, - "attrs": [ - {} - ], - "properties": { - "order": 95, - "id": 29, - "prevSize": 32, - "code": 58926, - "name": "clock" - }, - "setIdx": 0, - "setId": 7, - "iconIdx": 29 - }, - { - "icon": { - "paths": [ - "M337.541 1021.004h513.024l64.512-645.916h-639.128l61.592 645.916zM737.394 154.169v-116.508c0-19.191-15.398-34.702-34.361-34.702h-217.847c-19.001 0-34.361 15.55-34.361 34.702v114.574c-73.576 8.382-150.149 24.614-226.494 52.338v106.989h738.001v-109.833c0 0-90.074-31.403-224.977-47.559zM668.937 147.759c-47.749-3.224-99.252-4.096-153.297-0.986v-61.44c0-9.519 7.623-17.332 17.143-17.332h118.936c9.519 0 17.218 7.813 17.218 17.332v62.426z" - ], - "width": 1176, - "attrs": [ - {} - ], - "isMulticolor": false, - "isMulticolor2": false, - "tags": [ - "delete" - ], - "grid": 0 - }, - "attrs": [ - {} - ], - "properties": { - "order": 94, - "id": 30, - "prevSize": 32, - "code": 58928, - "name": "delete" - }, - "setIdx": 0, - "setId": 7, - "iconIdx": 30 - }, - { - "icon": { - "paths": [ - "M928.503 26.889l-111.502 112.109 156.065 156.9 111.502-112.071-156.065-156.937zM215.002 744.41l156.065 156.9 535.211-538.093-156.065-156.9-535.211 538.093zM103.917 1007.161l188.985-49.873-139.302-140.098-49.683 190.009z" - ], - "width": 1176, - "attrs": [ - {} - ], - "isMulticolor": false, - "isMulticolor2": false, - "tags": [ - "edit" - ], - "grid": 0 - }, - "attrs": [ - {} - ], - "properties": { - "order": 115, - "id": 31, - "prevSize": 32, - "code": 58929, - "name": "edit" - }, - "setIdx": 0, - "setId": 7, - "iconIdx": 31 - }, - { - "icon": { - "paths": [ - "M1014.67 822.651c0 0 0 0 0 0l-310.651-310.651 310.651-310.651c0 0 0 0 0 0 3.337-3.337 5.765-7.244 7.32-11.416 4.248-11.378 1.82-24.69-7.32-33.83l-146.735-146.735c-9.14-9.14-22.452-11.567-33.83-7.32-4.172 1.555-8.078 3.982-11.416 7.32 0 0 0 0 0 0l-310.651 310.651-310.651-310.651c0 0 0 0 0 0-3.337-3.337-7.244-5.765-11.416-7.32-11.378-4.248-24.69-1.82-33.83 7.32l-146.735 146.735c-9.14 9.14-11.567 22.452-7.32 33.83 1.555 4.172 3.982 8.078 7.32 11.416 0 0 0 0 0 0l310.651 310.651-310.651 310.651c0 0 0 0 0 0-3.337 3.337-5.765 7.244-7.32 11.416-4.248 11.378-1.82 24.69 7.32 33.83l146.735 146.735c9.14 9.14 22.452 11.567 33.83 7.32 4.172-1.555 8.078-3.982 11.416-7.32 0 0 0 0 0 0l310.651-310.651 310.651 310.651c0 0 0 0 0 0 3.337 3.337 7.244 5.765 11.416 7.32 11.378 4.248 24.69 1.82 33.83-7.32l146.735-146.735c9.14-9.14 11.567-22.452 7.32-33.83-1.555-4.172-3.982-8.078-7.32-11.416z" - ], - "attrs": [ - {} - ], - "isMulticolor": false, - "isMulticolor2": false, - "tags": [ - "error" - ], - "grid": 0 - }, - "attrs": [ - {} - ], - "properties": { - "order": 122, - "id": 32, - "prevSize": 32, - "code": 58930, - "name": "error" - }, - "setIdx": 0, - "setId": 7, - "iconIdx": 32 - }, - { - "icon": { - "paths": [ - "M593.351 22.566c-270.336 0-489.434 219.098-489.434 489.358s219.098 489.434 489.434 489.434 489.434-219.136 489.434-489.434-219.136-489.358-489.434-489.358zM635.752 826.596c-11.985 11.719-26.396 17.636-43.16 17.636-8.154 0-15.967-1.517-23.4-4.589-7.358-3.034-13.843-7.168-19.456-12.174-5.613-5.158-10.126-11.226-13.388-18.356-3.337-7.13-4.968-14.753-4.968-22.945 0-16.308 5.992-30.303 17.977-42.060 11.947-11.681 26.396-17.598 43.198-17.598 16.308 0 30.606 5.689 42.78 16.801 12.25 11.188 18.318 24.993 18.318 41.339-0.038 16.384-5.992 30.303-17.939 41.984zM778.923 382.673c-3.982 13.767-9.747 26.396-17.18 37.774-7.471 11.454-16.498 22.49-27.079 33.071s-22.49 21.618-35.65 33.033c-11.454 9.785-20.783 18.318-27.913 25.79-7.168 7.396-12.895 14.867-17.218 22.338-4.286 7.433-7.282 15.398-9.026 24.007-1.707 8.609-2.617 49.721-2.617 62.35v22.338h-101.376v-32.616c0-13.729 0.986-56.661 3.034-67.584s5.158-21.125 9.481-30.872 10.012-19.228 17.18-28.369c7.168-9.14 16.232-18.887 27.079-29.203l38.647-36.902c10.847-9.747 20.177-20.632 27.951-32.616 7.737-12.060 11.529-26.7 11.529-43.88 0-22.3-6.978-41.036-21.011-56.206-14.071-15.17-33.944-22.793-59.695-22.793-13.16 0-25.069 2.389-35.65 7.282-10.619 4.817-19.797 11.454-27.496 19.759-7.737 8.344-13.577 17.901-17.598 28.786-3.982 10.847-6.334 21.997-6.865 33.527l-105.624-9.444c3.413-27.496 10.733-51.959 21.921-73.463 11.112-21.466 25.562-39.595 43.311-54.575 17.711-14.829 38.078-26.169 61.023-33.944 22.869-7.699 47.521-11.605 73.842-11.605 24.614 0 47.976 3.603 70.049 10.771 21.959 7.168 41.491 17.711 58.406 31.782 16.839 14.033 30.227 31.365 39.936 51.959 9.709 20.632 14.564 44.411 14.564 71.263 0 18.356-2.010 34.475-5.992 48.166z" - ], - "width": 1176, - "attrs": [ - {} - ], - "isMulticolor": false, - "isMulticolor2": false, - "tags": [ - "help" - ], - "grid": 0 - }, - "attrs": [ - {} - ], - "properties": { - "order": 124, - "id": 33, - "prevSize": 32, - "code": 58931, - "name": "help" - }, - "setIdx": 0, - "setId": 7, - "iconIdx": 33 - }, - { - "icon": { - "paths": [ - "M574.805 92.16c-227.631 0-412.71 182.386-418.247 409.335h-125.838l188.378 209.958 188.302-209.958h-146.242c5.537-168.998 143.777-304.393 313.647-304.393 173.359 0 313.875 140.971 313.875 314.899s-140.478 314.861-313.875 314.861c-69.518 0-133.727-22.718-185.761-61.099l-71.983 76.99c71.073 55.751 160.503 89.050 257.745 89.050 231.121 0 418.513-187.961 418.513-419.84-0.038-231.879-187.43-419.84-418.513-419.84zM537.6 286.72v240.109l153.865 153.865 50.669-50.669-132.855-132.855v-210.413h-71.68z" - ], - "attrs": [ - {} - ], - "isMulticolor": false, - "isMulticolor2": false, - "tags": [ - "history" - ], - "grid": 0 - }, - "attrs": [ - {} - ], - "properties": { - "order": 45, - "id": 34, - "prevSize": 32, - "code": 58932, - "name": "history" - }, - "setIdx": 0, - "setId": 7, - "iconIdx": 34 - }, - { - "icon": { - "paths": [ - "M510.413 0c-281.907 0-510.413 228.582-510.413 510.413 0 281.933 228.506 510.464 510.413 510.464s510.387-228.557 510.387-510.464c0-281.83-228.48-510.413-510.387-510.413zM865.843 510.413c0 69.99-20.506 135.27-55.578 190.285l-490.163-490.163c55.091-35.021 120.32-55.475 190.31-55.475 195.942 0 355.43 159.411 355.43 355.354zM154.957 510.413c0-69.939 20.506-135.245 55.578-190.31l490.189 490.189c-55.066 35.072-120.371 55.501-190.31 55.501-195.942 0.026-355.456-159.437-355.456-355.379z" - ], - "attrs": [ - {} - ], - "isMulticolor": false, - "isMulticolor2": false, - "tags": [ - "not-installed" - ], - "grid": 0 - }, - "attrs": [ - {} - ], - "properties": { - "order": 58, - "id": 35, - "prevSize": 32, - "code": 58936, - "name": "not-installed" - }, - "setIdx": 0, - "setId": 7, - "iconIdx": 35 - }, - { - "icon": { - "paths": [ - "M511.77 0c-282.778 0-512.102 229.222-512.102 512.179 0 282.829 229.325 512.102 512.102 512.102 282.931 0.026 512.23-229.248 512.23-512.102 0-282.957-229.299-512.179-512.23-512.179zM143.718 419.968h736.205v184.269h-736.205v-184.269z" - ], - "attrs": [ - {} - ], - "isMulticolor": false, - "isMulticolor2": false, - "tags": [ - "disabled" - ], - "grid": 0 - }, - "attrs": [ - {} - ], - "properties": { - "order": 57, - "id": 36, - "prevSize": 32, - "code": 58937, - "name": "disabled" - }, - "setIdx": 0, - "setId": 7, - "iconIdx": 36 - }, - { - "icon": { - "paths": [ - "M505.139 0.085c-282.658 3.775-508.826 236.066-505.071 518.827 3.772 282.556 236.1 508.826 518.793 505.003 282.658-3.768 508.826-236.066 505.071-518.827-3.717-282.658-236.1-508.826-518.793-505.003z" - ], - "attrs": [ - {} - ], - "isMulticolor": false, - "isMulticolor2": false, - "tags": [ - "dot" - ], - "grid": 0 - }, - "attrs": [ - {} - ], - "properties": { - "order": 56, - "id": 37, - "prevSize": 32, - "code": 58935, - "name": "dot" - }, - "setIdx": 0, - "setId": 7, - "iconIdx": 37 - }, - { - "icon": { - "paths": [ - "M383.462 577.51h255.693v-213.043h127.795l-255.642-255.667-255.642 255.667h127.795z", - "M852.173 577.51v170.394h-681.754v-170.394h-170.419v340.89h1022.618v-340.89z" - ], - "attrs": [ - {}, - {} - ], - "isMulticolor": false, - "isMulticolor2": false, - "tags": [ - "export" - ], - "grid": 0 - }, - "attrs": [ - {}, - {} - ], - "properties": { - "order": 93, - "id": 38, - "prevSize": 32, - "code": 58933, - "name": "export" - }, - "setIdx": 0, - "setId": 7, - "iconIdx": 38 - }, - { - "icon": { - "paths": [ - "M639.155 108.8h-255.693v213.043h-127.795l255.667 255.667 255.616-255.667h-127.795z", - "M852.173 577.51v170.394h-681.754v-170.394h-170.419v340.89h1022.618v-340.89z" - ], - "attrs": [ - {}, - {} - ], - "isMulticolor": false, - "isMulticolor2": false, - "tags": [ - "import" - ], - "grid": 0 - }, - "attrs": [ - {}, - {} - ], - "properties": { - "order": 92, - "id": 39, - "prevSize": 32, - "code": 58934, - "name": "import" - }, - "setIdx": 0, - "setId": 7, - "iconIdx": 39 - }, - { - "icon": { - "paths": [ - "M259.2 0h214.323v214.323h-214.323v-214.323z", - "M259.2 269.875h214.323v214.349h-214.323v-214.349z", - "M259.2 539.776h214.323v214.349h-214.323v-214.349z", - "M259.2 809.651h214.323v214.349h-214.323v-214.349z", - "M549.325 0h214.323v214.323h-214.323v-214.323z", - "M549.325 269.875h214.323v214.349h-214.323v-214.349z", - "M549.325 539.776h214.323v214.349h-214.323v-214.349z", - "M549.325 809.651h214.323v214.349h-214.323v-214.349z" - ], - "attrs": [ - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {} - ], - "isMulticolor": false, - "isMulticolor2": false, - "tags": [ - "gripper" - ], - "grid": 0 - }, - "attrs": [ - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {} - ], - "properties": { - "order": 91, - "id": 40, - "prevSize": 32, - "code": 58903, - "name": "gripper" - }, - "setIdx": 0, - "setId": 7, - "iconIdx": 40 - }, - { - "icon": { - "paths": [ - "M860.058 185.062v272l-430.029-269.158-1.894 253.491-424.371-249.754-3.763 647.834 426.24-241.28-5.606 239.437 439.424-252.16v259.635h163.942v-660.045z" - ], - "attrs": [ - {} - ], - "isMulticolor": false, - "isMulticolor2": false, - "tags": [ - "forward" - ], - "grid": 0 - }, - "attrs": [ - {} - ], - "properties": { - "order": 90, - "id": 41, - "prevSize": 32, - "code": 58904, - "name": "forward" - }, - "setIdx": 0, - "setId": 7, - "iconIdx": 41 - }, - { - "icon": { - "paths": [ - "M163.942 845.107v-271.974l430.029 269.133 1.894-253.491 424.397 249.754 3.738-647.834-426.24 241.28 5.606-239.437-439.424 252.16v-259.635h-163.942v660.045z" - ], - "attrs": [ - {} - ], - "isMulticolor": false, - "isMulticolor2": false, - "tags": [ - "backward" - ], - "grid": 0 - }, - "attrs": [ - {} - ], - "properties": { - "order": 89, - "id": 42, - "prevSize": 32, - "code": 58905, - "name": "backward", - "ligatures": "" - }, - "setIdx": 0, - "setId": 7, - "iconIdx": 42 - }, - { - "icon": { - "paths": [ - "M512.794 0c-283.187 0-512.794 229.581-512.794 512.794 0 283.187 229.606 512.794 512.794 512.794s512.794-229.632 512.794-512.794c0-283.213-229.581-512.794-512.794-512.794zM512.794 971.213c-253.158 0-458.394-205.261-458.394-458.368 0-253.158 205.261-458.394 458.394-458.394 253.184 0 458.394 205.235 458.394 458.394 0.026 253.107-205.21 458.368-458.394 458.368z", - "M760.013 625.613l30.387-38.4-265.6-206.413-20.787-1.613-259.226 208.026 28.826 39.987 236.8-177.613z" - ], - "attrs": [ - {}, - {} - ], - "isMulticolor": false, - "isMulticolor2": false, - "tags": [ - "expand-close" - ], - "grid": 0 - }, - "attrs": [ - {}, - {} - ], - "properties": { - "order": 88, - "id": 43, - "prevSize": 32, - "code": 58901, - "name": "expand-close" - }, - "setIdx": 0, - "setId": 7, - "iconIdx": 43 - }, - { - "icon": { - "paths": [ - "M512.794 0c-283.187 0-512.794 229.581-512.794 512.794 0 283.187 229.606 512.794 512.794 512.794s512.794-229.606 512.794-512.794c0-283.213-229.581-512.794-512.794-512.794zM512.794 971.213c-253.158 0-458.394-205.261-458.394-458.394 0-253.158 205.261-458.394 458.394-458.394 253.184 0 458.394 205.235 458.394 458.394 0.026 253.133-205.21 458.394-458.394 458.394z", - "M265.6 454.4l-30.387 38.4 265.574 206.387 20.813 1.613 259.2-208-28.8-39.987-236.8 177.587z" - ], - "attrs": [ - {}, - {} - ], - "isMulticolor": false, - "isMulticolor2": false, - "tags": [ - "expand-open" - ], - "grid": 0 - }, - "attrs": [ - {}, - {} - ], - "properties": { - "order": 87, - "id": 44, - "prevSize": 32, - "code": 58902, - "name": "expand-open" - }, - "setIdx": 0, - "setId": 7, - "iconIdx": 44 - }, - { - "icon": { - "paths": [ - "M1020.032 565.555v-116.045l-16.41-5.376-124.237-40.525-33.152-80.102 63.718-134.784-82.048-82.125-15.411 7.808-116.531 59.213-80.077-33.178-50.278-140.442h-116.096l-45.875 140.698-80 33.126-134.963-63.744-82.022 82.074 7.834 15.334 59.162 116.608-33.126 80.026-140.518 50.253v116.147l16.435 5.325 124.288 40.576 33.075 80-63.693 134.886 82.048 82.099 131.942-66.97 80.026 33.152 50.304 140.39h116.096l5.35-16.41 40.55-124.237 80.077-33.178 134.886 63.718 82.074-82.074-7.834-15.386-59.213-116.582 33.203-80.026 140.416-50.253zM510.003 672.589c-89.754 0-162.509-72.832-162.509-162.611 0-89.754 72.755-162.483 162.509-162.483 89.83 0 162.509 72.73 162.509 162.483 0.026 89.805-72.653 162.611-162.509 162.611z" - ], - "attrs": [ - { - "visibility": false - } - ], - "isMulticolor": false, - "isMulticolor2": false, - "tags": [ - "system-config" - ], - "grid": 0 - }, - "attrs": [ - { - "visibility": false - } - ], - "properties": { - "order": 86, - "id": 45, - "prevSize": 32, - "code": 58896, - "name": "system-config" - }, - "setIdx": 0, - "setId": 7, - "iconIdx": 45 - }, - { - "icon": { - "paths": [ - "M509.978 54.426l-509.978 509.926 95.949 95.949 414.106-413.978 413.875 413.978 95.949-95.898-509.901-509.978zM146.253 688.563v335.437h259.917v-304.819h207.514v304.819h259.917v-335.488l-363.622-363.597-363.725 363.648z" - ], - "attrs": [ - { - "visibility": false - } - ], - "isMulticolor": false, - "isMulticolor2": false, - "tags": [ - "home" - ], - "grid": 0 - }, - "attrs": [ - { - "visibility": false - } - ], - "properties": { - "order": 85, - "id": 46, - "prevSize": 32, - "code": 58897, - "name": "home" - }, - "setIdx": 0, - "setId": 7, - "iconIdx": 46 - }, - { - "icon": { - "paths": [ - "M0 736.41l498.278 287.59v-421.402l-498.278-287.667v421.478zM894.464 224.486v44.262c0 32.819-62.797 59.418-140.365 59.418-77.466 0-140.262-26.598-140.262-59.418v-73.216h0.435c4.71 30.925 65.408 55.475 139.853 55.475 77.568 0 140.365-26.624 140.365-59.29 0-32.845-62.797-59.366-140.365-59.366-6.195 0-12.262 0.205-18.202 0.563l-90.317-52.147v55.706c0 32.819-62.72 59.392-140.262 59.392-48.691 0-91.597-10.496-116.813-26.47-3.584-3.712-7.987-7.245-13.312-10.598-6.579-6.861-10.24-14.387-10.24-22.323v-53.939l-87.322 50.381c-6.272-0.307-12.646-0.614-19.123-0.614-77.491 0-140.314 26.522-140.314 59.366 0 32.691 62.822 59.29 140.314 59.29 74.445 0 135.219-24.525 139.93-55.475h0.384v73.216c0 32.819-62.746 59.418-140.314 59.418-77.491 0-140.314-26.598-140.314-59.418v-43.622l-108.083 62.31 499.994 288.563 496.691-286.694-112.358-64.768zM646.784 408.013c0 32.794-62.874 59.315-140.365 59.315s-140.339-26.522-140.339-59.315v-73.267h0.41c4.762 30.95 65.459 55.475 139.93 55.475s135.142-24.525 139.904-55.475h0.486v73.267zM525.645 606.234v417.766l498.355-287.718v-417.766l-498.355 287.718zM505.318 118.656c77.542 0 140.262-26.547 140.262-59.315s-62.72-59.315-140.262-59.315c-77.491 0-140.339 26.573-140.339 59.315-0.026 32.768 62.822 59.315 140.339 59.315z" - ], - "attrs": [ - { - "visibility": false - } - ], - "isMulticolor": false, - "isMulticolor2": false, - "tags": [ - "lego" - ], - "grid": 0 - }, - "attrs": [ - { - "visibility": false - } - ], - "properties": { - "order": 84, - "id": 47, - "prevSize": 32, - "code": 58898, - "name": "lego" - }, - "setIdx": 0, - "setId": 7, - "iconIdx": 47 - }, - { - "icon": { - "paths": [ - "M287.002 481.664c0.205 0.23 0.461 0.486 0.691 0.717l103.347 103.373 36.045-36.045-56.55-56.499 90.266-90.189 11.904 1.28c3.046 0.307 6.093 0.538 9.19 0.538 6.246 0 12.314-0.768 18.253-2.125l-66.381-66.381c-1.357-1.382-2.765-2.611-4.173-3.814 20.454-73.6 1.766-155.725-56.038-213.555-57.421-57.421-138.803-76.237-211.968-56.525l123.955 123.981-32.563 121.446-121.395 32.589-124.032-124.006c-19.712 73.19-0.896 154.573 56.525 212.019 60.262 60.288 147.021 77.952 222.925 53.197zM653.235 555.802c-1.997 8.909-2.509 18.202-1.459 27.546l1.306 11.93-90.189 90.189-56.55-56.55-36.070 36.122 327.219 327.194c20.198 20.173 46.618 30.259 73.062 30.259s52.915-10.086 73.037-30.259c40.346-40.32 40.346-105.728 0-146.074l-290.355-290.355zM905.907 958.362l-51.866 13.875-42.112-42.112 13.901-51.891 51.866-13.926 42.112 42.138-13.901 51.917zM506.701 594.099l56.576 56.576 64.128-64.154c-3.482-31.334 6.707-63.821 30.669-87.808 24.013-23.962 56.474-34.176 87.808-30.72l280.397-280.346-157.056-157.056-280.448 280.397c3.482 31.258-6.682 63.821-30.669 87.782-24.013 23.987-56.525 34.176-87.808 30.643l-64.102 64.205 56.499 56.422-277.043 277.12-10.138-10.138-53.248 42.829-89.421 141.312 22.835 22.835 141.312-89.421 42.803-53.222-10.138-10.138 277.043-277.12z" - ], - "attrs": [ - { - "visibility": false - } - ], - "isMulticolor": false, - "isMulticolor2": false, - "tags": [ - "tool" - ], - "grid": 0 - }, - "attrs": [ - { - "visibility": false - } - ], - "properties": { - "order": 120, - "id": 48, - "prevSize": 32, - "code": 58899, - "name": "tool" - }, - "setIdx": 0, - "setId": 7, - "iconIdx": 48 - }, - { - "icon": { - "paths": [ - "M1023.932 505.105c-3.717-282.692-236.1-508.826-518.793-505.003-282.658 3.775-508.826 236.066-505.071 518.827 3.772 282.556 236.1 508.826 518.793 505.003 282.658-3.768 508.826-236.066 505.071-518.827zM623.991 481.304v298.633h-223.983v-298.633h-186.621l298.633-298.633 298.667 298.633h-186.679z" - ], - "attrs": [ - {} - ], - "isMulticolor": false, - "isMulticolor2": false, - "tags": [ - "upgrade" - ], - "grid": 0 - }, - "attrs": [ - {} - ], - "properties": { - "order": 125, - "id": 49, - "prevSize": 32, - "code": 58900, - "name": "upgrade" - }, - "setIdx": 0, - "setId": 7, - "iconIdx": 49 - }, - { - "icon": { - "paths": [ - "M870.821 731.837c-64.195-65.89-78.231-188.772-91.738-283.159-20.074-139.937-24.259-297.089-226.008-317.693v-25.318c0-25.424-39.195-46.028-64.937-46.028s-62.024 20.551-62.024 46.028v25.371c-200.054 20.816-206.993 177.914-226.855 317.693-13.453 94.439-27.331 217.268-91.049 283.264-12.818 13.348-16.473 32.998-9.11 49.947 7.362 16.843 24.153 27.913 42.797 27.913h695.343c18.75 0 35.593-11.070 42.903-28.019s3.655-36.653-9.322-50z", - "M489.569 963.883c51.060 0 92.373-40.837 92.373-91.367h-184.694c-0.053 50.53 41.314 91.367 92.32 91.367z" - ], - "width": 989, - "attrs": [ - { - "opacity": 1, - "visibility": false - }, - { - "opacity": 1, - "visibility": false - } - ], - "isMulticolor": false, - "isMulticolor2": false, - "tags": [ - "notification-02" - ], - "grid": 0 - }, - "attrs": [ - { - "opacity": 1, - "visibility": false - }, - { - "opacity": 1, - "visibility": false - } - ], - "properties": { - "order": 123, - "id": 50, - "prevSize": 32, - "code": 58887, - "name": "notification-02" - }, - "setIdx": 0, - "setId": 7, - "iconIdx": 50 - }, - { - "icon": { - "paths": [ - "M252.137 153.228l-160.070 92.393 378.042 218.205 160.023-92.393-377.996-218.205zM845.638 247.063l-377.996-218.252-145.222 83.828 377.996 218.205 145.222-83.782zM502.784 526.15v433.664l376.832-217.507v-433.711l-376.832 217.553zM55.668 742.26l376.785 217.507v-436.503l-376.785-217.46v436.457z" - ], - "width": 954, - "attrs": [ - { - "opacity": 1, - "visibility": false - } - ], - "isMulticolor": false, - "isMulticolor2": false, - "tags": [ - "product" - ], - "grid": 0 - }, - "attrs": [ - { - "opacity": 1, - "visibility": false - } - ], - "properties": { - "order": 7, - "id": 51, - "prevSize": 32, - "code": 58888, - "name": "product", - "ligatures": "" - }, - "setIdx": 0, - "setId": 7, - "iconIdx": 51 - }, - { - "icon": { - "paths": [ - "M454.495 48.899l-402.697 240.513v457.026l104.632 60.727v-457.049l298.157-178.728 299.698 179.142-0.138 455.922 103.528-60.013v-457.026l-403.18-240.513zM507.766 330.28v534.344l-53.271 32.124-53.34-32.262v-533.792l-138.090 83.853v456.934l191.453 115.516 193.087-116.322v-456.451l-139.839-83.945z" - ], - "width": 903, - "attrs": [ - { - "opacity": 1, - "visibility": false - }, - { - "opacity": 1, - "visibility": false - }, - { - "opacity": 1, - "visibility": false - } - ], - "isMulticolor": false, - "isMulticolor2": false, - "tags": [ - "logo" - ], - "grid": 0 - }, - "attrs": [ - { - "opacity": 1, - "visibility": false - }, - { - "opacity": 1, - "visibility": false - }, - { - "opacity": 1, - "visibility": false - } - ], - "properties": { - "order": 17, - "id": 52, - "prevSize": 32, - "code": 58886, - "name": "logo", - "ligatures": "" - }, - "setIdx": 0, - "setId": 7, - "iconIdx": 52 - }, - { - "icon": { - "paths": [ - "M709.921 158.694c8.139 32.295 8.927 34.974 8.192 68.162-0.263 12.813-7.772 71.943-5.724 90.112 1.628 14.966 5.461 16.174 11.448 28.514 10.398 21.425 6.984 51.095 2.941 72.678-2.206 11.868-6.827 28.725-13.916 38.387-7.667 10.66-23.211 10.713-30.142 23.158-9.872 17.854-4.306 43.008-10.503 62.385-7.142 21.898-25.101 23.421-26.466 52.145 8.822 1.155 17.592 2.468 26.466 3.623 8.822 18.59 25.049 55.874 41.59 67.059 13.863 3.728 27.727 7.457 41.59 11.185 48.627 19.64 102.558 43.061 151.237 63.33 44.373 18.432 97.411 24.996 113.48 70.84 0 31.035 2.941 104.501 2.153 145.25h-965.553c-0.893-40.697 2.153-114.215 2.153-145.25 15.964-45.844 69.002-52.408 113.375-70.84 48.679-20.27 102.61-43.691 151.237-63.33 13.811-3.728 27.674-7.457 41.59-11.185 16.489-11.185 32.715-48.522 41.538-67.059l19.692-4.621c-4.464-24.576-19.85-26.466-26.256-43.743-2.521-26.099-5.041-52.145-7.509-78.192 0.053 1.155-18.117-3.361-20.48-4.779-25.731-15.806-26.204-80.24-28.725-107.021-1.103-12.183 16.174-22.265 11.343-44.636-28.094-131.44 12.183-192.88 75.881-213.307 44.216-17.749 126.871-50.465 203.855-3.728l19.167 17.487 30.93 5.251c15.491 8.77 25.416 38.124 25.416 38.124z" - ], - "width": 1090, - "attrs": [ - { - "opacity": 1, - "visibility": false - } - ], - "isMulticolor": false, - "isMulticolor2": false, - "tags": [ - "account" - ], - "grid": 0 - }, - "attrs": [ - { - "opacity": 1, - "visibility": false - } - ], - "properties": { - "order": 9, - "id": 53, - "prevSize": 32, - "code": 58880, - "name": "account", - "ligatures": "" - }, - "setIdx": 0, - "setId": 7, - "iconIdx": 53 - }, - { - "icon": { - "paths": [ - "M529.203 886.14l-468.465-628.209h936.931l-468.465 628.209z" - ], - "width": 1085, - "attrs": [ - { - "opacity": 1, - "visibility": false - } - ], - "isMulticolor": false, - "isMulticolor2": false, - "tags": [ - "arrowdown" - ], - "grid": 0 - }, - "attrs": [ - { - "opacity": 1, - "visibility": false - } - ], - "properties": { - "order": 10, - "id": 54, - "prevSize": 32, - "code": 58881, - "name": "arrowdown", - "ligatures": "" - }, - "setIdx": 0, - "setId": 7, - "iconIdx": 54 - }, - { - "icon": { - "paths": [ - "M976.793 982.006h-910.388v-910.388h910.388v910.388zM912.622 135.789h-782.046v782.088h782.046v-782.088z", - "M221.432 822.8h152.876v-372.033h-152.876v372.033z", - "M466.323 820.234h350.932v-366.53h-350.932v366.53z", - "M221.432 360.489h595.865v-147.125h-595.865v147.125z" - ], - "width": 1034, - "attrs": [ - { - "opacity": 1, - "visibility": false - }, - { - "opacity": 1, - "visibility": false - }, - { - "opacity": 1, - "visibility": false - }, - { - "opacity": 1, - "visibility": false - } - ], - "isMulticolor": false, - "isMulticolor2": false, - "tags": [ - "cms" - ], - "grid": 0 - }, - "attrs": [ - { - "opacity": 1, - "visibility": false - }, - { - "opacity": 1, - "visibility": false - }, - { - "opacity": 1, - "visibility": false - }, - { - "opacity": 1, - "visibility": false - } - ], - "properties": { - "order": 83, - "id": 55, - "prevSize": 32, - "code": 58882, - "name": "cms", - "ligatures": "" - }, - "setIdx": 0, - "setId": 7, - "iconIdx": 55 - }, - { - "icon": { - "paths": [ - "M264.319 308.831c75.685 0 136.98-61.259 136.98-136.944 0-75.649-61.295-136.98-136.98-136.98s-137.017 61.331-137.017 136.98c0 75.649 61.331 136.944 137.017 136.944zM448.929 370.851c-28.962-28.926-63.325-46.252-187.655-46.252s-157.859 18.776-185.335 46.252c-27.44 27.44-18.196 320.43-18.196 320.43l60.824-144.411 38.241 430.334 110.23-220.278 102.907 220.278 36.393-430.334 60.824 144.411c-0.036 0 10.693-291.468-18.233-320.43z" - ], - "width": 489, - "attrs": [ - { - "opacity": 1, - "visibility": false - } - ], - "isMulticolor": false, - "isMulticolor2": false, - "tags": [ - "customers" - ], - "grid": 0 - }, - "attrs": [ - { - "opacity": 1, - "visibility": false - } - ], - "properties": { - "order": 82, - "id": 56, - "prevSize": 32, - "code": 58883, - "name": "customers", - "ligatures": "" - }, - "setIdx": 0, - "setId": 7, - "iconIdx": 56 - }, - { - "icon": { - "paths": [ - "M680.975 73.728c-337.523 0-610.976 273.515-611.038 610.976 0.122 37.72 1.039 251.812 1.039 251.812h1219.997c0 0 0.978-239.219 1.039-251.812-0.183-337.523-273.637-610.976-611.038-610.976zM737.708 197.831c31.117 3.607 61.379 10.271 90.418 19.624l-19.93 61.685c-25.004-8.070-51.169-13.939-78.191-16.995l7.703-64.313zM270.091 673.15h-64.864c0-31.423 3.118-62.235 8.803-92.007l63.702 12.349c-5.135 25.799-7.642 52.392-7.642 79.658zM305.855 504.419l-59.178-26.288c12.655-28.489 28-55.449 45.79-80.636l52.942 37.475c-15.284 21.825-28.611 45.056-39.554 69.449zM407.46 365.155l-43.405-48.113c22.925-20.541 47.807-39.187 74.462-54.96l33.318 55.571c-22.987 13.755-44.567 29.65-64.374 47.501zM536.943 217.455c29.039-9.292 59.178-16.017 90.418-19.624l7.581 64.313c-26.838 3.057-53.003 8.926-78.13 16.995l-19.869-61.685zM761.673 801.532l-152.897 27.205-38.881-150.452 395.172-404.22-203.394 527.467zM1019.476 434.971l52.942-37.414c17.79 25.187 33.257 52.148 45.851 80.636l-59.178 26.288c-10.943-24.454-24.209-47.685-39.615-69.51zM1094.916 673.15c0-27.266-2.69-53.859-7.703-79.658l63.702-12.349c5.808 29.834 8.803 60.645 8.803 92.007h-64.802zM646.006 770.659c26.777 17.056 62.174 9.415 79.291-17.24 17.118-26.593 9.292-62.051-17.301-79.108-26.655-17.24-62.051-9.354-79.23 17.362-17.118 26.349-9.476 61.99 17.24 78.986z" - ], - "width": 1376, - "attrs": [ - { - "opacity": 1, - "visibility": false - } - ], - "isMulticolor": false, - "isMulticolor2": false, - "tags": [ - "dashboard" - ], - "grid": 0 - }, - "attrs": [ - { - "opacity": 1, - "visibility": false - } - ], - "properties": { - "order": 81, - "id": 57, - "prevSize": 32, - "code": 58884, - "name": "dashboard", - "ligatures": "" - }, - "setIdx": 0, - "setId": 7, - "iconIdx": 57 - }, - { - "icon": { - "paths": [ - "M24.097 113.465h972.827v111.922l-410.504 412.792v238.366l-171.447 87.505v-325.871l-390.875-415.877v-108.837z" - ], - "attrs": [ - { - "opacity": 1, - "visibility": false - } - ], - "isMulticolor": false, - "isMulticolor2": false, - "tags": [ - "filter" - ], - "grid": 0 - }, - "attrs": [ - { - "opacity": 1, - "visibility": false - } - ], - "properties": { - "order": 80, - "id": 58, - "prevSize": 32, - "code": 58885, - "name": "filter", - "ligatures": "" - }, - "setIdx": 0, - "setId": 7, - "iconIdx": 58 - }, - { - "icon": { - "paths": [ - "M59.153 534.182l164.053 38.141v-303.902l-164.053 38.141v227.621zM1122.198 59.153l-837.712 194.959v335.978l140.328 376.832 151.712-57.45-104.049-279.113 649.668 151.18v-722.385z" - ], - "width": 1170, - "attrs": [ - { - "opacity": 1, - "visibility": false - } - ], - "isMulticolor": false, - "isMulticolor2": false, - "tags": [ - "promotions" - ], - "grid": 0 - }, - "attrs": [ - { - "opacity": 1, - "visibility": false - } - ], - "properties": { - "order": 79, - "id": 59, - "prevSize": 32, - "code": 58889, - "name": "promotions", - "ligatures": "" - }, - "setIdx": 0, - "setId": 7, - "iconIdx": 59 - }, - { - "icon": { - "paths": [ - "M736.707 981.234h207.134v-322.703h-207.134v322.703zM399.646 981.234h207.134v-946.793h-207.134v946.793zM62.673 981.19h207.134v-634.704h-207.134v634.704z" - ], - "width": 991, - "attrs": [ - { - "opacity": 1, - "visibility": false - } - ], - "isMulticolor": false, - "isMulticolor2": false, - "tags": [ - "reports" - ], - "grid": 0 - }, - "attrs": [ - { - "opacity": 1, - "visibility": false - } - ], - "properties": { - "order": 78, - "id": 60, - "prevSize": 32, - "code": 58890, - "name": "reports", - "ligatures": "" - }, - "setIdx": 0, - "setId": 7, - "iconIdx": 60 - }, - { - "icon": { - "paths": [ - "M426.502 612.517c-15.866-13.512-42.796-25.753-80.79-36.723v198.774c11.535-1.459 23.729-4.331 36.299-8.851 12.618-4.426 23.87-10.829 33.804-19.068 9.981-8.427 18.173-18.55 24.529-30.649 6.638-12.006 9.651-26.365 9.651-42.89 0.047-26.836-7.721-47.222-23.493-60.593zM576.736 736.856c-7.109 23.117-19.774 45.762-38.135 67.749-18.503 22.175-43.079 41.855-74.010 58.992-30.885 17.373-70.432 27.683-118.878 31.12v88.088h-57.014v-88.088c-72.080-5.603-128.483-29.237-169.113-71.374-40.536-42.090-63.935-104.095-70.432-185.544h136.251c-0.753 39.359 8.992 70.479 28.86 93.266 20.15 22.74 44.774 37.335 74.434 43.455v-216.523c-3.060-1.318-7.486-2.919-12.994-4.567-5.508-1.789-11.393-3.343-17.938-4.708-23.776-6.827-47.175-15.019-70.291-24.294-23.493-9.369-44.114-21.704-62.523-37.335-18.456-15.584-33.098-34.84-43.879-57.956-11.111-23.211-16.478-51.977-16.478-86.487 0-35.31 6.168-66.336 18.785-93.313 12.665-26.836 29.143-49.529 49.858-67.702 20.621-18.314 44.303-32.58 71.468-42.419 27.071-10.122 55.037-16.149 83.992-18.314v-79.66h57.014v79.66c29.143 3.531 56.308 10.169 81.638 20.292 25.423 10.028 47.787 23.729 67.137 41.478 19.585 17.514 35.357 39.453 47.457 65.771 12.288 26.13 19.35 57.109 21.28 93.172h-137.287c-0.518-27.636-8.616-51.082-23.917-70.432-15.725-19.303-34.275-29.002-56.308-29.002v183.331c7.862 2.072 15.631 4.143 23.729 6.12 8.098 2.072 16.525 4.567 25.565 7.297 47.645 13.983 84.415 31.12 110.168 51.318 25.8 20.292 44.726 41.666 56.92 63.653 12.335 22.175 19.633 44.256 21.704 66.336 2.448 22.081 3.531 41.713 3.531 59.039 0.047 15.207-3.531 34.416-10.593 57.579zM228.905 263.415c-8.38 7.156-15.113 16.196-19.962 26.883-4.802 10.781-7.062 23.352-7.062 37.759 0 22.834 6.733 40.536 20.103 52.824 13.653 12.618 35.734 22.552 66.713 30.131v-168.831c-10.829 0-21.516 1.695-31.826 5.226-10.216 3.437-19.633 8.851-27.966 16.007z" - ], - "width": 659, - "attrs": [ - { - "opacity": 1, - "visibility": false - } - ], - "isMulticolor": false, - "isMulticolor2": false, - "tags": [ - "sales" - ], - "grid": 0 - }, - "attrs": [ - { - "opacity": 1, - "visibility": false - } - ], - "properties": { - "order": 77, - "id": 61, - "prevSize": 32, - "code": 58891, - "name": "sales", - "ligatures": "" - }, - "setIdx": 0, - "setId": 7, - "iconIdx": 61 - }, - { - "icon": { - "paths": [ - "M555.139 21.642c-218.775-71.601-457.062 40.29-532.231 250.028-75.227 209.681 41.211 437.665 259.928 509.208 218.717 71.601 457.004-40.348 532.231-250.028s-41.211-437.665-259.928-509.208zM320.076 677.045c-158.915-52.089-243.467-217.681-188.903-369.978 54.679-152.296 227.754-233.625 386.669-181.593s243.409 217.624 188.788 369.92c-54.622 152.296-227.696 233.567-386.554 181.65z", - "M638.482 685.794l358.927 349.602 24.807-69.241 24.865-69.241-310.348-302.29z" - ], - "width": 1109, - "attrs": [ - { - "opacity": 1, - "visibility": false - }, - { - "opacity": 1, - "visibility": false - } - ], - "isMulticolor": false, - "isMulticolor2": false, - "tags": [ - "search" - ], - "grid": 0 - }, - "attrs": [ - { - "opacity": 1, - "visibility": false - }, - { - "opacity": 1, - "visibility": false - } - ], - "properties": { - "order": 76, - "id": 62, - "prevSize": 32, - "code": 58892, - "name": "search", - "ligatures": "" - }, - "setIdx": 0, - "setId": 7, - "iconIdx": 62 - }, - { - "icon": { - "paths": [ - "M1098.281 85.45c19.777-3.723 34.901-21.232 34.901-42.347-0.058-23.791-19.196-43.103-42.812-43.103h-900.508c-23.675 0-42.754 19.312-42.754 43.103 0 21.057 15.007 38.566 34.843 42.347l-181.951 354.421v68.988c0 30.946 32.516 56.016 72.594 56.016 13.437 0 26.001-2.908 36.821-7.795v466.919h1061.286v-466.919c10.878 4.944 23.326 7.795 36.879 7.795 40.078 0 72.594-25.071 72.594-56.016v-68.988l-181.893-354.421zM214.758 564.875c-38.217 0-69.221-25.071-69.221-56.016v-6.457h-0.349v-62.531l137.162-353.665h109.648l-107.961 353.665v68.988c0 0 0 0 0 0 0 30.946-31.004 56.016-69.279 56.016zM498.447 564.875c-38.217 0-69.221-25.071-69.221-56.016v-68.988l57.354-353.665h109.241l-28.095 353.665v68.93c-0.058 31.004-31.004 56.075-69.279 56.075zM782.077 564.875c-38.217 0-69.162-25.071-69.162-56.016v-68.988l-28.154-353.665h108.892l57.296 353.665v68.988c0 0.931 0.175 1.92 0.233 2.792-1.803 29.666-32.051 53.224-69.104 53.224zM1134.637 508.859c0 30.946-31.004 56.016-69.221 56.016s-69.162-25.071-69.162-56.016v-68.988l-108.019-353.665h109.59l137.22 353.665v62.473h-0.349v6.515h-0.058z" - ], - "width": 1280, - "attrs": [ - { - "opacity": 1, - "visibility": false - } - ], - "isMulticolor": false, - "isMulticolor2": false, - "tags": [ - "stores" - ], - "grid": 0 - }, - "attrs": [ - { - "opacity": 1, - "visibility": false - } - ], - "properties": { - "order": 75, - "id": 63, - "prevSize": 32, - "code": 58893, - "name": "stores", - "ligatures": "" - }, - "setIdx": 0, - "setId": 7, - "iconIdx": 63 - }, - { - "icon": { - "paths": [ - "M944.97 329.042c-97.861 0-177.522 79.581-177.522 177.443 0 97.94 79.66 177.679 177.522 177.679 98.019 0 177.679-79.739 177.679-177.679 0-97.861-79.66-177.443-177.679-177.443zM944.97-0c-470.712 0-944.97 512-944.97 512s474.258 512 944.97 512c470.949 0 945.128-512 945.128-512s-474.179-512-945.128-512zM944.97 868.856c-200.057 0-362.292-162.078-362.292-362.45 0-200.057 162.236-362.292 362.292-362.292 200.214 0 362.45 162.236 362.45 362.292 0 200.451-162.236 362.45-362.45 362.45z" - ], - "width": 1890, - "attrs": [ - { - "opacity": 1, - "visibility": false - } - ], - "isMulticolor": false, - "isMulticolor2": false, - "tags": [ - "views" - ], - "grid": 0 - }, - "attrs": [ - { - "opacity": 1, - "visibility": false - } - ], - "properties": { - "order": 73, - "id": 64, - "prevSize": 32, - "code": 58895, - "name": "views", - "ligatures": "" - }, - "setIdx": 0, - "setId": 7, - "iconIdx": 64 - }, - { - "icon": { - "paths": [ - "M1042.226 299.849h-598.393v-299.849l-443.833 384.316 443.833 384.403v-299.859h598.393c106.478 0 192.801 86.318 192.801 192.801s-86.318 192.796-192.801 192.796v0.483l-452.707 0.005c-46.695 0.005-84.53 37.845-84.53 84.535 0 46.68 37.84 84.525 84.535 84.525 0.377 0 0.744-0.053 1.121-0.058h451.581c199.964 0 362.044-162.085 362.044-362.039 0-199.964-162.080-362.059-362.044-362.059z" - ], - "width": 1404, - "attrs": [], - "isMulticolor": false, - "isMulticolor2": false, - "tags": [ - "revert" - ], - "grid": 0 - }, - "attrs": [], - "properties": { - "order": 129, - "id": 65, - "prevSize": 32, - "code": 58946, - "name": "revert" - }, - "setIdx": 0, - "setId": 7, - "iconIdx": 65 - }, - { - "icon": { - "paths": [ - "M1023.959 505.088c-3.717-282.665-236.121-508.842-518.817-505.040-282.689 3.772-508.866 236.091-505.094 518.868 3.772 282.58 236.121 508.842 518.813 505.040 282.689-3.772 508.866-236.067 505.098-518.868zM580.086 904.359h-136.149v-136.163h136.149v136.163zM597.168 293.742l-44.103 388.928h-83.113l-43.099-388.928v-171.575h170.318v171.575z" - ], - "attrs": [ - { - "fill": "rgb(100, 97, 96)" - } - ], - "isMulticolor": false, - "isMulticolor2": false, - "tags": [ - "alert-round" - ], - "grid": 32 - }, - "attrs": [ - { - "fill": "rgb(100, 97, 96)" - } - ], - "properties": { - "order": 132, - "id": 0, - "name": "alert-round", - "prevSize": 32, - "code": 58952 - }, - "setIdx": 1, - "setId": 6, - "iconIdx": 0 - }, - { - "icon": { - "paths": [ - "M793.271 222.6l-192.695-83.055v80.482c-2.517 31.926-83.182 57.618-182.582 57.618-99.309 0-180.126-25.692-182.398-57.618h-0.318l-0.465-80.482-197.709 83.055 381.218 167.697 374.95-167.697zM265.959 118.114l-1.104 0.428c32.596 16.331 89.086 27.124 153.551 27.124 64.726 0 121.621-10.94 153.996-27.355l-1.168-0.512c18.811-9.3 29.664-20.34 29.664-32.264 0-32.713-81.606-59.114-182.492-59.114-100.759 0-182.806 26.401-182.806 59.114-0.003 12.007 11.295 23.218 30.36 32.579zM418.418 462.436l-418.418-191.009v563.335l418.321 189.238 418.321-189.238v-563.733l-418.224 191.407z" - ], - "width": 883, - "attrs": [ - {} - ], - "isMulticolor": false, - "isMulticolor2": false, - "tags": [ - "module" - ], - "grid": 32 - }, - "attrs": [ - {} - ], - "properties": { - "order": 131, - "id": 1, - "name": "module", - "prevSize": 32, - "code": 58951 - }, - "setIdx": 1, - "setId": 6, - "iconIdx": 1 - }, - { - "icon": { - "paths": [ - "M939.616 148.384c112.512 112.448 112.512 294.816 0 407.264l-350.944 350.976c-12.512 12.544-32.736 12.544-45.248 0-12.576-12.512-12.576-32.704 0-45.248l346.432-346.464c87.488-87.488 87.488-229.248-0.064-316.768-87.36-87.488-229.248-87.488-316.736 0l-462.304 456.864c-62.496 62.464-62.496 163.776 0 226.24 62.496 62.496 163.744 62.496 226.24 0l466.88-461.344c37.44-37.44 37.44-98.336 0-135.776-37.44-37.408-98.304-37.408-135.744 0l-351.008 351.008c-12.512 12.512-32.736 12.512-45.248 0-12.512-12.544-12.512-32.736 0-45.28l350.976-350.976c62.432-62.464 163.744-62.464 226.24 0 62.496 62.496 62.496 163.776 0 226.272l-466.88 461.376c-87.296 87.328-229.408 87.328-316.736 0-87.328-87.328-87.328-229.472 0-316.8l466.88-461.344c112.448-112.512 294.816-112.512 407.264 0z" - ], - "attrs": [], - "isMulticolor": false, - "isMulticolor2": false, - "tags": [ - "clip", - "paperclip", - "attachment" - ], - "grid": 32 - }, - "attrs": [], - "properties": { - "id": 2, - "order": 130, - "prevSize": 32, - "code": 58947, - "name": "clip" - }, - "setIdx": 1, - "setId": 6, - "iconIdx": 2 + "IcoMoonType": "selection", + "icons": [ + { + "icon": { + "paths": [ + "M0 512v512h793.43v-771.052l-42.045-36.62c-23.735-19.666-46.114-39.332-50.183-43.401-4.069-3.391-16.275-14.241-27.126-23.735s-53.574-46.792-94.94-83.412l-75.952-65.78h-503.184v512zM465.886 213.616c0.678 56.286 1.356 105.791 2.034 109.86 0 6.781 25.77 8.816 107.147 8.816h107.147v287.534c-0.678 252.27-1.356 288.212-10.85 290.246-5.425 1.356-133.595 2.034-284.821 2.034l-274.649-0.678-1.356-392.646c-0.678-216.328-0.678-396.715 0.678-400.106 1.356-4.069 67.136-6.781 177.674-6.781h175.64l1.356 101.722z" + ], + "attrs": [ + {} + ], + "width": 793, + "isMulticolor": false, + "isMulticolor2": false, + "grid": 32, + "tags": [ + "document" + ] + }, + "attrs": [ + {} + ], + "properties": { + "order": 133, + "id": 0, + "name": "document", + "prevSize": 32, + "code": 58953 + }, + "setIdx": 0, + "setId": 2, + "iconIdx": 0 + }, + { + "icon": { + "paths": [ + "M1023.959 505.088c-3.717-282.665-236.121-508.842-518.817-505.040-282.689 3.772-508.866 236.091-505.094 518.868 3.772 282.58 236.121 508.842 518.813 505.040 282.689-3.772 508.866-236.067 505.098-518.868zM580.086 904.359h-136.149v-136.163h136.149v136.163zM597.168 293.742l-44.103 388.928h-83.113l-43.099-388.928v-171.575h170.318v171.575z" + ], + "attrs": [ + { + "fill": "rgb(100, 97, 96)" + } + ], + "isMulticolor": false, + "isMulticolor2": false, + "tags": [ + "alert-round" + ], + "grid": 32 + }, + "attrs": [ + { + "fill": "rgb(100, 97, 96)" } - ], - "height": 1024, - "metadata": { - "name": "icomoon" - }, - "preferences": { - "showGlyphs": true, - "showQuickUse": true, - "showQuickUse2": true, - "showSVGs": true, - "fontPref": { - "prefix": "icon-", - "metadata": { - "fontFamily": "icomoon", - "majorVersion": 1, - "minorVersion": 0 - }, - "metrics": { - "emSize": 1024, - "baseline": 6.25, - "whitespace": 50 - }, - "resetPoint": 58880, - "showVersion": true, - "showSelector": false, - "showMetrics": false, - "showMetadata": false, - "embed": false - }, - "imagePref": { - "prefix": "icon-", - "png": true, - "useClassSelector": true, - "classSelector": ".icon" - }, - "historySize": 100, - "showCodes": true, - "search": "", - "gridSize": 16, - "showLiga": false + ], + "properties": { + "order": 132, + "id": 0, + "name": "alert-round", + "prevSize": 32, + "code": 58952 + }, + "setIdx": 1, + "setId": 1, + "iconIdx": 66 + }, + { + "icon": { + "paths": [ + "M793.271 222.6l-192.695-83.055v80.482c-2.517 31.926-83.182 57.618-182.582 57.618-99.309 0-180.126-25.692-182.398-57.618h-0.318l-0.465-80.482-197.709 83.055 381.218 167.697 374.95-167.697zM265.959 118.114l-1.104 0.428c32.596 16.331 89.086 27.124 153.551 27.124 64.726 0 121.621-10.94 153.996-27.355l-1.168-0.512c18.811-9.3 29.664-20.34 29.664-32.264 0-32.713-81.606-59.114-182.492-59.114-100.759 0-182.806 26.401-182.806 59.114-0.003 12.007 11.295 23.218 30.36 32.579zM418.418 462.436l-418.418-191.009v563.335l418.321 189.238 418.321-189.238v-563.733l-418.224 191.407z" + ], + "width": 883, + "attrs": [ + {} + ], + "isMulticolor": false, + "isMulticolor2": false, + "tags": [ + "module" + ], + "grid": 32 + }, + "attrs": [ + {} + ], + "properties": { + "order": 131, + "id": 1, + "name": "module", + "prevSize": 32, + "code": 58951 + }, + "setIdx": 1, + "setId": 1, + "iconIdx": 67 + }, + { + "icon": { + "paths": [ + "M939.616 148.384c112.512 112.448 112.512 294.816 0 407.264l-350.944 350.976c-12.512 12.544-32.736 12.544-45.248 0-12.576-12.512-12.576-32.704 0-45.248l346.432-346.464c87.488-87.488 87.488-229.248-0.064-316.768-87.36-87.488-229.248-87.488-316.736 0l-462.304 456.864c-62.496 62.464-62.496 163.776 0 226.24 62.496 62.496 163.744 62.496 226.24 0l466.88-461.344c37.44-37.44 37.44-98.336 0-135.776-37.44-37.408-98.304-37.408-135.744 0l-351.008 351.008c-12.512 12.512-32.736 12.512-45.248 0-12.512-12.544-12.512-32.736 0-45.28l350.976-350.976c62.432-62.464 163.744-62.464 226.24 0 62.496 62.496 62.496 163.776 0 226.272l-466.88 461.376c-87.296 87.328-229.408 87.328-316.736 0-87.328-87.328-87.328-229.472 0-316.8l466.88-461.344c112.448-112.512 294.816-112.512 407.264 0z" + ], + "attrs": [], + "isMulticolor": false, + "isMulticolor2": false, + "tags": [ + "clip", + "paperclip", + "attachment" + ], + "grid": 32 + }, + "attrs": [], + "properties": { + "id": 2, + "order": 130, + "prevSize": 32, + "code": 58947, + "name": "clip" + }, + "setIdx": 1, + "setId": 1, + "iconIdx": 68 + }, + { + "icon": { + "paths": [ + "M2041.366 1.102v1021.449h-175.926l-411.263-409.297v-204.59l411.263-407.568h175.926z", + "M1305.997 989.076c0 19.377-15.608 34.924-34.856 34.924h-1236.279c-19.255 0-34.863-15.547-34.863-34.924v-954.275c0-19.248 15.608-34.801 34.863-34.801h1236.279c19.248 0 34.856 15.553 34.856 34.801v954.275z" + ], + "width": 2041, + "attrs": [], + "isMulticolor": false, + "isMulticolor2": false, + "tags": [ + "video" + ], + "grid": 0 + }, + "attrs": [], + "properties": { + "order": 127, + "id": 0, + "prevSize": 32, + "code": 58945, + "name": "video" + }, + "setIdx": 1, + "setId": 1, + "iconIdx": 0 + }, + { + "icon": { + "paths": [ + "M723.661 889.601c-2.404-10.843-4.034-21.47-5.282-31.583h-277.528c-2.458 20.233-6.917 43.087-14.646 64.305-7.79 21.277-18.796 40.54-33.824 54.15-15.028 13.552-33.689 22.104-59.788 22.158v25.369h494.020v-25.369c-26.142-0.058-44.737-8.61-59.838-22.158-22.44-20.307-35.961-53.91-43.114-86.873zM1126.214 0h-1093.209c-18.22 0-33.005 15.024-33.005 33.596v731.259c0 18.576 14.785 33.623 33.005 33.623h1093.209c18.224 0 33.067-15.051 33.067-33.623v-731.259c0-18.572-14.843-33.596-33.067-33.596zM1079.193 716.922h-999.234v-635.394h999.234v635.394z" + ], + "width": 1159, + "attrs": [], + "isMulticolor": false, + "isMulticolor2": false, + "tags": [ + "screen" + ], + "grid": 0 + }, + "attrs": [], + "properties": { + "order": 72, + "id": 1, + "prevSize": 32, + "code": 58944, + "name": "screen" + }, + "setIdx": 1, + "setId": 1, + "iconIdx": 1 + }, + { + "icon": { + "paths": [ + "M771.001 776.737c-55.445 0-100.448 44.754-100.448 100.2s44.879 100.324 100.448 100.324 100.448-44.879 100.448-100.324-45.003-100.2-100.448-100.2zM771.001 918.707c-23.123 0-41.77-18.648-41.77-41.771s18.647-41.77 41.77-41.77c23.247 0 41.895 18.648 41.895 41.77s-18.648 41.771-41.895 41.771z", + "M469.532 776.737c-55.445 0-100.449 44.754-100.449 100.2s45.003 100.324 100.449 100.324c55.445 0 100.448-44.879 100.448-100.324s-45.003-100.2-100.448-100.2zM469.532 918.707c-23.123 0-41.771-18.648-41.771-41.771s18.648-41.77 41.771-41.77 41.77 18.648 41.77 41.77-18.648 41.771-41.77 41.771z", + "M823.587 494.412c-130.036 0-238.441-91.622-264.547-213.825h-207.237l-136.749-198.162v-1.865h-207.237v83.541h169.942l78.693 117.729 83.417 412.857h581.183l49.23-243.786c-42.268 27.474-92.616 43.511-146.694 43.511z", + "M1023.862 249.756v-45.376l-55.073-18.026-12.929-31.204 24.863-52.71-31.95-32.074-5.967 2.984-45.5 23.123-31.328-12.929-19.642-54.948h-45.376l-2.114 6.464-15.912 48.608-31.203 12.929-52.835-24.863-32.074 31.95 3.108 5.967 23.247 45.624-13.053 31.328-54.948 19.766v45.376l6.34 2.113 48.732 15.788 12.929 31.204-24.863 52.71 32.074 32.074 6.092-3.108 45.376-22.999 31.328 12.929 19.642 54.824h45.376l2.113-6.464 15.913-48.359 31.203-12.929 52.71 24.988 32.198-32.074-3.108-6.092-23.247-45.624 12.929-31.203 54.948-19.766zM824.582 291.527c-35.057 0-63.65-28.469-63.65-63.526 0-35.182 28.469-63.526 63.65-63.526s63.526 28.469 63.526 63.526c-0.124 35.182-28.469 63.526-63.526 63.526z" + ], + "attrs": [], + "isMulticolor": false, + "isMulticolor2": false, + "tags": [ + "cart" + ], + "grid": 0 + }, + "attrs": [], + "properties": { + "order": 71, + "id": 2, + "prevSize": 32, + "code": 58943, + "name": "cart" + }, + "setIdx": 1, + "setId": 1, + "iconIdx": 2 + }, + { + "icon": { + "paths": [ + "M0.010 188.484h1023.966v136.509h-1023.966z", + "M0.010 442.47h1023.966v136.506h-1023.966z", + "M0.010 699.017h1023.966v136.513h-1023.966z" + ], + "attrs": [ + {}, + {}, + {} + ], + "isMulticolor": false, + "isMulticolor2": false, + "tags": [ + "list-menu" + ], + "grid": 0 + }, + "attrs": [ + {}, + {}, + {} + ], + "properties": { + "order": 61, + "id": 3, + "prevSize": 32, + "code": 58942, + "name": "list-menu" + }, + "setIdx": 1, + "setId": 1, + "iconIdx": 3 + }, + { + "icon": { + "paths": [ + "M0.010 0.372h279.074v279.074h-279.074z", + "M372.77 0.372h279.074v279.074h-279.074z", + "M744.892 0.372h279.074v279.074h-279.074z", + "M0.010 372.497h279.074v279.074h-279.074z", + "M372.77 372.497h279.074v279.074h-279.074z", + "M744.892 372.497h279.074v279.074h-279.074z", + "M0.010 744.585h279.074v279.074h-279.074z", + "M372.77 744.585h279.074v279.074h-279.074z", + "M744.892 744.585h279.074v279.074h-279.074z" + ], + "attrs": [ + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {} + ], + "isMulticolor": false, + "isMulticolor2": false, + "tags": [ + "grid" + ], + "grid": 0 + }, + "attrs": [ + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {} + ], + "properties": { + "order": 112, + "id": 4, + "prevSize": 32, + "code": 58941, + "name": "grid" + }, + "setIdx": 1, + "setId": 1, + "iconIdx": 4 + }, + { + "icon": { + "paths": [ + "M982.767 231.902h-250.095l-59.255-121.364c0 0-11.827-25.201-42.11-25.201-23.375 0-169.366 0-235.25 0-32.969 0-44.001 25.027-44.001 25.027l-57.484 121.539h-253.406c-22.74 0-41.131 18.459-41.131 41.267v624.333c0 22.743 18.401 41.199 41.131 41.199h941.636c22.74 0 41.199-18.459 41.199-41.199v-624.299c0-22.798-18.456-41.267-41.199-41.267zM512 823.91c-138.793 0-251.597-113.015-251.597-251.931 0-138.912 112.845-251.87 251.597-251.87 138.68 0 251.597 112.981 251.597 251.87 0 138.909-112.913 251.931-251.597 251.931z", + "M512 420.932c-83.255 0-150.972 67.714-150.972 150.972 0 83.197 67.71 150.903 150.972 150.903 83.258 0 150.903-67.714 150.903-150.903 0-83.255-67.652-150.972-150.903-150.972z" + ], + "attrs": [ + {}, + {} + ], + "isMulticolor": false, + "isMulticolor2": false, + "tags": [ + "camera" + ], + "grid": 0 + }, + "attrs": [ + {}, + {} + ], + "properties": { + "order": 121, + "id": 5, + "prevSize": 32, + "code": 58940, + "name": "camera" + }, + "setIdx": 1, + "setId": 1, + "iconIdx": 5 + }, + { + "icon": { + "paths": [ + "M904.192 0.027l-307.234 0.116-596.89 596.958 426.906 426.906 596.958-596.958-0.113-305.596-119.603-121.426zM858.679 313.337c-39.997 40.001-104.854 40.001-144.794 0-40.001-40.001-40.001-104.796 0-144.794 39.939-40.001 104.796-40.001 144.794 0 39.997 39.997 39.997 104.793 0 144.794z" + ], + "attrs": [ + {} + ], + "isMulticolor": false, + "isMulticolor2": false, + "tags": [ + "tag" + ], + "grid": 0 + }, + "attrs": [ + {} + ], + "properties": { + "order": 111, + "id": 6, + "prevSize": 32, + "code": 58939, + "name": "tag" + }, + "setIdx": 1, + "setId": 1, + "iconIdx": 6 + }, + { + "icon": { + "paths": [ + "M1094.391 77.71l-77.71-77.71-423.329 423.347-423.33-423.347-77.71 77.672 423.35 423.368-423.312 423.329 77.672 77.71 423.338-423.338 423.283 423.3 77.671-77.71-423.263-423.281z" + ], + "width": 1176, + "attrs": [ + {} + ], + "isMulticolor": false, + "isMulticolor2": false, + "colorPermutations": { + "6868681": [ + { + "f": 0 + } + ] + }, + "tags": [ + "close-mage" + ], + "grid": 0 + }, + "attrs": [ + {} + ], + "properties": { + "order": 110, + "id": 7, + "prevSize": 32, + "code": 58927, + "name": "close-mage" + }, + "setIdx": 1, + "setId": 1, + "iconIdx": 7 + }, + { + "icon": { + "paths": [ + "M857.675 289.413l-403.18-240.514-402.726 240.514v457.026l403.18 240.515 402.726-240.514v-457.027zM454.857 864.465l-298.427-178.383v-335.966l298.157-178.729 298.428 178.383v335.966l-298.158 178.729z" + ], + "width": 903, + "attrs": [ + {} + ], + "isMulticolor": false, + "isMulticolor2": false, + "colorPermutations": { + "6868681": [ + { + "f": 0 + } + ] + }, + "tags": [ + "menu-item" + ], + "grid": 0 + }, + "attrs": [ + {} + ], + "properties": { + "order": 109, + "id": 8, + "prevSize": 32, + "code": 58938, + "name": "menu-item" + }, + "setIdx": 1, + "setId": 1, + "iconIdx": 8 + }, + { + "icon": { + "paths": [ + "M505.704 40.998c-260.096 3.489-468.158 217.202-464.706 477.336 3.489 259.982 217.202 468.12 477.298 464.631s468.158-217.202 464.706-477.336c-3.413-260.058-217.202-468.12-477.298-464.631zM557.928 197.973c47.863 0 62.009 27.762 62.009 59.544 0 39.671-31.782 76.383-86.016 76.383-45.359 0-66.901-22.831-65.65-60.53 0-31.782 26.624-75.435 89.657-75.435zM435.162 806.381c-32.73 0-56.661-19.873-33.792-107.217l37.547-154.814c6.485-24.841 7.585-34.778 0-34.778-9.785 0-52.262 17.143-77.407 34.057l-16.346-26.776c79.607-66.446 171.16-105.472 210.375-105.472 32.73 0 38.153 38.722 21.807 98.266l-43.008 162.816c-7.585 28.786-4.286 38.722 3.262 38.722 9.785 0 41.984-11.871 73.614-36.75l18.47 24.841c-77.369 77.369-161.792 107.179-194.56 107.179z" + ], + "attrs": [ + {} + ], + "isMulticolor": false, + "isMulticolor2": false, + "tags": [ + "info" + ], + "grid": 0 + }, + "attrs": [ + {} + ], + "properties": { + "order": 108, + "id": 9, + "prevSize": 32, + "code": 58906, + "name": "info" + }, + "setIdx": 1, + "setId": 1, + "iconIdx": 9 + }, + { + "icon": { + "paths": [ + "M591.986 448.019h-16.005v-192.019c0-105.851-86.13-192.019-192.019-192.019h-128c-105.851 0-192.019 86.13-192.019 192.019v192.019h-16.005c-26.396 0-48.014 21.618-48.014 48.014v479.991c0 26.396 21.618 48.014 48.014 48.014h544.009c26.396 0 48.014-21.618 48.014-48.014v-479.991c0-26.396-21.618-48.014-48.014-48.014zM384 896h-128l27.838-139.188c-16.801-11.529-27.838-30.872-27.838-52.793 0-35.347 28.672-64.019 64.019-64.019s64.019 28.672 64.019 64.019c0 21.921-11.036 41.263-27.838 52.793l27.838 139.188zM448.019 448.019h-256v-192.019c0-35.271 28.71-64.019 64.019-64.019h128c35.271 0 64.019 28.71 64.019 64.019v192.019z" + ], + "attrs": [ + {} + ], + "isMulticolor": false, + "isMulticolor2": false, + "tags": [ + "lock" + ], + "grid": 0 + }, + "attrs": [ + {} + ], + "properties": { + "order": 107, + "id": 10, + "prevSize": 32, + "code": 58907, + "name": "lock" + }, + "setIdx": 1, + "setId": 1, + "iconIdx": 10 + }, + { + "icon": { + "paths": [ + "M870.4 317.44h-194.56v143.36h153.6v215.040h-634.88v-215.040h215.040v112.64l204.8-184.32-204.8-184.32v112.64h-256c-56.51 0-102.4 45.815-102.4 102.4v296.96c0 56.51 45.89 102.4 102.4 102.4h716.8c56.585 0 102.4-45.89 102.4-102.4v-296.96c0-56.585-45.815-102.4-102.4-102.4z" + ], + "attrs": [ + {} + ], + "isMulticolor": false, + "isMulticolor2": false, + "tags": [ + "loop" + ], + "grid": 0 + }, + "attrs": [ + {} + ], + "properties": { + "order": 106, + "id": 11, + "prevSize": 32, + "code": 58908, + "name": "loop" + }, + "setIdx": 1, + "setId": 1, + "iconIdx": 11 + }, + { + "icon": { + "paths": [ + "M991.991 384h-351.991v-351.991c0-17.673-14.336-32.009-32.009-32.009h-192.019c-17.673 0-32.009 14.336-32.009 32.009v351.991h-351.991c-17.673 0-32.009 14.336-32.009 32.009v192.019c0 17.673 14.336 32.009 32.009 32.009h351.991v351.991c0 17.673 14.336 32.009 32.009 32.009h192.019c17.673 0 32.009-14.336 32.009-32.009v-351.991h351.991c17.673 0 32.009-14.336 32.009-32.009v-192.019c0-17.673-14.336-32.009-32.009-32.009z" + ], + "attrs": [ + {} + ], + "isMulticolor": false, + "isMulticolor2": false, + "tags": [ + "plus" + ], + "grid": 0 + }, + "attrs": [ + {} + ], + "properties": { + "order": 105, + "id": 12, + "prevSize": 32, + "code": 58909, + "name": "plus" + }, + "setIdx": 1, + "setId": 1, + "iconIdx": 12 + }, + { + "icon": { + "paths": [ + "M505.704 40.998c-260.096 3.489-468.158 217.126-464.706 477.298 3.489 260.21 217.202 468.158 477.298 464.744 260.134-3.489 468.233-217.202 464.706-477.298-3.489-260.21-217.202-468.233-477.298-464.744zM506.577 102.4c70.163-0.986 136.382 15.853 194.56 46.118l-63.374 105.662c-38.002-18.47-80.631-28.937-125.762-28.937-45.056 0-87.723 10.43-125.687 28.975l-63.336-105.624c54.993-28.672 117.343-45.321 183.599-46.232zM254.255 637.687l-105.586 63.298c-28.672-54.955-45.321-117.305-46.194-183.486-0.986-70.201 15.853-136.457 46.118-194.56l105.624 63.45c-18.546 37.926-28.975 80.555-28.975 125.649 0 45.056 10.43 87.723 28.975 125.687zM517.461 921.562c-70.163 0.986-136.457-15.853-194.56-46.118l63.374-105.662c38.002 18.546 80.631 28.975 125.687 28.975 45.094 0 87.761-10.392 125.687-28.937l63.336 105.586c-54.993 28.634-117.305 45.246-183.561 46.194zM512 737.242c-124.397 0-225.242-100.883-225.242-225.242 0-124.397 100.883-225.28 225.242-225.28 124.473 0 225.28 100.883 225.28 225.28s-100.807 225.242-225.28 225.242zM769.745 637.687c18.546-38.002 28.975-80.631 28.975-125.687 0-45.094-10.43-87.723-28.975-125.687l105.586-63.374c28.672 54.993 45.359 117.305 46.232 183.561 0.91 70.201-15.929 136.457-46.194 194.56l-105.624-63.336z" + ], + "attrs": [ + {} + ], + "isMulticolor": false, + "isMulticolor2": false, + "tags": [ + "recover" + ], + "grid": 0 + }, + "attrs": [ + {} + ], + "properties": { + "order": 104, + "id": 13, + "prevSize": 32, + "code": 58910, + "name": "recover" + }, + "setIdx": 1, + "setId": 1, + "iconIdx": 13 + }, + { + "icon": { + "paths": [ + "M906.126 135.813v0c-91.174-75.89-202.487-113.171-312.548-113.057-127.014-0.038-253.611 49.683-348.16 145.636l-95.004-79.265-1.593 305.342 300.184-56.282-99.442-82.944c67.546-64.247 155.269-97.204 244.015-97.28 79.948 0.038 159.782 26.7 226.114 81.806 84.347 70.125 127.659 170.629 127.772 272.46-0.038 14.715-0.948 29.431-2.769 44.070l137.519-26.283c0.19-5.954 0.303-11.871 0.303-17.787 0.152-140.098-60.151-279.78-176.431-376.415zM839.035 766.976c-67.736 65.498-156.255 99.025-245.912 99.1-79.986-0.038-159.82-26.738-226.114-81.806-84.347-70.125-127.697-170.629-127.772-272.498 0-16.839 1.252-33.716 3.679-50.366l-138.164 25.941c-0.379 8.116-0.683 16.346-0.683 24.462-0.114 140.174 60.226 279.817 176.545 376.491 91.136 75.852 202.411 113.057 312.51 112.981h0.341c127.924 0 255.241-50.441 349.943-147.759l90.795 75.207 0.569-305.38-299.956 57.344 104.183 86.281z" + ], + "width": 1176, + "attrs": [ + {} + ], + "isMulticolor": false, + "isMulticolor2": false, + "tags": [ + "refresh" + ], + "grid": 0 + }, + "attrs": [ + {} + ], + "properties": { + "order": 113, + "id": 14, + "prevSize": 32, + "code": 58911, + "name": "refresh" + }, + "setIdx": 1, + "setId": 1, + "iconIdx": 14 + }, + { + "icon": { + "paths": [ + "M593.351 21.732c-270.753 0-490.268 219.477-490.268 490.231s219.515 490.268 490.268 490.268 490.231-219.515 490.231-490.268c0-270.753-219.477-490.231-490.231-490.231zM828.947 683.653l-72.363 72.363-162.095-162.133-164.902 164.902-73.121-73.121 164.902-164.902-161.678-161.678 72.363-72.325 161.602 161.678 165.774-165.736 73.121 73.083-165.774 165.736 162.171 162.133z" + ], + "width": 1176, + "attrs": [ + {} + ], + "isMulticolor": false, + "isMulticolor2": false, + "tags": [ + "remove-small" + ], + "grid": 0 + }, + "attrs": [ + {} + ], + "properties": { + "order": 114, + "id": 15, + "prevSize": 32, + "code": 58912, + "name": "remove-small" + }, + "setIdx": 1, + "setId": 1, + "iconIdx": 15 + }, + { + "icon": { + "paths": [ + "M254.976 675.84v-267.264h103.424l-179.2-203.776-179.2 203.776h103.424v308.224c0 56.51 45.815 102.4 102.4 102.4h459.776l-131.186-143.36h-279.438zM920.538 615.424v-308.224c0-56.51-45.89-102.4-102.4-102.4h-459.738l131.11 143.36h279.514v267.264h-103.424l179.2 203.776 179.2-203.776h-103.462z" + ], + "attrs": [ + {} + ], + "isMulticolor": false, + "isMulticolor2": false, + "tags": [ + "retweet" + ], + "grid": 0 + }, + "attrs": [ + {} + ], + "properties": { + "order": 117, + "id": 16, + "prevSize": 32, + "code": 58913, + "name": "retweet" + }, + "setIdx": 1, + "setId": 1, + "iconIdx": 16 + }, + { + "icon": { + "paths": [ + "M768 64.019h-128c-105.851 0-192.019 86.13-192.019 192.019v192.019h-400.005c-26.396 0-48.014 21.618-48.014 48.014v479.991c0 26.396 21.618 48.014 48.014 48.014h544.009c26.396 0 48.014-21.618 48.014-48.014v-479.991c0-26.396-21.618-48.014-48.014-48.014h-16.005v-192.019c0-35.271 28.71-64.019 64.019-64.019h128c35.271 0 64.019 28.71 64.019 64.019v192.019h128v-192.019c0-105.851-86.13-192.019-192.019-192.019zM384 896h-128l27.838-139.188c-16.801-11.529-27.838-30.872-27.838-52.793 0-35.347 28.672-64.019 64.019-64.019s64.019 28.672 64.019 64.019c0 21.921-11.036 41.263-27.838 52.793l27.838 139.188z" + ], + "attrs": [ + {} + ], + "isMulticolor": false, + "isMulticolor2": false, + "tags": [ + "unlocked" + ], + "grid": 0 + }, + "attrs": [ + {} + ], + "properties": { + "order": 36, + "id": 17, + "prevSize": 32, + "code": 58914, + "name": "unlocked" + }, + "setIdx": 1, + "setId": 1, + "iconIdx": 17 + }, + { + "icon": { + "paths": [ + "M593.351 0l-593.351 1023.962h1186.74l-593.351-1023.962zM653.236 899.451h-125.421v-121.211h125.421v121.211zM622.175 728.329h-62.502l-34.816-288.313v-156.748h131.3v156.748l-33.982 288.313z" + ], + "width": 1176, + "attrs": [ + {} + ], + "isMulticolor": false, + "isMulticolor2": false, + "tags": [ + "warning" + ], + "grid": 0 + }, + "attrs": [ + {} + ], + "properties": { + "order": 37, + "id": 18, + "prevSize": 32, + "code": 58915, + "name": "warning" + }, + "setIdx": 1, + "setId": 1, + "iconIdx": 18 + }, + { + "icon": { + "paths": [ + "M0 512l512 512v-320.019h512v-384h-512v-320.019z" + ], + "attrs": [ + {} + ], + "isMulticolor": false, + "isMulticolor2": false, + "tags": [ + "arrow-left" + ], + "grid": 0 + }, + "attrs": [ + {} + ], + "properties": { + "order": 38, + "id": 19, + "prevSize": 32, + "code": 58916, + "name": "arrow-left" + }, + "setIdx": 1, + "setId": 1, + "iconIdx": 19 + }, + { + "icon": { + "paths": [ + "M1024 512l-512-512v320.019h-512v384h512v320.019z" + ], + "attrs": [ + {} + ], + "isMulticolor": false, + "isMulticolor2": false, + "tags": [ + "arrow-right" + ], + "grid": 0 + }, + "attrs": [ + {} + ], + "properties": { + "order": 39, + "id": 20, + "prevSize": 32, + "code": 58917, + "name": "arrow-right" + }, + "setIdx": 1, + "setId": 1, + "iconIdx": 20 + }, + { + "icon": { + "paths": [ + "M402.735 146.735l-320.019 320.019c-24.993 24.993-24.993 65.498 0 90.491l320.019 320.019c24.993 24.993 65.498 24.993 90.491 0s24.993-65.498 0-90.491l-210.754-210.754h613.49c35.347 0 64.019-28.634 64.019-64.019s-28.672-64.019-64.019-64.019h-613.49l210.754-210.754c12.478-12.478 18.735-28.862 18.735-45.246s-6.258-32.768-18.735-45.246c-24.993-24.993-65.498-24.993-90.491 0z" + ], + "attrs": [ + {} + ], + "isMulticolor": false, + "isMulticolor2": false, + "tags": [ + "back-arrow" + ], + "grid": 0 + }, + "attrs": [ + {} + ], + "properties": { + "order": 103, + "id": 21, + "prevSize": 32, + "code": 58918, + "name": "back-arrow" + }, + "setIdx": 1, + "setId": 1, + "iconIdx": 21 + }, + { + "icon": { + "paths": [ + "M507.259 578.522h-102.059v101.717h102.059v-101.717zM650.885 714.714h-101.945v101.717h101.945v-101.717zM507.259 714.714h-102.059v101.717h102.059v-101.717zM507.259 442.33h-102.059v101.679h102.059v-101.679zM843.131 244.091c23.4 0 42.287-18.887 42.287-42.174v-145.408c0-23.324-18.887-42.174-42.287-42.174s-42.325 18.849-42.325 42.174v145.408c0.038 23.324 18.925 42.174 42.325 42.174zM343.419 244.091c23.362 0 42.249-18.887 42.249-42.174v-145.408c0-23.324-18.887-42.174-42.249-42.174-23.4 0-42.325 18.849-42.325 42.174v145.408c0 23.324 18.925 42.174 42.325 42.174zM363.444 578.522h-102.059v101.717h102.059v-101.717zM363.444 714.714h-102.059v101.717h102.059v-101.717zM650.885 578.522h-101.945v101.717h101.945v-101.717zM938.325 578.522h-102.059v101.717h102.059v-101.717zM938.325 442.33h-102.059v101.679h102.059v-101.679zM899.337 84.385v46.914c17.598 15.474 28.71 38.153 28.71 63.412 0 46.801-37.964 84.764-84.916 84.764s-84.954-37.964-84.954-84.764c0-25.259 11.15-47.938 28.71-63.412v-46.914h-387.262v46.914c17.56 15.474 28.71 38.153 28.71 63.412 0 46.801-38.002 84.764-84.916 84.764s-84.954-37.964-84.954-84.764c0-25.259 11.15-47.938 28.71-63.412v-46.914h-192.322v925.279h997.035v-925.279h-192.512zM999.234 915.304h-809.832v-589.938h809.832v589.938zM650.885 442.33h-101.945v101.679h101.945v-101.679zM794.624 442.33h-101.983v101.679h101.983v-101.679zM794.624 714.714h-101.983v101.717h101.983v-101.717zM794.624 578.522h-101.983v101.717h101.983v-101.717z" + ], + "width": 1176, + "attrs": [ + {} + ], + "isMulticolor": false, + "isMulticolor2": false, + "tags": [ + "calendar" + ], + "grid": 0 + }, + "attrs": [ + {} + ], + "properties": { + "order": 102, + "id": 22, + "prevSize": 32, + "code": 58919, + "name": "calendar" + }, + "setIdx": 1, + "setId": 1, + "iconIdx": 22 + }, + { + "icon": { + "paths": [ + "M132.21 286.758c-13.881-13.729-36.295-13.729-50.138 0-13.805 13.653-13.805 35.878 0 49.607l404.897 400.877c13.881 13.729 36.257 13.729 50.138 0l404.897-400.877c13.805-13.729 13.881-35.878 0-49.607s-36.371-13.729-50.138-0.038l-379.866 365.606-379.79-365.568z" + ], + "attrs": [ + {} + ], + "isMulticolor": false, + "isMulticolor2": false, + "tags": [ + "caret-down" + ], + "grid": 0 + }, + "attrs": [ + {} + ], + "properties": { + "order": 101, + "id": 23, + "prevSize": 32, + "code": 58920, + "name": "caret-down" + }, + "setIdx": 1, + "setId": 1, + "iconIdx": 23 + }, + { + "icon": { + "paths": [ + "M737.242 891.79c13.729 13.881 13.729 36.257 0 50.138s-35.878 13.881-49.607 0l-400.877-404.821c-13.729-13.881-13.729-36.295 0-50.138l400.877-404.897c13.729-13.881 35.878-13.881 49.607 0s13.729 36.257 0 50.138l-365.568 379.79 365.568 379.79z" + ], + "attrs": [ + {} + ], + "isMulticolor": false, + "isMulticolor2": false, + "tags": [ + "caret-left" + ], + "grid": 0 + }, + "attrs": [ + {} + ], + "properties": { + "order": 100, + "id": 24, + "prevSize": 32, + "code": 58921, + "name": "caret-left" + }, + "setIdx": 1, + "setId": 1, + "iconIdx": 24 + }, + { + "icon": { + "paths": [ + "M286.72 891.79c-13.729 13.881-13.729 36.257 0 50.138s35.878 13.881 49.607 0l400.877-404.821c13.729-13.881 13.729-36.295 0-50.138l-400.915-404.897c-13.729-13.881-35.878-13.881-49.607 0s-13.729 36.257 0 50.138l365.568 379.79-365.568 379.79z" + ], + "attrs": [ + {} + ], + "isMulticolor": false, + "isMulticolor2": false, + "tags": [ + "caret-right" + ], + "grid": 0 + }, + "attrs": [ + {} + ], + "properties": { + "order": 99, + "id": 25, + "prevSize": 32, + "code": 58922, + "name": "caret-right" + }, + "setIdx": 1, + "setId": 1, + "iconIdx": 25 + }, + { + "icon": { + "paths": [ + "M891.79 737.242c13.881 13.729 36.295 13.729 50.138 0 13.881-13.729 13.881-35.878 0-49.607l-404.897-400.877c-13.805-13.729-36.257-13.729-50.062 0l-404.897 400.877c-13.805 13.729-13.881 35.878 0 49.607s36.257 13.729 50.138 0l379.79-365.606 379.79 365.606z" + ], + "attrs": [ + {} + ], + "isMulticolor": false, + "isMulticolor2": false, + "tags": [ + "caret-up" + ], + "grid": 0 + }, + "attrs": [ + {} + ], + "properties": { + "order": 98, + "id": 26, + "prevSize": 32, + "code": 58923, + "name": "caret-up" + }, + "setIdx": 1, + "setId": 1, + "iconIdx": 26 + }, + { + "icon": { + "paths": [ + "M574.767 92.16c-227.593 0-412.672 182.386-418.247 409.335h-125.8l188.378 209.92 188.302-209.92h-146.242c5.537-168.998 143.777-304.393 313.609-304.393 173.397 0 313.913 140.971 313.913 314.899s-140.478 314.861-313.913 314.861c-69.48 0-133.689-22.718-185.685-61.099l-71.983 76.99c70.997 55.751 160.465 89.050 257.707 89.050 231.159 0 418.551-187.961 418.551-419.84-0.038-231.879-187.43-419.84-418.551-419.84z" + ], + "attrs": [ + {} + ], + "isMulticolor": false, + "isMulticolor2": false, + "tags": [ + "ccw" + ], + "grid": 0 + }, + "attrs": [ + {} + ], + "properties": { + "order": 97, + "id": 27, + "prevSize": 32, + "code": 58924, + "name": "ccw" + }, + "setIdx": 1, + "setId": 1, + "iconIdx": 27 + }, + { + "icon": { + "paths": [ + "M996.617 126.786l-513.555 513.555-256.796-256.834-128.379 128.417 385.214 385.252 641.896-642.010z" + ], + "width": 1176, + "attrs": [ + {} + ], + "isMulticolor": false, + "isMulticolor2": false, + "tags": [ + "check-mage" + ], + "grid": 0 + }, + "attrs": [ + {} + ], + "properties": { + "order": 96, + "id": 28, + "prevSize": 32, + "code": 58925, + "name": "check-mage" + }, + "setIdx": 1, + "setId": 1, + "iconIdx": 28 + }, + { + "icon": { + "paths": [ + "M512 40.96c-260.134 0-471.040 210.944-471.040 471.040 0 260.134 210.906 471.040 471.040 471.040s471.040-210.906 471.040-471.040c0-260.134-210.906-471.040-471.040-471.040zM512 880.64c-203.624 0-368.64-165.054-368.64-368.64s165.016-368.64 368.64-368.64 368.64 165.054 368.64 368.64-165.016 368.64-368.64 368.64zM547.84 245.76h-71.68v281.069l174.345 174.345 50.669-50.707-153.335-153.335z" + ], + "attrs": [ + {} + ], + "isMulticolor": false, + "isMulticolor2": false, + "tags": [ + "clock" + ], + "grid": 0 + }, + "attrs": [ + {} + ], + "properties": { + "order": 95, + "id": 29, + "prevSize": 32, + "code": 58926, + "name": "clock" + }, + "setIdx": 1, + "setId": 1, + "iconIdx": 29 + }, + { + "icon": { + "paths": [ + "M337.541 1021.004h513.024l64.512-645.916h-639.128l61.592 645.916zM737.394 154.169v-116.508c0-19.191-15.398-34.702-34.361-34.702h-217.847c-19.001 0-34.361 15.55-34.361 34.702v114.574c-73.576 8.382-150.149 24.614-226.494 52.338v106.989h738.001v-109.833c0 0-90.074-31.403-224.977-47.559zM668.937 147.759c-47.749-3.224-99.252-4.096-153.297-0.986v-61.44c0-9.519 7.623-17.332 17.143-17.332h118.936c9.519 0 17.218 7.813 17.218 17.332v62.426z" + ], + "width": 1176, + "attrs": [ + {} + ], + "isMulticolor": false, + "isMulticolor2": false, + "tags": [ + "delete" + ], + "grid": 0 + }, + "attrs": [ + {} + ], + "properties": { + "order": 94, + "id": 30, + "prevSize": 32, + "code": 58928, + "name": "delete" + }, + "setIdx": 1, + "setId": 1, + "iconIdx": 30 + }, + { + "icon": { + "paths": [ + "M928.503 26.889l-111.502 112.109 156.065 156.9 111.502-112.071-156.065-156.937zM215.002 744.41l156.065 156.9 535.211-538.093-156.065-156.9-535.211 538.093zM103.917 1007.161l188.985-49.873-139.302-140.098-49.683 190.009z" + ], + "width": 1176, + "attrs": [ + {} + ], + "isMulticolor": false, + "isMulticolor2": false, + "tags": [ + "edit" + ], + "grid": 0 + }, + "attrs": [ + {} + ], + "properties": { + "order": 115, + "id": 31, + "prevSize": 32, + "code": 58929, + "name": "edit" + }, + "setIdx": 1, + "setId": 1, + "iconIdx": 31 + }, + { + "icon": { + "paths": [ + "M1014.67 822.651c0 0 0 0 0 0l-310.651-310.651 310.651-310.651c0 0 0 0 0 0 3.337-3.337 5.765-7.244 7.32-11.416 4.248-11.378 1.82-24.69-7.32-33.83l-146.735-146.735c-9.14-9.14-22.452-11.567-33.83-7.32-4.172 1.555-8.078 3.982-11.416 7.32 0 0 0 0 0 0l-310.651 310.651-310.651-310.651c0 0 0 0 0 0-3.337-3.337-7.244-5.765-11.416-7.32-11.378-4.248-24.69-1.82-33.83 7.32l-146.735 146.735c-9.14 9.14-11.567 22.452-7.32 33.83 1.555 4.172 3.982 8.078 7.32 11.416 0 0 0 0 0 0l310.651 310.651-310.651 310.651c0 0 0 0 0 0-3.337 3.337-5.765 7.244-7.32 11.416-4.248 11.378-1.82 24.69 7.32 33.83l146.735 146.735c9.14 9.14 22.452 11.567 33.83 7.32 4.172-1.555 8.078-3.982 11.416-7.32 0 0 0 0 0 0l310.651-310.651 310.651 310.651c0 0 0 0 0 0 3.337 3.337 7.244 5.765 11.416 7.32 11.378 4.248 24.69 1.82 33.83-7.32l146.735-146.735c9.14-9.14 11.567-22.452 7.32-33.83-1.555-4.172-3.982-8.078-7.32-11.416z" + ], + "attrs": [ + {} + ], + "isMulticolor": false, + "isMulticolor2": false, + "tags": [ + "error" + ], + "grid": 0 + }, + "attrs": [ + {} + ], + "properties": { + "order": 122, + "id": 32, + "prevSize": 32, + "code": 58930, + "name": "error" + }, + "setIdx": 1, + "setId": 1, + "iconIdx": 32 + }, + { + "icon": { + "paths": [ + "M593.351 22.566c-270.336 0-489.434 219.098-489.434 489.358s219.098 489.434 489.434 489.434 489.434-219.136 489.434-489.434-219.136-489.358-489.434-489.358zM635.752 826.596c-11.985 11.719-26.396 17.636-43.16 17.636-8.154 0-15.967-1.517-23.4-4.589-7.358-3.034-13.843-7.168-19.456-12.174-5.613-5.158-10.126-11.226-13.388-18.356-3.337-7.13-4.968-14.753-4.968-22.945 0-16.308 5.992-30.303 17.977-42.060 11.947-11.681 26.396-17.598 43.198-17.598 16.308 0 30.606 5.689 42.78 16.801 12.25 11.188 18.318 24.993 18.318 41.339-0.038 16.384-5.992 30.303-17.939 41.984zM778.923 382.673c-3.982 13.767-9.747 26.396-17.18 37.774-7.471 11.454-16.498 22.49-27.079 33.071s-22.49 21.618-35.65 33.033c-11.454 9.785-20.783 18.318-27.913 25.79-7.168 7.396-12.895 14.867-17.218 22.338-4.286 7.433-7.282 15.398-9.026 24.007-1.707 8.609-2.617 49.721-2.617 62.35v22.338h-101.376v-32.616c0-13.729 0.986-56.661 3.034-67.584s5.158-21.125 9.481-30.872 10.012-19.228 17.18-28.369c7.168-9.14 16.232-18.887 27.079-29.203l38.647-36.902c10.847-9.747 20.177-20.632 27.951-32.616 7.737-12.060 11.529-26.7 11.529-43.88 0-22.3-6.978-41.036-21.011-56.206-14.071-15.17-33.944-22.793-59.695-22.793-13.16 0-25.069 2.389-35.65 7.282-10.619 4.817-19.797 11.454-27.496 19.759-7.737 8.344-13.577 17.901-17.598 28.786-3.982 10.847-6.334 21.997-6.865 33.527l-105.624-9.444c3.413-27.496 10.733-51.959 21.921-73.463 11.112-21.466 25.562-39.595 43.311-54.575 17.711-14.829 38.078-26.169 61.023-33.944 22.869-7.699 47.521-11.605 73.842-11.605 24.614 0 47.976 3.603 70.049 10.771 21.959 7.168 41.491 17.711 58.406 31.782 16.839 14.033 30.227 31.365 39.936 51.959 9.709 20.632 14.564 44.411 14.564 71.263 0 18.356-2.010 34.475-5.992 48.166z" + ], + "width": 1176, + "attrs": [ + {} + ], + "isMulticolor": false, + "isMulticolor2": false, + "tags": [ + "help" + ], + "grid": 0 + }, + "attrs": [ + {} + ], + "properties": { + "order": 124, + "id": 33, + "prevSize": 32, + "code": 58931, + "name": "help" + }, + "setIdx": 1, + "setId": 1, + "iconIdx": 33 + }, + { + "icon": { + "paths": [ + "M574.805 92.16c-227.631 0-412.71 182.386-418.247 409.335h-125.838l188.378 209.958 188.302-209.958h-146.242c5.537-168.998 143.777-304.393 313.647-304.393 173.359 0 313.875 140.971 313.875 314.899s-140.478 314.861-313.875 314.861c-69.518 0-133.727-22.718-185.761-61.099l-71.983 76.99c71.073 55.751 160.503 89.050 257.745 89.050 231.121 0 418.513-187.961 418.513-419.84-0.038-231.879-187.43-419.84-418.513-419.84zM537.6 286.72v240.109l153.865 153.865 50.669-50.669-132.855-132.855v-210.413h-71.68z" + ], + "attrs": [ + {} + ], + "isMulticolor": false, + "isMulticolor2": false, + "tags": [ + "history" + ], + "grid": 0 + }, + "attrs": [ + {} + ], + "properties": { + "order": 45, + "id": 34, + "prevSize": 32, + "code": 58932, + "name": "history" + }, + "setIdx": 1, + "setId": 1, + "iconIdx": 34 + }, + { + "icon": { + "paths": [ + "M510.413 0c-281.907 0-510.413 228.582-510.413 510.413 0 281.933 228.506 510.464 510.413 510.464s510.387-228.557 510.387-510.464c0-281.83-228.48-510.413-510.387-510.413zM865.843 510.413c0 69.99-20.506 135.27-55.578 190.285l-490.163-490.163c55.091-35.021 120.32-55.475 190.31-55.475 195.942 0 355.43 159.411 355.43 355.354zM154.957 510.413c0-69.939 20.506-135.245 55.578-190.31l490.189 490.189c-55.066 35.072-120.371 55.501-190.31 55.501-195.942 0.026-355.456-159.437-355.456-355.379z" + ], + "attrs": [ + {} + ], + "isMulticolor": false, + "isMulticolor2": false, + "tags": [ + "not-installed" + ], + "grid": 0 + }, + "attrs": [ + {} + ], + "properties": { + "order": 58, + "id": 35, + "prevSize": 32, + "code": 58936, + "name": "not-installed" + }, + "setIdx": 1, + "setId": 1, + "iconIdx": 35 + }, + { + "icon": { + "paths": [ + "M511.77 0c-282.778 0-512.102 229.222-512.102 512.179 0 282.829 229.325 512.102 512.102 512.102 282.931 0.026 512.23-229.248 512.23-512.102 0-282.957-229.299-512.179-512.23-512.179zM143.718 419.968h736.205v184.269h-736.205v-184.269z" + ], + "attrs": [ + {} + ], + "isMulticolor": false, + "isMulticolor2": false, + "tags": [ + "disabled" + ], + "grid": 0 + }, + "attrs": [ + {} + ], + "properties": { + "order": 57, + "id": 36, + "prevSize": 32, + "code": 58937, + "name": "disabled" + }, + "setIdx": 1, + "setId": 1, + "iconIdx": 36 + }, + { + "icon": { + "paths": [ + "M505.139 0.085c-282.658 3.775-508.826 236.066-505.071 518.827 3.772 282.556 236.1 508.826 518.793 505.003 282.658-3.768 508.826-236.066 505.071-518.827-3.717-282.658-236.1-508.826-518.793-505.003z" + ], + "attrs": [ + {} + ], + "isMulticolor": false, + "isMulticolor2": false, + "tags": [ + "dot" + ], + "grid": 0 + }, + "attrs": [ + {} + ], + "properties": { + "order": 56, + "id": 37, + "prevSize": 32, + "code": 58935, + "name": "dot" + }, + "setIdx": 1, + "setId": 1, + "iconIdx": 37 + }, + { + "icon": { + "paths": [ + "M383.462 577.51h255.693v-213.043h127.795l-255.642-255.667-255.642 255.667h127.795z", + "M852.173 577.51v170.394h-681.754v-170.394h-170.419v340.89h1022.618v-340.89z" + ], + "attrs": [ + {}, + {} + ], + "isMulticolor": false, + "isMulticolor2": false, + "tags": [ + "export" + ], + "grid": 0 + }, + "attrs": [ + {}, + {} + ], + "properties": { + "order": 93, + "id": 38, + "prevSize": 32, + "code": 58933, + "name": "export" + }, + "setIdx": 1, + "setId": 1, + "iconIdx": 38 + }, + { + "icon": { + "paths": [ + "M639.155 108.8h-255.693v213.043h-127.795l255.667 255.667 255.616-255.667h-127.795z", + "M852.173 577.51v170.394h-681.754v-170.394h-170.419v340.89h1022.618v-340.89z" + ], + "attrs": [ + {}, + {} + ], + "isMulticolor": false, + "isMulticolor2": false, + "tags": [ + "import" + ], + "grid": 0 + }, + "attrs": [ + {}, + {} + ], + "properties": { + "order": 92, + "id": 39, + "prevSize": 32, + "code": 58934, + "name": "import" + }, + "setIdx": 1, + "setId": 1, + "iconIdx": 39 + }, + { + "icon": { + "paths": [ + "M259.2 0h214.323v214.323h-214.323v-214.323z", + "M259.2 269.875h214.323v214.349h-214.323v-214.349z", + "M259.2 539.776h214.323v214.349h-214.323v-214.349z", + "M259.2 809.651h214.323v214.349h-214.323v-214.349z", + "M549.325 0h214.323v214.323h-214.323v-214.323z", + "M549.325 269.875h214.323v214.349h-214.323v-214.349z", + "M549.325 539.776h214.323v214.349h-214.323v-214.349z", + "M549.325 809.651h214.323v214.349h-214.323v-214.349z" + ], + "attrs": [ + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {} + ], + "isMulticolor": false, + "isMulticolor2": false, + "tags": [ + "gripper" + ], + "grid": 0 + }, + "attrs": [ + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {} + ], + "properties": { + "order": 91, + "id": 40, + "prevSize": 32, + "code": 58903, + "name": "gripper" + }, + "setIdx": 1, + "setId": 1, + "iconIdx": 40 + }, + { + "icon": { + "paths": [ + "M860.058 185.062v272l-430.029-269.158-1.894 253.491-424.371-249.754-3.763 647.834 426.24-241.28-5.606 239.437 439.424-252.16v259.635h163.942v-660.045z" + ], + "attrs": [ + {} + ], + "isMulticolor": false, + "isMulticolor2": false, + "tags": [ + "forward" + ], + "grid": 0 + }, + "attrs": [ + {} + ], + "properties": { + "order": 90, + "id": 41, + "prevSize": 32, + "code": 58904, + "name": "forward" + }, + "setIdx": 1, + "setId": 1, + "iconIdx": 41 + }, + { + "icon": { + "paths": [ + "M163.942 845.107v-271.974l430.029 269.133 1.894-253.491 424.397 249.754 3.738-647.834-426.24 241.28 5.606-239.437-439.424 252.16v-259.635h-163.942v660.045z" + ], + "attrs": [ + {} + ], + "isMulticolor": false, + "isMulticolor2": false, + "tags": [ + "backward" + ], + "grid": 0 + }, + "attrs": [ + {} + ], + "properties": { + "order": 89, + "id": 42, + "prevSize": 32, + "code": 58905, + "name": "backward", + "ligatures": "" + }, + "setIdx": 1, + "setId": 1, + "iconIdx": 42 + }, + { + "icon": { + "paths": [ + "M512.794 0c-283.187 0-512.794 229.581-512.794 512.794 0 283.187 229.606 512.794 512.794 512.794s512.794-229.632 512.794-512.794c0-283.213-229.581-512.794-512.794-512.794zM512.794 971.213c-253.158 0-458.394-205.261-458.394-458.368 0-253.158 205.261-458.394 458.394-458.394 253.184 0 458.394 205.235 458.394 458.394 0.026 253.107-205.21 458.368-458.394 458.368z", + "M760.013 625.613l30.387-38.4-265.6-206.413-20.787-1.613-259.226 208.026 28.826 39.987 236.8-177.613z" + ], + "attrs": [ + {}, + {} + ], + "isMulticolor": false, + "isMulticolor2": false, + "tags": [ + "expand-close" + ], + "grid": 0 + }, + "attrs": [ + {}, + {} + ], + "properties": { + "order": 88, + "id": 43, + "prevSize": 32, + "code": 58901, + "name": "expand-close" + }, + "setIdx": 1, + "setId": 1, + "iconIdx": 43 + }, + { + "icon": { + "paths": [ + "M512.794 0c-283.187 0-512.794 229.581-512.794 512.794 0 283.187 229.606 512.794 512.794 512.794s512.794-229.606 512.794-512.794c0-283.213-229.581-512.794-512.794-512.794zM512.794 971.213c-253.158 0-458.394-205.261-458.394-458.394 0-253.158 205.261-458.394 458.394-458.394 253.184 0 458.394 205.235 458.394 458.394 0.026 253.133-205.21 458.394-458.394 458.394z", + "M265.6 454.4l-30.387 38.4 265.574 206.387 20.813 1.613 259.2-208-28.8-39.987-236.8 177.587z" + ], + "attrs": [ + {}, + {} + ], + "isMulticolor": false, + "isMulticolor2": false, + "tags": [ + "expand-open" + ], + "grid": 0 + }, + "attrs": [ + {}, + {} + ], + "properties": { + "order": 87, + "id": 44, + "prevSize": 32, + "code": 58902, + "name": "expand-open" + }, + "setIdx": 1, + "setId": 1, + "iconIdx": 44 + }, + { + "icon": { + "paths": [ + "M1020.032 565.555v-116.045l-16.41-5.376-124.237-40.525-33.152-80.102 63.718-134.784-82.048-82.125-15.411 7.808-116.531 59.213-80.077-33.178-50.278-140.442h-116.096l-45.875 140.698-80 33.126-134.963-63.744-82.022 82.074 7.834 15.334 59.162 116.608-33.126 80.026-140.518 50.253v116.147l16.435 5.325 124.288 40.576 33.075 80-63.693 134.886 82.048 82.099 131.942-66.97 80.026 33.152 50.304 140.39h116.096l5.35-16.41 40.55-124.237 80.077-33.178 134.886 63.718 82.074-82.074-7.834-15.386-59.213-116.582 33.203-80.026 140.416-50.253zM510.003 672.589c-89.754 0-162.509-72.832-162.509-162.611 0-89.754 72.755-162.483 162.509-162.483 89.83 0 162.509 72.73 162.509 162.483 0.026 89.805-72.653 162.611-162.509 162.611z" + ], + "attrs": [ + { + "visibility": false + } + ], + "isMulticolor": false, + "isMulticolor2": false, + "tags": [ + "system-config" + ], + "grid": 0 + }, + "attrs": [ + { + "visibility": false + } + ], + "properties": { + "order": 86, + "id": 45, + "prevSize": 32, + "code": 58896, + "name": "system-config" + }, + "setIdx": 1, + "setId": 1, + "iconIdx": 45 + }, + { + "icon": { + "paths": [ + "M509.978 54.426l-509.978 509.926 95.949 95.949 414.106-413.978 413.875 413.978 95.949-95.898-509.901-509.978zM146.253 688.563v335.437h259.917v-304.819h207.514v304.819h259.917v-335.488l-363.622-363.597-363.725 363.648z" + ], + "attrs": [ + { + "visibility": false + } + ], + "isMulticolor": false, + "isMulticolor2": false, + "tags": [ + "home" + ], + "grid": 0 + }, + "attrs": [ + { + "visibility": false + } + ], + "properties": { + "order": 85, + "id": 46, + "prevSize": 32, + "code": 58897, + "name": "home" + }, + "setIdx": 1, + "setId": 1, + "iconIdx": 46 + }, + { + "icon": { + "paths": [ + "M0 736.41l498.278 287.59v-421.402l-498.278-287.667v421.478zM894.464 224.486v44.262c0 32.819-62.797 59.418-140.365 59.418-77.466 0-140.262-26.598-140.262-59.418v-73.216h0.435c4.71 30.925 65.408 55.475 139.853 55.475 77.568 0 140.365-26.624 140.365-59.29 0-32.845-62.797-59.366-140.365-59.366-6.195 0-12.262 0.205-18.202 0.563l-90.317-52.147v55.706c0 32.819-62.72 59.392-140.262 59.392-48.691 0-91.597-10.496-116.813-26.47-3.584-3.712-7.987-7.245-13.312-10.598-6.579-6.861-10.24-14.387-10.24-22.323v-53.939l-87.322 50.381c-6.272-0.307-12.646-0.614-19.123-0.614-77.491 0-140.314 26.522-140.314 59.366 0 32.691 62.822 59.29 140.314 59.29 74.445 0 135.219-24.525 139.93-55.475h0.384v73.216c0 32.819-62.746 59.418-140.314 59.418-77.491 0-140.314-26.598-140.314-59.418v-43.622l-108.083 62.31 499.994 288.563 496.691-286.694-112.358-64.768zM646.784 408.013c0 32.794-62.874 59.315-140.365 59.315s-140.339-26.522-140.339-59.315v-73.267h0.41c4.762 30.95 65.459 55.475 139.93 55.475s135.142-24.525 139.904-55.475h0.486v73.267zM525.645 606.234v417.766l498.355-287.718v-417.766l-498.355 287.718zM505.318 118.656c77.542 0 140.262-26.547 140.262-59.315s-62.72-59.315-140.262-59.315c-77.491 0-140.339 26.573-140.339 59.315-0.026 32.768 62.822 59.315 140.339 59.315z" + ], + "attrs": [ + { + "visibility": false + } + ], + "isMulticolor": false, + "isMulticolor2": false, + "tags": [ + "lego" + ], + "grid": 0 + }, + "attrs": [ + { + "visibility": false + } + ], + "properties": { + "order": 84, + "id": 47, + "prevSize": 32, + "code": 58898, + "name": "lego" + }, + "setIdx": 1, + "setId": 1, + "iconIdx": 47 + }, + { + "icon": { + "paths": [ + "M287.002 481.664c0.205 0.23 0.461 0.486 0.691 0.717l103.347 103.373 36.045-36.045-56.55-56.499 90.266-90.189 11.904 1.28c3.046 0.307 6.093 0.538 9.19 0.538 6.246 0 12.314-0.768 18.253-2.125l-66.381-66.381c-1.357-1.382-2.765-2.611-4.173-3.814 20.454-73.6 1.766-155.725-56.038-213.555-57.421-57.421-138.803-76.237-211.968-56.525l123.955 123.981-32.563 121.446-121.395 32.589-124.032-124.006c-19.712 73.19-0.896 154.573 56.525 212.019 60.262 60.288 147.021 77.952 222.925 53.197zM653.235 555.802c-1.997 8.909-2.509 18.202-1.459 27.546l1.306 11.93-90.189 90.189-56.55-56.55-36.070 36.122 327.219 327.194c20.198 20.173 46.618 30.259 73.062 30.259s52.915-10.086 73.037-30.259c40.346-40.32 40.346-105.728 0-146.074l-290.355-290.355zM905.907 958.362l-51.866 13.875-42.112-42.112 13.901-51.891 51.866-13.926 42.112 42.138-13.901 51.917zM506.701 594.099l56.576 56.576 64.128-64.154c-3.482-31.334 6.707-63.821 30.669-87.808 24.013-23.962 56.474-34.176 87.808-30.72l280.397-280.346-157.056-157.056-280.448 280.397c3.482 31.258-6.682 63.821-30.669 87.782-24.013 23.987-56.525 34.176-87.808 30.643l-64.102 64.205 56.499 56.422-277.043 277.12-10.138-10.138-53.248 42.829-89.421 141.312 22.835 22.835 141.312-89.421 42.803-53.222-10.138-10.138 277.043-277.12z" + ], + "attrs": [ + { + "visibility": false + } + ], + "isMulticolor": false, + "isMulticolor2": false, + "tags": [ + "tool" + ], + "grid": 0 + }, + "attrs": [ + { + "visibility": false + } + ], + "properties": { + "order": 120, + "id": 48, + "prevSize": 32, + "code": 58899, + "name": "tool" + }, + "setIdx": 1, + "setId": 1, + "iconIdx": 48 + }, + { + "icon": { + "paths": [ + "M1023.932 505.105c-3.717-282.692-236.1-508.826-518.793-505.003-282.658 3.775-508.826 236.066-505.071 518.827 3.772 282.556 236.1 508.826 518.793 505.003 282.658-3.768 508.826-236.066 505.071-518.827zM623.991 481.304v298.633h-223.983v-298.633h-186.621l298.633-298.633 298.667 298.633h-186.679z" + ], + "attrs": [ + {} + ], + "isMulticolor": false, + "isMulticolor2": false, + "tags": [ + "upgrade" + ], + "grid": 0 + }, + "attrs": [ + {} + ], + "properties": { + "order": 125, + "id": 49, + "prevSize": 32, + "code": 58900, + "name": "upgrade" + }, + "setIdx": 1, + "setId": 1, + "iconIdx": 49 + }, + { + "icon": { + "paths": [ + "M870.821 731.837c-64.195-65.89-78.231-188.772-91.738-283.159-20.074-139.937-24.259-297.089-226.008-317.693v-25.318c0-25.424-39.195-46.028-64.937-46.028s-62.024 20.551-62.024 46.028v25.371c-200.054 20.816-206.993 177.914-226.855 317.693-13.453 94.439-27.331 217.268-91.049 283.264-12.818 13.348-16.473 32.998-9.11 49.947 7.362 16.843 24.153 27.913 42.797 27.913h695.343c18.75 0 35.593-11.070 42.903-28.019s3.655-36.653-9.322-50z", + "M489.569 963.883c51.060 0 92.373-40.837 92.373-91.367h-184.694c-0.053 50.53 41.314 91.367 92.32 91.367z" + ], + "width": 989, + "attrs": [ + { + "opacity": 1, + "visibility": false + }, + { + "opacity": 1, + "visibility": false + } + ], + "isMulticolor": false, + "isMulticolor2": false, + "tags": [ + "notification-02" + ], + "grid": 0 + }, + "attrs": [ + { + "opacity": 1, + "visibility": false + }, + { + "opacity": 1, + "visibility": false + } + ], + "properties": { + "order": 123, + "id": 50, + "prevSize": 32, + "code": 58887, + "name": "notification-02" + }, + "setIdx": 1, + "setId": 1, + "iconIdx": 50 + }, + { + "icon": { + "paths": [ + "M252.137 153.228l-160.070 92.393 378.042 218.205 160.023-92.393-377.996-218.205zM845.638 247.063l-377.996-218.252-145.222 83.828 377.996 218.205 145.222-83.782zM502.784 526.15v433.664l376.832-217.507v-433.711l-376.832 217.553zM55.668 742.26l376.785 217.507v-436.503l-376.785-217.46v436.457z" + ], + "width": 954, + "attrs": [ + { + "opacity": 1, + "visibility": false + } + ], + "isMulticolor": false, + "isMulticolor2": false, + "tags": [ + "product" + ], + "grid": 0 + }, + "attrs": [ + { + "opacity": 1, + "visibility": false + } + ], + "properties": { + "order": 7, + "id": 51, + "prevSize": 32, + "code": 58888, + "name": "product", + "ligatures": "" + }, + "setIdx": 1, + "setId": 1, + "iconIdx": 51 + }, + { + "icon": { + "paths": [ + "M454.495 48.899l-402.697 240.513v457.026l104.632 60.727v-457.049l298.157-178.728 299.698 179.142-0.138 455.922 103.528-60.013v-457.026l-403.18-240.513zM507.766 330.28v534.344l-53.271 32.124-53.34-32.262v-533.792l-138.090 83.853v456.934l191.453 115.516 193.087-116.322v-456.451l-139.839-83.945z" + ], + "width": 903, + "attrs": [ + { + "opacity": 1, + "visibility": false + }, + { + "opacity": 1, + "visibility": false + }, + { + "opacity": 1, + "visibility": false + } + ], + "isMulticolor": false, + "isMulticolor2": false, + "tags": [ + "logo" + ], + "grid": 0 + }, + "attrs": [ + { + "opacity": 1, + "visibility": false + }, + { + "opacity": 1, + "visibility": false + }, + { + "opacity": 1, + "visibility": false + } + ], + "properties": { + "order": 17, + "id": 52, + "prevSize": 32, + "code": 58886, + "name": "logo", + "ligatures": "" + }, + "setIdx": 1, + "setId": 1, + "iconIdx": 52 + }, + { + "icon": { + "paths": [ + "M709.921 158.694c8.139 32.295 8.927 34.974 8.192 68.162-0.263 12.813-7.772 71.943-5.724 90.112 1.628 14.966 5.461 16.174 11.448 28.514 10.398 21.425 6.984 51.095 2.941 72.678-2.206 11.868-6.827 28.725-13.916 38.387-7.667 10.66-23.211 10.713-30.142 23.158-9.872 17.854-4.306 43.008-10.503 62.385-7.142 21.898-25.101 23.421-26.466 52.145 8.822 1.155 17.592 2.468 26.466 3.623 8.822 18.59 25.049 55.874 41.59 67.059 13.863 3.728 27.727 7.457 41.59 11.185 48.627 19.64 102.558 43.061 151.237 63.33 44.373 18.432 97.411 24.996 113.48 70.84 0 31.035 2.941 104.501 2.153 145.25h-965.553c-0.893-40.697 2.153-114.215 2.153-145.25 15.964-45.844 69.002-52.408 113.375-70.84 48.679-20.27 102.61-43.691 151.237-63.33 13.811-3.728 27.674-7.457 41.59-11.185 16.489-11.185 32.715-48.522 41.538-67.059l19.692-4.621c-4.464-24.576-19.85-26.466-26.256-43.743-2.521-26.099-5.041-52.145-7.509-78.192 0.053 1.155-18.117-3.361-20.48-4.779-25.731-15.806-26.204-80.24-28.725-107.021-1.103-12.183 16.174-22.265 11.343-44.636-28.094-131.44 12.183-192.88 75.881-213.307 44.216-17.749 126.871-50.465 203.855-3.728l19.167 17.487 30.93 5.251c15.491 8.77 25.416 38.124 25.416 38.124z" + ], + "width": 1090, + "attrs": [ + { + "opacity": 1, + "visibility": false + } + ], + "isMulticolor": false, + "isMulticolor2": false, + "tags": [ + "account" + ], + "grid": 0 + }, + "attrs": [ + { + "opacity": 1, + "visibility": false + } + ], + "properties": { + "order": 9, + "id": 53, + "prevSize": 32, + "code": 58880, + "name": "account", + "ligatures": "" + }, + "setIdx": 1, + "setId": 1, + "iconIdx": 53 + }, + { + "icon": { + "paths": [ + "M529.203 886.14l-468.465-628.209h936.931l-468.465 628.209z" + ], + "width": 1085, + "attrs": [ + { + "opacity": 1, + "visibility": false + } + ], + "isMulticolor": false, + "isMulticolor2": false, + "tags": [ + "arrowdown" + ], + "grid": 0 + }, + "attrs": [ + { + "opacity": 1, + "visibility": false + } + ], + "properties": { + "order": 10, + "id": 54, + "prevSize": 32, + "code": 58881, + "name": "arrowdown", + "ligatures": "" + }, + "setIdx": 1, + "setId": 1, + "iconIdx": 54 + }, + { + "icon": { + "paths": [ + "M976.793 982.006h-910.388v-910.388h910.388v910.388zM912.622 135.789h-782.046v782.088h782.046v-782.088z", + "M221.432 822.8h152.876v-372.033h-152.876v372.033z", + "M466.323 820.234h350.932v-366.53h-350.932v366.53z", + "M221.432 360.489h595.865v-147.125h-595.865v147.125z" + ], + "width": 1034, + "attrs": [ + { + "opacity": 1, + "visibility": false + }, + { + "opacity": 1, + "visibility": false + }, + { + "opacity": 1, + "visibility": false + }, + { + "opacity": 1, + "visibility": false + } + ], + "isMulticolor": false, + "isMulticolor2": false, + "tags": [ + "cms" + ], + "grid": 0 + }, + "attrs": [ + { + "opacity": 1, + "visibility": false + }, + { + "opacity": 1, + "visibility": false + }, + { + "opacity": 1, + "visibility": false + }, + { + "opacity": 1, + "visibility": false + } + ], + "properties": { + "order": 83, + "id": 55, + "prevSize": 32, + "code": 58882, + "name": "cms", + "ligatures": "" + }, + "setIdx": 1, + "setId": 1, + "iconIdx": 55 + }, + { + "icon": { + "paths": [ + "M264.319 308.831c75.685 0 136.98-61.259 136.98-136.944 0-75.649-61.295-136.98-136.98-136.98s-137.017 61.331-137.017 136.98c0 75.649 61.331 136.944 137.017 136.944zM448.929 370.851c-28.962-28.926-63.325-46.252-187.655-46.252s-157.859 18.776-185.335 46.252c-27.44 27.44-18.196 320.43-18.196 320.43l60.824-144.411 38.241 430.334 110.23-220.278 102.907 220.278 36.393-430.334 60.824 144.411c-0.036 0 10.693-291.468-18.233-320.43z" + ], + "width": 489, + "attrs": [ + { + "opacity": 1, + "visibility": false + } + ], + "isMulticolor": false, + "isMulticolor2": false, + "tags": [ + "customers" + ], + "grid": 0 + }, + "attrs": [ + { + "opacity": 1, + "visibility": false + } + ], + "properties": { + "order": 82, + "id": 56, + "prevSize": 32, + "code": 58883, + "name": "customers", + "ligatures": "" + }, + "setIdx": 1, + "setId": 1, + "iconIdx": 56 + }, + { + "icon": { + "paths": [ + "M680.975 73.728c-337.523 0-610.976 273.515-611.038 610.976 0.122 37.72 1.039 251.812 1.039 251.812h1219.997c0 0 0.978-239.219 1.039-251.812-0.183-337.523-273.637-610.976-611.038-610.976zM737.708 197.831c31.117 3.607 61.379 10.271 90.418 19.624l-19.93 61.685c-25.004-8.070-51.169-13.939-78.191-16.995l7.703-64.313zM270.091 673.15h-64.864c0-31.423 3.118-62.235 8.803-92.007l63.702 12.349c-5.135 25.799-7.642 52.392-7.642 79.658zM305.855 504.419l-59.178-26.288c12.655-28.489 28-55.449 45.79-80.636l52.942 37.475c-15.284 21.825-28.611 45.056-39.554 69.449zM407.46 365.155l-43.405-48.113c22.925-20.541 47.807-39.187 74.462-54.96l33.318 55.571c-22.987 13.755-44.567 29.65-64.374 47.501zM536.943 217.455c29.039-9.292 59.178-16.017 90.418-19.624l7.581 64.313c-26.838 3.057-53.003 8.926-78.13 16.995l-19.869-61.685zM761.673 801.532l-152.897 27.205-38.881-150.452 395.172-404.22-203.394 527.467zM1019.476 434.971l52.942-37.414c17.79 25.187 33.257 52.148 45.851 80.636l-59.178 26.288c-10.943-24.454-24.209-47.685-39.615-69.51zM1094.916 673.15c0-27.266-2.69-53.859-7.703-79.658l63.702-12.349c5.808 29.834 8.803 60.645 8.803 92.007h-64.802zM646.006 770.659c26.777 17.056 62.174 9.415 79.291-17.24 17.118-26.593 9.292-62.051-17.301-79.108-26.655-17.24-62.051-9.354-79.23 17.362-17.118 26.349-9.476 61.99 17.24 78.986z" + ], + "width": 1376, + "attrs": [ + { + "opacity": 1, + "visibility": false + } + ], + "isMulticolor": false, + "isMulticolor2": false, + "tags": [ + "dashboard" + ], + "grid": 0 + }, + "attrs": [ + { + "opacity": 1, + "visibility": false + } + ], + "properties": { + "order": 81, + "id": 57, + "prevSize": 32, + "code": 58884, + "name": "dashboard", + "ligatures": "" + }, + "setIdx": 1, + "setId": 1, + "iconIdx": 57 + }, + { + "icon": { + "paths": [ + "M24.097 113.465h972.827v111.922l-410.504 412.792v238.366l-171.447 87.505v-325.871l-390.875-415.877v-108.837z" + ], + "attrs": [ + { + "opacity": 1, + "visibility": false + } + ], + "isMulticolor": false, + "isMulticolor2": false, + "tags": [ + "filter" + ], + "grid": 0 + }, + "attrs": [ + { + "opacity": 1, + "visibility": false + } + ], + "properties": { + "order": 80, + "id": 58, + "prevSize": 32, + "code": 58885, + "name": "filter", + "ligatures": "" + }, + "setIdx": 1, + "setId": 1, + "iconIdx": 58 + }, + { + "icon": { + "paths": [ + "M59.153 534.182l164.053 38.141v-303.902l-164.053 38.141v227.621zM1122.198 59.153l-837.712 194.959v335.978l140.328 376.832 151.712-57.45-104.049-279.113 649.668 151.18v-722.385z" + ], + "width": 1170, + "attrs": [ + { + "opacity": 1, + "visibility": false + } + ], + "isMulticolor": false, + "isMulticolor2": false, + "tags": [ + "promotions" + ], + "grid": 0 + }, + "attrs": [ + { + "opacity": 1, + "visibility": false + } + ], + "properties": { + "order": 79, + "id": 59, + "prevSize": 32, + "code": 58889, + "name": "promotions", + "ligatures": "" + }, + "setIdx": 1, + "setId": 1, + "iconIdx": 59 + }, + { + "icon": { + "paths": [ + "M736.707 981.234h207.134v-322.703h-207.134v322.703zM399.646 981.234h207.134v-946.793h-207.134v946.793zM62.673 981.19h207.134v-634.704h-207.134v634.704z" + ], + "width": 991, + "attrs": [ + { + "opacity": 1, + "visibility": false + } + ], + "isMulticolor": false, + "isMulticolor2": false, + "tags": [ + "reports" + ], + "grid": 0 + }, + "attrs": [ + { + "opacity": 1, + "visibility": false + } + ], + "properties": { + "order": 78, + "id": 60, + "prevSize": 32, + "code": 58890, + "name": "reports", + "ligatures": "" + }, + "setIdx": 1, + "setId": 1, + "iconIdx": 60 + }, + { + "icon": { + "paths": [ + "M426.502 612.517c-15.866-13.512-42.796-25.753-80.79-36.723v198.774c11.535-1.459 23.729-4.331 36.299-8.851 12.618-4.426 23.87-10.829 33.804-19.068 9.981-8.427 18.173-18.55 24.529-30.649 6.638-12.006 9.651-26.365 9.651-42.89 0.047-26.836-7.721-47.222-23.493-60.593zM576.736 736.856c-7.109 23.117-19.774 45.762-38.135 67.749-18.503 22.175-43.079 41.855-74.010 58.992-30.885 17.373-70.432 27.683-118.878 31.12v88.088h-57.014v-88.088c-72.080-5.603-128.483-29.237-169.113-71.374-40.536-42.090-63.935-104.095-70.432-185.544h136.251c-0.753 39.359 8.992 70.479 28.86 93.266 20.15 22.74 44.774 37.335 74.434 43.455v-216.523c-3.060-1.318-7.486-2.919-12.994-4.567-5.508-1.789-11.393-3.343-17.938-4.708-23.776-6.827-47.175-15.019-70.291-24.294-23.493-9.369-44.114-21.704-62.523-37.335-18.456-15.584-33.098-34.84-43.879-57.956-11.111-23.211-16.478-51.977-16.478-86.487 0-35.31 6.168-66.336 18.785-93.313 12.665-26.836 29.143-49.529 49.858-67.702 20.621-18.314 44.303-32.58 71.468-42.419 27.071-10.122 55.037-16.149 83.992-18.314v-79.66h57.014v79.66c29.143 3.531 56.308 10.169 81.638 20.292 25.423 10.028 47.787 23.729 67.137 41.478 19.585 17.514 35.357 39.453 47.457 65.771 12.288 26.13 19.35 57.109 21.28 93.172h-137.287c-0.518-27.636-8.616-51.082-23.917-70.432-15.725-19.303-34.275-29.002-56.308-29.002v183.331c7.862 2.072 15.631 4.143 23.729 6.12 8.098 2.072 16.525 4.567 25.565 7.297 47.645 13.983 84.415 31.12 110.168 51.318 25.8 20.292 44.726 41.666 56.92 63.653 12.335 22.175 19.633 44.256 21.704 66.336 2.448 22.081 3.531 41.713 3.531 59.039 0.047 15.207-3.531 34.416-10.593 57.579zM228.905 263.415c-8.38 7.156-15.113 16.196-19.962 26.883-4.802 10.781-7.062 23.352-7.062 37.759 0 22.834 6.733 40.536 20.103 52.824 13.653 12.618 35.734 22.552 66.713 30.131v-168.831c-10.829 0-21.516 1.695-31.826 5.226-10.216 3.437-19.633 8.851-27.966 16.007z" + ], + "width": 659, + "attrs": [ + { + "opacity": 1, + "visibility": false + } + ], + "isMulticolor": false, + "isMulticolor2": false, + "tags": [ + "sales" + ], + "grid": 0 + }, + "attrs": [ + { + "opacity": 1, + "visibility": false + } + ], + "properties": { + "order": 77, + "id": 61, + "prevSize": 32, + "code": 58891, + "name": "sales", + "ligatures": "" + }, + "setIdx": 1, + "setId": 1, + "iconIdx": 61 + }, + { + "icon": { + "paths": [ + "M555.139 21.642c-218.775-71.601-457.062 40.29-532.231 250.028-75.227 209.681 41.211 437.665 259.928 509.208 218.717 71.601 457.004-40.348 532.231-250.028s-41.211-437.665-259.928-509.208zM320.076 677.045c-158.915-52.089-243.467-217.681-188.903-369.978 54.679-152.296 227.754-233.625 386.669-181.593s243.409 217.624 188.788 369.92c-54.622 152.296-227.696 233.567-386.554 181.65z", + "M638.482 685.794l358.927 349.602 24.807-69.241 24.865-69.241-310.348-302.29z" + ], + "width": 1109, + "attrs": [ + { + "opacity": 1, + "visibility": false + }, + { + "opacity": 1, + "visibility": false + } + ], + "isMulticolor": false, + "isMulticolor2": false, + "tags": [ + "search" + ], + "grid": 0 + }, + "attrs": [ + { + "opacity": 1, + "visibility": false + }, + { + "opacity": 1, + "visibility": false + } + ], + "properties": { + "order": 76, + "id": 62, + "prevSize": 32, + "code": 58892, + "name": "search", + "ligatures": "" + }, + "setIdx": 1, + "setId": 1, + "iconIdx": 62 + }, + { + "icon": { + "paths": [ + "M1098.281 85.45c19.777-3.723 34.901-21.232 34.901-42.347-0.058-23.791-19.196-43.103-42.812-43.103h-900.508c-23.675 0-42.754 19.312-42.754 43.103 0 21.057 15.007 38.566 34.843 42.347l-181.951 354.421v68.988c0 30.946 32.516 56.016 72.594 56.016 13.437 0 26.001-2.908 36.821-7.795v466.919h1061.286v-466.919c10.878 4.944 23.326 7.795 36.879 7.795 40.078 0 72.594-25.071 72.594-56.016v-68.988l-181.893-354.421zM214.758 564.875c-38.217 0-69.221-25.071-69.221-56.016v-6.457h-0.349v-62.531l137.162-353.665h109.648l-107.961 353.665v68.988c0 0 0 0 0 0 0 30.946-31.004 56.016-69.279 56.016zM498.447 564.875c-38.217 0-69.221-25.071-69.221-56.016v-68.988l57.354-353.665h109.241l-28.095 353.665v68.93c-0.058 31.004-31.004 56.075-69.279 56.075zM782.077 564.875c-38.217 0-69.162-25.071-69.162-56.016v-68.988l-28.154-353.665h108.892l57.296 353.665v68.988c0 0.931 0.175 1.92 0.233 2.792-1.803 29.666-32.051 53.224-69.104 53.224zM1134.637 508.859c0 30.946-31.004 56.016-69.221 56.016s-69.162-25.071-69.162-56.016v-68.988l-108.019-353.665h109.59l137.22 353.665v62.473h-0.349v6.515h-0.058z" + ], + "width": 1280, + "attrs": [ + { + "opacity": 1, + "visibility": false + } + ], + "isMulticolor": false, + "isMulticolor2": false, + "tags": [ + "stores" + ], + "grid": 0 + }, + "attrs": [ + { + "opacity": 1, + "visibility": false + } + ], + "properties": { + "order": 75, + "id": 63, + "prevSize": 32, + "code": 58893, + "name": "stores", + "ligatures": "" + }, + "setIdx": 1, + "setId": 1, + "iconIdx": 63 + }, + { + "icon": { + "paths": [ + "M944.97 329.042c-97.861 0-177.522 79.581-177.522 177.443 0 97.94 79.66 177.679 177.522 177.679 98.019 0 177.679-79.739 177.679-177.679 0-97.861-79.66-177.443-177.679-177.443zM944.97-0c-470.712 0-944.97 512-944.97 512s474.258 512 944.97 512c470.949 0 945.128-512 945.128-512s-474.179-512-945.128-512zM944.97 868.856c-200.057 0-362.292-162.078-362.292-362.45 0-200.057 162.236-362.292 362.292-362.292 200.214 0 362.45 162.236 362.45 362.292 0 200.451-162.236 362.45-362.45 362.45z" + ], + "width": 1890, + "attrs": [ + { + "opacity": 1, + "visibility": false + } + ], + "isMulticolor": false, + "isMulticolor2": false, + "tags": [ + "views" + ], + "grid": 0 + }, + "attrs": [ + { + "opacity": 1, + "visibility": false + } + ], + "properties": { + "order": 73, + "id": 64, + "prevSize": 32, + "code": 58895, + "name": "views", + "ligatures": "" + }, + "setIdx": 1, + "setId": 1, + "iconIdx": 64 + }, + { + "icon": { + "paths": [ + "M1042.226 299.849h-598.393v-299.849l-443.833 384.316 443.833 384.403v-299.859h598.393c106.478 0 192.801 86.318 192.801 192.801s-86.318 192.796-192.801 192.796v0.483l-452.707 0.005c-46.695 0.005-84.53 37.845-84.53 84.535 0 46.68 37.84 84.525 84.535 84.525 0.377 0 0.744-0.053 1.121-0.058h451.581c199.964 0 362.044-162.085 362.044-362.039 0-199.964-162.080-362.059-362.044-362.059z" + ], + "width": 1404, + "attrs": [], + "isMulticolor": false, + "isMulticolor2": false, + "tags": [ + "revert" + ], + "grid": 0 + }, + "attrs": [], + "properties": { + "order": 129, + "id": 65, + "prevSize": 32, + "code": 58946, + "name": "revert" + }, + "setIdx": 1, + "setId": 1, + "iconIdx": 65 } + ], + "height": 1024, + "metadata": { + "name": "icomoon" + }, + "preferences": { + "showGlyphs": true, + "showQuickUse": true, + "showQuickUse2": true, + "showSVGs": true, + "fontPref": { + "prefix": "icon-", + "metadata": { + "fontFamily": "icomoon", + "majorVersion": 1, + "minorVersion": 0 + }, + "metrics": { + "emSize": 1024, + "baseline": 6.25, + "whitespace": 50 + }, + "resetPoint": 58880, + "showVersion": true, + "showSelector": false, + "showMetrics": false, + "showMetadata": false, + "embed": false + }, + "imagePref": { + "prefix": "icon-", + "png": true, + "useClassSelector": true, + "classSelector": ".icon" + }, + "historySize": 100, + "showCodes": true, + "search": "", + "gridSize": 16, + "showLiga": false + } } \ No newline at end of file diff --git a/app/design/frontend/Magento/blank/etc/view.xml b/app/design/frontend/Magento/blank/etc/view.xml index 6c53a8613f09ca1f91c9e024b8e2cec723f0b309..3bf5fc6fc77af5a67becb60920343c6f6ce48db8 100644 --- a/app/design/frontend/Magento/blank/etc/view.xml +++ b/app/design/frontend/Magento/blank/etc/view.xml @@ -73,10 +73,18 @@ <height>140</height> </image> <image id="product_page_image_large" type="image"/> + <image id="product_page_image_large_no_frame" type="image"> + <frame>false</frame> + </image> <image id="product_page_image_medium" type="image"> <width>700</width> <height>700</height> </image> + <image id="product_page_image_medium_no_frame" type="image"> + <width>700</width> + <height>700</height> + <frame>false</frame> + </image> <image id="product_page_image_small" type="thumbnail"> <width>90</width> <height>90</height> diff --git a/app/design/frontend/Magento/luma/etc/view.xml b/app/design/frontend/Magento/luma/etc/view.xml index 12a51ee065edba43c9afde39ce31c2aace3d00a8..33fc64af977c557f17fd7e9db0779a881fa77e08 100644 --- a/app/design/frontend/Magento/luma/etc/view.xml +++ b/app/design/frontend/Magento/luma/etc/view.xml @@ -77,10 +77,18 @@ <height>140</height> </image> <image id="product_page_image_large" type="image"/> + <image id="product_page_image_large_no_frame" type="image"> + <frame>false</frame> + </image> <image id="product_page_image_medium" type="image"> <width>700</width> <height>560</height> </image> + <image id="product_page_image_medium_no_frame" type="image"> + <width>700</width> + <height>700</height> + <frame>false</frame> + </image> <image id="product_page_image_small" type="thumbnail"> <width>88</width> <height>110</height> diff --git a/app/etc/di.xml b/app/etc/di.xml index e430c15729d3d0cced20bf2b326d40f152b174e6..1b347574f4b2a2d3f010cb9a712da6cd6c7dbec2 100755 --- a/app/etc/di.xml +++ b/app/etc/di.xml @@ -433,7 +433,7 @@ </virtualType> <virtualType name="layoutObjectArgumentInterpreter" type="Magento\Framework\View\Layout\Argument\Interpreter\DataObject"> <arguments> - <argument name="expectedClass" xsi:type="string">Magento\Framework\Data\CollectionDataSourceInterface</argument> + <argument name="expectedClass" xsi:type="string">Magento\Framework\View\Element\Block\ArgumentInterface</argument> </arguments> </virtualType> <type name="Magento\Framework\View\Layout\Argument\Interpreter\NamedParams"> @@ -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/composer.json b/composer.json index f9e49415d6ad3aff6976144df442861909155d2d..7840f84720b6cac97073647c90c184315a80eb4b 100644 --- a/composer.json +++ b/composer.json @@ -217,9 +217,6 @@ "tinymce/tinymce": "lib/web/tiny_mce" } }, - "config": { - "use-include-path": true - }, "autoload": { "psr-4": { "Magento\\Framework\\": "lib/internal/Magento/Framework/", @@ -227,10 +224,18 @@ "Magento\\": "app/code/Magento/" }, "psr-0": { - "": "app/code/" + "": [ + "app/code/", + "var/generation" + ] }, "files": [ "app/etc/NonComposerComponentRegistration.php" + ], + "exclude-from-classmap": [ + "**/dev/**", + "**/update/**", + "**/Test/**" ] }, "autoload-dev": { diff --git a/composer.lock b/composer.lock index 02f0e31a325638840641667cac1c6783cf381e87..7b3c6ccc9928df82fc72f6e397d1b98d3f2823d0 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "1f34dce6d48c9e4e694c27e001414000", + "hash": "8c0f23eee8426e8aeba5a897f6f2ccbd", "content-hash": "600aca1692cf3fe5c2ea1cbf66de09ab", "packages": [ { diff --git a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductAttributeMediaGalleryManagementInterfaceTest.php b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductAttributeMediaGalleryManagementInterfaceTest.php index 324404ead6c9f5845526512ed6ed39e87f94157c..0f5a0a425a5a5358cf98715827a7950d5e0489fd 100644 --- a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductAttributeMediaGalleryManagementInterfaceTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductAttributeMediaGalleryManagementInterfaceTest.php @@ -237,8 +237,8 @@ class ProductAttributeMediaGalleryManagementInterfaceTest extends \Magento\TestF $targetProduct = $this->getTargetSimpleProduct(); $this->assertEquals('/m/a/magento_image.jpg', $targetProduct->getData('thumbnail')); - $this->assertNull($targetProduct->getData('image')); - $this->assertNull($targetProduct->getData('small_image')); + $this->assertEquals('no_selection', $targetProduct->getData('image')); + $this->assertEquals('no_selection', $targetProduct->getData('small_image')); $mediaGallery = $targetProduct->getData('media_gallery'); $this->assertCount(1, $mediaGallery['images']); $updatedImage = array_shift($mediaGallery['images']); 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/functional/.htaccess.sample b/dev/tests/functional/.htaccess.sample index f5c3be7db01e97c551085e09a493fceb11e2ad1f..f1e60cf9b67e91779153e4c9d9f780c8f7bc9438 100644 --- a/dev/tests/functional/.htaccess.sample +++ b/dev/tests/functional/.htaccess.sample @@ -1,6 +1,6 @@ ############################################## ## Allow access to command.php and website.php - <FilesMatch "command.php|website.php"> + <FilesMatch "command.php|website.php|export.php"> order allow,deny allow from all </FilesMatch> diff --git a/dev/tests/functional/composer.json b/dev/tests/functional/composer.json index e4a9bd10fa65832e7fdc4ae01f10578056b55a47..3567ec530f437996c0ed28d792ebd929d2188e0c 100644 --- a/dev/tests/functional/composer.json +++ b/dev/tests/functional/composer.json @@ -1,6 +1,6 @@ { "require": { - "magento/mtf": "1.0.0-rc49", + "magento/mtf": "1.0.0-rc51", "php": "~5.6.5|7.0.2|~7.0.6", "phpunit/phpunit": "~4.8.0|~5.5.0", "phpunit/phpunit-selenium": ">=1.2" diff --git a/dev/tests/functional/credentials.xml.dist b/dev/tests/functional/credentials.xml.dist index 88794d183e8781d5cea1c9199370c67daae1585c..1061ca183f7f9e6ef4d4c1f740159423729e7c75 100644 --- a/dev/tests/functional/credentials.xml.dist +++ b/dev/tests/functional/credentials.xml.dist @@ -32,10 +32,15 @@ <field path="payment/authorizenet_directpost/trans_key" value="" /> <field path="payment/authorizenet_directpost/trans_md5" value="" /> - <field path="payment/braintree_section/braintree/braintree_advanced/merchant_account_id" value="" /> - <field path="payment/braintree_section/braintree/braintree_required/merchant_id" value="" /> - <field path="payment/braintree_section/braintree/braintree_required/public_key" value="" /> - <field path="payment/braintree_section/braintree/braintree_required/private_key" value="" /> + <field replace="braintree_enabled_fraud_merchant_account_id" value="" /> + <field replace="braintree_enabled_fraud_merchant_id" value="" /> + <field replace="braintree_enabled_fraud_public_key" value="" /> + <field replace="braintree_enabled_fraud_private_key" value="" /> + + <field replace="braintree_disabled_fraud_merchant_account_id" value="" /> + <field replace="braintree_disabled_fraud_merchant_id" value="" /> + <field replace="braintree_disabled_fraud_public_key" value="" /> + <field replace="braintree_disabled_fraud_private_key" value="" /> <field path="payment/paypal_group_all_in_one/wpp_usuk/wpp_required_settings/wpp_and_express_checkout/business_account" value="" /> <field path="payment/paypal_group_all_in_one/wpp_usuk/wpp_required_settings/wpp_and_express_checkout/api_username" value="" /> @@ -43,20 +48,32 @@ <field path="payment/paypal_group_all_in_one/wpp_usuk/wpp_required_settings/wpp_and_express_checkout/api_signature" value="" /> <field path="payment/paypal_express/merchant_id" value="" /> - <field path="payment/paypal_payment_gateways/paypal_payflowpro_with_express_checkout/paypal_payflow_required/paypal_payflow_api_settings/business_account" value="" /> - <field path="payment/paypal_payment_gateways/paypal_payflowpro_with_express_checkout/paypal_payflow_required/paypal_payflow_api_settings/partner" value="" /> - <field path="payment/paypal_payment_gateways/paypal_payflowpro_with_express_checkout/paypal_payflow_required/paypal_payflow_api_settings/user" value="" /> - <field path="payment/paypal_payment_gateways/paypal_payflowpro_with_express_checkout/paypal_payflow_required/paypal_payflow_api_settings/pwd" value="" /> - <field path="payment/paypal_payment_gateways/paypal_payflowpro_with_express_checkout/paypal_payflow_required/paypal_payflow_api_settings/vendor" value="" /> + <field replace="payflow_pro_fraud_protection_enabled_business_account" value="" /> + <field replace="payflow_pro_fraud_protection_enabled_partner" value="" /> + <field replace="payflow_pro_fraud_protection_enabled_user" value="" /> + <field replace="payflow_pro_fraud_protection_enabled_pwd" value="" /> + <field replace="payflow_pro_fraud_protection_enabled_vendor" value="" /> + + <field replace="payflow_pro_business_account" value="" /> + <field replace="payflow_pro_partner" value="" /> + <field replace="payflow_pro_user" value="" /> + <field replace="payflow_pro_pwd" value="" /> + <field replace="payflow_pro_vendor" value="" /> + + <field replace="payflow_link_business_account_email" value="" /> + <field replace="payflow_link_partner" value="" /> + <field replace="payflow_link_user" value="" /> + <field replace="payflow_link_password" value="" /> + <field replace="payflow_link_vendor" value="" /> + + <field path="payment/paypal_group_all_in_one/payments_pro_hosted_solution_with_express_checkout/pphs_required_settings/pphs_required_settings_pphs/business_account" value="" /> + <field path="payment/paypal_group_all_in_one/payments_pro_hosted_solution_with_express_checkout/pphs_required_settings/pphs_required_settings_pphs/api_username" value="" /> + <field path="payment/paypal_group_all_in_one/payments_pro_hosted_solution_with_express_checkout/pphs_required_settings/pphs_required_settings_pphs/api_password" value="" /> + <field path="payment/paypal_group_all_in_one/payments_pro_hosted_solution_with_express_checkout/pphs_required_settings/pphs_required_settings_pphs/api_signature" value="" /> <field path="payment/paypal_alternative_payment_methods/express_checkout_us/express_checkout_required/express_checkout_required_express_checkout/business_account" value="" /> <field path="payment/paypal_alternative_payment_methods/express_checkout_us/express_checkout_required/express_checkout_required_express_checkout/api_username" value="" /> <field path="payment/paypal_alternative_payment_methods/express_checkout_us/express_checkout_required/express_checkout_required_express_checkout/api_password" value="" /> <field path="payment/paypal_alternative_payment_methods/express_checkout_us/express_checkout_required/express_checkout_required_express_checkout/api_signature" value="" /> - <field path="payment/paypal_payment_gateways/payflow_link_us/payflow_link_required/payflow_link_payflow_link/business_account" value="" /> - <field path="payment/paypal_payment_gateways/payflow_link_us/payflow_link_required/payflow_link_payflow_link/partner" value="" /> - <field path="payment/paypal_payment_gateways/payflow_link_us/payflow_link_required/payflow_link_payflow_link/user" value="" /> - <field path="payment/paypal_payment_gateways/payflow_link_us/payflow_link_required/payflow_link_payflow_link/pwd" value="" /> - <field path="payment/paypal_payment_gateways/payflow_link_us/payflow_link_required/payflow_link_payflow_link/vendor" value="" /> </replace> diff --git a/dev/tests/functional/etc/di.xml b/dev/tests/functional/etc/di.xml index 69951a2cc1b86248040074c45ee967c93dc0bb82..b21e507a5af023b18326d2c1cf5bc038a5abdb3a 100644 --- a/dev/tests/functional/etc/di.xml +++ b/dev/tests/functional/etc/di.xml @@ -6,6 +6,11 @@ */ --> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd"> + <preference for="Magento\Mtf\Util\Command\File\ExportInterface" type="\Magento\Mtf\Util\Command\File\Export" /> + <preference for="Magento\Mtf\Util\Command\File\Export\ReaderInterface" type="\Magento\Mtf\Util\Command\File\Export\Reader" /> + + <type name="\Magento\Mtf\Util\Command\File\Export" shared="false" /> + <virtualType name="Magento\Mtf\Config\SchemaLocator\Config" type="Magento\Mtf\Config\SchemaLocator"> <arguments> <argument name="schemaPath" xsi:type="string">etc/config.xsd</argument> @@ -13,4 +18,22 @@ </virtualType> <type name="Magento\Mtf\Util\Protocol\CurlTransport\WebapiDecorator" shared="true" /> + + <type name="Magento\Mtf\Util\Command\File\Export\Reader"> + <arguments> + <argument name="template" xsi:type="string">\w*?\.csv</argument> + </arguments> + </type> + + <virtualType name="Magento\Mtf\Util\Command\File\Export\ProductReader" type="Magento\Mtf\Util\Command\File\Export\Reader"> + <arguments> + <argument name="template" xsi:type="string">catalog_product.*?\.csv</argument> + </arguments> + </virtualType> + + <virtualType name="Magento\Mtf\Util\Command\File\Export\CustomerReader" type="Magento\Mtf\Util\Command\File\Export\Reader"> + <arguments> + <argument name="template" xsi:type="string">customer.*?\.csv</argument> + </arguments> + </virtualType> </config> diff --git a/dev/tests/functional/lib/Magento/Mtf/Client/Element/DatepickerElement.php b/dev/tests/functional/lib/Magento/Mtf/Client/Element/DatepickerElement.php index e09ca5647cf590831e10b47ce8f86e20ef670ef3..07ac39363119094f9da91ab2b3d4dda8aa5129c3 100644 --- a/dev/tests/functional/lib/Magento/Mtf/Client/Element/DatepickerElement.php +++ b/dev/tests/functional/lib/Magento/Mtf/Client/Element/DatepickerElement.php @@ -67,8 +67,8 @@ class DatepickerElement extends SimpleElement $date[1] = ltrim($date[1], '0'); $this->find($this->datePickerButton, Locator::SELECTOR_XPATH)->click(); $datapicker = $this->find($this->datePickerBlock, Locator::SELECTOR_XPATH); - $datapicker->find($this->datePickerMonth, Locator::SELECTOR_XPATH, 'select')->setValue($date[0]); $datapicker->find($this->datePickerYear, Locator::SELECTOR_XPATH, 'select')->setValue($date[2]); + $datapicker->find($this->datePickerMonth, Locator::SELECTOR_XPATH, 'select')->setValue($date[0]); $datapicker->find(sprintf($this->datePickerCalendar, $date[1]), Locator::SELECTOR_XPATH)->click(); if ($datapicker->isVisible()) { $datapicker->find($this->datePickerButtonClose, Locator::SELECTOR_XPATH)->click(); diff --git a/dev/tests/functional/lib/Magento/Mtf/Constraint/AbstractAssertForm.php b/dev/tests/functional/lib/Magento/Mtf/Constraint/AbstractAssertForm.php index ba1eca68a2436d1be756d82542ec412c95858e42..7114ec405ea28f4afd48537523ee9725e6058639 100644 --- a/dev/tests/functional/lib/Magento/Mtf/Constraint/AbstractAssertForm.php +++ b/dev/tests/functional/lib/Magento/Mtf/Constraint/AbstractAssertForm.php @@ -118,8 +118,8 @@ abstract class AbstractAssertForm extends AbstractConstraint /** * Sort multidimensional array by paths. - * Pattern path: key/subKey::sorkKey. - * Exapmle: + * Pattern path: key/subKey::sortKey. + * Example: * $data = [ * 'custom_options' => [ * 'options' => [ diff --git a/dev/tests/functional/lib/Magento/Mtf/Util/Command/Cli.php b/dev/tests/functional/lib/Magento/Mtf/Util/Command/Cli.php index 96be468a6eb377f619339c02a2be00835f8425eb..db39bdcb5b7a5e1e323ee434b2e8b1d744b0570a 100644 --- a/dev/tests/functional/lib/Magento/Mtf/Util/Command/Cli.php +++ b/dev/tests/functional/lib/Magento/Mtf/Util/Command/Cli.php @@ -7,7 +7,6 @@ namespace Magento\Mtf\Util\Command; use Magento\Mtf\Util\Protocol\CurlInterface; -use Magento\Mtf\ObjectManager; use Magento\Mtf\Util\Protocol\CurlTransport; /** @@ -28,7 +27,6 @@ class Cli private $transport; /** - * @constructor * @param CurlTransport $transport */ public function __construct(CurlTransport $transport) @@ -61,6 +59,6 @@ class Cli private function prepareUrl($command, array $options) { $command .= ' ' . implode(' ', $options); - return $_ENV['app_frontend_url'] . Cli::URL . '?command=' . urlencode($command); + return $_ENV['app_frontend_url'] . self::URL . '?command=' . urlencode($command); } } diff --git a/dev/tests/functional/lib/Magento/Mtf/Util/Command/File/Export.php b/dev/tests/functional/lib/Magento/Mtf/Util/Command/File/Export.php new file mode 100644 index 0000000000000000000000000000000000000000..6d5defadbc44a5d30e69423cafe96653450f51bf --- /dev/null +++ b/dev/tests/functional/lib/Magento/Mtf/Util/Command/File/Export.php @@ -0,0 +1,131 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Mtf\Util\Command\File; + +use Magento\Mtf\ObjectManagerInterface; +use Magento\Mtf\Util\Command\File\Export\Data; +use Magento\Mtf\Util\Command\File\Export\ReaderInterface; + +/** + * Get Exporting file from the Magento. + */ +class Export implements ExportInterface +{ + /** + * Path to the Reader. + * + * @var string + */ + private $readerPath = 'Magento\Mtf\Util\Command\File\Export\%sReader'; + + /** + * Object manager instance. + * + * @var ObjectManagerInterface + */ + private $objectManager; + + /** + * File reader for Magento export files. + * + * @var ReaderInterface + */ + private $reader; + + /** + * @param ObjectManagerInterface $objectManager + * @param string $type [optional] + */ + public function __construct(ObjectManagerInterface $objectManager, $type = 'product') + { + $this->objectManager = $objectManager; + $this->reader = $this->getReader($type); + } + + /** + * Get reader for export files. + * + * @param string $type + * @return ReaderInterface + * @throws \ReflectionException + */ + private function getReader($type) + { + $readerPath = sprintf($this->readerPath, ucfirst($type)); + try { + return $this->objectManager->create($readerPath); + } catch (\ReflectionException $e) { + throw new \ReflectionException("Virtual type '$readerPath' does not exist. Please, check it in di.xml."); + } + } + + /** + * Get the export file by name. + * + * @param string $name + * @return Data|null + */ + public function getByName($name) + { + $this->reader->getData(); + foreach ($this->reader->getData() as $file) { + if ($file->getName() === $name) { + return $file; + } + } + + return null; + } + + /** + * Get latest created the export file. + * + * @return Data|null + */ + public function getLatest() + { + $max = 0; + $latest = null; + foreach ($this->reader->getData() as $file) { + if ($file->getDate() > $max) { + $max = $file->getDate(); + $latest = $file; + } + } + + return $latest; + } + + /** + * Get all export files by date range using unix time stamp. + * + * @param string $start + * @param string $end + * @return Data[] + */ + public function getByDateRange($start, $end) + { + $files = []; + foreach ($this->reader->getData() as $file) { + if ($file->getDate() > $start && $file->getDate() < $end) { + $files[] = $file; + } + } + + return $files; + } + + /** + * Get all export files. + * + * @return Data[] + */ + public function getAll() + { + return $this->reader->getData(); + } +} diff --git a/dev/tests/functional/lib/Magento/Mtf/Util/Command/File/Export/Data.php b/dev/tests/functional/lib/Magento/Mtf/Util/Command/File/Export/Data.php new file mode 100644 index 0000000000000000000000000000000000000000..a6756aac0052a28bc04cc7c7d420c4ace8d5c472 --- /dev/null +++ b/dev/tests/functional/lib/Magento/Mtf/Util/Command/File/Export/Data.php @@ -0,0 +1,58 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Mtf\Util\Command\File\Export; + +/** + * Data mapping for Export file. + */ +class Data +{ + /** + * File data. + * + * @var array + */ + private $data; + + /** + * @param array $data + */ + public function __construct(array $data) + { + $this->data = $data; + } + + /** + * Get file name. + * + * @return string + */ + public function getName() + { + return $this->data['name']; + } + + /** + * Get file content. + * + * @return string + */ + public function getContent() + { + return $this->data['content']; + } + + /** + * Get file creation date. + * + * @return string + */ + public function getDate() + { + return $this->data['date']; + } +} diff --git a/dev/tests/functional/lib/Magento/Mtf/Util/Command/File/Export/Reader.php b/dev/tests/functional/lib/Magento/Mtf/Util/Command/File/Export/Reader.php new file mode 100644 index 0000000000000000000000000000000000000000..3a8287daae2ab54cc8adbd8fff2249864cbed9a5 --- /dev/null +++ b/dev/tests/functional/lib/Magento/Mtf/Util/Command/File/Export/Reader.php @@ -0,0 +1,89 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Mtf\Util\Command\File\Export; + +use Magento\Mtf\ObjectManagerInterface; +use Magento\Mtf\Util\Protocol\CurlTransport; +use Magento\Mtf\Util\Protocol\CurlInterface; + +/** + * File reader for Magento export files. + */ +class Reader implements ReaderInterface +{ + /** + * Pattern for file name in Magento. + * + * @var string + */ + private $template; + + /** + * Object manager instance. + * + * @var ObjectManagerInterface + */ + private $objectManager; + + /** + * Curl transport protocol. + * + * @var CurlTransport + */ + private $transport; + + /** + * @param ObjectManagerInterface $objectManager + * @param CurlTransport $transport + * @param string $template + */ + public function __construct(ObjectManagerInterface $objectManager, CurlTransport $transport, $template) + { + $this->objectManager = $objectManager; + $this->template = $template; + $this->transport = $transport; + } + + /** + * Exporting files as Data object from Magento. + * + * @return Data[] + */ + public function getData() + { + $data = []; + foreach ($this->getFiles() as $file) { + $data[] = $this->objectManager->create(Data::class, ['data' => $file]); + } + + return $data; + } + + /** + * Get files by template from the Magento. + * + * @return array + */ + private function getFiles() + { + $this->transport->write($this->prepareUrl(), [], CurlInterface::GET); + $serializedFiles = $this->transport->read(); + $this->transport->close(); + + return unserialize($serializedFiles); + } + + /** + * Prepare url. + * + * @return string + */ + private function prepareUrl() + { + return $_ENV['app_frontend_url'] . self::URL . '?template=' . urlencode($this->template); + } +} diff --git a/dev/tests/functional/lib/Magento/Mtf/Util/Command/File/Export/ReaderInterface.php b/dev/tests/functional/lib/Magento/Mtf/Util/Command/File/Export/ReaderInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..5d305513ec68080ec4e7ec6bad8e776f8653bf15 --- /dev/null +++ b/dev/tests/functional/lib/Magento/Mtf/Util/Command/File/Export/ReaderInterface.php @@ -0,0 +1,25 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Mtf\Util\Command\File\Export; + +/** + * File reader interface for Magento export files. + */ +interface ReaderInterface +{ + /** + * Url to export.php. + */ + const URL = 'dev/tests/functional/utils/export.php'; + + /** + * Exporting files as Data object from Magento. + * + * @return Data[] + */ + public function getData(); +} diff --git a/dev/tests/functional/lib/Magento/Mtf/Util/Command/File/ExportInterface.php b/dev/tests/functional/lib/Magento/Mtf/Util/Command/File/ExportInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..0bc4f9e59a2433b1078805e8431f9f45d8d34e20 --- /dev/null +++ b/dev/tests/functional/lib/Magento/Mtf/Util/Command/File/ExportInterface.php @@ -0,0 +1,46 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Mtf\Util\Command\File; + +use Magento\Mtf\Util\Command\File\Export\Data; + +/** + * Interface for getting Exporting file from the Magento. + */ +interface ExportInterface +{ + /** + * Get the export file by name. + * + * @param string $name + * @return Data|null + */ + public function getByName($name); + + /** + * Get latest created the export file. + * + * @return Data|null + */ + public function getLatest(); + + /** + * Get all export files by date range using unix time stamp. + * + * @param string $start + * @param string $end + * @return Data[] + */ + public function getByDateRange($start, $end); + + /** + * Get all export files. + * + * @return Data[] + */ + public function getAll(); +} diff --git a/dev/tests/functional/lib/Magento/Mtf/Util/Command/Website.php b/dev/tests/functional/lib/Magento/Mtf/Util/Command/Website.php index 611f46894c8bca850d10a519fe7a2850f31b5533..d0c4be34888d2ae863173fbbedc203c08d95fb90 100644 --- a/dev/tests/functional/lib/Magento/Mtf/Util/Command/Website.php +++ b/dev/tests/functional/lib/Magento/Mtf/Util/Command/Website.php @@ -58,6 +58,6 @@ class Website */ private function prepareUrl($websiteCode) { - return $_ENV['app_frontend_url'] . Website::URL . '?website_code=' . urlencode($websiteCode); + return $_ENV['app_frontend_url'] . self::URL . '?website_code=' . urlencode($websiteCode); } } diff --git a/dev/tests/functional/tests/app/Magento/Authorizenet/Test/Block/Form/Cc.php b/dev/tests/functional/tests/app/Magento/Authorizenet/Test/Block/Form/Cc.php deleted file mode 100644 index 7918859e53715c5215f772d988d91ac475a6150d..0000000000000000000000000000000000000000 --- a/dev/tests/functional/tests/app/Magento/Authorizenet/Test/Block/Form/Cc.php +++ /dev/null @@ -1,18 +0,0 @@ -<?php -/** - * Copyright © 2016 Magento. All rights reserved. - * See COPYING.txt for license details. - */ - -namespace Magento\Authorizenet\Test\Block\Form; - -use Magento\Payment\Test\Block\Form\Cc as CreditCard; - -/** - * Class Cc - * Form for filling credit card data for Authorize.Net payment method - */ -class Cc extends CreditCard -{ - // -} diff --git a/dev/tests/functional/tests/app/Magento/Authorizenet/Test/Block/Form/Cc.xml b/dev/tests/functional/tests/app/Magento/Authorizenet/Test/Block/Form/Cc.xml deleted file mode 100755 index a7d2ae40b89c527f1d6bd5bcc1b55a9c0a8a4f03..0000000000000000000000000000000000000000 --- a/dev/tests/functional/tests/app/Magento/Authorizenet/Test/Block/Form/Cc.xml +++ /dev/null @@ -1,20 +0,0 @@ -<?xml version="1.0" ?> -<!-- -/** - * Copyright © 2016 Magento. All rights reserved. - * See COPYING.txt for license details. - */ ---> -<mapping strict="0"> - <wrapper>payment</wrapper> - <fields> - <cc_number /> - <cc_exp_month> - <input>select</input> - </cc_exp_month> - <cc_exp_year> - <input>select</input> - </cc_exp_year> - <cc_cid /> - </fields> -</mapping> diff --git a/dev/tests/functional/tests/app/Magento/Authorizenet/Test/Fixture/CreditCardAuthorizenet.xml b/dev/tests/functional/tests/app/Magento/Authorizenet/Test/Fixture/CreditCardAuthorizenet.xml deleted file mode 100644 index 2777d09b4f16336c3b49a68fc6bdb1e47fe1d186..0000000000000000000000000000000000000000 --- a/dev/tests/functional/tests/app/Magento/Authorizenet/Test/Fixture/CreditCardAuthorizenet.xml +++ /dev/null @@ -1,20 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/** - * Copyright © 2016 Magento. All rights reserved. - * See COPYING.txt for license details. - */ - --> -<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/fixture.xsd"> - <fixture name="credit_card_authorizenet" - module="Magento_Authorizenet" - type="virtual" - entity_type="credit_card_authorizenet" - repository_class="Magento\Authorizenet\Test\Repository\CreditCard" - class="Magento\Authorizenet\Test\Fixture\CreditCardAuthorizenet"> - <field name="cc_number" /> - <field name="cc_exp_month" /> - <field name="cc_exp_year" /> - <field name="cc_cid" /> - </fixture> -</config> diff --git a/dev/tests/functional/tests/app/Magento/Authorizenet/Test/TestCase/OnePageCheckoutTest.xml b/dev/tests/functional/tests/app/Magento/Authorizenet/Test/TestCase/OnePageCheckoutTest.xml index d629bcba9e174251a1bc1e4c8fff6cc664911598..d25149f645f056d7f6e47e10706de3a0bc27e831 100644 --- a/dev/tests/functional/tests/app/Magento/Authorizenet/Test/TestCase/OnePageCheckoutTest.xml +++ b/dev/tests/functional/tests/app/Magento/Authorizenet/Test/TestCase/OnePageCheckoutTest.xml @@ -17,9 +17,8 @@ <data name="prices" xsi:type="array"> <item name="grandTotal" xsi:type="string">15.00</item> </data> - <data name="creditCardClass" xsi:type="string">credit_card_authorizenet</data> <data name="payment/method" xsi:type="string">authorizenet_directpost</data> - <data name="creditCard/dataset" xsi:type="string">visa_authorizenet</data> + <data name="creditCard/dataset" xsi:type="string">visa_default</data> <data name="configData" xsi:type="string">authorizenet</data> <data name="status" xsi:type="string">Processing</data> <data name="tag" xsi:type="string">test_type:3rd_party_test, severity:S0</data> diff --git a/dev/tests/functional/tests/app/Magento/Braintree/Test/Block/Form/Cc.php b/dev/tests/functional/tests/app/Magento/Braintree/Test/Block/Form/BraintreeCc.php similarity index 65% rename from dev/tests/functional/tests/app/Magento/Braintree/Test/Block/Form/Cc.php rename to dev/tests/functional/tests/app/Magento/Braintree/Test/Block/Form/BraintreeCc.php index 2179efc0d5bf16c1299fba2439ddf415b3f575f7..60354b0f9ca28ae680039ecef9ce9cd47fd309e1 100644 --- a/dev/tests/functional/tests/app/Magento/Braintree/Test/Block/Form/Cc.php +++ b/dev/tests/functional/tests/app/Magento/Braintree/Test/Block/Form/BraintreeCc.php @@ -9,26 +9,33 @@ namespace Magento\Braintree\Test\Block\Form; use Magento\Mtf\Client\Locator; use Magento\Mtf\Client\Element\SimpleElement; use Magento\Mtf\Fixture\FixtureInterface; -use Magento\Payment\Test\Block\Form\Cc as CreditCard; +use Magento\Mtf\ObjectManager; +use Magento\Payment\Test\Block\Form\PaymentCc; /** - * Class Cc - * Form for filling credit card data for Braintree payment method + * Form for filling credit card data for Braintree payment method. */ -class Cc extends CreditCard +class BraintreeCc extends PaymentCc { /** - * Braintree iFrame locator + * Braintree iFrame locator. * * @var array */ protected $braintreeForm = [ - "credit_card_number" => "#braintree-hosted-field-number", - "credit_card_exp_month" => "#braintree-hosted-field-expirationMonth", - "credit_card_exp_year" => "#braintree-hosted-field-expirationYear", - "cvv" => "#braintree-hosted-field-cvv", + "cc_number" => "#braintree-hosted-field-number", + "cc_exp_month" => "#braintree-hosted-field-expirationMonth", + "cc_exp_year" => "#braintree-hosted-field-expirationYear", + "cc_cid" => "#braintree-hosted-field-cvv", ]; + /** + * Fill Braintree credit card form. + * + * @param FixtureInterface $fixture + * @param SimpleElement|null $element + * @return void + */ public function fill(FixtureInterface $fixture, SimpleElement $element = null) { $mapping = $this->dataMapping($fixture->getData()); @@ -40,7 +47,8 @@ class Cc extends CreditCard return $fieldElement->isVisible() ? true : null; } ); - $this->browser->switchToFrame(new Locator($iframe)); + $iframeLocator = ObjectManager::getInstance()->create(Locator::class, ['value' => $iframe]); + $this->browser->switchToFrame($iframeLocator); $element = $this->browser->find('body'); $this->browser->waitUntil( function () use ($element) { diff --git a/dev/tests/functional/tests/app/Magento/Braintree/Test/Block/Form/Cc.xml b/dev/tests/functional/tests/app/Magento/Braintree/Test/Block/Form/BraintreeCc.xml similarity index 63% rename from dev/tests/functional/tests/app/Magento/Braintree/Test/Block/Form/Cc.xml rename to dev/tests/functional/tests/app/Magento/Braintree/Test/Block/Form/BraintreeCc.xml index 6ea1ba9ee6e15ffe8d86aea81f8dc46aa5abc79d..d1d09ec7b1dd70bfa6413afe00bfff4ae95d735e 100644 --- a/dev/tests/functional/tests/app/Magento/Braintree/Test/Block/Form/Cc.xml +++ b/dev/tests/functional/tests/app/Magento/Braintree/Test/Block/Form/BraintreeCc.xml @@ -7,17 +7,17 @@ --> <mapping strict="0"> <fields> - <credit_card_number> + <cc_number> <selector>#credit-card-number</selector> - </credit_card_number> - <credit_card_exp_month> + </cc_number> + <cc_exp_month> <selector>#expiration-month</selector> - </credit_card_exp_month> - <credit_card_exp_year> + </cc_exp_month> + <cc_exp_year> <selector>#expiration-year</selector> - </credit_card_exp_year> - <cvv> + </cc_exp_year> + <cc_cid> <selector>#cvv</selector> - </cvv> + </cc_cid> </fields> </mapping> \ No newline at end of file diff --git a/dev/tests/functional/tests/app/Magento/Braintree/Test/Block/Info.php b/dev/tests/functional/tests/app/Magento/Braintree/Test/Block/Info.php deleted file mode 100644 index 32dfb8f40fe87695cbe251048757385dc8310116..0000000000000000000000000000000000000000 --- a/dev/tests/functional/tests/app/Magento/Braintree/Test/Block/Info.php +++ /dev/null @@ -1,38 +0,0 @@ -<?php -/** - * Copyright © 2016 Magento. All rights reserved. - * See COPYING.txt for license details. - */ - -namespace Magento\Braintree\Test\Block; - -use Magento\Mtf\Block\Block; -use Magento\Mtf\Client\Locator; - -/** - * Payment information block. - */ -class Info extends Block -{ - /** - * Braintree Payment information block locator. - */ - private $info = './/tr'; - - /** - * Get Braintree payment information block data. - * - * @return array - */ - public function getPaymentInfo() - { - $result = []; - $elements = $this->_rootElement->getElements($this->info, Locator::SELECTOR_XPATH); - foreach ($elements as $row) { - $key = rtrim($row->find('./th', Locator::SELECTOR_XPATH)->getText(), ':'); - $value = $row->find('./td', Locator::SELECTOR_XPATH)->getText(); - $result[$key] = $value; - } - return $result; - } -} diff --git a/dev/tests/functional/tests/app/Magento/Braintree/Test/Constraint/Assert3dSecureInfoIsPresent.php b/dev/tests/functional/tests/app/Magento/Braintree/Test/Constraint/Assert3dSecureInfoIsPresent.php index bb1e0670231574d4e6c53eaf483e419e0ecab0ae..29af7632f7fd748a82e359164c80098c0fd59941 100644 --- a/dev/tests/functional/tests/app/Magento/Braintree/Test/Constraint/Assert3dSecureInfoIsPresent.php +++ b/dev/tests/functional/tests/app/Magento/Braintree/Test/Constraint/Assert3dSecureInfoIsPresent.php @@ -6,13 +6,16 @@ namespace Magento\Braintree\Test\Constraint; -use Magento\Sales\Test\Page\Adminhtml\SalesOrderView; use Magento\Mtf\Constraint\AbstractConstraint; +use Magento\Sales\Test\Page\Adminhtml\SalesOrderView; +/** + * Assert that 3D Secure information is present on order page in Admin. + */ class Assert3dSecureInfoIsPresent extends AbstractConstraint { /** - * Assert that 3D Secure information is present on order page in Admin. + * Assert that 3D Secure information is present on order page in Admin. * * @param SalesOrderView $salesOrderView * @param array $paymentInformation @@ -20,7 +23,9 @@ class Assert3dSecureInfoIsPresent extends AbstractConstraint */ public function processAssert(SalesOrderView $salesOrderView, array $paymentInformation) { - $actualPaymentInformation = $salesOrderView->getBraintreeInfoBlock()->getPaymentInfo(); + /** @var \Magento\Sales\Test\Block\Adminhtml\Order\View\Tab\Info $infoTab */ + $infoTab = $salesOrderView->getOrderForm()->openTab('info')->getTab('info'); + $actualPaymentInformation = $infoTab->getPaymentInfoBlock()->getData(); foreach ($paymentInformation as $key => $value) { \PHPUnit_Framework_Assert::assertArrayHasKey( $key, diff --git a/dev/tests/functional/tests/app/Magento/Braintree/Test/Fixture/CreditCardBraintree.xml b/dev/tests/functional/tests/app/Magento/Braintree/Test/Fixture/CreditCardBraintree.xml deleted file mode 100644 index e9baa301509ce6212e0374dd26c8442157cb6cbf..0000000000000000000000000000000000000000 --- a/dev/tests/functional/tests/app/Magento/Braintree/Test/Fixture/CreditCardBraintree.xml +++ /dev/null @@ -1,20 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/** - * Copyright © 2016 Magento. All rights reserved. - * See COPYING.txt for license details. - */ - --> -<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/fixture.xsd"> - <fixture name="credit_card_braintree" - module="Magento_Braintree" - type="virtual" - entity_type="credit_card_braintree" - repository_class="Magento\Braintree\Test\Repository\CreditCard" - class="Magento\Braintree\Test\Fixture\CreditCardBraintree"> - <field name="credit_card_number" /> - <field name="credit_card_exp_month" /> - <field name="credit_card_exp_year" /> - <field name="cvv" /> - </fixture> -</config> diff --git a/dev/tests/functional/tests/app/Magento/Braintree/Test/Page/Adminhtml/SalesOrderView.xml b/dev/tests/functional/tests/app/Magento/Braintree/Test/Page/Adminhtml/SalesOrderView.xml deleted file mode 100644 index be96e88c35f81a40cc384d4fb137effe58261e53..0000000000000000000000000000000000000000 --- a/dev/tests/functional/tests/app/Magento/Braintree/Test/Page/Adminhtml/SalesOrderView.xml +++ /dev/null @@ -1,12 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/** - * Copyright © 2016 Magento. All rights reserved. - * See COPYING.txt for license details. - */ - --> -<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../vendor/magento/mtf/etc/pages.xsd"> - <page name="SalesOrderView" area="Adminhtml" mca="sales/order/view" module="Magento_Sales"> - <block name="BraintreeInfoBlock" class="Magento\Braintree\Test\Block\Info" locator="//div[contains(@class, 'admin__page-section-item order-payment-method')]" strategy="xpath"/> - </page> -</config> diff --git a/dev/tests/functional/tests/app/Magento/Braintree/Test/Repository/ConfigData.xml b/dev/tests/functional/tests/app/Magento/Braintree/Test/Repository/ConfigData.xml index 7f01e4f46106c020c10457a8f3e0fb0a7f1de8d7..268ce5795221dbbe3f545891c4d2e420bc87440e 100644 --- a/dev/tests/functional/tests/app/Magento/Braintree/Test/Repository/ConfigData.xml +++ b/dev/tests/functional/tests/app/Magento/Braintree/Test/Repository/ConfigData.xml @@ -11,26 +11,26 @@ <field name="payment/braintree_section/braintree/braintree_required/merchant_id" xsi:type="array"> <item name="scope" xsi:type="string">payment</item> <item name="scope_id" xsi:type="number">1</item> - <item name="label" xsi:type="string">PAYMENT_BRAINTREE_MERCHANT_ID</item> - <item name="value" xsi:type="string">PAYMENT_BRAINTREE_MERCHANT_ID</item> + <item name="label" xsi:type="string">Merchant ID</item> + <item name="value" xsi:type="string">%braintree_disabled_fraud_merchant_id%</item> </field> <field name="payment/braintree_section/braintree/braintree_required/public_key" xsi:type="array"> <item name="scope" xsi:type="string">payment</item> <item name="scope_id" xsi:type="number">1</item> - <item name="label" xsi:type="string">PAYMENT_PAYMENT_BRAINTREE_PUBLIC_KEY</item> - <item name="value" xsi:type="string">PAYMENT_PAYMENT_BRAINTREE_PUBLIC_KEY</item> + <item name="label" xsi:type="string">Public Key</item> + <item name="value" xsi:type="string">%braintree_disabled_fraud_public_key%</item> </field> <field name="payment/braintree_section/braintree/braintree_required/private_key" xsi:type="array"> <item name="scope" xsi:type="string">payment</item> <item name="scope_id" xsi:type="number">1</item> - <item name="label" xsi:type="string">PAYMENT_BRAINTREE_PRIVATE_KEY</item> - <item name="value" xsi:type="string">PAYMENT_BRAINTREE_PRIVATE_KEY</item> + <item name="label" xsi:type="string">Private Key</item> + <item name="value" xsi:type="string">%braintree_disabled_fraud_private_key%</item> </field> <field name="payment/braintree_section/braintree/braintree_advanced/merchant_account_id" xsi:type="array"> <item name="scope" xsi:type="string">payment</item> <item name="scope_id" xsi:type="number">1</item> - <item name="label" xsi:type="string">PAYMENT_BRAINTREE_MERCHANT_ACCOUNT_ID</item> - <item name="value" xsi:type="string">PAYMENT_BRAINTREE_MERCHANT_ACCOUNT_ID</item> + <item name="label" xsi:type="string">Merchant Account ID</item> + <item name="value" xsi:type="string">%braintree_disabled_fraud_merchant_account_id%</item> </field> <field name="payment/braintree_section/braintree/braintree_required/payment_action" xsi:type="array"> <item name="scope" xsi:type="string">payment</item> @@ -51,6 +51,7 @@ <item name="value" xsi:type="number">1</item> </field> </dataset> + <dataset name="braintree_rollback"> <field name="payment/braintree/active" xsi:type="array"> <item name="scope" xsi:type="string">payment</item> @@ -59,6 +60,16 @@ <item name="value" xsi:type="number">0</item> </field> </dataset> + + <dataset name="braintree_incorrect_merchant_account_id"> + <field name="payment/braintree_section/braintree/braintree_advanced/merchant_account_id" xsi:type="array"> + <item name="scope" xsi:type="string">payment</item> + <item name="scope_id" xsi:type="number">1</item> + <item name="label" xsi:type="string">Merchant Account ID</item> + <item name="value" xsi:type="string">incorrect</item> + </field> + </dataset> + <dataset name="braintree_sale"> <field name="payment/braintree/payment_action" xsi:type="array"> <item name="scope" xsi:type="string">payment</item> @@ -67,6 +78,7 @@ <item name="value" xsi:type="string">authorize_capture</item> </field> </dataset> + <dataset name="braintree_3d_secure"> <field name="payment/braintree_section/braintree/braintree_3dsecure/verify_3dsecure" xsi:type="array"> <item name="scope" xsi:type="string">payment</item> @@ -75,6 +87,7 @@ <item name="value" xsi:type="number">1</item> </field> </dataset> + <dataset name="braintree_3d_secure_rollback"> <field name="payment/braintree_section/braintree/braintree_3dsecure/verify_3dsecure" xsi:type="array"> <item name="scope" xsi:type="string">payment</item> @@ -83,6 +96,7 @@ <item name="value" xsi:type="number">0</item> </field> </dataset> + <dataset name="braintree_3d_secure_uk"> <field name="payment/braintree/verify_3dsecure" xsi:type="array"> <item name="scope" xsi:type="string">payment</item> @@ -107,6 +121,7 @@ </item> </field> </dataset> + <dataset name="braintree_3d_secure_uk_rollback"> <field name="payment/braintree_section/braintree/braintree_3dsecure/verify_3dsecure" xsi:type="array"> <item name="scope" xsi:type="string">payment</item> @@ -121,6 +136,7 @@ <item name="value" xsi:type="number">0</item> </field> </dataset> + <dataset name="braintree_3d_secure_not_triggered_due_threshold"> <field name="payment/braintree/verify_3dsecure" xsi:type="array"> <item name="scope" xsi:type="string">payment</item> @@ -135,6 +151,7 @@ <item name="value" xsi:type="number">300</item> </field> </dataset> + <dataset name="braintree_3d_secure_not_triggered_due_threshold_rollback"> <field name="payment/braintree/verify_3dsecure" xsi:type="array"> <item name="scope" xsi:type="string">payment</item> @@ -143,6 +160,7 @@ <item name="value" xsi:type="number">0</item> </field> </dataset> + <dataset name="braintree_use_vault"> <field name="payment/braintree_section/braintree/braintree_cc_vault_active" xsi:type="array"> <item name="scope" xsi:type="string">payment</item> @@ -151,6 +169,7 @@ <item name="value" xsi:type="number">1</item> </field> </dataset> + <dataset name="braintree_use_vault_rollback"> <field name="payment/braintree_section/braintree/braintree_cc_vault_active" xsi:type="array"> <item name="scope" xsi:type="string">payment</item> @@ -159,6 +178,7 @@ <item name="value" xsi:type="number">0</item> </field> </dataset> + <dataset name="braintree_paypal"> <field name="payment/braintree_section/braintree/active_braintree_paypal" xsi:type="array"> <item name="scope" xsi:type="string">payment</item> @@ -173,6 +193,7 @@ <item name="value" xsi:type="string">authorize</item> </field> </dataset> + <dataset name="braintree_paypal_rollback"> <field name="payment/braintree_section/braintree/active_braintree_paypal" xsi:type="array"> <item name="scope" xsi:type="string">payment</item> @@ -181,7 +202,14 @@ <item name="value" xsi:type="number">0</item> </field> </dataset> + <dataset name="braintree_paypal_sale"> + <field name="payment/braintree_section/braintree/active_braintree_paypal" xsi:type="array"> + <item name="scope" xsi:type="string">payment</item> + <item name="scope_id" xsi:type="number">1</item> + <item name="label" xsi:type="string">Yes</item> + <item name="value" xsi:type="number">1</item> + </field> <field name="payment/braintree_section/braintree/braintree_paypal/payment_action" xsi:type="array"> <item name="scope" xsi:type="string">payment</item> <item name="scope_id" xsi:type="number">1</item> @@ -189,6 +217,16 @@ <item name="value" xsi:type="string">authorize_capture</item> </field> </dataset> + + <dataset name="braintree_paypal_sale_rollback"> + <field name="payment/braintree_section/braintree/active_braintree_paypal" xsi:type="array"> + <item name="scope" xsi:type="string">payment</item> + <item name="scope_id" xsi:type="number">1</item> + <item name="label" xsi:type="string">No</item> + <item name="value" xsi:type="number">0</item> + </field> + </dataset> + <dataset name="braintree_paypal_skip_order_review"> <field name="payment/braintree_section/braintree/braintree_paypal/skip_order_review" xsi:type="array"> <item name="scope" xsi:type="string">payment</item> @@ -197,6 +235,7 @@ <item name="value" xsi:type="number">1</item> </field> </dataset> + <dataset name="braintree_paypal_skip_order_review_rollback"> <field name="payment/braintree_section/braintree/braintree_paypal/skip_order_review" xsi:type="array"> <item name="scope" xsi:type="string">payment</item> @@ -205,6 +244,7 @@ <item name="value" xsi:type="number">0</item> </field> </dataset> + <dataset name="braintree_paypal_use_vault"> <field name="payment/braintree_section/braintree/braintree_paypal/braintree_paypal_vault_active" xsi:type="array"> <item name="scope" xsi:type="string">payment</item> @@ -213,6 +253,7 @@ <item name="value" xsi:type="number">1</item> </field> </dataset> + <dataset name="braintree_paypal_use_vault_rollback"> <field name="payment/braintree_section/braintree/braintree_paypal/braintree_paypal_vault_active" xsi:type="array"> <item name="scope" xsi:type="string">payment</item> @@ -221,6 +262,7 @@ <item name="value" xsi:type="number">0</item> </field> </dataset> + <dataset name="braintree_fraudprotection"> <field name="payment/braintree/fraudprotection" xsi:type="array"> <item name="scope" xsi:type="string">payment</item> @@ -229,6 +271,7 @@ <item name="value" xsi:type="number">1</item> </field> </dataset> + <dataset name="braintree_fraudprotection_rollback"> <field name="payment/braintree/fraudprotection" xsi:type="array"> <item name="scope" xsi:type="string">payment</item> @@ -237,5 +280,59 @@ <item name="value" xsi:type="number">0</item> </field> </dataset> + + <dataset name="braintree_fraud_tool_enabled_account"> + <field name="payment/braintree_section/braintree/braintree_required/merchant_id" xsi:type="array"> + <item name="scope" xsi:type="string">payment</item> + <item name="scope_id" xsi:type="number">1</item> + <item name="label" xsi:type="string">Merchant ID</item> + <item name="value" xsi:type="string">%braintree_enabled_fraud_merchant_id%</item> + </field> + <field name="payment/braintree_section/braintree/braintree_required/public_key" xsi:type="array"> + <item name="scope" xsi:type="string">payment</item> + <item name="scope_id" xsi:type="number">1</item> + <item name="label" xsi:type="string">Public Key</item> + <item name="value" xsi:type="string">%braintree_enabled_fraud_public_key%</item> + </field> + <field name="payment/braintree_section/braintree/braintree_required/private_key" xsi:type="array"> + <item name="scope" xsi:type="string">payment</item> + <item name="scope_id" xsi:type="number">1</item> + <item name="label" xsi:type="string">Private Key</item> + <item name="value" xsi:type="string">%braintree_enabled_fraud_private_key%</item> + </field> + <field name="payment/braintree_section/braintree/braintree_advanced/merchant_account_id" xsi:type="array"> + <item name="scope" xsi:type="string">payment</item> + <item name="scope_id" xsi:type="number">1</item> + <item name="label" xsi:type="string">Merchant Account ID</item> + <item name="value" xsi:type="string">%braintree_enabled_fraud_merchant_account_id%</item> + </field> + <field name="payment/braintree_section/braintree/braintree_required/payment_action" xsi:type="array"> + <item name="scope" xsi:type="string">payment</item> + <item name="scope_id" xsi:type="number">1</item> + <item name="label" xsi:type="string">Authorize</item> + <item name="value" xsi:type="string">authorize</item> + </field> + <field name="payment/braintree_section/braintree/braintree_advanced/debug" xsi:type="array"> + <item name="scope" xsi:type="string">payment</item> + <item name="scope_id" xsi:type="number">1</item> + <item name="label" xsi:type="string">Yes</item> + <item name="value" xsi:type="number">1</item> + </field> + <field name="payment/braintree_section/braintree/active" xsi:type="array"> + <item name="scope" xsi:type="string">payment</item> + <item name="scope_id" xsi:type="number">1</item> + <item name="label" xsi:type="string">Yes</item> + <item name="value" xsi:type="number">1</item> + </field> + </dataset> + + <dataset name="braintree_fraud_tool_enabled_account_rollback"> + <field name="payment/braintree/active" xsi:type="array"> + <item name="scope" xsi:type="string">payment</item> + <item name="scope_id" xsi:type="number">1</item> + <item name="label" xsi:type="string">No</item> + <item name="value" xsi:type="number">0</item> + </field> + </dataset> </repository> </config> diff --git a/dev/tests/functional/tests/app/Magento/Braintree/Test/Repository/CreditCard.xml b/dev/tests/functional/tests/app/Magento/Braintree/Test/Repository/CreditCard.xml index e750aa9cb423444e2cc17b8e269a7a62b9289f20..e780ece1ab971ef3edeb89fed253db6b1cd93a8c 100644 --- a/dev/tests/functional/tests/app/Magento/Braintree/Test/Repository/CreditCard.xml +++ b/dev/tests/functional/tests/app/Magento/Braintree/Test/Repository/CreditCard.xml @@ -6,24 +6,29 @@ */ --> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/Magento/Mtf/Repository/etc/repository.xsd"> - <repository class="Magento\Braintree\Test\Repository\CreditCard"> - <dataset name="visa_braintree"> - <field name="credit_card_number" xsi:type="string">4111111111111111</field> - <field name="credit_card_exp_month" xsi:type="string">01</field> - <field name="credit_card_exp_year" xsi:type="string">2020</field> - <field name="cvv" xsi:type="string">123</field> - </dataset> + <repository class="Magento\Payment\Test\Repository\CreditCard"> <dataset name="visa_braintree_3dsecure"> - <field name="credit_card_number" xsi:type="string">4000000000000002</field> - <field name="credit_card_exp_month" xsi:type="string">01</field> - <field name="credit_card_exp_year" xsi:type="string">20</field> - <field name="cvv" xsi:type="string">123</field> + <field name="payment_code" xsi:type="string">braintree</field> + <field name="cc_number" xsi:type="string">4000000000000002</field> + <field name="cc_exp_month" xsi:type="string">01</field> + <field name="cc_exp_year" xsi:type="string">20</field> + <field name="cc_cid" xsi:type="string">123</field> </dataset> + <dataset name="visa_braintree_3dsecure_failed"> - <field name="credit_card_number" xsi:type="string">4000000000000028</field> - <field name="credit_card_exp_month" xsi:type="string">01</field> - <field name="credit_card_exp_year" xsi:type="string">2020</field> - <field name="cvv" xsi:type="string">123</field> + <field name="payment_code" xsi:type="string">braintree</field> + <field name="cc_number" xsi:type="string">4000000000000028</field> + <field name="cc_exp_month" xsi:type="string">01</field> + <field name="cc_exp_year" xsi:type="string">2020</field> + <field name="cc_cid" xsi:type="string">123</field> + </dataset> + + <dataset name="visa_braintree_fraud_rejected"> + <field name="payment_code" xsi:type="string">braintree</field> + <field name="cc_number" xsi:type="string">4000111111111511</field> + <field name="cc_exp_month" xsi:type="string">01</field> + <field name="cc_exp_year" xsi:type="string">2020</field> + <field name="cc_cid" xsi:type="string">123</field> </dataset> </repository> </config> diff --git a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/BraintreeSettlementReportTest.xml b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/BraintreeSettlementReportTest.xml index e80f6071ae5d1d33b37bb7c26c7389ed08aa8962..dba818e57659d86757a11c213c70e314ead2b0c7 100644 --- a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/BraintreeSettlementReportTest.xml +++ b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/BraintreeSettlementReportTest.xml @@ -18,8 +18,8 @@ <item name="grandTotal" xsi:type="string">15.00</item> </data> <data name="payment/method" xsi:type="string">braintree</data> - <data name="creditCardClass" xsi:type="string">credit_card_braintree</data> - <data name="creditCard/dataset" xsi:type="string">visa_braintree</data> + <data name="creditCard/dataset" xsi:type="string">visa_default</data> + <data name="creditCard/data/payment_code" xsi:type="string">braintree</data> <data name="configData" xsi:type="string">braintree</data> <data name="status" xsi:type="string">Processing</data> <data name="tag" xsi:type="string">test_type:extended_acceptance_test, test_type:3rd_party_test, severity:S1</data> diff --git a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/CreateOnlineCreditMemoBraintreePaypalTest.xml b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/CreateOnlineCreditMemoBraintreePaypalTest.xml index 53847e55fd9f91e29fbeeb6c71a0402a1fb6a6f6..2f14871eda96e102a51ed4ceefd4578af49967b8 100644 --- a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/CreateOnlineCreditMemoBraintreePaypalTest.xml +++ b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/CreateOnlineCreditMemoBraintreePaypalTest.xml @@ -14,7 +14,7 @@ <data name="checkoutMethod" xsi:type="string">login</data> <data name="taxRule" xsi:type="string">us_ca_ny_rule</data> <data name="refundedPrices" xsi:type="array"> - <item name="0" xsi:type="string">139.9</item> + <item name="0" xsi:type="string">139.90</item> </data> <data name="shippingAddress/dataset" xsi:type="string">US_address_1_without_email</data> <data name="shipping/shipping_service" xsi:type="string">Flat Rate</data> @@ -34,7 +34,7 @@ <data name="checkoutMethod" xsi:type="string">login</data> <data name="taxRule" xsi:type="string">us_ca_ny_rule</data> <data name="refundedPrices" xsi:type="array"> - <item name="0" xsi:type="string">621.2</item> + <item name="0" xsi:type="string">621.20</item> </data> <data name="shippingAddress/dataset" xsi:type="string">US_address_1_without_email</data> <data name="shipping/shipping_service" xsi:type="string">Flat Rate</data> diff --git a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/CreateOnlineInvoiceEntityTest.xml b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/CreateOnlineInvoiceEntityTest.xml index d9f382e4b650e5ce48955e264c67b36c893dbb84..da73da001338ade7fdd655609ff4b04d0f8602db 100644 --- a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/CreateOnlineInvoiceEntityTest.xml +++ b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/CreateOnlineInvoiceEntityTest.xml @@ -18,11 +18,11 @@ <data name="shipping/shipping_service" xsi:type="string">Flat Rate</data> <data name="shipping/shipping_method" xsi:type="string">Fixed</data> <data name="capturedPrices" xsi:type="array"> - <item name="0" xsi:type="string">139.9</item> + <item name="0" xsi:type="string">139.90</item> </data> <data name="payment/method" xsi:type="string">braintree</data> - <data name="creditCardClass" xsi:type="string">credit_card_braintree</data> - <data name="creditCard/dataset" xsi:type="string">visa_braintree</data> + <data name="creditCard/dataset" xsi:type="string">visa_default</data> + <data name="creditCard/data/payment_code" xsi:type="string">braintree</data> <data name="configData" xsi:type="string">braintree</data> <data name="status" xsi:type="string">Processing</data> <data name="orderButtonsAvailable" xsi:type="string">Back, Send Email, Credit Memo, Hold, Ship, Reorder</data> @@ -50,8 +50,8 @@ <item name="1" xsi:type="string">118.25</item> </data> <data name="payment/method" xsi:type="string">braintree</data> - <data name="creditCardClass" xsi:type="string">credit_card_braintree</data> - <data name="creditCard/dataset" xsi:type="string">visa_braintree</data> + <data name="creditCard/dataset" xsi:type="string">visa_default</data> + <data name="creditCard/data/payment_code" xsi:type="string">braintree</data> <data name="configData" xsi:type="string">braintree</data> <data name="status" xsi:type="string">Processing</data> <data name="orderButtonsAvailable" xsi:type="string">Back, Send Email, Credit Memo, Hold, Ship, Reorder</data> diff --git a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/CreateOrderBackendTest.xml b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/CreateOrderBackendTest.xml index 9614923691c6c097702c3a222bfc52edfcd2489a..7e010fc4d1f0d31a9e735386ab36a47a5828d6da 100644 --- a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/CreateOrderBackendTest.xml +++ b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/CreateOrderBackendTest.xml @@ -22,8 +22,8 @@ <item name="grandTotal" xsi:type="string">145.98</item> </data> <data name="payment/method" xsi:type="string">braintree</data> - <data name="creditCardClass" xsi:type="string">credit_card_braintree</data> - <data name="creditCard/dataset" xsi:type="string">visa_braintree</data> + <data name="creditCard/dataset" xsi:type="string">visa_default</data> + <data name="creditCard/data/payment_code" xsi:type="string">braintree</data> <data name="configData" xsi:type="string">braintree</data> <data name="status" xsi:type="string">Processing</data> <data name="orderButtonsAvailable" xsi:type="string">Back, Cancel, Send Email, Hold, Invoice, Ship, Reorder, Edit</data> @@ -52,8 +52,8 @@ <item name="0" xsi:type="string">145.98</item> </data> <data name="payment/method" xsi:type="string">braintree</data> - <data name="creditCardClass" xsi:type="string">credit_card_braintree</data> - <data name="creditCard/dataset" xsi:type="string">visa_braintree</data> + <data name="creditCard/dataset" xsi:type="string">visa_default</data> + <data name="creditCard/data/payment_code" xsi:type="string">braintree</data> <data name="configData" xsi:type="string">braintree, braintree_sale</data> <data name="status" xsi:type="string">Processing</data> <data name="orderButtonsAvailable" xsi:type="string">Back, Send Email, Hold, Ship, Reorder</data> @@ -64,5 +64,27 @@ <constraint name="Magento\Sales\Test\Constraint\AssertCaptureInCommentsHistory" /> <constraint name="Magento\Sales\Test\Constraint\AssertOrderInOrdersGridOnFrontend" /> </variation> + <variation name="CreateOrderBackendTestBraintreeVariation3" summary="Checkout with Braintree Credit Card from Admin (Basic Fraud Protection)" ticketId="MAGETWO-46470"> + <data name="tag" xsi:type="string">test_type:3rd_party_test, severity:S0</data> + <data name="products/0" xsi:type="string">catalogProductSimple::product_10_dollar</data> + <data name="products/1" xsi:type="string">configurableProduct::with_one_option</data> + <data name="products/2" xsi:type="string">bundleProduct::bundle_fixed_100_dollar_product</data> + <data name="customer/dataset" xsi:type="string">default</data> + <data name="taxRule" xsi:type="string">us_ca_ny_rule</data> + <data name="billingAddress/dataset" xsi:type="string">US_address_1_without_email</data> + <data name="saveAddress" xsi:type="string">No</data> + <data name="shipping/shipping_service" xsi:type="string">Flat Rate</data> + <data name="shipping/shipping_method" xsi:type="string">Fixed</data> + <data name="prices" xsi:type="array"> + <item name="grandTotal" xsi:type="string">145.98</item> + </data> + <data name="payment/method" xsi:type="string">braintree</data> + <data name="creditCard/dataset" xsi:type="string">visa_braintree_fraud_rejected</data> + <data name="configData" xsi:type="string">braintree</data> + <data name="status" xsi:type="string">Processing</data> + <constraint name="Magento\Sales\Test\Constraint\AssertOrderSuccessCreateMessage" /> + <constraint name="Magento\Sales\Test\Constraint\AssertOrderStatusIsCorrect" /> + <constraint name="Magento\Sales\Test\Constraint\AssertOrderInOrdersGridOnFrontend" /> + </variation> </testCase> </config> diff --git a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/CreateVaultOrderBackendTest.xml b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/CreateVaultOrderBackendTest.xml index c9b26df050cfc9cf9ef4913a4f538459cee1923f..123a453a921d648fa3a5e2d579904d3373c5e1db 100644 --- a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/CreateVaultOrderBackendTest.xml +++ b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/CreateVaultOrderBackendTest.xml @@ -20,8 +20,8 @@ </data> <data name="payment/method" xsi:type="string">braintree</data> <data name="vault/method" xsi:type="string">braintree_cc_vault</data> - <data name="creditCardClass" xsi:type="string">credit_card_braintree</data> - <data name="creditCard/dataset" xsi:type="string">visa_braintree</data> + <data name="creditCard/dataset" xsi:type="string">visa_default</data> + <data name="creditCard/data/payment_code" xsi:type="string">braintree</data> <data name="creditCardSave" xsi:type="string">Yes</data> <data name="configData" xsi:type="string">braintree, braintree_use_vault</data> <data name="status" xsi:type="string">Processing</data> diff --git a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/InvoicePayPalBraintreeTest.php b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/InvoicePayPalBraintreeTest.php index 062de338d8921e15b786de0fd4b656e824354d80..ca5fbe8799d5144a2a9e68e7b8fbca4530c26790 100644 --- a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/InvoicePayPalBraintreeTest.php +++ b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/InvoicePayPalBraintreeTest.php @@ -33,7 +33,7 @@ class InvoicePayPalBraintreeTest extends Scenario /* end tags */ /** - * Runs one page checkout test. + * Create invoice for order placed within Braintree PayPal. * * @return void */ diff --git a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/InvoicePaypalBraintreeTest.xml b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/InvoicePaypalBraintreeTest.xml index 352e0ed684919a43df66b429d5b8250d90cae351..1d98e2d792a3e75fd815fe78149e43100aad12ae 100644 --- a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/InvoicePaypalBraintreeTest.xml +++ b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/InvoicePaypalBraintreeTest.xml @@ -15,10 +15,10 @@ <data name="shipping/shipping_service" xsi:type="string">Flat Rate</data> <data name="shipping/shipping_method" xsi:type="string">Fixed</data> <data name="prices" xsi:type="array"> - <item name="grandTotal" xsi:type="string">139.9</item> + <item name="grandTotal" xsi:type="string">139.90</item> </data> <data name="capturedPrices" xsi:type="array"> - <item name="0" xsi:type="string">139.9</item> + <item name="0" xsi:type="string">139.90</item> </data> <data name="payment/method" xsi:type="string">braintree_paypal</data> <data name="configData" xsi:type="string">braintree, braintree_paypal, braintree_paypal_skip_order_review</data> @@ -31,7 +31,7 @@ <constraint name="Magento\Sales\Test\Constraint\AssertOrderButtonsAvailable" /> <constraint name="Magento\Sales\Test\Constraint\AssertInvoiceItems" /> </variation> - <variation name="InvoicePayPalBraintreeTestVariation2" summary="Partial capture for order placed within Braintree PayPal" ticketId="MAGETWO-48615"> + <variation name="InvoicePayPalBraintreeTestVariation2" summary="Partial capture for order placed within Braintree PayPal" ticketId="MAGETWO-48615, MAGETWO-48684"> <data name="description" xsi:type="string">Partial capture for order placed within Braintree PayPal</data> <data name="products/0" xsi:type="string">catalogProductSimple::product_100_dollar</data> <data name="taxRule" xsi:type="string">us_illinois_tax_rule</data> @@ -43,7 +43,6 @@ </data> <data name="capturedPrices" xsi:type="array"> <item name="0" xsi:type="string">118.25</item> - <item name="1" xsi:type="string">108.25</item> </data> <data name="payment/method" xsi:type="string">braintree_paypal</data> <data name="configData" xsi:type="string">braintree, braintree_paypal, braintree_paypal_skip_order_review</data> @@ -51,10 +50,18 @@ <data name="data/items_data/0/qty" xsi:type="string">1</data> <data name="data/form_data/do_shipment" xsi:type="string">No</data> <data name="data/form_data/comment_text" xsi:type="string">comments</data> - <data name="tag" xsi:type="string">test_type:3rd_party_test, severity:S1</data> + <data name="status" xsi:type="string">Processing</data> + <data name="transactions/Capture" xsi:type="array"> + <item name="transactionType" xsi:type="string">Capture</item> + <item name="statusIsClosed" xsi:type="string">No</item> + </data> + <data name="tag" xsi:type="string">test_type:3rd_party_test, severity:S0</data> <constraint name="Magento\Sales\Test\Constraint\AssertInvoiceSuccessCreateMessage" /> <constraint name="Magento\Sales\Test\Constraint\AssertOrderButtonsAvailable" /> - <constraint name="Magento\Sales\Test\Constraint\AssertInvoiceItems" /> + <constraint name="Magento\Sales\Test\Constraint\AssertCaptureInCommentsHistory" /> + <constraint name="Magento\Sales\Test\Constraint\AssertOrderStatusIsCorrect" /> + <constraint name="Magento\Sales\Test\Constraint\AssertInvoiceInInvoicesGrid" /> + <constraint name="Magento\Sales\Test\Constraint\AssertTransactionStatus" /> </variation> </testCase> </config> diff --git a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/OnePageCheckoutAcceptPaymentTest.xml b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/OnePageCheckoutAcceptPaymentTest.xml index 841145d7a5fdfaa92f1a82ac00c9bf51f0601643..1b9540c443650216b2288dedab699f292f20aa77 100644 --- a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/OnePageCheckoutAcceptPaymentTest.xml +++ b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/OnePageCheckoutAcceptPaymentTest.xml @@ -17,8 +17,8 @@ <data name="shipping/shipping_service" xsi:type="string">Flat Rate</data> <data name="shipping/shipping_method" xsi:type="string">Fixed</data> <data name="payment/method" xsi:type="string">braintree</data> - <data name="creditCardClass" xsi:type="string">credit_card_braintree</data> - <data name="creditCard/dataset" xsi:type="string">visa_braintree</data> + <data name="creditCard/dataset" xsi:type="string">visa_default</data> + <data name="creditCard/data/payment_code" xsi:type="string">braintree</data> <data name="configData" xsi:type="string">braintree,braintree_fraudprotection</data> <data name="status" xsi:type="string">Processing</data> <data name="tag" xsi:type="string">test_type:3rd_party_test, severity:S2</data> diff --git a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/OnePageCheckoutDeclinedTest.xml b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/OnePageCheckoutDeclinedTest.xml new file mode 100644 index 0000000000000000000000000000000000000000..510d27d324f928e46571708ea457256be5ad93a8 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/OnePageCheckoutDeclinedTest.xml @@ -0,0 +1,42 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + --> +<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd"> + <testCase name="Magento\Checkout\Test\TestCase\OnePageCheckoutDeclinedTest" summary="Error message during OnePageCheckout"> + <variation name="OnePageCheckoutBraintreeDeclinedTestVariation1" summary="Registered Checkout with Braintree Credit Card from Storefront with Advanced Fraud Protection failed" ticketId="MAGETWO-46469"> + <data name="products/0" xsi:type="string">catalogProductSimple::product_10_dollar</data> + <data name="customer/dataset" xsi:type="string">default</data> + <data name="shippingAddress/dataset" xsi:type="string">US_address_1_without_email</data> + <data name="checkoutMethod" xsi:type="string">login</data> + <data name="shipping/shipping_service" xsi:type="string">Flat Rate</data> + <data name="shipping/shipping_method" xsi:type="string">Fixed</data> + <data name="payment/method" xsi:type="string">braintree</data> + <data name="creditCard/dataset" xsi:type="string">visa_braintree_fraud_rejected</data> + <data name="expectedErrorMessage" xsi:type="string">Transaction has been declined. Please try again later.</data> + <data name="configData" xsi:type="string">braintree_fraud_tool_enabled_account, braintree_fraudprotection</data> + <data name="status" xsi:type="string">Processing</data> + <data name="tag" xsi:type="string">test_type:3rd_party_test, severity:S1</data> + <constraint name="Magento\Checkout\Test\Constraint\AssertCheckoutErrorMessage" /> + </variation> + <variation name="OnePageCheckoutBraintreeDeclinedTestVariation2" summary="Checkout with Braintree Credit Card configured with incorrect credentials" ticketId="MAGETWO-46244"> + <data name="products/0" xsi:type="string">catalogProductSimple::product_10_dollar</data> + <data name="customer/dataset" xsi:type="string">default</data> + <data name="shippingAddress/dataset" xsi:type="string">US_address_1</data> + <data name="checkoutMethod" xsi:type="string">guest</data> + <data name="shipping/shipping_service" xsi:type="string">Flat Rate</data> + <data name="shipping/shipping_method" xsi:type="string">Fixed</data> + <data name="payment/method" xsi:type="string">braintree</data> + <data name="creditCard/dataset" xsi:type="string">visa_default</data> + <data name="creditCard/data/payment_code" xsi:type="string">braintree</data> + <data name="expectedErrorMessage" xsi:type="string">Sorry, but something went wrong</data> + <data name="configData" xsi:type="string">braintree, braintree_incorrect_merchant_account_id</data> + <data name="status" xsi:type="string">Processing</data> + <data name="tag" xsi:type="string">test_type:3rd_party_test, severity:S1</data> + <constraint name="Magento\Checkout\Test\Constraint\AssertCheckoutErrorMessage" /> + </variation> + </testCase> +</config> diff --git a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/OnePageCheckoutDenyPaymentTest.xml b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/OnePageCheckoutDenyPaymentTest.xml index 95d07079ef36c9ae66672ec8cc465325273ecda4..8d16fcc3fcae11aa51f45c426406d842804fe936 100644 --- a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/OnePageCheckoutDenyPaymentTest.xml +++ b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/OnePageCheckoutDenyPaymentTest.xml @@ -17,8 +17,8 @@ <data name="shipping/shipping_service" xsi:type="string">Flat Rate</data> <data name="shipping/shipping_method" xsi:type="string">Fixed</data> <data name="payment/method" xsi:type="string">braintree</data> - <data name="creditCardClass" xsi:type="string">credit_card_braintree</data> - <data name="creditCard/dataset" xsi:type="string">visa_braintree</data> + <data name="creditCard/dataset" xsi:type="string">visa_default</data> + <data name="creditCard/data/payment_code" xsi:type="string">braintree</data> <data name="configData" xsi:type="string">braintree,braintree_fraudprotection</data> <data name="status" xsi:type="string">Canceled</data> <data name="tag" xsi:type="string">test_type:3rd_party_test, severity:S2</data> diff --git a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/OnePageCheckoutTest.xml b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/OnePageCheckoutTest.xml index 920047e7037e135115424a192b9c9cb3267982d5..c99a855b236a5ee45f7eba8d604bd3c0db50bb7a 100644 --- a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/OnePageCheckoutTest.xml +++ b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/OnePageCheckoutTest.xml @@ -21,9 +21,8 @@ <item name="grandTotal" xsi:type="string">145.98</item> </data> <data name="payment/method" xsi:type="string">braintree</data> - <data name="creditCardClass" xsi:type="string">credit_card_braintree</data> <data name="creditCard/dataset" xsi:type="string">visa_braintree_3dsecure</data> - <data name="isVaultEnabled" xsi:type="boolean">false</data> + <data name="isVaultPresent" xsi:type="boolean">false</data> <data name="configData" xsi:type="string">braintree, braintree_3d_secure_not_triggered_due_threshold</data> <data name="status" xsi:type="string">Processing</data> <data name="tag" xsi:type="string">test_type:3rd_party_test, severity:S1</data> @@ -45,9 +44,8 @@ <item name="grandTotal" xsi:type="string">145.98</item> </data> <data name="payment/method" xsi:type="string">braintree</data> - <data name="creditCardClass" xsi:type="string">credit_card_braintree</data> <data name="creditCard/dataset" xsi:type="string">visa_braintree_3dsecure</data> - <data name="isVaultEnabled" xsi:type="boolean">false</data> + <data name="isVaultPresent" xsi:type="boolean">false</data> <data name="configData" xsi:type="string">braintree, braintree_3d_secure_uk</data> <data name="status" xsi:type="string">Processing</data> <data name="tag" xsi:type="string">test_type:3rd_party_test, severity:S1</data> @@ -69,9 +67,9 @@ <item name="grandTotal" xsi:type="string">145.98</item> </data> <data name="payment/method" xsi:type="string">braintree</data> - <data name="creditCardClass" xsi:type="string">credit_card_braintree</data> - <data name="creditCard/dataset" xsi:type="string">visa_braintree</data> - <data name="isVaultEnabled" xsi:type="boolean">false</data> + <data name="creditCard/dataset" xsi:type="string">visa_default</data> + <data name="creditCard/data/payment_code" xsi:type="string">braintree</data> + <data name="isVaultPresent" xsi:type="boolean">false</data> <data name="configData" xsi:type="string">braintree</data> <data name="status" xsi:type="string">Processing</data> <data name="tag" xsi:type="string">test_type:extended_acceptance_test, test_type:3rd_party_test, severity:S0</data> @@ -97,9 +95,9 @@ <item name="0" xsi:type="string">145.98</item> </data> <data name="payment/method" xsi:type="string">braintree</data> - <data name="creditCardClass" xsi:type="string">credit_card_braintree</data> - <data name="creditCard/dataset" xsi:type="string">visa_braintree</data> - <data name="isVaultEnabled" xsi:type="boolean">false</data> + <data name="creditCard/dataset" xsi:type="string">visa_default</data> + <data name="creditCard/data/payment_code" xsi:type="string">braintree</data> + <data name="isVaultPresent" xsi:type="boolean">false</data> <data name="configData" xsi:type="string">braintree, braintree_sale</data> <data name="status" xsi:type="string">Processing</data> <data name="tag" xsi:type="string">test_type:3rd_party_test, severity:S0</data> diff --git a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/OnePageCheckoutWith3dSecureFailedTest.php b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/OnePageCheckoutWith3dSecureFailedTest.php new file mode 100644 index 0000000000000000000000000000000000000000..0f21b8f219cb13dd426c1aad3cdb0f6ba24b06a6 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/OnePageCheckoutWith3dSecureFailedTest.php @@ -0,0 +1,49 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Braintree\Test\TestCase; + +use Magento\Mtf\TestCase\Scenario; + +/** + * Preconditions: + * 1. Configure payment method. + * 2. Create products. + * + * Steps: + * 1. Log in Storefront. + * 2. Add products to the Shopping Cart. + * 5. Click the 'Proceed to Checkout' button. + * 6. Fill shipping information. + * 7. Select shipping method. + * 8. Select payment method. + * 9. Verify order total on review step. + * 10. Click 'Place Order' button. + * 11. Specify password in 3D Secure popup. + * 12. Click 'Submit'. + * 13. Perform assertions. + * + * @group Braintree + * @ZephyrId MAGETWO-46477 + */ +class OnePageCheckoutWith3dSecureFailedTest extends Scenario +{ + /* tags */ + const MVP = 'yes'; + const TEST_TYPE = '3rd_party_test'; + const SEVERITY = 'S1'; + /* end tags */ + + /** + * Verifies error message on Onepage Checkout if 3d secure validation is failed. + * + * @return void + */ + public function test() + { + $this->executeScenario(); + } +} diff --git a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/OnePageCheckoutWith3dSecureFailedTest.xml b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/OnePageCheckoutWith3dSecureFailedTest.xml new file mode 100644 index 0000000000000000000000000000000000000000..12cde9b6233a96f0ff94396adf9e42e057af883b --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/OnePageCheckoutWith3dSecureFailedTest.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + --> +<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd"> + <testCase name="Magento\Braintree\Test\TestCase\OnePageCheckoutWith3dSecureFailedTest" summary="Onepage checkout with Braintree payment method with 3D Secure enabled."> + <variation name="OnePageCheckoutBraintree3dSecureFailedTestVariation1" summary="Guest Checkout with Braintree Credit Card from Storefront with 3D Secure verification failed" ticketId="MAGETWO-46477"> + <data name="products/0" xsi:type="string">catalogProductSimple::product_10_dollar</data> + <data name="customer/dataset" xsi:type="string">default</data> + <data name="shippingAddress/dataset" xsi:type="string">US_address_1</data> + <data name="checkoutMethod" xsi:type="string">guest</data> + <data name="shipping/shipping_service" xsi:type="string">Flat Rate</data> + <data name="shipping/shipping_method" xsi:type="string">Fixed</data> + <data name="payment/method" xsi:type="string">braintree</data> + <data name="creditCard/dataset" xsi:type="string">visa_braintree_3dsecure_failed</data> + <data name="secure3d/dataset" xsi:type="string">secure3d_braintree</data> + <data name="configData" xsi:type="string">braintree, braintree_3d_secure</data> + <data name="expectedErrorMessage" xsi:type="string">Please try again with another form of payment.</data> + <data name="status" xsi:type="string">Processing</data> + <data name="tag" xsi:type="string">test_type:3rd_party_test, severity:S1</data> + <constraint name="Magento\Checkout\Test\Constraint\AssertCheckoutErrorMessage" /> + </variation> + </testCase> +</config> diff --git a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/OnePageCheckoutWith3dSecureTest.xml b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/OnePageCheckoutWith3dSecureTest.xml index 295a9dcd5c5332dce7d6e5fad9dfcdc6f5352596..051700480fcb3f49f551190d557f210b3686e719 100644 --- a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/OnePageCheckoutWith3dSecureTest.xml +++ b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/OnePageCheckoutWith3dSecureTest.xml @@ -22,7 +22,6 @@ <item name="grandTotal" xsi:type="string">145.98</item> </data> <data name="payment/method" xsi:type="string">braintree</data> - <data name="creditCardClass" xsi:type="string">credit_card_braintree</data> <data name="creditCard/dataset" xsi:type="string">visa_braintree_3dsecure</data> <data name="paymentInformation" xsi:type="array"> <item name="Liability Shifted" xsi:type="string">1</item> diff --git a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/OnePageCheckoutWithDiscountTest.xml b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/OnePageCheckoutWithDiscountTest.xml index f8ffa51982f1fae4d34a6290e1bebce28ba85712..06299e2e5a10c3ea7658ff3e06c42861820edc13 100644 --- a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/OnePageCheckoutWithDiscountTest.xml +++ b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/OnePageCheckoutWithDiscountTest.xml @@ -17,8 +17,8 @@ <data name="shipping/shipping_service" xsi:type="string">Flat Rate</data> <data name="shipping/shipping_method" xsi:type="string">Fixed</data> <data name="payment/method" xsi:type="string">braintree</data> - <data name="creditCardClass" xsi:type="string">credit_card_braintree</data> - <data name="creditCard/dataset" xsi:type="string">visa_braintree</data> + <data name="creditCard/dataset" xsi:type="string">visa_default</data> + <data name="creditCard/data/payment_code" xsi:type="string">braintree</data> <data name="prices" xsi:type="array"> <item name="grandTotal" xsi:type="string">10.00</item> </data> diff --git a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/ReorderUsingVaultTest.xml b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/ReorderUsingVaultTest.xml index ad4d5cc06e92e260aed4c90e6f534f2540d25034..1b7d248d537dc839ae258f3a1d16040d12f95fd1 100644 --- a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/ReorderUsingVaultTest.xml +++ b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/ReorderUsingVaultTest.xml @@ -7,7 +7,7 @@ --> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd"> <testCase name="Magento\Vault\Test\TestCase\ReorderUsingVaultTest" summary="Reorder from Admin with saved within Braintree credit card"> - <variation name="ReorderUsingVaultBraintreeTestVariation1" summary="Reorder from Admin with saved within Braintree credit card for Guest Customer" ticketId="MAGETWO-54870"> + <variation name="ReorderUsingVaultBraintreeTestVariation1" summary="Reorder from Admin with saved within Braintree credit card for Guest Customer" ticketId="MAGETWO-54869, MAGETWO-54870"> <data name="description" xsi:type="string">Reorder from Admin with saved within Braintree credit card for Guest Customer</data> <data name="products/0" xsi:type="string">catalogProductSimple::product_10_dollar</data> <data name="customer/dataset" xsi:type="string">default</data> @@ -20,8 +20,9 @@ </data> <data name="payment/method" xsi:type="string">braintree</data> <data name="vault/method" xsi:type="string">braintree_cc_vault</data> - <data name="creditCardClass" xsi:type="string">credit_card_braintree</data> - <data name="creditCard/dataset" xsi:type="string">visa_braintree</data> + <data name="isVaultPresent" xsi:type="boolean">false</data> + <data name="creditCard/dataset" xsi:type="string">visa_default</data> + <data name="creditCard/data/payment_code" xsi:type="string">braintree</data> <data name="configData" xsi:type="string">braintree, braintree_use_vault</data> <data name="status" xsi:type="string">Processing</data> <data name="tag" xsi:type="string">test_type:3rd_party_test, severity:S1</data> diff --git a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/UseVaultOnCheckoutTest.xml b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/UseVaultOnCheckoutTest.xml index 35d55784b676236d808cf0f54fc969fc65193b0b..327a1f8eb2ca2b9db845f7c78a98db11feb047ef 100644 --- a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/UseVaultOnCheckoutTest.xml +++ b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/UseVaultOnCheckoutTest.xml @@ -17,8 +17,8 @@ <data name="shipping/shipping_method" xsi:type="string">Fixed</data> <data name="payment/method" xsi:type="string">braintree</data> <data name="vault/method" xsi:type="string">braintree_cc_vault</data> - <data name="creditCardClass" xsi:type="string">credit_card_braintree</data> - <data name="creditCard/dataset" xsi:type="string">visa_braintree</data> + <data name="creditCard/dataset" xsi:type="string">visa_default</data> + <data name="creditCard/data/payment_code" xsi:type="string">braintree</data> <data name="creditCardSave" xsi:type="string">Yes</data> <data name="configData" xsi:type="string">braintree, braintree_use_vault</data> <data name="status" xsi:type="string">Processing</data> diff --git a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/UseVaultWith3dSecureOnCheckoutTest.xml b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/UseVaultWith3dSecureOnCheckoutTest.xml index a5aa7645148e158ad62a174bc26d08abfd037192..8dd9239d38526622b5facb9ab71b1c9e3e1511b3 100644 --- a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/UseVaultWith3dSecureOnCheckoutTest.xml +++ b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/UseVaultWith3dSecureOnCheckoutTest.xml @@ -17,7 +17,6 @@ <data name="shipping/shipping_method" xsi:type="string">Fixed</data> <data name="payment/method" xsi:type="string">braintree</data> <data name="vault/method" xsi:type="string">braintree_cc_vault</data> - <data name="creditCardClass" xsi:type="string">credit_card_braintree</data> <data name="creditCard/dataset" xsi:type="string">visa_braintree_3dsecure</data> <data name="paymentInformation" xsi:type="array"> <item name="Liability Shifted" xsi:type="string">1</item> diff --git a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestStep/PlaceOrderWith3dSecureFailedStep.php b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestStep/PlaceOrderWith3dSecureFailedStep.php new file mode 100644 index 0000000000000000000000000000000000000000..00a8fce571617e5cd643d9b05bd914dc24e3eb43 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestStep/PlaceOrderWith3dSecureFailedStep.php @@ -0,0 +1,55 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Braintree\Test\TestStep; + +use Magento\Checkout\Test\Page\CheckoutOnepage; +use Magento\Mtf\TestStep\TestStepInterface; +use Magento\Braintree\Test\Fixture\Secure3dBraintree; + +/** + * Click 'Place order' button and submit 3D secure verification step. + */ +class PlaceOrderWith3dSecureFailedStep implements TestStepInterface +{ + /** + * Onepage checkout page. + * + * @var CheckoutOnepage + */ + private $checkoutOnepage; + + /** + * 3D Secure fixture. + * + * @var Secure3dBraintree + */ + private $secure3d; + + /** + * @param CheckoutOnepage $checkoutOnepage + * @param Secure3dBraintree $secure3d + */ + public function __construct( + CheckoutOnepage $checkoutOnepage, + Secure3dBraintree $secure3d + ) { + $this->checkoutOnepage = $checkoutOnepage; + $this->secure3d = $secure3d; + } + + /** + * Click 'Place order' button and submit 3D secure verification. + * + * @return array + */ + public function run() + { + $this->checkoutOnepage->getPaymentBlock()->getSelectedPaymentMethodBlock()->clickPlaceOrder(); + + $this->checkoutOnepage->getBraintree3dSecureBlock()->fill($this->secure3d); + } +} diff --git a/dev/tests/functional/tests/app/Magento/Braintree/Test/etc/testcase.xml b/dev/tests/functional/tests/app/Magento/Braintree/Test/etc/testcase.xml index 12aa92d35064d457cef4a544daace01314723d99..6ad46774f0f765b01761f6227465c63b695535d6 100644 --- a/dev/tests/functional/tests/app/Magento/Braintree/Test/etc/testcase.xml +++ b/dev/tests/functional/tests/app/Magento/Braintree/Test/etc/testcase.xml @@ -21,6 +21,19 @@ <step name="fillBillingInformation" module="Magento_Checkout" next="placeOrderWith3dSecure" /> <step name="placeOrderWith3dSecure" module="Magento_Braintree" /> </scenario> + <scenario name="OnePageCheckoutWith3dSecureFailedTest" firstStep="setupConfiguration"> + <step name="setupConfiguration" module="Magento_Config" next="createProducts" /> + <step name="createProducts" module="Magento_Catalog" next="addProductsToTheCart" /> + <step name="addProductsToTheCart" module="Magento_Checkout" next="proceedToCheckout" /> + <step name="proceedToCheckout" module="Magento_Checkout" next="createCustomer" /> + <step name="createCustomer" module="Magento_Customer" next="selectCheckoutMethod" /> + <step name="selectCheckoutMethod" module="Magento_Checkout" next="fillShippingAddress" /> + <step name="fillShippingAddress" module="Magento_Checkout" next="fillShippingMethod" /> + <step name="fillShippingMethod" module="Magento_Checkout" next="selectPaymentMethod" /> + <step name="selectPaymentMethod" module="Magento_Checkout" next="fillBillingInformation" /> + <step name="fillBillingInformation" module="Magento_Checkout" next="placeOrderWith3dSecureFailed" /> + <step name="placeOrderWith3dSecureFailed" module="Magento_Braintree" /> + </scenario> <scenario name="UseVaultWith3dSecureOnCheckoutTest" firstStep="setupConfiguration"> <step name="setupConfiguration" module="Magento_Config" next="createProducts" /> <step name="createProducts" module="Magento_Catalog" next="addProductsToTheCart" /> diff --git a/dev/tests/functional/tests/app/Magento/Bundle/Test/Block/Catalog/Product/View.php b/dev/tests/functional/tests/app/Magento/Bundle/Test/Block/Catalog/Product/View.php index a688ffac5ac019627c137fcb678c56f374599c8b..071604e9cde32e5c8c83484a582ab95099256203 100644 --- a/dev/tests/functional/tests/app/Magento/Bundle/Test/Block/Catalog/Product/View.php +++ b/dev/tests/functional/tests/app/Magento/Bundle/Test/Block/Catalog/Product/View.php @@ -95,6 +95,7 @@ class View extends \Magento\Catalog\Test\Block\Product\View ); $this->_rootElement->find($this->customizeButton)->click(); $this->waitForElementVisible($this->addToCart); + $this->waitForElementVisible($this->visibleOptions, Locator::SELECTOR_XPATH); } /** diff --git a/dev/tests/functional/tests/app/Magento/Bundle/Test/Block/Catalog/Product/View/Type/Option/Hidden.xml b/dev/tests/functional/tests/app/Magento/Bundle/Test/Block/Catalog/Product/View/Type/Option/Hidden.xml index 356f6a52d6b0c296abc0eb857fe2d8b3dccc4b84..ecced21254cdc113b5f0d5d3d46be1dbd3a4386e 100644 --- a/dev/tests/functional/tests/app/Magento/Bundle/Test/Block/Catalog/Product/View/Type/Option/Hidden.xml +++ b/dev/tests/functional/tests/app/Magento/Bundle/Test/Block/Catalog/Product/View/Type/Option/Hidden.xml @@ -8,8 +8,7 @@ <mapping strict="1"> <fields> <qty> - <selector>//input[contains(@class,"qty")]</selector> - <strategy>xpath</strategy> + <selector>input.qty</selector> <class>Magento\Bundle\Test\Block\Catalog\Product\View\Type\Option\Element\Qty</class> </qty> </fields> diff --git a/dev/tests/functional/tests/app/Magento/Bundle/Test/Constraint/AssertBundleProductForm.php b/dev/tests/functional/tests/app/Magento/Bundle/Test/Constraint/AssertBundleProductForm.php index d9b843cc37a0f2ac109ac662183b93119d3e1edc..9a2304c876f89ca8598e47b720154642f9b96ca0 100644 --- a/dev/tests/functional/tests/app/Magento/Bundle/Test/Constraint/AssertBundleProductForm.php +++ b/dev/tests/functional/tests/app/Magento/Bundle/Test/Constraint/AssertBundleProductForm.php @@ -52,6 +52,7 @@ class AssertBundleProductForm extends AssertProductForm protected function prepareBundleOptions(array $bundleSelections) { foreach ($bundleSelections as &$item) { + unset($item['frontend_type']); foreach ($item['assigned_products'] as &$selection) { $selection['data']['getProductName'] = $selection['search_data']['name']; $selection = $selection['data']; diff --git a/dev/tests/functional/tests/app/Magento/Bundle/Test/Fixture/Cart/Item.php b/dev/tests/functional/tests/app/Magento/Bundle/Test/Fixture/Cart/Item.php index cb46e728191bffb5a770a2809019fb2833f9f0d3..be3abf935c5a42557bea3b6feea86e4301b001f1 100644 --- a/dev/tests/functional/tests/app/Magento/Bundle/Test/Fixture/Cart/Item.php +++ b/dev/tests/functional/tests/app/Magento/Bundle/Test/Fixture/Cart/Item.php @@ -6,9 +6,6 @@ namespace Magento\Bundle\Test\Fixture\Cart; -use Magento\Bundle\Test\Fixture\BundleProduct; -use Magento\Mtf\Fixture\FixtureInterface; - /** * Data for verify cart item block on checkout page. * @@ -18,42 +15,32 @@ use Magento\Mtf\Fixture\FixtureInterface; class Item extends \Magento\Catalog\Test\Fixture\Cart\Item { /** - * @constructor - * @param FixtureInterface $product + * Return prepared dataset. + * + * @param null|string $key + * @return array */ - public function __construct(FixtureInterface $product) + public function getData($key = null) { - parent::__construct($product); - - /** @var BundleProduct $product */ - $bundleSelection = $product->getBundleSelections(); - $checkoutData = $product->getCheckoutData(); + parent::getData($key); + $bundleSelection = $this->product->getBundleSelections(); + $checkoutData = $this->product->getCheckoutData(); $checkoutBundleOptions = isset($checkoutData['options']['bundle_options']) ? $checkoutData['options']['bundle_options'] : []; + $productSku = [$this->product->getSku()]; foreach ($checkoutBundleOptions as $checkoutOptionKey => $checkoutOption) { - // Find option and value keys - $attributeKey = null; - $optionKey = null; - foreach ($bundleSelection['bundle_options'] as $key => $option) { - if ($option['title'] == $checkoutOption['title']) { - $attributeKey = $key; - - foreach ($option['assigned_products'] as $valueKey => $value) { - if (false !== strpos($value['search_data']['name'], $checkoutOption['value']['name'])) { - $optionKey = $valueKey; - } - } - } - } - + $keys = $this->getKeys($bundleSelection['bundle_options'], $checkoutOption); + $attributeKey = $keys['attribute']; + $optionKey = $keys['option']; // Prepare option data $bundleSelectionAttribute = $bundleSelection['products'][$attributeKey]; $bundleOptions = $bundleSelection['bundle_options'][$attributeKey]; $value = $bundleSelectionAttribute[$optionKey]->getName(); + $this->product->getSkuType() == 'No' ?: $productSku[] = $bundleSelectionAttribute[$optionKey]->getSku(); $qty = $bundleOptions['assigned_products'][$optionKey]['data']['selection_qty']; - $price = $product->getPriceType() == 'Yes' + $price = $this->product->getPriceType() == 'Yes' ? number_format($bundleSelectionAttribute[$optionKey]->getPrice(), 2) : number_format($bundleOptions['assigned_products'][$optionKey]['data']['selection_price_value'], 2); $optionData = [ @@ -64,6 +51,47 @@ class Item extends \Magento\Catalog\Test\Fixture\Cart\Item $checkoutBundleOptions[$checkoutOptionKey] = $optionData; } + $this->data['sku'] = implode('-', $productSku); $this->data['options'] += $checkoutBundleOptions; + + return $this->data; + } + + /** + * Get option key. + * + * @param array $assignedProducts + * @param string $checkoutOption + * @return null|string + */ + private function getOptionKey(array $assignedProducts, $checkoutOption) + { + foreach ($assignedProducts as $key => $value) { + if (false !== strpos($value['search_data']['name'], $checkoutOption)) { + return $key; + } + } + + return null; + } + + /** + * Find option and attribute keys. + * + * @param array $bundleOptions + * @param string $checkoutOption + * @return array + */ + private function getKeys(array $bundleOptions, $checkoutOption) + { + $keys = []; + foreach ($bundleOptions as $key => $option) { + if ($option['title'] == $checkoutOption['title']) { + $keys['attribute'] = $key; + $keys['option'] = $this->getOptionKey($option['assigned_products'], $checkoutOption['value']['name']); + } + } + + return $keys; } } diff --git a/dev/tests/functional/tests/app/Magento/Bundle/Test/Repository/BundleProduct/CheckoutData.xml b/dev/tests/functional/tests/app/Magento/Bundle/Test/Repository/BundleProduct/CheckoutData.xml index 3bf2e7b7f2ad1387c89752282148fc582d65a0e1..e694b65110e89cd1840ad1249e6c14a61302a877 100644 --- a/dev/tests/functional/tests/app/Magento/Bundle/Test/Repository/BundleProduct/CheckoutData.xml +++ b/dev/tests/functional/tests/app/Magento/Bundle/Test/Repository/BundleProduct/CheckoutData.xml @@ -353,6 +353,7 @@ <item name="3" xsi:type="array"> <item name="title" xsi:type="string">Multiple Select Option</item> <item name="type" xsi:type="string">Multiple</item> + <item name="frontend_type" xsi:type="string">Multiple</item> <item name="value" xsi:type="array"> <item name="name" xsi:type="string">product_100_dollar</item> </item> @@ -367,6 +368,7 @@ <item name="0" xsi:type="array"> <item name="title" xsi:type="string">Drop-down Option</item> <item name="type" xsi:type="string">Drop-down</item> + <item name="frontend_type" xsi:type="string">Drop-down</item> <item name="value" xsi:type="array"> <item name="name" xsi:type="string">Test simple product</item> </item> diff --git a/dev/tests/functional/tests/app/Magento/Bundle/Test/TestCase/MoveRecentlyComparedProductsOnOrderPageTest.xml b/dev/tests/functional/tests/app/Magento/Bundle/Test/TestCase/MoveRecentlyComparedProductsOnOrderPageTest.xml new file mode 100644 index 0000000000000000000000000000000000000000..a34bf44d38cae01f46f711fd6181c1ae8895ae68 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Bundle/Test/TestCase/MoveRecentlyComparedProductsOnOrderPageTest.xml @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + --> +<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../vendor/magento/mtf/etc/variations.xsd"> + <testCase name="Magento\Sales\Test\TestCase\MoveRecentlyComparedProductsOnOrderPageTest"> + <variation name="MoveRecentlyComparedProductsOnOrderPageTestVariationWithBundleProduct1"> + <data name="products/0" xsi:type="string">bundleProduct::bundle_dynamic_product</data> + <data name="products/1" xsi:type="string">bundleProduct::bundle_dynamic_product</data> + <data name="productsIsConfigured" xsi:type="boolean">true</data> + <constraint name="Magento\Sales\Test\Constraint\AssertProductInItemsOrderedGrid" /> + </variation> + </testCase> +</config> diff --git a/dev/tests/functional/tests/app/Magento/Bundle/Test/etc/di.xml b/dev/tests/functional/tests/app/Magento/Bundle/Test/etc/di.xml index 402dcca44c9485a46d9c40b5103f1cac50b86122..61eac871df9722550fff8735930febc339e4ea4d 100644 --- a/dev/tests/functional/tests/app/Magento/Bundle/Test/etc/di.xml +++ b/dev/tests/functional/tests/app/Magento/Bundle/Test/etc/di.xml @@ -11,4 +11,17 @@ <argument name="severity" xsi:type="string">S2</argument> </arguments> </type> + <type name="Magento\Sales\Test\Block\Adminhtml\Order\Create\CustomerActivities\Sidebar\RecentlyComparedProducts"> + <arguments> + <argument name="config" xsi:type="array"> + <item name="renders" xsi:type="array"> + <item name="bundle" xsi:type="array"> + <item name="class" xsi:type="string">\Magento\Bundle\Test\Block\Adminhtml\Product\Composite\Configure</item> + <item name="locator" xsi:type="string">//ancestor::body//*[contains(@class, "modal-slide") and contains(@class, "_show")]</item> + <item name="strategy" xsi:type="string">xpath</item> + </item> + </item> + </argument> + </arguments> + </type> </config> diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Attribute/CustomAttribute.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Attribute/CustomAttribute.php index 53fe49b759c64ec85b5eb8fedd8bae8aa7627757..3c324de0cabab5d35abf23d4d9ae354675bfdbe6 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Attribute/CustomAttribute.php +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Attribute/CustomAttribute.php @@ -102,7 +102,7 @@ class CustomAttribute extends SimpleElement { $element = null; foreach (array_keys($this->classReferences) as $key) { - if (strpos($class, $key) !== false) { + if ($class == $key) { return $this->classReferences[$class]; } } diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Links/CompareLink.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Links/CompareLink.php index c81d85a724dcf22ef37e2aa497bf2c6be22f51bd..86c30f4caf8a4ccb10bd7cdebc5f5b8137bfa6b2 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Links/CompareLink.php +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Links/CompareLink.php @@ -20,6 +20,13 @@ class CompareLink extends Block */ protected $qtyCompareProducts = '.compare .counter.qty'; + /** + * Locator value for Compare Products link. + * + * @var string + */ + protected $linkCompareProducts = '[data-role="compare-products-link"] a.compare'; + /** * Get qty of Products in Compare list. * @@ -32,4 +39,14 @@ class CompareLink extends Block preg_match_all('/^\d+/', $compareProductLink->getText(), $matches); return $matches[0][0]; } + + /** + * Wait for compare products link to appear + * + * @return void + */ + public function waitForCompareProductsLinks() + { + $this->waitForElementVisible($this->linkCompareProducts); + } } diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Product/View.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Product/View.php index de6adb0efd8b21df23cf0531624fa0b90983225d..5baf4a4cb7c3e273588d85c1217e6824cdefad92 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Product/View.php +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Product/View.php @@ -522,14 +522,16 @@ class View extends AbstractConfigureBlock } /** - * Check id media gallery is visible for the product. + * Check if media gallery is visible for the product. * * @return bool */ public function isGalleryVisible() { $this->waitForElementNotVisible($this->galleryLoader); - return $this->_rootElement->find($this->mediaGallery)->isVisible(); + $this->waitForElementVisible($this->mediaGallery); + + return true; } /** diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductPage.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductPage.php index e99b63d5b8ce7727b93cc3ef2898ef6ba95caf01..fd6f99d13f40fb8bce3f99142d6004f8652087d1 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductPage.php +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductPage.php @@ -31,6 +31,11 @@ class AssertProductPage extends AbstractAssertForm */ protected $product; + /** + * @var CatalogProductView + */ + protected $pageView; + /** * Assert that displayed product data on product page(front-end) equals passed from fixture: * 1. Product Name @@ -53,6 +58,7 @@ class AssertProductPage extends AbstractAssertForm $browser->open($_ENV['app_frontend_url'] . $product->getUrlKey() . '.html'); $this->product = $product; + $this->pageView = $catalogProductView; $this->productView = $catalogProductView->getViewBlock(); $errors = $this->verify(); diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductTierPriceInCart.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductTierPriceInCart.php index 1bc689d8e1b1e3009bbf2f3fc563b3aa51ccc3c7..f8266026b3927798fa2a04128deb65a70254188e 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductTierPriceInCart.php +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductTierPriceInCart.php @@ -110,7 +110,7 @@ class AssertProductTierPriceInCart extends AbstractConstraint { $tierPrice = $product->getDataFieldConfig('tier_price')['source']->getData()[0]; - if ($tierPrice['value_type'] === "Percent") { + if ($tierPrice['value_type'] === "Discount") { $this->fixtureActualPrice = $this->fixturePrice * (1 - $tierPrice['percentage_value'] / 100); } else { $this->fixtureActualPrice = $tierPrice['price']; diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/Cart/Item.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/Cart/Item.php index c7dbba386958a30f19ec9001add2566da76a7b7f..fb0ecca863582cd50f619320f62d0b4ffc1f1a58 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/Cart/Item.php +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/Cart/Item.php @@ -8,7 +8,6 @@ namespace Magento\Catalog\Test\Fixture\Cart; use Magento\Mtf\Fixture\DataSource; use Magento\Mtf\Fixture\FixtureInterface; -use Magento\Catalog\Test\Fixture\CatalogProductSimple; /** * Data for verify cart item block on checkout page. @@ -21,15 +20,31 @@ use Magento\Catalog\Test\Fixture\CatalogProductSimple; class Item extends DataSource { /** - * @constructor + * Product fixture. + * + * @var FixtureInterface + */ + protected $product; + + /** * @param FixtureInterface $product */ public function __construct(FixtureInterface $product) { - /** @var CatalogProductSimple $product */ - $checkoutData = $product->getCheckoutData(); + $this->product = $product; + } + + /** + * Return prepared dataset. + * + * @param null|string $key + * @return array + */ + public function getData($key = null) + { + $checkoutData = $this->product->getCheckoutData(); $cartItem = isset($checkoutData['cartItem']) ? $checkoutData['cartItem'] : []; - $customOptions = $product->hasData('custom_options') ? $product->getCustomOptions() : []; + $customOptions = $this->product->hasData('custom_options') ? $this->product->getCustomOptions() : []; $checkoutCustomOptions = isset($checkoutData['options']['custom_options']) ? $checkoutData['options']['custom_options'] : []; @@ -52,9 +67,12 @@ class Item extends DataSource ? $cartItem['options'] + $checkoutCustomOptions : $checkoutCustomOptions; $cartItem['qty'] = isset($checkoutData['qty']) - ? $checkoutData['qty'] - : 1; - + ? $checkoutData['qty'] + : 1; + $cartItem['sku'] = $this->product->getSku(); + $cartItem['name'] = $this->product->getName(); $this->data = $cartItem; + + return parent::getData($key); } } diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/CatalogProductSimple/CheckoutData.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/CatalogProductSimple/CheckoutData.xml index 180da27ca2a099ab36c00473ac35572c45a31ffd..a1f34f46b0a7cb89342a17a382a0ba1c86de9059 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/CatalogProductSimple/CheckoutData.xml +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/CatalogProductSimple/CheckoutData.xml @@ -137,6 +137,14 @@ </field> </dataset> + <dataset name="simple_order_tier_price_5"> + <field name="qty" xsi:type="string">5</field> + <field name="cartItem" xsi:type="array"> + <item name="price" xsi:type="string">40</item> + <item name="subtotal" xsi:type="string">40</item> + </field> + </dataset> + <dataset name="simple_order_10_dollar_product"> <field name="qty" xsi:type="string">1</field> <field name="cartItem" xsi:type="array"> diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/Category.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/Category.xml index 2fd8c04d1d80dfe643616ee7c550699da91aeece..dc5e9c12ebcaebc1e49c8394f4d4308a11762309 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/Category.xml +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/Category.xml @@ -72,5 +72,18 @@ <field name="is_active" xsi:type="string">Yes</field> <field name="include_in_menu" xsi:type="string">Yes</field> </dataset> + + <dataset name="default_subcategory_with_assigned_simple_product"> + <field name="name" xsi:type="string">Category%isolation%</field> + <field name="url_key" xsi:type="string">category%isolation%</field> + <field name="is_active" xsi:type="string">Yes</field> + <field name="include_in_menu" xsi:type="string">Yes</field> + <field name="parent_id" xsi:type="array"> + <item name="dataset" xsi:type="string">default_category</item> + </field> + <field name="category_products" xsi:type="array"> + <item name="dataset" xsi:type="string">catalogProductSimple::default</item> + </field> + </dataset> </repository> </config> diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/Product/TierPrice.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/Product/TierPrice.xml index 2f517f4d6cf3cc03020abc575d4e91cd7f7188da..9581427d16ec6f9e597e420dcee0329c2dddee32 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/Product/TierPrice.xml +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/Product/TierPrice.xml @@ -92,7 +92,7 @@ <dataset name="custom_with_percentage_discount"> <field name="0" xsi:type="array"> - <item name="value_type" xsi:type="string">Percent</item> + <item name="value_type" xsi:type="string">Discount</item> <item name="percentage_value" xsi:type="string">3</item> <item name="website" xsi:type="string">All Websites [USD]</item> <item name="price_qty" xsi:type="string">10</item> diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/etc/di.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/etc/di.xml index 82a7c263b1ca9671d8b125ac6a3f07e6324fa072..fee6efedff2e281742738d02cfdf36a644203b4e 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/etc/di.xml +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/etc/di.xml @@ -167,7 +167,7 @@ <item name="selector" xsi:type="string">[name="product[%code%]"]</item> <item name="type" xsi:type="string">null</item> </item> - <item name="hasDatepicker" xsi:type="array"> + <item name="admin__control-text _has-datepicker" xsi:type="array"> <item name="selector" xsi:type="string">[name="product[%code%]"]</item> <item name="type" xsi:type="string">datepicker</item> </item> diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Onepage/Login.php b/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Onepage/Login.php index 49b900e4eedce313df7809a574e150f3c63c4787..507bb5673effc80e7525b238d0b14b2ee6d40c11 100644 --- a/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Onepage/Login.php +++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Onepage/Login.php @@ -6,6 +6,7 @@ namespace Magento\Checkout\Test\Block\Onepage; use Magento\Checkout\Test\Fixture\Checkout; +use Magento\Customer\Test\Fixture\Customer; use Magento\Mtf\Block\Form; use Magento\Mtf\Fixture\FixtureInterface; @@ -93,14 +94,15 @@ class Login extends Form /** * Fill required fields for guest checkout. * - * @param FixtureInterface $customer + * @param Customer $customer * @return void */ - public function fillGuestFields(FixtureInterface $customer) + public function fillGuestFields(Customer $customer) { $mapping = $this->dataMapping(); $this->_rootElement->find($mapping['email']['selector'], $mapping['email']['strategy']) ->setValue($customer->getEmail()); + $this->waitForElementNotVisible($this->loadingMask); } /** diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Onepage/Payment.php b/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Onepage/Payment.php index ce8f5a4cbfd99b41e990a11fc89527f28b0fec5f..31002bd8129c4f39d6a2ffd670f70af7fcf48da2 100644 --- a/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Onepage/Payment.php +++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Onepage/Payment.php @@ -7,7 +7,7 @@ namespace Magento\Checkout\Test\Block\Onepage; use Magento\Mtf\Block\Block; -use Magento\Mtf\Fixture\InjectableFixture; +use Magento\Payment\Test\Fixture\CreditCard; /** * Checkout payment block. @@ -47,7 +47,7 @@ class Payment extends Block * * @var string */ - protected $placeOrder = '.action.primary.checkout'; + protected $placeOrder = '.payment-method._active .action.primary.checkout'; /** * Wait element. @@ -74,14 +74,19 @@ class Payment extends Block * Select payment method. * * @param array $payment - * @param InjectableFixture|null $creditCard + * @param CreditCard|null $creditCard + * @param bool $fillCreditCardOn3rdParty * @throws \Exception * @return void */ - public function selectPaymentMethod(array $payment, InjectableFixture $creditCard = null) - { - $paymentSelector = sprintf($this->paymentMethodInput, $payment['method']); - $paymentLabelSelector = sprintf($this->paymentMethodLabel, $payment['method']); + public function selectPaymentMethod( + array $payment, + CreditCard $creditCard = null, + $fillCreditCardOn3rdParty = false + ) { + $paymentMethod = $payment['method']; + $paymentSelector = sprintf($this->paymentMethodInput, $paymentMethod); + $paymentLabelSelector = sprintf($this->paymentMethodLabel, $paymentMethod); try { $this->waitForElementNotVisible($this->waitElement); @@ -100,16 +105,15 @@ class Payment extends Block $paymentRadioButton->click(); } - if ($payment['method'] == "purchaseorder") { + if ($paymentMethod == "purchaseorder") { $this->_rootElement->find($this->purchaseOrderNumber)->setValue($payment['po_number']); } - if ($creditCard !== null) { - $class = explode('\\', get_class($creditCard)); - $module = $class[1]; - /** @var \Magento\Payment\Test\Block\Form\Cc $formBlock */ + if ($creditCard !== null && $fillCreditCardOn3rdParty === false) { + $module = $creditCard->hasData('payment_code') ? ucfirst($creditCard->getPaymentCode()) : 'Payment'; + /** @var \Magento\Payment\Test\Block\Form\PaymentCc $formBlock */ $formBlock = $this->blockFactory->create( - "\\Magento\\{$module}\\Test\\Block\\Form\\Cc", - ['element' => $this->_rootElement->find('#payment_form_' . $payment['method'])] + "\\Magento\\{$module}\\Test\\Block\\Form\\{$module}Cc", + ['element' => $this->_rootElement->find('#payment_form_' . $paymentMethod)] ); $formBlock->fill($creditCard); } diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Onepage/Shipping/AddressModal.php b/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Onepage/Shipping/AddressModal.php index 8a949c474bc847942f1bd5922d00514cd6133d08..43bd771f609cd86fddcfb99c21ac05687bfe06a9 100644 --- a/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Onepage/Shipping/AddressModal.php +++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Onepage/Shipping/AddressModal.php @@ -65,4 +65,20 @@ class AddressModal extends Form return $result; } + + /** + * Fixture mapping. + * + * @param array|null $fields + * @param string|null $parent + * @return array + */ + protected function dataMapping(array $fields = null, $parent = null) + { + if (isset($fields['custom_attribute'])) { + $this->placeholders = ['attribute_code' => $fields['custom_attribute']['code']]; + $this->applyPlaceholders(); + } + return parent::dataMapping($fields, $parent); + } } diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Onepage/Shipping/AddressModal.xml b/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Onepage/Shipping/AddressModal.xml index 13403b792684512c9741bca74a78f7c84036eb48..4a6160698839382c83809824913ebcf3770a0f7f 100644 --- a/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Onepage/Shipping/AddressModal.xml +++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Onepage/Shipping/AddressModal.xml @@ -22,5 +22,8 @@ </country_id> <telephone /> <postcode /> + <custom_attribute> + <selector>[name="custom_attributes[%attribute_code%]"]</selector> + </custom_attribute> </fields> </mapping> diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Onepage/Shipping/Method.php b/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Onepage/Shipping/Method.php index cce29d23f63b18fc2c469e3df964cb2dd81188e0..24bddf79c1a07c9205e0b22426946e11b92d0489 100644 --- a/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Onepage/Shipping/Method.php +++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Onepage/Shipping/Method.php @@ -22,26 +22,49 @@ class Method extends Block protected $shippingMethod = './/tbody//tr[td[contains(., "%s")] and td[contains(., "%s")]]//input'; /** - * Continue checkout button + * Continue checkout button. * * @var string */ protected $continue = '#shipping-method-buttons-container button'; /** - * Wait element + * Wait element. * * @var string */ protected $waitElement = '.loading-mask'; /** - * Block wait element + * Block wait element. * * @var string */ protected $blockWaitElement = '._block-content-loading'; + /** + * Wait until shipping rates will appear. + * + * @return void + */ + private function waitForShippingRates() + { + // Code under test uses JavaScript setTimeout at this point as well. + sleep(3); + $this->waitForElementNotVisible($this->blockWaitElement); + } + + /** + * Retrieve if the shipping methods loader appears. + * + * @return bool|null + */ + public function isLoaderAppeared() + { + $this->_rootElement->click(); + return $this->waitForElementVisible($this->waitElement); + } + /** * Select shipping method. * @@ -50,15 +73,26 @@ class Method extends Block */ public function selectShippingMethod(array $method) { - // Code under test uses JavaScript setTimeout at this point as well. - sleep(3); + $this->waitForShippingRates(); $selector = sprintf($this->shippingMethod, $method['shipping_method'], $method['shipping_service']); - $this->waitForElementNotVisible($this->blockWaitElement); $this->_rootElement->find($selector, Locator::SELECTOR_XPATH)->click(); } /** - * Click continue button + * Check whether shipping method is available in the shipping rates. + * + * @param array $method + * @return bool + */ + public function isShippingMethodAvaiable(array $method) + { + $this->waitForShippingRates(); + $selector = sprintf($this->shippingMethod, $method['shipping_method'], $method['shipping_service']); + return $this->_rootElement->find($selector, Locator::SELECTOR_XPATH)->isVisible(); + } + + /** + * Click continue button. * * @return void */ diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/Constraint/AssertCancelSuccessMessageInShoppingCart.php b/dev/tests/functional/tests/app/Magento/Checkout/Test/Constraint/AssertCancelSuccessMessageInShoppingCart.php new file mode 100644 index 0000000000000000000000000000000000000000..d549e14c7afd94bc35d2540662012fd9f970b872 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/Constraint/AssertCancelSuccessMessageInShoppingCart.php @@ -0,0 +1,47 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Checkout\Test\Constraint; + +use Magento\Checkout\Test\Page\CheckoutCart; +use Magento\Mtf\Constraint\AbstractConstraint; + +/** + * Assert that success message about canceled order is present and correct. + */ +class AssertCancelSuccessMessageInShoppingCart extends AbstractConstraint +{ + /** + * Cancel success message text. + */ + const SUCCESS_MESSAGE = 'Payment was canceled.'; + + /** + * Assert that success message about canceled order is present and correct. + * + * @param CheckoutCart $checkoutCart + * @return void + */ + public function processAssert(CheckoutCart $checkoutCart) + { + $actualMessage = $checkoutCart->getMessagesBlock()->getSuccessMessage(); + \PHPUnit_Framework_Assert::assertEquals( + self::SUCCESS_MESSAGE, + $actualMessage, + 'Success message is not present or has wrong text.' + ); + } + + /** + * Returns a string representation of the object. + * + * @return string + */ + public function toString() + { + return 'Cancel success message is present or has a correct text.'; + } +} diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/Constraint/AssertCheckoutErrorMessage.php b/dev/tests/functional/tests/app/Magento/Checkout/Test/Constraint/AssertCheckoutErrorMessage.php new file mode 100644 index 0000000000000000000000000000000000000000..24fc2419721b51e3b16c4bcc25e88d13497591c2 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/Constraint/AssertCheckoutErrorMessage.php @@ -0,0 +1,42 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Checkout\Test\Constraint; + +use Magento\Checkout\Test\Page\CheckoutOnepage; +use Magento\Mtf\Constraint\AbstractConstraint; + +/** + * Assert that error message is correct. + */ +class AssertCheckoutErrorMessage extends AbstractConstraint +{ + /** + * Assert that error message is correct. + * + * @param CheckoutOnepage $checkoutOnepage + * @param string $expectedErrorMessage + * @return void + */ + public function processAssert(CheckoutOnepage $checkoutOnepage, $expectedErrorMessage) + { + \PHPUnit_Framework_Assert::assertEquals( + $expectedErrorMessage, + $checkoutOnepage->getMessagesBlock()->getErrorMessage(), + 'Wrong error message is displayed.' + ); + } + + /** + * Returns string representation of successful assertion. + * + * @return string + */ + public function toString() + { + return 'Error message on Checkout onepage page is correct.'; + } +} diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/Fixture/Cart.xml b/dev/tests/functional/tests/app/Magento/Checkout/Test/Fixture/Cart.xml index 04b191b2b65834a0786510a61fd4c3170530476b..5286881980704c62438816aa23155f092a6eb56c 100644 --- a/dev/tests/functional/tests/app/Magento/Checkout/Test/Fixture/Cart.xml +++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/Fixture/Cart.xml @@ -10,7 +10,6 @@ module="Magento_Checkout" type="flat" entity_type="quote" - repository_class="Magento\Checkout\Test\Repository\Cart" handler_interface="Magento\Checkout\Test\Handler\Cart\CartInterface" class="Magento\Checkout\Test\Fixture\Cart"> <field name="entity_id" is_required="1" /> diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/Page/CheckoutOnepage.xml b/dev/tests/functional/tests/app/Magento/Checkout/Test/Page/CheckoutOnepage.xml index 0ab3bbb2c2cfcb01330fecd582bb235ed7805068..00ac573da2e7e658b2dc3a9de50a7185bb2512fb 100644 --- a/dev/tests/functional/tests/app/Magento/Checkout/Test/Page/CheckoutOnepage.xml +++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/Page/CheckoutOnepage.xml @@ -17,7 +17,7 @@ <block name="paymentBlock" class="Magento\Checkout\Test\Block\Onepage\Payment" locator="#checkout-step-payment" strategy="css selector" /> <block name="discountCodesBlock" class="Magento\Checkout\Test\Block\Onepage\Payment\DiscountCodes" locator=".discount-code" strategy="css selector" /> <block name="reviewBlock" class="Magento\Checkout\Test\Block\Onepage\Review" locator=".opc-block-summary" strategy="css selector" /> - <block name="messagesBlock" class="Magento\Backend\Test\Block\Messages" locator=".page.messages" strategy="css selector" /> + <block name="messagesBlock" class="Magento\Backend\Test\Block\Messages" locator="//*[@id='checkout']//div[@data-role='checkout-messages' and .//div]" strategy="xpath" /> <block name="customAddressBlock" class="Magento\Checkout\Test\Block\Onepage\CustomAddress" locator=".checkout-billing-address" strategy="css selector" /> </page> </config> diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/AddProductsToShoppingCartEntityTest.php b/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/AddProductsToShoppingCartEntityTest.php index 0733d778b9662dba9c857eff90b213b4da77e4c3..e41af50cca9f624c489dd8af497d601f0d41a426 100644 --- a/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/AddProductsToShoppingCartEntityTest.php +++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/AddProductsToShoppingCartEntityTest.php @@ -30,6 +30,7 @@ class AddProductsToShoppingCartEntityTest extends Injectable { /* tags */ const MVP = 'yes'; + const SEVERITY = 'S0'; /* end tags */ /** diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/AddProductsToShoppingCartEntityTest.xml b/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/AddProductsToShoppingCartEntityTest.xml index 9a539d856e7082ae5131e903d7d86eec5f37d6c5..cac5e0a9c2182a05e8925a375396b7fe6f610a99 100644 --- a/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/AddProductsToShoppingCartEntityTest.xml +++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/AddProductsToShoppingCartEntityTest.xml @@ -8,7 +8,7 @@ <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd"> <testCase name="Magento\Checkout\Test\TestCase\AddProductsToShoppingCartEntityTest" summary="Add Products to Shopping Cart" ticketId="MAGETWO-25382"> <variation name="AddProductsToShoppingCartEntityTestVariation1"> - <data name="tag" xsi:type="string">to_maintain:yes</data> + <data name="tag" xsi:type="string">to_maintain:yes, severity:S2</data> <data name="productsData/0" xsi:type="string">bundleProduct::bundle_dynamic_product</data> <data name="cart/data/grand_total" xsi:type="string">210</data> <data name="cart/data/subtotal" xsi:type="string">200</data> @@ -21,7 +21,7 @@ <constraint name="Magento\Checkout\Test\Constraint\AssertSubtotalInMiniShoppingCart" /> </variation> <variation name="AddProductsToShoppingCartEntityTestVariation2"> - <data name="tag" xsi:type="string">to_maintain:yes</data> + <data name="tag" xsi:type="string">to_maintain:yes, severity:S2</data> <data name="productsData/0" xsi:type="string">bundleProduct::bundle_fixed_product</data> <data name="cart/data/grand_total" xsi:type="string">761</data> <data name="cart/data/subtotal" xsi:type="string">756</data> @@ -34,7 +34,7 @@ <constraint name="Magento\Checkout\Test\Constraint\AssertSubtotalInMiniShoppingCart" /> </variation> <variation name="AddProductsToShoppingCartEntityTestVariation3"> - <data name="tag" xsi:type="string">to_maintain:yes</data> + <data name="tag" xsi:type="string">to_maintain:yes, severity:S0</data> <data name="productsData/0" xsi:type="string">catalogProductSimple::with_two_custom_option</data> <data name="cart/data/grand_total" xsi:type="string">345</data> <data name="cart/data/subtotal" xsi:type="string">340</data> @@ -47,7 +47,7 @@ <constraint name="Magento\Checkout\Test\Constraint\AssertSubtotalInMiniShoppingCart" /> </variation> <variation name="AddProductsToShoppingCartEntityTestVariation4"> - <data name="tag" xsi:type="string">to_maintain:yes</data> + <data name="tag" xsi:type="string">to_maintain:yes, severity:S1</data> <data name="productsData/0" xsi:type="string">catalogProductVirtual::product_50_dollar</data> <data name="cart/data/grand_total" xsi:type="string">50</data> <data name="cart/data/subtotal" xsi:type="string">50</data> @@ -60,7 +60,7 @@ <constraint name="Magento\Checkout\Test\Constraint\AssertSubtotalInMiniShoppingCart" /> </variation> <variation name="AddProductsToShoppingCartEntityTestVariation5"> - <data name="tag" xsi:type="string">to_maintain:yes</data> + <data name="tag" xsi:type="string">to_maintain:yes, severity:S0</data> <data name="productsData/0" xsi:type="string">configurableProduct::default</data> <data name="cart/data/grand_total" xsi:type="string">135</data> <data name="cart/data/subtotal" xsi:type="string">120</data> @@ -73,6 +73,7 @@ <constraint name="Magento\Checkout\Test\Constraint\AssertSubtotalInMiniShoppingCart" /> </variation> <variation name="AddProductsToShoppingCartEntityTestVariation6"> + <data name="tag" xsi:type="string">severity:S2</data> <data name="productsData/0" xsi:type="string">downloadableProduct::with_two_separately_links</data> <data name="cart/data/grand_total" xsi:type="string">22.43</data> <data name="cart/data/subtotal" xsi:type="string">22.43</data> @@ -85,7 +86,7 @@ <constraint name="Magento\Checkout\Test\Constraint\AssertSubtotalInMiniShoppingCart" /> </variation> <variation name="AddProductsToShoppingCartEntityTestVariation7"> - <data name="tag" xsi:type="string">to_maintain:yes</data> + <data name="tag" xsi:type="string">to_maintain:yes, severity:S2</data> <data name="productsData/0" xsi:type="string">groupedProduct::three_simple_products</data> <data name="cart/data/grand_total" xsi:type="string">1950</data> <data name="cart/data/subtotal" xsi:type="string">1920</data> @@ -98,7 +99,7 @@ <constraint name="Magento\Checkout\Test\Constraint\AssertSubtotalInMiniShoppingCart" /> </variation> <variation name="AddProductsToShoppingCartEntityTestVariation8"> - <data name="tag" xsi:type="string">to_maintain:yes</data> + <data name="tag" xsi:type="string">to_maintain:yes, severity:S0</data> <data name="productsData/0" xsi:type="string">catalogProductSimple::with_two_custom_option</data> <data name="productsData/1" xsi:type="string">catalogProductVirtual::product_50_dollar</data> <data name="productsData/2" xsi:type="string">downloadableProduct::with_two_separately_links</data> diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/DeleteProductFromMiniShoppingCartTest.php b/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/DeleteProductFromMiniShoppingCartTest.php index f2a809656ed65449fc63d5405b3449f8587005c5..d19ad5497b5dc6009d6e825571dd2f0ab8d67df4 100644 --- a/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/DeleteProductFromMiniShoppingCartTest.php +++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/DeleteProductFromMiniShoppingCartTest.php @@ -32,6 +32,7 @@ class DeleteProductFromMiniShoppingCartTest extends Injectable { /* tags */ const MVP = 'yes'; + const SEVERITY = 'S0'; /* end tags */ /** diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/DeleteProductFromMiniShoppingCartTest.xml b/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/DeleteProductFromMiniShoppingCartTest.xml index 10f1245c2e4fbf20764519641b443e978bc04bf6..47387bb32ca9ebc857cf5df0d4c9129c8f459742 100644 --- a/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/DeleteProductFromMiniShoppingCartTest.xml +++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/DeleteProductFromMiniShoppingCartTest.xml @@ -8,6 +8,7 @@ <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd"> <testCase name="Magento\Checkout\Test\TestCase\DeleteProductFromMiniShoppingCartTest" summary="Delete Product from Mini Shopping Cart" ticketId="MAGETWO-29104"> <variation name="DeleteProductFromMiniShoppingCartTestVariation1"> + <data name="tag" xsi:type="string">severity:S0</data> <data name="description" xsi:type="string">delete Simple</data> <data name="products/0" xsi:type="string">catalogProductSimple::default</data> <data name="products/1" xsi:type="string">catalogProductVirtual::default</data> @@ -16,6 +17,7 @@ <constraint name="Magento\Checkout\Test\Constraint\AssertProductPresentInMiniShoppingCart" /> </variation> <variation name="DeleteProductFromMiniShoppingCartTestVariation2"> + <data name="tag" xsi:type="string">severity:S1</data> <data name="description" xsi:type="string">delete Simple</data> <data name="products/0" xsi:type="string">catalogProductSimple::default</data> <data name="deletedProductIndex" xsi:type="string">0</data> diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/DeleteProductsFromShoppingCartTest.php b/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/DeleteProductsFromShoppingCartTest.php index ae48e6e6b79487571539aa28567f7dd930b57237..877fd28593cfb060a0b1ac1e2d33bc3d42a425f7 100644 --- a/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/DeleteProductsFromShoppingCartTest.php +++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/DeleteProductsFromShoppingCartTest.php @@ -30,6 +30,7 @@ class DeleteProductsFromShoppingCartTest extends Injectable { /* tags */ const MVP = 'yes'; + const SEVERITY = 'S1'; /* end tags */ /** diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/DeleteProductsFromShoppingCartTest.xml b/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/DeleteProductsFromShoppingCartTest.xml index 033ea76a2a5ff17c5233d7f1b543f6b72f013c61..2af59cbaac6a49bd64706d52477e9b481a28e976 100644 --- a/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/DeleteProductsFromShoppingCartTest.xml +++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/DeleteProductsFromShoppingCartTest.xml @@ -8,36 +8,42 @@ <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd"> <testCase name="Magento\Checkout\Test\TestCase\DeleteProductsFromShoppingCartTest" summary="Delete Products from Shopping Cart" ticketId="MAGETWO-25218"> <variation name="DeleteProductsFromShoppingCartTestVariation1"> + <data name="tag" xsi:type="string">severity:S2</data> <data name="productsData/0" xsi:type="string">bundleProduct::bundle_dynamic_product</data> <constraint name="Magento\Checkout\Test\Constraint\AssertCartIsEmpty" /> </variation> <variation name="DeleteProductsFromShoppingCartTestVariation2"> + <data name="tag" xsi:type="string">severity:S2</data> <data name="productsData/0" xsi:type="string">bundleProduct::bundle_fixed_product</data> <constraint name="Magento\Checkout\Test\Constraint\AssertCartIsEmpty" /> </variation> <variation name="DeleteProductsFromShoppingCartTestVariation3"> - <data name="tag" xsi:type="string">to_maintain:yes</data> + <data name="tag" xsi:type="string">to_maintain:yes, severity:S1</data> <data name="productsData/0" xsi:type="string">catalogProductSimple::with_two_custom_option</data> <constraint name="Magento\Checkout\Test\Constraint\AssertCartIsEmpty" /> </variation> <variation name="DeleteProductsFromShoppingCartTestVariation4"> + <data name="tag" xsi:type="string">severity:S2</data> <data name="productsData/0" xsi:type="string">catalogProductVirtual::product_50_dollar</data> <constraint name="Magento\Checkout\Test\Constraint\AssertCartIsEmpty" /> </variation> <variation name="DeleteProductsFromShoppingCartTestVariation5"> + <data name="tag" xsi:type="string">severity:S1</data> <data name="productsData/0" xsi:type="string">configurableProduct::default</data> <constraint name="Magento\Checkout\Test\Constraint\AssertCartIsEmpty" /> </variation> <variation name="DeleteProductsFromShoppingCartTestVariation6"> + <data name="tag" xsi:type="string">severity:S2</data> <data name="productsData/0" xsi:type="string">downloadableProduct::with_two_separately_links</data> <constraint name="Magento\Checkout\Test\Constraint\AssertCartIsEmpty" /> </variation> <variation name="DeleteProductsFromShoppingCartTestVariation7"> + <data name="tag" xsi:type="string">severity:S2</data> <data name="productsData/0" xsi:type="string">groupedProduct::three_simple_products</data> <constraint name="Magento\Checkout\Test\Constraint\AssertCartIsEmpty" /> </variation> <variation name="DeleteProductsFromShoppingCartTestVariation8"> - <data name="tag" xsi:type="string">to_maintain:yes</data> + <data name="tag" xsi:type="string">to_maintain:yes, severity:S1</data> <data name="productsData/0" xsi:type="string">catalogProductSimple::with_two_custom_option</data> <data name="productsData/1" xsi:type="string">catalogProductVirtual::product_50_dollar</data> <data name="productsData/2" xsi:type="string">downloadableProduct::with_two_separately_links</data> diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/OnePageCheckoutDeclinedTest.php b/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/OnePageCheckoutDeclinedTest.php new file mode 100644 index 0000000000000000000000000000000000000000..990c3df13e9b1f00e6a2171dfb8f2216b38f0ec3 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/OnePageCheckoutDeclinedTest.php @@ -0,0 +1,46 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Checkout\Test\TestCase; + +use Magento\Mtf\TestCase\Scenario; + +/** + * Preconditions: + * 1. Configure payment method. + * 2. Create products. + * + * Steps: + * 1. Log in Storefront. + * 2. Add products to the Shopping Cart. + * 3. Click the 'Proceed to Checkout' button. + * 4. Fill shipping information. + * 5. Select shipping method. + * 6. Select payment method. + * 7. Click 'Place Order' button. + * 8. Perform assertions. + * + * @group Checkout + * @ZephyrId MAGETWO-46469 + */ +class OnePageCheckoutDeclinedTest extends Scenario +{ + /* tags */ + const MVP = 'yes'; + const TEST_TYPE = '3rd_party_test'; + const SEVERITY = 'S1'; + /* end tags */ + + /** + * Verifies error message on Onepage Checkout. + * + * @return void + */ + public function test() + { + $this->executeScenario(); + } +} diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/OnePageCheckoutJsValidationTest.php b/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/OnePageCheckoutJsValidationTest.php index 5361ee6e3c127bafc03e53cd717ac067688f826a..a3ba73a1caf41c3d5ab2220feeab58ff3bc510df 100644 --- a/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/OnePageCheckoutJsValidationTest.php +++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/OnePageCheckoutJsValidationTest.php @@ -21,6 +21,10 @@ use Magento\Mtf\TestCase\Scenario; */ class OnePageCheckoutJsValidationTest extends Scenario { + /* tags */ + const SEVERITY = 'S2'; + /* end tags */ + /** * Runs one page checkout js validation test. * diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/OnePageCheckoutJsValidationTest.xml b/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/OnePageCheckoutJsValidationTest.xml index e930ff29882ceed4e8f99947a6a6ef4b4acc1c7a..f8f9b93661aa1b914e6fd4000cd0ece8f7dac302 100644 --- a/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/OnePageCheckoutJsValidationTest.xml +++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/OnePageCheckoutJsValidationTest.xml @@ -8,6 +8,7 @@ <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd"> <testCase name="Magento\Checkout\Test\TestCase\OnePageCheckoutJsValidationTest" summary="JS validation verification for Checkout flow" ticketId="MAGETWO-59697"> <variation name="OnePageCheckoutJsValidationTestVariation1" summary="JS validation is not applied for empty required checkout fields if customer did not fill them"> + <data name="tag" xsi:type="string">severity:S2</data> <data name="products/0" xsi:type="string">catalogProductSimple::default</data> <data name="checkoutMethod" xsi:type="string">guest</data> <constraint name="Magento\Checkout\Test\Constraint\AssertShippingAddressJsValidationMessagesIsAbsent" /> diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/OnePageCheckoutTest.php b/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/OnePageCheckoutTest.php index 25922102e1269c95280697db6c3175c36d6253fc..63454c8137975a4a64ee36e20ac596c5fcbc4f7d 100644 --- a/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/OnePageCheckoutTest.php +++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/OnePageCheckoutTest.php @@ -41,6 +41,7 @@ class OnePageCheckoutTest extends Scenario /* tags */ const MVP = 'yes'; const TEST_TYPE = 'acceptance_test, extended_acceptance_test, 3rd_party_test'; + const SEVERITY = 'S0'; /* end tags */ /** diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/OnePageCheckoutTest.xml b/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/OnePageCheckoutTest.xml index 24f63035645f22ebbf051f2ab0cb8cbf48c59c93..1b6f78148a129a1bd575fe12a91b99e7cbde87aa 100644 --- a/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/OnePageCheckoutTest.xml +++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/OnePageCheckoutTest.xml @@ -8,6 +8,7 @@ <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd"> <testCase name="Magento\Checkout\Test\TestCase\OnePageCheckoutTest" summary="OnePageCheckout within Offline Payment Methods" ticketId="MAGETWO-27485"> <variation name="OnePageCheckoutUsingLoginPopup" summary="Customer is redirected to checkout on login if guest is disabled, flow for existed Customer" ticketId="MAGETWO-49916"> + <data name="tag" xsi:type="string">severity:S1</data> <data name="products/0" xsi:type="string">catalogProductSimple::default</data> <data name="customer/dataset" xsi:type="string">johndoe_with_addresses</data> <data name="checkoutMethod" xsi:type="string">login</data> @@ -21,6 +22,7 @@ <constraint name="Magento\Checkout\Test\Constraint\AssertOrderSuccessPlacedMessage" /> </variation> <variation name="OnePageCheckoutUsingRegisterLink" summary="Customer is redirected to checkout on login if guest is disabled, flow with registration new Customer" ticketId="MAGETWO-49917"> + <data name="tag" xsi:type="string">severity:S1</data> <data name="issue" xsi:type="string">MAGETWO-59816: Redirect works improperly in a browser incognito mode</data> <data name="products/0" xsi:type="string">catalogProductSimple::default</data> <data name="customer/dataset" xsi:type="string">register_customer</data> @@ -36,6 +38,7 @@ <constraint name="Magento\Checkout\Test\Constraint\AssertOrderSuccessPlacedMessage" /> </variation> <variation name="OnePageCheckoutTestVariation1" summary="Checkout as UK guest with virtual product and downloadable product using coupon for not logged in customers"> + <data name="tag" xsi:type="string">severity:S0</data> <data name="products/0" xsi:type="string">catalogProductVirtual::default</data> <data name="products/1" xsi:type="string">downloadableProduct::with_two_separately_links</data> <data name="salesRule" xsi:type="string">active_sales_rule_for_all_groups</data> @@ -55,7 +58,7 @@ <constraint name="Magento\Sales\Test\Constraint\AssertOrderGrandTotal" /> </variation> <variation name="OnePageCheckoutTestVariation2" summary="US customer during checkout using coupon for all customer groups"> - <data name="tag" xsi:type="string">stable:no</data> + <data name="tag" xsi:type="string">stable:no, severity:S0</data> <data name="products/0" xsi:type="string">catalogProductSimple::default</data> <data name="salesRule" xsi:type="string">active_sales_rule_for_all_groups</data> <data name="customer/dataset" xsi:type="string">default</data> @@ -77,7 +80,7 @@ <constraint name="Magento\Sales\Test\Constraint\AssertOrderGrandTotal" /> </variation> <variation name="OnePageCheckoutTestVariation3" summary="Checkout as UK guest with simple product" ticketId="MAGETWO-42603"> - <data name="tag" xsi:type="string">stable:no</data> + <data name="tag" xsi:type="string">stable:no, severity:S1</data> <data name="products/0" xsi:type="string">catalogProductSimple::default</data> <data name="customer/dataset" xsi:type="string">default</data> <data name="checkoutMethod" xsi:type="string">guest</data> @@ -98,7 +101,7 @@ <constraint name="Magento\Sales\Test\Constraint\AssertOrderGrandTotal" /> </variation> <variation name="OnePageCheckoutTestVariation4" summary="One Page Checkout Products with Special Prices" ticketId="MAGETWO-12429"> - <data name="tag" xsi:type="string">test_type:acceptance_test, test_type:extended_acceptance_test</data> + <data name="tag" xsi:type="string">test_type:acceptance_test, test_type:extended_acceptance_test, severity:S0</data> <data name="products/0" xsi:type="string">catalogProductSimple::product_with_special_price</data> <data name="products/1" xsi:type="string">configurableProduct::product_with_special_price</data> <data name="customer/dataset" xsi:type="string">default</data> @@ -120,7 +123,7 @@ <constraint name="Magento\Sales\Test\Constraint\AssertOrderGrandTotal"/> </variation> <variation name="OnePageCheckoutTestVariation5" summary="Guest Checkout using Check/Money Order and Free Shipping with Prices/Taxes Verifications" ticketId="MAGETWO-12412"> - <data name="tag" xsi:type="string">test_type:acceptance_test, test_type:extended_acceptance_test</data> + <data name="tag" xsi:type="string">test_type:acceptance_test, test_type:extended_acceptance_test, stable:no, severity:S0</data> <data name="products/0" xsi:type="string">catalogProductSimple::product_10_dollar</data> <data name="products/1" xsi:type="string">configurableProduct::with_one_option</data> <data name="products/2" xsi:type="string">bundleProduct::bundle_fixed_100_dollar_product</data> @@ -144,6 +147,7 @@ <constraint name="Magento\Sales\Test\Constraint\AssertOrderGrandTotal" /> </variation> <variation name="OnePageCheckoutTestVariation6" summary="Checkout as UK guest with virtual product using coupon for not logged in customers with Zero Subtotal Checkout payment method"> + <data name="tag" xsi:type="string">severity:S0</data> <data name="products/0" xsi:type="string">catalogProductVirtual::product_50_dollar</data> <data name="salesRule" xsi:type="string">active_sales_rule_with_fixed_price_discount_coupon</data> <data name="customer/dataset" xsi:type="string">default</data> @@ -163,6 +167,7 @@ <constraint name="Magento\Sales\Test\Constraint\AssertOrderGrandTotal" /> </variation> <variation name="OnePageCheckoutTestVariation7" summary="Checkout as UK guest with condition available product qty = ordered product qty"> + <data name="tag" xsi:type="string">severity:S1</data> <data name="products/0" xsi:type="string">catalogProductSimple::product_with_qty_25</data> <data name="checkoutMethod" xsi:type="string">guest</data> <data name="shippingAddress/dataset" xsi:type="string">UK_address</data> @@ -182,6 +187,7 @@ <constraint name="Magento\Catalog\Test\Constraint\AssertProductsOutOfStock" /> </variation> <variation name="OnePageCheckoutTestVariation8" summary="Checkout as UK customer with different shipping/billing address and register checkout method"> + <data name="tag" xsi:type="string">severity:S0</data> <data name="products/0" xsi:type="string">catalogProductSimple::default</data> <data name="customer/dataset" xsi:type="string">default</data> <data name="checkoutMethod" xsi:type="string">register</data> @@ -197,7 +203,7 @@ <constraint name="Magento\Sales\Test\Constraint\AssertOrderGrandTotal" /> </variation> <variation name="OnePageCheckoutTestVariation9" summary="One Page Checkout Products with different shipping/billing address and Tier Prices" ticketId="MAGETWO-42604"> - <data name="tag" xsi:type="string">stable:no</data> + <data name="tag" xsi:type="string">stable:no, severity:S1</data> <data name="products/0" xsi:type="string">catalogProductSimple::simple_with_tier_price_and_order_qty_3</data> <data name="customer/dataset" xsi:type="string">default</data> <data name="checkoutMethod" xsi:type="string">login</data> @@ -216,7 +222,7 @@ <constraint name="Magento\Sales\Test\Constraint\AssertOrderGrandTotal" /> </variation> <variation name="OnePageCheckoutTestVariation10" summary="One Page Checkout with all product types"> - <data name="tag" xsi:type="string">stable:no</data> + <data name="tag" xsi:type="string">stable:no, severity:S0</data> <data name="products/0" xsi:type="string">catalogProductVirtual::default</data> <data name="products/1" xsi:type="string">downloadableProduct::with_two_separately_links</data> <data name="products/2" xsi:type="string">configurableProduct::with_one_option</data> @@ -237,6 +243,7 @@ <constraint name="Magento\Sales\Test\Constraint\AssertOrderGrandTotal" /> </variation> <variation name="OnePageCheckoutUsingSingInLink" summary="Login during checkout using 'Sign In' link" ticketId="MAGETWO-42547"> + <data name="tag" xsi:type="string">severity:S1</data> <data name="products/0" xsi:type="string">catalogProductSimple::default</data> <data name="customer/dataset" xsi:type="string">customer_UK_US_addresses</data> <data name="checkoutMethod" xsi:type="string">sign_in</data> @@ -257,6 +264,7 @@ <constraint name="Magento\Sales\Test\Constraint\AssertOrderAddresses" /> </variation> <variation name="OnePageCheckoutUsingNonDefaultAddress" summary="Checkout as Customer using non default address" ticketId="MAGETWO-42602"> + <data name="tag" xsi:type="string">severity:S1</data> <data name="products/0" xsi:type="string">catalogProductSimple::default</data> <data name="customer/dataset" xsi:type="string">customer_US_DE_UK</data> <data name="checkoutMethod" xsi:type="string">login</data> @@ -278,6 +286,7 @@ <constraint name="Magento\Sales\Test\Constraint\AssertOrderAddresses" /> </variation> <variation name="OnePageCheckoutUsingNewAddress" summary="Checkout as Customer using New address" ticketId="MAGETWO-42601"> + <data name="tag" xsi:type="string">severity:S1</data> <data name="products/0" xsi:type="string">catalogProductSimple::default</data> <data name="customer/dataset" xsi:type="string">johndoe_with_addresses</data> <data name="checkoutMethod" xsi:type="string">sign_in</data> @@ -296,6 +305,7 @@ <constraint name="Magento\Sales\Test\Constraint\AssertOrderAddresses" /> </variation> <variation name="OnePageCheckoutTestVariation11" summary="Checkout as Customer using default address" ticketId="MAGETWO-42600, MAGETWO-42546"> + <data name="tag" xsi:type="string">severity:S1</data> <data name="products/0" xsi:type="string">catalogProductSimple::default</data> <data name="customer/dataset" xsi:type="string">customer_UK_US_addresses</data> <data name="checkoutMethod" xsi:type="string">login</data> diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/UpdateProductFromMiniShoppingCartEntityTest.php b/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/UpdateProductFromMiniShoppingCartEntityTest.php index 0bfe42f7fe78ced0ffb2282d69790ca42c4a1dec..3a9d381de3d810b59437fd3a73028bb058d3915c 100644 --- a/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/UpdateProductFromMiniShoppingCartEntityTest.php +++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/UpdateProductFromMiniShoppingCartEntityTest.php @@ -34,6 +34,7 @@ class UpdateProductFromMiniShoppingCartEntityTest extends Injectable /* tags */ const MVP = 'yes'; const TEST_TYPE = 'extended_acceptance_test'; + const SEVERITY = 'S0'; /* end tags */ /** diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/UpdateProductFromMiniShoppingCartEntityTest.xml b/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/UpdateProductFromMiniShoppingCartEntityTest.xml index cd500a935485cd0e08981d32a53b9280a7d2ad57..f7a675d36c5bd38c5ffc2153f0c7f47fe60f986f 100644 --- a/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/UpdateProductFromMiniShoppingCartEntityTest.xml +++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/UpdateProductFromMiniShoppingCartEntityTest.xml @@ -8,7 +8,7 @@ <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd"> <testCase name="Magento\Checkout\Test\TestCase\UpdateProductFromMiniShoppingCartEntityTest" summary="Update Product from Mini Shopping Cart" ticketId="MAGETWO-29812"> <variation name="UpdateProductFromMiniShoppingCartEntityTestVariation1" summary="Update Product Qty on Mini Shopping Cart" ticketId=" MAGETWO-35536"> - <data name="tag" xsi:type="string">test_type:extended_acceptance_test</data> + <data name="tag" xsi:type="string">test_type:extended_acceptance_test, severity:S0</data> <data name="originalProduct/0" xsi:type="string">catalogProductSimple::default</data> <data name="checkoutData/dataset" xsi:type="string">simple_order_qty_2</data> <data name="use_minicart_to_edit_qty" xsi:type="boolean">true</data> @@ -25,7 +25,7 @@ <constraint name="Magento\Checkout\Test\Constraint\AssertCustomerIsRedirectedToCheckoutFromCart" /> </variation> <variation name="UpdateProductFromMiniShoppingCartEntityTestVariation2" summary="Update Configurable and verify previous product was updated to new one in shopping cart and mini shopping cart"> - <data name="tag" xsi:type="string">test_type:extended_acceptance_test, to_maintain:yes</data> + <data name="tag" xsi:type="string">test_type:extended_acceptance_test, to_maintain:yes, severity:S0</data> <data name="originalProduct/0" xsi:type="string">configurableProduct::default</data> <data name="checkoutData/dataset" xsi:type="string">configurable_update_mini_shopping_cart</data> <constraint name="Magento\Checkout\Test\Constraint\AssertCartItemsOptions" /> @@ -34,7 +34,7 @@ <constraint name="Magento\Checkout\Test\Constraint\AssertProductOptionsAbsentInShoppingCart" /> </variation> <variation name="UpdateProductFromMiniShoppingCartEntityTestVariation3" summary="Update Bundle and verify previous product was updated to new one in shopping cart and mini shopping cart"> - <data name="tag" xsi:type="string">test_type:extended_acceptance_test, to_maintain:yes</data> + <data name="tag" xsi:type="string">test_type:extended_acceptance_test, to_maintain:yes, severity:S0</data> <data name="originalProduct/0" xsi:type="string">bundleProduct::bundle_fixed_product</data> <data name="checkoutData/dataset" xsi:type="string">bundle_update_mini_shopping_cart</data> <constraint name="Magento\Checkout\Test\Constraint\AssertCartItemsOptions" /> @@ -43,7 +43,7 @@ <constraint name="Magento\Checkout\Test\Constraint\AssertProductOptionsAbsentInShoppingCart" /> </variation> <variation name="UpdateProductFromMiniShoppingCartEntityTestVariation4" summary="Update Downloadable and check previous link was updated to new one in shopping cart and mini shopping cart"> - <data name="tag" xsi:type="string">test_type:extended_acceptance_test, to_maintain:yes</data> + <data name="tag" xsi:type="string">test_type:extended_acceptance_test, to_maintain:yes, severity:S1</data> <data name="originalProduct/0" xsi:type="string">downloadableProduct::with_two_separately_links</data> <data name="checkoutData/dataset" xsi:type="string">downloadable_update_mini_shopping_cart</data> <constraint name="Magento\Checkout\Test\Constraint\AssertCartItemsOptions" /> @@ -52,7 +52,7 @@ <constraint name="Magento\Checkout\Test\Constraint\AssertProductOptionsAbsentInShoppingCart" /> </variation> <variation name="UpdateProductFromMiniShoppingCartEntityTestVariation5" summary="Update Virtual product in mini shopping cart"> - <data name="tag" xsi:type="string">test_type:extended_acceptance_test, to_maintain:yes</data> + <data name="tag" xsi:type="string">test_type:extended_acceptance_test, to_maintain:yes, severity:S1</data> <data name="originalProduct/0" xsi:type="string">catalogProductVirtual::default</data> <data name="checkoutData/dataset" xsi:type="string">virtual_update_mini_shopping_cart</data> <constraint name="Magento\Checkout\Test\Constraint\AssertProductDataInMiniShoppingCart" /> diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/UpdateShoppingCartTest.php b/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/UpdateShoppingCartTest.php index 3dba57e26e003726e856577f5e4b48a427428a24..57ef98528c877e96bd21d0773aa16d79466aed7a 100644 --- a/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/UpdateShoppingCartTest.php +++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/UpdateShoppingCartTest.php @@ -34,6 +34,7 @@ class UpdateShoppingCartTest extends Injectable /* tags */ const MVP = 'yes'; const STABLE = 'no'; + const SEVERITY = 'S0'; /* end tags */ /** diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/UpdateShoppingCartTest.xml b/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/UpdateShoppingCartTest.xml index 42428189f44b06b3c33550efb453d34900045133..912bb57e3f1eb2b00e4e481b8fa83c64975380dd 100644 --- a/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/UpdateShoppingCartTest.xml +++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/UpdateShoppingCartTest.xml @@ -8,6 +8,7 @@ <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd"> <testCase name="Magento\Checkout\Test\TestCase\UpdateShoppingCartTest" summary="Update Shopping Cart" ticketId="MAGETWO-25081"> <variation name="UpdateShoppingCartTestVariation1"> + <data name="tag" xsi:type="string">severity:S0</data> <data name="product/dataset" xsi:type="string">default</data> <data name="product/data/price/value" xsi:type="string">100</data> <data name="product/data/checkout_data/qty" xsi:type="string">3</data> @@ -19,6 +20,7 @@ <constraint name="Magento\Checkout\Test\Constraint\AssertSubtotalInShoppingCart" /> </variation> <variation name="UpdateShoppingCartTestVariation2"> + <data name="tag" xsi:type="string">severity:S0</data> <data name="product/dataset" xsi:type="string">with_two_custom_option</data> <data name="product/data/price/value" xsi:type="string">50</data> <data name="product/data/checkout_data/qty" xsi:type="string">11</data> diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/TestStep/AddProductsToTheCartStep.php b/dev/tests/functional/tests/app/Magento/Checkout/Test/TestStep/AddProductsToTheCartStep.php index 37df8ea8b89255ca5a1d522b1b0c7c6bc6ffcf5c..d6fb3a272b4290f50a32c88a739f5620c0066c99 100644 --- a/dev/tests/functional/tests/app/Magento/Checkout/Test/TestStep/AddProductsToTheCartStep.php +++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/TestStep/AddProductsToTheCartStep.php @@ -10,6 +10,7 @@ use Magento\Catalog\Test\Page\Product\CatalogProductView; use Magento\Checkout\Test\Page\CheckoutCart; use Magento\Cms\Test\Page\CmsIndex; use Magento\Mtf\Client\BrowserInterface; +use Magento\Mtf\Fixture\FixtureFactory; use Magento\Mtf\TestStep\TestStepInterface; /** @@ -18,46 +19,53 @@ use Magento\Mtf\TestStep\TestStepInterface; class AddProductsToTheCartStep implements TestStepInterface { /** - * Array with products + * Array with products. * * @var array */ - protected $products; + private $products; /** - * Frontend product view page + * Storefront product view page. * * @var CatalogProductView */ - protected $catalogProductView; + private $catalogProductView; /** - * Page of checkout page + * Page of checkout page. * * @var CheckoutCart */ - protected $checkoutCart; + private $checkoutCart; /** - * Cms index page + * Cms index page. * * @var CmsIndex */ - protected $cmsIndex; + private $cmsIndex; /** - * Interface Browser + * Client Browser instance. * * @var BrowserInterface */ - protected $browser; + private $browser; + + /** + * Fixture factory. + * + * @var FixtureFactory + */ + private $fixtureFactory; /** - * @constructor * @param CatalogProductView $catalogProductView * @param CheckoutCart $checkoutCart * @param CmsIndex $cmsIndex * @param BrowserInterface $browser + * @param FixtureFactory $fixtureFactory * @param array $products */ public function __construct( @@ -65,19 +73,21 @@ class AddProductsToTheCartStep implements TestStepInterface CheckoutCart $checkoutCart, CmsIndex $cmsIndex, BrowserInterface $browser, + FixtureFactory $fixtureFactory, array $products ) { - $this->products = $products; $this->catalogProductView = $catalogProductView; $this->checkoutCart = $checkoutCart; $this->cmsIndex = $cmsIndex; $this->browser = $browser; + $this->fixtureFactory = $fixtureFactory; + $this->products = $products; } /** - * Add products to the cart + * Add products to the cart. * - * @return void + * @return array */ public function run() { @@ -89,5 +99,7 @@ class AddProductsToTheCartStep implements TestStepInterface $this->catalogProductView->getViewBlock()->addToCart($product); $this->catalogProductView->getMessagesBlock()->waitSuccessMessage(); } + $cart['data']['items'] = ['products' => $this->products]; + return ['cart' => $this->fixtureFactory->createByCode('cart', $cart)]; } } diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/TestStep/ClickPlaceOrderButtonStep.php b/dev/tests/functional/tests/app/Magento/Checkout/Test/TestStep/ClickPlaceOrderButtonStep.php new file mode 100644 index 0000000000000000000000000000000000000000..cf086e55d5a305f716f4b64513190b32c7708cba --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/TestStep/ClickPlaceOrderButtonStep.php @@ -0,0 +1,41 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Checkout\Test\TestStep; + +use Magento\Checkout\Test\Page\CheckoutOnepage; +use Magento\Mtf\TestStep\TestStepInterface; + +/** + * Click 'Place order' button. + */ +class ClickPlaceOrderButtonStep implements TestStepInterface +{ + /** + * Onepage checkout page. + * + * @var CheckoutOnepage + */ + private $checkoutOnepage; + + /** + * @param CheckoutOnepage $checkoutOnepage + */ + public function __construct(CheckoutOnepage $checkoutOnepage) + { + $this->checkoutOnepage = $checkoutOnepage; + } + + /** + * Click 'Place order' button. + * + * @return array + */ + public function run() + { + $this->checkoutOnepage->getPaymentBlock()->getSelectedPaymentMethodBlock()->clickPlaceOrder(); + } +} diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/TestStep/GetPlacedOrderIdStep.php b/dev/tests/functional/tests/app/Magento/Checkout/Test/TestStep/GetPlacedOrderIdStep.php new file mode 100644 index 0000000000000000000000000000000000000000..8d4fa8e471fbc18519f9c9cc3a5917c51789a066 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/TestStep/GetPlacedOrderIdStep.php @@ -0,0 +1,74 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Checkout\Test\TestStep; + +use Magento\Mtf\TestStep\TestStepInterface; +use Magento\Checkout\Test\Page\CheckoutOnepageSuccess; +use Magento\Mtf\Util\Protocol\CurlTransport\WebapiDecorator; + +/** + * Get successfully placed order id. + */ +class GetPlacedOrderIdStep implements TestStepInterface +{ + /** + * Order success page. + * + * @var CheckoutOnepageSuccess + */ + private $checkoutOnepageSuccess; + + /** + * Curl transport on webapi. + * + * @var WebapiDecorator + */ + private $decorator; + + /** + * @param CheckoutOnepageSuccess $checkoutOnepageSuccess + * @param WebapiDecorator $decorator + */ + public function __construct( + CheckoutOnepageSuccess $checkoutOnepageSuccess, + WebapiDecorator $decorator + ) { + $this->checkoutOnepageSuccess = $checkoutOnepageSuccess; + $this->decorator = $decorator; + } + + /** + * Get success placed order id. + * + * @return array + */ + public function run() + { + $incrementId = $this->checkoutOnepageSuccess->getSuccessBlock()->getGuestOrderId(); + return [ + 'entityId' => $this->getEntityId($incrementId), + 'orderId' => $incrementId + ]; + } + + /** + * Get order entity id by increment id. + * + * @param string $incrementId + * @return string + */ + private function getEntityId($incrementId) + { + $url = $_ENV['app_frontend_url'] . 'rest/V1/orders/'; + $url .= '?searchCriteria[filterGroups][0][filters][0][field]=increment_id'; + $url .= '&searchCriteria[filterGroups][0][filters][0][value]=' . $incrementId; + $this->decorator->write($url, [], WebapiDecorator::GET); + $response = json_decode($this->decorator->read(), true); + $this->decorator->close(); + return $response['items'][0]['entity_id']; + } +} diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/TestStep/PlaceOrderStep.php b/dev/tests/functional/tests/app/Magento/Checkout/Test/TestStep/PlaceOrderStep.php index 2bfd346fbcaebe0545a3b65ce76af7a8bc52de25..8beada29036b8a3cf2ff367a0b30b59b78faf0e8 100644 --- a/dev/tests/functional/tests/app/Magento/Checkout/Test/TestStep/PlaceOrderStep.php +++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/TestStep/PlaceOrderStep.php @@ -22,41 +22,44 @@ class PlaceOrderStep implements TestStepInterface * * @var CheckoutOnepage */ - protected $checkoutOnepage; + private $checkoutOnepage; /** * Assert that Order Grand Total is correct on checkout page review block. * * @var AssertGrandTotalOrderReview */ - protected $assertGrandTotalOrderReview; + private $assertGrandTotalOrderReview; /** * One page checkout success page. * * @var CheckoutOnepageSuccess */ - protected $checkoutOnepageSuccess; + private $checkoutOnepageSuccess; /** * Price array. * * @var array */ - protected $prices; + private $prices; /** + * Factory for fixtures. + * * @var FixtureFactory */ private $fixtureFactory; /** + * Array of product entities. + * * @var array */ private $products; /** - * @construct * @param CheckoutOnepage $checkoutOnepage * @param AssertGrandTotalOrderReview $assertGrandTotalOrderReview * @param CheckoutOnepageSuccess $checkoutOnepageSuccess @@ -74,10 +77,10 @@ class PlaceOrderStep implements TestStepInterface ) { $this->checkoutOnepage = $checkoutOnepage; $this->assertGrandTotalOrderReview = $assertGrandTotalOrderReview; - $this->prices = $prices; $this->checkoutOnepageSuccess = $checkoutOnepageSuccess; $this->fixtureFactory = $fixtureFactory; $this->products = $products; + $this->prices = $prices; } /** @@ -91,18 +94,20 @@ class PlaceOrderStep implements TestStepInterface $this->assertGrandTotalOrderReview->processAssert($this->checkoutOnepage, $this->prices['grandTotal']); } $this->checkoutOnepage->getPaymentBlock()->getSelectedPaymentMethodBlock()->clickPlaceOrder(); + $orderId = $this->checkoutOnepageSuccess->getSuccessBlock()->getGuestOrderId(); $order = $this->fixtureFactory->createByCode( 'orderInjectable', [ 'data' => [ - 'entity_id' => ['products' => $this->products] + 'id' => $orderId, + 'entity_id' => ['products' => $this->products], ] ] ); return [ - 'orderId' => $this->checkoutOnepageSuccess->getSuccessBlock()->getGuestOrderId(), - 'order' => $order + 'orderId' => $orderId, + 'order' => $order, ]; } } diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/TestStep/SelectCheckoutMethodStep.php b/dev/tests/functional/tests/app/Magento/Checkout/Test/TestStep/SelectCheckoutMethodStep.php index cb32e5f0ddfe61d9e97e8ef211ce71bfa46ee71a..3af915e22bfcb1c85ebb53b84872ef4ed255fac2 100644 --- a/dev/tests/functional/tests/app/Magento/Checkout/Test/TestStep/SelectCheckoutMethodStep.php +++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/TestStep/SelectCheckoutMethodStep.php @@ -59,13 +59,6 @@ class SelectCheckoutMethodStep implements TestStepInterface */ private $customerAccountCreatePage; - /** - * Shipping carrier and method. - * - * @var array - */ - protected $shipping; - /** * @constructor * @param CheckoutOnepage $checkoutOnepage @@ -74,7 +67,6 @@ class SelectCheckoutMethodStep implements TestStepInterface * @param LogoutCustomerOnFrontendStep $logoutCustomerOnFrontend * @param ClickProceedToCheckoutStep $clickProceedToCheckoutStep * @param string $checkoutMethod - * @param array $shipping */ public function __construct( CheckoutOnepage $checkoutOnepage, @@ -82,8 +74,7 @@ class SelectCheckoutMethodStep implements TestStepInterface Customer $customer, LogoutCustomerOnFrontendStep $logoutCustomerOnFrontend, ClickProceedToCheckoutStep $clickProceedToCheckoutStep, - $checkoutMethod, - array $shipping = [] + $checkoutMethod ) { $this->checkoutOnepage = $checkoutOnepage; $this->customerAccountCreatePage = $customerAccountCreatePage; @@ -91,7 +82,6 @@ class SelectCheckoutMethodStep implements TestStepInterface $this->logoutCustomerOnFrontend = $logoutCustomerOnFrontend; $this->clickProceedToCheckoutStep = $clickProceedToCheckoutStep; $this->checkoutMethod = $checkoutMethod; - $this->shipping = $shipping; } /** @@ -120,9 +110,7 @@ class SelectCheckoutMethodStep implements TestStepInterface $this->checkoutOnepage->getLoginBlock()->loginCustomer($this->customer); } } elseif ($this->checkoutMethod === 'guest') { - if (empty($this->shipping)) { - $this->checkoutOnepage->getLoginBlock()->fillGuestFields($this->customer); - } + $this->checkoutOnepage->getLoginBlock()->fillGuestFields($this->customer); } elseif ($this->checkoutMethod === 'sign_in') { $this->checkoutOnepage->getAuthenticationWrapperBlock()->signInLinkClick(); $this->checkoutOnepage->getAuthenticationWrapperBlock()->loginCustomer($this->customer); diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/TestStep/SelectPaymentMethodStep.php b/dev/tests/functional/tests/app/Magento/Checkout/Test/TestStep/SelectPaymentMethodStep.php index 1f5d80bdbde49f35a62dad5dd9fbefb326107b45..5eea876f02b40c6dd93de18d9f7c378179772756 100644 --- a/dev/tests/functional/tests/app/Magento/Checkout/Test/TestStep/SelectPaymentMethodStep.php +++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/TestStep/SelectPaymentMethodStep.php @@ -7,68 +7,73 @@ namespace Magento\Checkout\Test\TestStep; use Magento\Checkout\Test\Page\CheckoutOnepage; -use Magento\Mtf\Fixture\FixtureFactory; use Magento\Mtf\TestStep\TestStepInterface; use Magento\Payment\Test\Fixture\CreditCard; /** - * Class SelectPaymentMethodStep - * Selecting payment method + * Select payment method step. */ class SelectPaymentMethodStep implements TestStepInterface { /** - * Onepage checkout page + * Onepage checkout page. * * @var CheckoutOnepage */ protected $checkoutOnepage; /** - * Payment information + * Payment information. * * @var string */ protected $payment; /** - * Credit card information + * Credit card information. * * @var string */ protected $creditCard; /** - * @constructor + * If fill credit card data should be filled on 3rd party side. + * + * @var bool + */ + private $fillCreditCardOn3rdParty; + + /** * @param CheckoutOnepage $checkoutOnepage * @param array $payment - * @param FixtureFactory $fixtureFactory - * @param string $creditCardClass - * @param array|CreditCard|null $creditCard + * @param CreditCard|null $creditCard + * @param bool $fillCreditCardOn3rdParty */ public function __construct( CheckoutOnepage $checkoutOnepage, array $payment, - FixtureFactory $fixtureFactory, - $creditCardClass = 'credit_card', - $creditCard = null + CreditCard $creditCard = null, + $fillCreditCardOn3rdParty = false ) { $this->checkoutOnepage = $checkoutOnepage; $this->payment = $payment; - if (isset($creditCard['dataset'])) { - $this->creditCard = $fixtureFactory->createByCode($creditCardClass, ['dataset' => $creditCard['dataset']]); - } + $this->creditCard = $creditCard; + $this->fillCreditCardOn3rdParty = $fillCreditCardOn3rdParty; } /** - * Run step that selecting payment method + * Run step that selecting payment method. * * @return void */ public function run() { if ($this->payment['method'] !== 'free') { - $this->checkoutOnepage->getPaymentBlock()->selectPaymentMethod($this->payment, $this->creditCard); + $this->checkoutOnepage->getPaymentBlock()->selectPaymentMethod( + $this->payment, + $this->creditCard, + $this->fillCreditCardOn3rdParty + ); } } } diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/etc/di.xml b/dev/tests/functional/tests/app/Magento/Checkout/Test/etc/di.xml index 24b369200e71d99df604457603969594b40862ca..0a0622936a23d7688cf0e94b61ebc2ef56d052f4 100644 --- a/dev/tests/functional/tests/app/Magento/Checkout/Test/etc/di.xml +++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/etc/di.xml @@ -7,9 +7,9 @@ --> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd"> - <type name="Magento\Checkout\Test\Constraint\AssertCartIsEmpty"> + <type name="Magento\Checkout\Test\Constraint\AssertAddedProductToCartSuccessMessage"> <arguments> - <argument name="severity" xsi:type="string">middle</argument> + <argument name="severity" xsi:type="string">S2</argument> </arguments> </type> <type name="Magento\Checkout\Test\Constraint\AssertBillingAddressAbsentInPayment"> @@ -17,9 +17,149 @@ <argument name="severity" xsi:type="string">S2</argument> </arguments> </type> + <type name="Magento\Checkout\Test\Constraint\AssertBillingAddressSameAsShippingCheckbox"> + <arguments> + <argument name="severity" xsi:type="string">S2</argument> + </arguments> + </type> + <type name="Magento\Checkout\Test\Constraint\AssertCartIsEmpty"> + <arguments> + <argument name="severity" xsi:type="string">S2</argument> + </arguments> + </type> + <type name="Magento\Checkout\Test\Constraint\AssertCartItemsOptions"> + <arguments> + <argument name="severity" xsi:type="string">S2</argument> + </arguments> + </type> + <type name="Magento\Checkout\Test\Constraint\AssertCheckoutErrorMessage"> + <arguments> + <argument name="severity" xsi:type="string">S1</argument> + </arguments> + </type> + <type name="Magento\Checkout\Test\Constraint\AssertCustomerIsRedirectedToCheckoutFromCart"> + <arguments> + <argument name="severity" xsi:type="string">S2</argument> + </arguments> + </type> + <type name="Magento\Checkout\Test\Constraint\AssertDiscountInShoppingCart"> + <arguments> + <argument name="severity" xsi:type="string">S2</argument> + </arguments> + </type> + <type name="Magento\Checkout\Test\Constraint\AssertEstimateShippingAndTax"> + <arguments> + <argument name="severity" xsi:type="string">S2</argument> + </arguments> + </type> + <type name="Magento\Checkout\Test\Constraint\AssertGrandTotalInShoppingCart"> + <arguments> + <argument name="severity" xsi:type="string">S2</argument> + </arguments> + </type> + <type name="Magento\Checkout\Test\Constraint\AssertGrandTotalOrderReview"> + <arguments> + <argument name="severity" xsi:type="string">S2</argument> + </arguments> + </type> + <type name="Magento\Checkout\Test\Constraint\AssertMinicartEmpty"> + <arguments> + <argument name="severity" xsi:type="string">S2</argument> + </arguments> + </type> <type name="Magento\Checkout\Test\Constraint\AssertOrderSuccessPlacedMessage"> <arguments> <argument name="severity" xsi:type="string">S0</argument> </arguments> </type> + <type name="Magento\Checkout\Test\Constraint\AssertPriceInShoppingCart"> + <arguments> + <argument name="severity" xsi:type="string">S2</argument> + </arguments> + </type> + <type name="Magento\Checkout\Test\Constraint\AssertProductAbsentInMiniShoppingCart"> + <arguments> + <argument name="severity" xsi:type="string">S2</argument> + </arguments> + </type> + <type name="Magento\Checkout\Test\Constraint\AssertProductDataInMiniShoppingCart"> + <arguments> + <argument name="severity" xsi:type="string">S2</argument> + </arguments> + </type> + <type name="Magento\Checkout\Test\Constraint\AssertProductIsNotEditable"> + <arguments> + <argument name="severity" xsi:type="string">S2</argument> + </arguments> + </type> + <type name="Magento\Checkout\Test\Constraint\AssertProductOptionsAbsentInShoppingCart"> + <arguments> + <argument name="severity" xsi:type="string">S2</argument> + </arguments> + </type> + <type name="Magento\Checkout\Test\Constraint\AssertProductPresentInMiniShoppingCart"> + <arguments> + <argument name="severity" xsi:type="string">S2</argument> + </arguments> + </type> + <type name="Magento\Checkout\Test\Constraint\AssertProductQtyInShoppingCart"> + <arguments> + <argument name="severity" xsi:type="string">S2</argument> + </arguments> + </type> + <type name="Magento\Checkout\Test\Constraint\AssertProductsAbsentInShoppingCart"> + <arguments> + <argument name="severity" xsi:type="string">S2</argument> + </arguments> + </type> + <type name="Magento\Checkout\Test\Constraint\AssertShippingAddressJsValidationMessagesIsAbsent"> + <arguments> + <argument name="severity" xsi:type="string">S2</argument> + </arguments> + </type> + <type name="Magento\Checkout\Test\Constraint\AssertShippingInShoppingCart"> + <arguments> + <argument name="severity" xsi:type="string">S2</argument> + </arguments> + </type> + <type name="Magento\Checkout\Test\Constraint\AssertShippingTotalOrderReview"> + <arguments> + <argument name="severity" xsi:type="string">S2</argument> + </arguments> + </type> + <type name="Magento\Checkout\Test\Constraint\AssertSubtotalInMiniShoppingCart"> + <arguments> + <argument name="severity" xsi:type="string">S2</argument> + </arguments> + </type> + <type name="Magento\Checkout\Test\Constraint\AssertSubtotalInShoppingCart"> + <arguments> + <argument name="severity" xsi:type="string">S2</argument> + </arguments> + </type> + <type name="Magento\Checkout\Test\Constraint\AssertSubTotalOrderReview"> + <arguments> + <argument name="severity" xsi:type="string">S2</argument> + </arguments> + </type> + <type name="Magento\Checkout\Test\Constraint\AssertTaxInShoppingCart"> + <arguments> + <argument name="severity" xsi:type="string">S2</argument> + </arguments> + </type> + <type name="Magento\Checkout\Test\Constraint\AssertTaxTotalOrderReview"> + <arguments> + <argument name="severity" xsi:type="string">S2</argument> + </arguments> + </type> + <type name="Magento\Checkout\Test\Constraint\AssertCancelSuccessMessageInShoppingCart"> + <arguments> + <argument name="severity" xsi:type="string">S1</argument> + </arguments> + </type> + <type name="Magento\Checkout\Test\Constraint\AssertProductPresentInShoppingCart"> + <arguments> + <argument name="severity" xsi:type="string">S0</argument> + </arguments> + </type> </config> diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/etc/testcase.xml b/dev/tests/functional/tests/app/Magento/Checkout/Test/etc/testcase.xml index 24eb96c0a9347741384ffd6718bf349eeb452c85..e9b49babbba1936aae49b20339a56732b5b2531b 100644 --- a/dev/tests/functional/tests/app/Magento/Checkout/Test/etc/testcase.xml +++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/etc/testcase.xml @@ -28,4 +28,17 @@ <step name="addProductsToTheCart" module="Magento_Checkout" next="ProceedToCheckout" /> <step name="ProceedToCheckout" module="Magento_Checkout" /> </scenario> + <scenario name="OnePageCheckoutDeclinedTest" firstStep="setupConfiguration"> + <step name="setupConfiguration" module="Magento_Config" next="createProducts" /> + <step name="createProducts" module="Magento_Catalog" next="addProductsToTheCart" /> + <step name="addProductsToTheCart" module="Magento_Checkout" next="proceedToCheckout" /> + <step name="proceedToCheckout" module="Magento_Checkout" next="createCustomer" /> + <step name="createCustomer" module="Magento_Customer" next="selectCheckoutMethod" /> + <step name="selectCheckoutMethod" module="Magento_Checkout" next="fillShippingAddress" /> + <step name="fillShippingAddress" module="Magento_Checkout" next="fillShippingMethod" /> + <step name="fillShippingMethod" module="Magento_Checkout" next="selectPaymentMethod" /> + <step name="selectPaymentMethod" module="Magento_Checkout" next="fillBillingInformation" /> + <step name="fillBillingInformation" module="Magento_Checkout" next="clickPlaceOrderButton" /> + <step name="clickPlaceOrderButton" module="Magento_Checkout" /> + </scenario> </config> diff --git a/dev/tests/functional/tests/app/Magento/CheckoutAgreements/Test/TestCase/CreateTermEntityTest.php b/dev/tests/functional/tests/app/Magento/CheckoutAgreements/Test/TestCase/CreateTermEntityTest.php index 21f48abef963d288415d09b24d08a3fe8fd34ebe..b397b73f3a43d6c3d819d105e82efdb48568ec76 100644 --- a/dev/tests/functional/tests/app/Magento/CheckoutAgreements/Test/TestCase/CreateTermEntityTest.php +++ b/dev/tests/functional/tests/app/Magento/CheckoutAgreements/Test/TestCase/CreateTermEntityTest.php @@ -27,6 +27,7 @@ class CreateTermEntityTest extends Scenario /* tags */ const MVP = 'yes'; const TEST_TYPE = 'extended_acceptance_test'; + const SEVERITY = 'S3'; /* end tags */ /** diff --git a/dev/tests/functional/tests/app/Magento/CheckoutAgreements/Test/TestCase/CreateTermEntityTest.xml b/dev/tests/functional/tests/app/Magento/CheckoutAgreements/Test/TestCase/CreateTermEntityTest.xml index 8b1c1929d0f9d068d5a78382beb8237e3dced4fe..8f418b92e09a5ff53c44d3d4bacd538347e2ccfa 100644 --- a/dev/tests/functional/tests/app/Magento/CheckoutAgreements/Test/TestCase/CreateTermEntityTest.xml +++ b/dev/tests/functional/tests/app/Magento/CheckoutAgreements/Test/TestCase/CreateTermEntityTest.xml @@ -8,7 +8,7 @@ <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd"> <testCase name="Magento\CheckoutAgreements\Test\TestCase\CreateTermEntityTest" summary="Create Terms And Conditions" ticketId="MAGETWO-29586"> <variation name="CreateTermEntityTestVariation1" summary="Create enabled term entity with text value"> - <data name="tag" xsi:type="string">test_type:extended_acceptance_test</data> + <data name="tag" xsi:type="string">test_type:extended_acceptance_test, severity:S3</data> <data name="configData" xsi:type="string">checkout_term_condition</data> <data name="products/0" xsi:type="string">catalogProductSimple::default</data> <data name="agreement/data/name" xsi:type="string">name%isolation%</data> @@ -26,6 +26,7 @@ <constraint name="Magento\CheckoutAgreements\Test\Constraint\AssertTermOnCheckout" /> </variation> <variation name="CreateTermEntityTestVariation2" summary="Create enabled term entity with HTML value"> + <data name="tag" xsi:type="string">severity:S3</data> <data name="configData" xsi:type="string">checkout_term_condition</data> <data name="products/0" xsi:type="string">catalogProductSimple::default</data> <data name="agreement/data/name" xsi:type="string">name%isolation%</data> @@ -43,6 +44,7 @@ <constraint name="Magento\CheckoutAgreements\Test\Constraint\AssertTermOnCheckout" /> </variation> <variation name="CreateTermEntityTestVariation3" summary="Create disabled term entity"> + <data name="tag" xsi:type="string">severity:S3</data> <data name="configData" xsi:type="string">checkout_term_condition</data> <data name="products/0" xsi:type="string">catalogProductSimple::default</data> <data name="agreement/data/name" xsi:type="string">name%isolation%</data> @@ -60,7 +62,7 @@ <constraint name="Magento\CheckoutAgreements\Test\Constraint\AssertTermAbsentOnCheckout" /> </variation> <variation name="CreateTermEntityTestVariation4" summary="Terms and conditions on multishipping" ticketId="MAGETWO-32499"> - <data name="tag" xsi:type="string">test_type:extended_acceptance_test</data> + <data name="tag" xsi:type="string">test_type:extended_acceptance_test, severity:S3</data> <data name="configData" xsi:type="string">checkout_term_condition</data> <data name="products/0" xsi:type="string">catalogProductSimple::default</data> <data name="products/1" xsi:type="string">catalogProductSimple::default</data> diff --git a/dev/tests/functional/tests/app/Magento/CheckoutAgreements/Test/TestCase/DeleteTermEntityTest.php b/dev/tests/functional/tests/app/Magento/CheckoutAgreements/Test/TestCase/DeleteTermEntityTest.php index 2c65150aa697371c1fe050e5e4f5f9dfbdcb25b1..0f7dd2c1bf1631557de590ee37fb804c020c5ad9 100644 --- a/dev/tests/functional/tests/app/Magento/CheckoutAgreements/Test/TestCase/DeleteTermEntityTest.php +++ b/dev/tests/functional/tests/app/Magento/CheckoutAgreements/Test/TestCase/DeleteTermEntityTest.php @@ -26,6 +26,7 @@ class DeleteTermEntityTest extends Scenario { /* tags */ const MVP = 'yes'; + const SEVERITY = 'S3'; /* end tags */ /** diff --git a/dev/tests/functional/tests/app/Magento/CheckoutAgreements/Test/TestCase/DeleteTermEntityTest.xml b/dev/tests/functional/tests/app/Magento/CheckoutAgreements/Test/TestCase/DeleteTermEntityTest.xml index 50e4af5a2dc36ce151de313ad22fc906921a59ac..3bfd5a63cc4e387c3ec52cba76def7601eff5cb1 100644 --- a/dev/tests/functional/tests/app/Magento/CheckoutAgreements/Test/TestCase/DeleteTermEntityTest.xml +++ b/dev/tests/functional/tests/app/Magento/CheckoutAgreements/Test/TestCase/DeleteTermEntityTest.xml @@ -8,6 +8,7 @@ <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd"> <testCase name="Magento\CheckoutAgreements\Test\TestCase\DeleteTermEntityTest" summary="Delete Terms And Conditions" ticketId="MAGETWO-29687"> <variation name="DeleteTermEntityTestVariation1"> + <data name="tag" xsi:type="string">severity:S3</data> <data name="configData" xsi:type="string">checkout_term_condition</data> <data name="products/0" xsi:type="string">catalogProductSimple::default</data> <data name="agreement/dataset" xsi:type="string">term_enabled_text</data> diff --git a/dev/tests/functional/tests/app/Magento/CheckoutAgreements/Test/TestCase/NavigateMenuTest.xml b/dev/tests/functional/tests/app/Magento/CheckoutAgreements/Test/TestCase/NavigateMenuTest.xml index 1387c7e1e1268085d100112302054fa9c374cde5..57580e2f10e1dc07a8034b414a28b556b6337897 100644 --- a/dev/tests/functional/tests/app/Magento/CheckoutAgreements/Test/TestCase/NavigateMenuTest.xml +++ b/dev/tests/functional/tests/app/Magento/CheckoutAgreements/Test/TestCase/NavigateMenuTest.xml @@ -8,6 +8,7 @@ <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd"> <testCase name="Magento\Backend\Test\TestCase\NavigateMenuTest"> <variation name="NavigateMenuTest17"> + <data name="tag" xsi:type="string">severity:S2</data> <data name="menuItem" xsi:type="string">Stores > Terms and Conditions</data> <data name="pageTitle" xsi:type="string">Terms and Conditions</data> <constraint name="Magento\Backend\Test\Constraint\AssertBackendPageIsAvailable"/> diff --git a/dev/tests/functional/tests/app/Magento/CheckoutAgreements/Test/TestCase/UpdateTermEntityTest.php b/dev/tests/functional/tests/app/Magento/CheckoutAgreements/Test/TestCase/UpdateTermEntityTest.php index 277f38e0c7e1f1bdda9f122183415b35aa772f40..4266338ac6ef7818a5a670646be2090c64bf20a9 100644 --- a/dev/tests/functional/tests/app/Magento/CheckoutAgreements/Test/TestCase/UpdateTermEntityTest.php +++ b/dev/tests/functional/tests/app/Magento/CheckoutAgreements/Test/TestCase/UpdateTermEntityTest.php @@ -27,6 +27,7 @@ class UpdateTermEntityTest extends Scenario { /* tags */ const MVP = 'yes'; + const SEVERITY = 'S2'; /* end tags */ /** diff --git a/dev/tests/functional/tests/app/Magento/CheckoutAgreements/Test/TestCase/UpdateTermEntityTest.xml b/dev/tests/functional/tests/app/Magento/CheckoutAgreements/Test/TestCase/UpdateTermEntityTest.xml index 69ea6309843d1ad7452c463a7d951675c745714d..537c61d83d7b5d079a6e80a174544f5aa7cbbead 100644 --- a/dev/tests/functional/tests/app/Magento/CheckoutAgreements/Test/TestCase/UpdateTermEntityTest.xml +++ b/dev/tests/functional/tests/app/Magento/CheckoutAgreements/Test/TestCase/UpdateTermEntityTest.xml @@ -8,6 +8,7 @@ <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd"> <testCase name="Magento\CheckoutAgreements\Test\TestCase\UpdateTermEntityTest" summary="Update Terms And Conditions" ticketId="MAGETWO-29635"> <variation name="UpdateTermEntityTestVariation1"> + <data name="tag" xsi:type="string">severity:S2</data> <data name="configData" xsi:type="string">checkout_term_condition</data> <data name="products/0" xsi:type="string">catalogProductSimple::default</data> <data name="agreement/dataset" xsi:type="string">term_disabled_text</data> @@ -26,6 +27,7 @@ <constraint name="Magento\CheckoutAgreements\Test\Constraint\AssertTermOnCheckout" /> </variation> <variation name="UpdateTermEntityTestVariation2"> + <data name="tag" xsi:type="string">severity:S3</data> <data name="configData" xsi:type="string">checkout_term_condition</data> <data name="products/0" xsi:type="string">catalogProductSimple::default</data> <data name="agreement/dataset" xsi:type="string">term_disabled_html</data> @@ -44,6 +46,7 @@ <constraint name="Magento\CheckoutAgreements\Test\Constraint\AssertTermOnCheckout" /> </variation> <variation name="UpdateTermEntityTestVariation3"> + <data name="tag" xsi:type="string">severity:S3</data> <data name="configData" xsi:type="string">checkout_term_condition</data> <data name="products/0" xsi:type="string">catalogProductSimple::default</data> <data name="agreement/dataset" xsi:type="string">term_enabled_text</data> diff --git a/dev/tests/functional/tests/app/Magento/CheckoutAgreements/Test/etc/di.xml b/dev/tests/functional/tests/app/Magento/CheckoutAgreements/Test/etc/di.xml index 7dc8356351f2f7228a2c4ac5ceec524380dcd5e6..66381d8985802ed12fd9a83633e2ef8c1eebc75c 100644 --- a/dev/tests/functional/tests/app/Magento/CheckoutAgreements/Test/etc/di.xml +++ b/dev/tests/functional/tests/app/Magento/CheckoutAgreements/Test/etc/di.xml @@ -6,9 +6,39 @@ */ --> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd"> - <type name="Magento\CheckoutAgreements\Test\Constraint\AssertTermRequireMessageOnMultishippingCheckout"> - <arguments> - <argument name="severity" xsi:type="string">high</argument> - </arguments> - </type> + <type name="Magento\CheckoutAgreements\Test\Constraint\AssertTermRequireMessageOnMultishippingCheckout"> + <arguments> + <argument name="severity" xsi:type="string">S3</argument> + </arguments> + </type> + <type name="Magento\CheckoutAgreements\Test\Constraint\AssertTermSuccessSaveMessage"> + <arguments> + <argument name="severity" xsi:type="string">S2</argument> + </arguments> + </type> + <type name="Magento\CheckoutAgreements\Test\Constraint\AssertTermInGrid"> + <arguments> + <argument name="severity" xsi:type="string">S2</argument> + </arguments> + </type> + <type name="Magento\CheckoutAgreements\Test\Constraint\AssertTermOnCheckout"> + <arguments> + <argument name="severity" xsi:type="string">S2</argument> + </arguments> + </type> + <type name="Magento\CheckoutAgreements\Test\Constraint\AssertTermAbsentOnCheckout"> + <arguments> + <argument name="severity" xsi:type="string">S2</argument> + </arguments> + </type> + <type name="Magento\CheckoutAgreements\Test\Constraint\AssertTermSuccessDeleteMessage"> + <arguments> + <argument name="severity" xsi:type="string">S2</argument> + </arguments> + </type> + <type name="Magento\CheckoutAgreements\Test\Constraint\AssertTermAbsentInGrid"> + <arguments> + <argument name="severity" xsi:type="string">S3</argument> + </arguments> + </type> </config> diff --git a/dev/tests/functional/tests/app/Magento/Cms/Test/TestCase/GridFilteringTest.xml b/dev/tests/functional/tests/app/Magento/Cms/Test/TestCase/GridFilteringTest.xml index 715190039162b4fdbab91af72ca564e0c0732858..0b237e506636cf1beb8ff22122c515079cda176e 100644 --- a/dev/tests/functional/tests/app/Magento/Cms/Test/TestCase/GridFilteringTest.xml +++ b/dev/tests/functional/tests/app/Magento/Cms/Test/TestCase/GridFilteringTest.xml @@ -8,7 +8,7 @@ <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd"> <testCase name="Magento\Ui\Test\TestCase\GridFilteringTest" summary="Grid UI Component Filtering" ticketId="MAGETWO-41329"> <variation name="CmsPageGridFiltering"> - <data name="tag" xsi:type="string">severity:S2</data> + <data name="tag" xsi:type="string">severity:S3</data> <data name="description" xsi:type="string">Verify cms page grid filtering</data> <data name="itemsCount" xsi:type="string">2</data> <data name="fixtureName" xsi:type="string">cmsPage</data> @@ -29,7 +29,7 @@ <constraint name="\Magento\Ui\Test\Constraint\AssertGridFiltering"/> </variation> <variation name="CmsBlockGridFiltering"> - <data name="tag" xsi:type="string">severity:S2</data> + <data name="tag" xsi:type="string">severity:S3</data> <data name="description" xsi:type="string">Verify cms block grid filtering</data> <data name="itemsCount" xsi:type="string">2</data> <data name="fixtureName" xsi:type="string">cmsBlock</data> diff --git a/dev/tests/functional/tests/app/Magento/Cms/Test/TestCase/GridFullTextSearchTest.xml b/dev/tests/functional/tests/app/Magento/Cms/Test/TestCase/GridFullTextSearchTest.xml index fc279aad59d3d7e21590be2c256f83831e7295cf..b17f32db04b23727a6583db5227dbf79d0f0d19d 100644 --- a/dev/tests/functional/tests/app/Magento/Cms/Test/TestCase/GridFullTextSearchTest.xml +++ b/dev/tests/functional/tests/app/Magento/Cms/Test/TestCase/GridFullTextSearchTest.xml @@ -8,7 +8,7 @@ <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd"> <testCase name="Magento\Ui\Test\TestCase\GridFullTextSearchTest" summary="Grid UI Component Full Text Search" ticketId="MAGETWO-41023"> <variation name="CmsPageGridFullTextSearch"> - <data name="tag" xsi:type="string">severity:S2, stable:no</data> + <data name="tag" xsi:type="string">severity:S3, stable:no</data> <data name="description" xsi:type="string">Verify cms page grid full text search</data> <data name="itemsCount" xsi:type="string">2</data> <data name="fixtureName" xsi:type="string">cmsPage</data> @@ -20,7 +20,7 @@ <constraint name="Magento\Ui\Test\Constraint\AssertGridFullTextSearch"/> </variation> <variation name="CmsBlockGridFullTextSearch"> - <data name="tag" xsi:type="string">severity:S2</data> + <data name="tag" xsi:type="string">severity:S3</data> <data name="description" xsi:type="string">Verify cms blocks grid full text search</data> <data name="itemsCount" xsi:type="string">2</data> <data name="fixtureName" xsi:type="string">cmsBlock</data> diff --git a/dev/tests/functional/tests/app/Magento/Cms/Test/TestCase/GridSortingTest.xml b/dev/tests/functional/tests/app/Magento/Cms/Test/TestCase/GridSortingTest.xml index 1be7e61f6bd0ea27a99733a63828f438ab481215..053d32a0598ef1677cf67c83c307aa2352ac7803 100644 --- a/dev/tests/functional/tests/app/Magento/Cms/Test/TestCase/GridSortingTest.xml +++ b/dev/tests/functional/tests/app/Magento/Cms/Test/TestCase/GridSortingTest.xml @@ -8,7 +8,7 @@ <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd"> <testCase name="Magento\Ui\Test\TestCase\GridSortingTest" summary="Grid UI Component Sorting" ticketId="MAGETWO-41328"> <variation name="CmsPagesGridSorting"> - <data name="tag" xsi:type="string">severity:S2, stable:no</data> + <data name="tag" xsi:type="string">severity:S3, stable:no</data> <data name="description" xsi:type="string">Verify cms page grid sorting</data> <data name="columnsForSorting" xsi:type="array"> <item name="id" xsi:type="string">ID</item> @@ -19,7 +19,7 @@ <constraint name="Magento\Ui\Test\Constraint\AssertGridSorting"/> </variation> <variation name="CmsBlocksGridSorting"> - <data name="tag" xsi:type="string">severity:S2, stable:no</data> + <data name="tag" xsi:type="string">severity:S3, stable:no</data> <data name="description" xsi:type="string">Verify cms blocks grid sorting</data> <data name="steps" xsi:type="array"> <item name="0" xsi:type="string">-</item> diff --git a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Product/View/ConfigurableOptions.php b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Product/View/ConfigurableOptions.php index d5279557ec5af84902fbc2a57548df2dcf0aadf6..4edee00a57dbefd8a15846731fa7e888b66186ad 100644 --- a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Product/View/ConfigurableOptions.php +++ b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Product/View/ConfigurableOptions.php @@ -34,6 +34,13 @@ class ConfigurableOptions extends CustomOptions */ protected $priceBlock = '//*[@class="product-info-main"]//*[contains(@class,"price-box")]'; + /** + * Selector for tier prices. + * + * @var string + */ + private $tierPricesSelector = '.prices-tier li'; + /** * Get configurable product options * @@ -93,11 +100,16 @@ class ConfigurableOptions extends CustomOptions } $productVariations = array_keys($productVariations); - $result = []; foreach ($productVariations as $variation) { $variationOptions = explode(' ', $variation); - $result[$variation]['price'] = $this->getOptionPrice($variationOptions, $attributesData); + //Select all options specified in variation + $this->chooseOptions($variationOptions, $attributesData); + $result[$variation]['price'] = $this->getOptionPrice(); + $tierPrices = $this->getOptionTierPrices(); + if (count($tierPrices) > 0) { + $result[$variation]['tierPrices'] = $tierPrices; + } } return $result; @@ -106,25 +118,34 @@ class ConfigurableOptions extends CustomOptions /** * Get option price * - * @param array $variationOptions - * @param array $attributesData * @return null|string */ - protected function getOptionPrice($variationOptions, $attributesData) + protected function getOptionPrice() { - //Select all options specified in variation - foreach ($variationOptions as $variationSelection) { - list ($attribute, $option) = explode(':', $variationSelection); - $attributeTitle = $attributesData[$attribute]['label']; - $optionTitle = $attributesData[$attribute]['options'][$option]['label']; - $this->selectOption($attributeTitle, $optionTitle); - } - $priceBlock = $this->getPriceBlock(); $price = ($priceBlock->isOldPriceVisible()) ? $priceBlock->getOldPrice() : $priceBlock->getPrice(); return $price; } + /** + * Get tier prices of all variations + * + * @return array + */ + private function getOptionTierPrices() + { + $prices = []; + $tierPricesNodes = $this->_rootElement->getElements($this->tierPricesSelector); + foreach ($tierPricesNodes as $node) { + preg_match('#^[^\d]+(\d+)[^\d]+(\d+(?:(?:,\d+)*)+(?:.\d+)*).*#i', $node->getText(), $matches); + $prices[] = [ + 'qty' => isset($matches[1]) ? $matches[1] : null, + 'price_qty' => isset($matches[2]) ? $matches[2] : null, + ]; + } + return $prices; + } + /** * Get block price. * @@ -139,6 +160,8 @@ class ConfigurableOptions extends CustomOptions } /** + * Select option from the select element. + * * @param string $attributeTitle * @param string $optionTitle */ @@ -147,4 +170,22 @@ class ConfigurableOptions extends CustomOptions $this->_rootElement->find(sprintf($this->optionSelector, $attributeTitle), Locator::SELECTOR_XPATH, 'select') ->setValue($optionTitle); } + + /** + * Choose options of the configurable product + * + * @param $variationOptions + * @param $attributesData + * @return void + */ + protected function chooseOptions($variationOptions, $attributesData) + { + //Select all options specified in variation + foreach ($variationOptions as $variationSelection) { + list ($attribute, $option) = explode(':', $variationSelection); + $attributeTitle = $attributesData[$attribute]['label']; + $optionTitle = $attributesData[$attribute]['options'][$option]['label']; + $this->selectOption($attributeTitle, $optionTitle); + } + } } diff --git a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Constraint/AssertProductTierPriceOnProductPage.php b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Constraint/AssertProductTierPriceOnProductPage.php new file mode 100644 index 0000000000000000000000000000000000000000..74c885a727880edffd79717f5f30689135a3704d --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Constraint/AssertProductTierPriceOnProductPage.php @@ -0,0 +1,47 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\ConfigurableProduct\Test\Constraint; + +use Magento\Catalog\Test\Constraint\AssertProductPage; +use Magento\ConfigurableProduct\Test\Block\Product\View\ConfigurableOptions; + +/** + * Open created configurble product on frontend and choose variation with tier price + */ +class AssertProductTierPriceOnProductPage extends AssertProductPage +{ + /** + * Verify that tier prices configured for all variations of configured product displayed as expected. + * + * @return array + */ + public function verify() + { + $errors = []; + /** @var ConfigurableOptions $optionsBlock */ + $optionsBlock = $this->pageView->getConfigurableAttributesBlock(); + $formTierPrices = $optionsBlock->getOptionsPrices($this->product); + $products = ($this->product->getDataFieldConfig('configurable_attributes_data')['source'])->getProducts(); + foreach ($products as $key => $product) { + $configuredTierPrice = []; + $actualTierPrices = isset($formTierPrices[$key]['tierPrices']) ? $formTierPrices[$key]['tierPrices'] : []; + $tierPrices = $product->getTierPrice() ?: []; + foreach ($tierPrices as $tierPrice) { + $configuredTierPrice[] = [ + 'qty' => $tierPrice['price_qty'], + 'price_qty' => $tierPrice['price'], + ]; + } + + if ($configuredTierPrice != $actualTierPrices) { + $errors[] = sprintf('Tier prices for variation %s doesn\'t equals to configured.', $key); + } + } + + return $errors; + } +} diff --git a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Fixture/Cart/Item.php b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Fixture/Cart/Item.php index d2a999627cb95d8336314bc643e194e5fb3461c8..46cf2ceefe8ac9e830b029e0357c0735465503b2 100644 --- a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Fixture/Cart/Item.php +++ b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Fixture/Cart/Item.php @@ -6,9 +6,6 @@ namespace Magento\ConfigurableProduct\Test\Fixture\Cart; -use Magento\ConfigurableProduct\Test\Fixture\ConfigurableProduct; -use Magento\Mtf\Fixture\FixtureInterface; - /** * Data for verify cart item block on checkout page. * @@ -20,25 +17,27 @@ use Magento\Mtf\Fixture\FixtureInterface; class Item extends \Magento\Catalog\Test\Fixture\Cart\Item { /** - * @constructor - * @param FixtureInterface $product + * Return prepared dataset. + * + * @param null|string $key + * @return array */ - public function __construct(FixtureInterface $product) + public function getData($key = null) { - parent::__construct($product); - - /** @var ConfigurableProduct $product */ - $checkoutData = $product->getCheckoutData(); + parent::getData($key); + $productData = $this->product->getData(); + $checkoutData = $this->product->getCheckoutData(); $cartItem = isset($checkoutData['cartItem']) ? $checkoutData['cartItem'] : []; - $attributesData = $product->getConfigurableAttributesData()['attributes_data']; + $attributesData = $this->product->getConfigurableAttributesData()['attributes_data']; $checkoutConfigurableOptions = isset($checkoutData['options']['configurable_options']) ? $checkoutData['options']['configurable_options'] : []; + $attributeKey = []; foreach ($checkoutConfigurableOptions as $key => $checkoutConfigurableOption) { $attribute = $checkoutConfigurableOption['title']; $option = $checkoutConfigurableOption['value']; - + $attributeKey[] = "$attribute:$option"; $checkoutConfigurableOptions[$key] = [ 'title' => isset($attributesData[$attribute]['label']) ? $attributesData[$attribute]['label'] @@ -48,10 +47,15 @@ class Item extends \Magento\Catalog\Test\Fixture\Cart\Item : $option, ]; } + $attributeKey = implode(' ', $attributeKey); + $cartItem['sku'] = $productData['configurable_attributes_data']['matrix'][$attributeKey]['sku']; + $cartItem['name'] = $productData['name']; $cartItem['options'] = isset($cartItem['options']) ? $cartItem['options'] + $checkoutConfigurableOptions : $checkoutConfigurableOptions; $this->data = $cartItem; + + return $this->data; } } diff --git a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Fixture/ConfigurableProduct/ConfigurableAttributesData.php b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Fixture/ConfigurableProduct/ConfigurableAttributesData.php index 65f80eb7144638b59e61a984c27582a316e9b129..65715d116ab45780dcacae89ef987a16e9127ceb 100644 --- a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Fixture/ConfigurableProduct/ConfigurableAttributesData.php +++ b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Fixture/ConfigurableProduct/ConfigurableAttributesData.php @@ -277,10 +277,12 @@ class ConfigurableAttributesData extends DataSource $variationsMatrix = $this->addVariationMatrix($variationsMatrix, $attribute, $attributeKey); } - foreach ($data['matrix'] as $key => $value) { - if (isset($value['sku']) && $value['sku'] === '') { - unset($variationsMatrix[$key]['sku']); - unset($data['matrix'][$key]['sku']); + if (isset($data['matrix'])) { + foreach ($data['matrix'] as $key => $value) { + if (isset($value['sku']) && $value['sku'] === '') { + unset($variationsMatrix[$key]['sku']); + unset($data['matrix'][$key]['sku']); + } } } diff --git a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Page/Adminhtml/OrderCreateIndex.xml b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Page/Adminhtml/OrderCreateIndex.xml index a67119cbf19aa5ac5aa1541672a30242edd29a93..97809af4bff7875f1bb4c90fe0f3a9c05d037b24 100644 --- a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Page/Adminhtml/OrderCreateIndex.xml +++ b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Page/Adminhtml/OrderCreateIndex.xml @@ -6,9 +6,9 @@ */ --> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../vendor/magento/mtf/etc/pages.xsd"> - <page name="OrderCreateIndex" area="Adminhtml" mca="sales/order_create/index"> - <block name="configureProductBlock"> - <render name="configurable" class="Magento\ConfigurableProduct\Test\Block\Adminhtml\Product\Composite\Configure"/> - </block> - </page> + <page name="OrderCreateIndex" area="Adminhtml" mca="sales/order_create/index"> + <block name="configureProductBlock"> + <render name="configurable" class="Magento\ConfigurableProduct\Test\Block\Adminhtml\Product\Composite\Configure" /> + </block> + </page> </config> diff --git a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Page/Product/CatalogProductView.xml b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Page/Product/CatalogProductView.xml index c2c5d8428b480dd5ccae46f67d2065bc203b8331..c825f733de1790ef5e8f0a81ad38c37a493df12f 100644 --- a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Page/Product/CatalogProductView.xml +++ b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Page/Product/CatalogProductView.xml @@ -10,6 +10,6 @@ <block name="viewBlock"> <render name="configurable" class="Magento\ConfigurableProduct\Test\Block\Product\View"/> </block> - <block name="configurableAttributesBlock" class="Magento\ConfigurableProduct\Test\Block\Product\View\ConfigurableOptions" locator="#product-options-wrapper" strategy="css selector"/> + <block name="configurableAttributesBlock" class="Magento\ConfigurableProduct\Test\Block\Product\View\ConfigurableOptions" locator=".product-info-main" strategy="css selector"/> </page> </config> diff --git a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Repository/ConfigurableProduct/CheckoutData.xml b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Repository/ConfigurableProduct/CheckoutData.xml index bb9f7a4ae03b19500b954e187a8765121579acf7..949c6dc065c494a18e2ae617ef859f6663dd05d4 100644 --- a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Repository/ConfigurableProduct/CheckoutData.xml +++ b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Repository/ConfigurableProduct/CheckoutData.xml @@ -154,6 +154,22 @@ </field> </dataset> + <dataset name="configurable_two_new_options_with_tier_price"> + <field name="options" xsi:type="array"> + <item name="configurable_options" xsi:type="array"> + <item name="0" xsi:type="array"> + <item name="title" xsi:type="string">attribute_key_0</item> + <item name="value" xsi:type="string">option_key_1</item> + </item> + </item> + </field> + <field name="cartItem" xsi:type="array"> + <item name="price" xsi:type="string">9</item> + <item name="qty" xsi:type="string">1</item> + <item name="subtotal" xsi:type="string">9</item> + </field> + </dataset> + <dataset name="configurable_two_options_with_assigned_product"> <field name="options" xsi:type="array"> <item name="configurable_options" xsi:type="array"> diff --git a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Repository/ConfigurableProduct/ConfigurableAttributesData.xml b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Repository/ConfigurableProduct/ConfigurableAttributesData.xml index cf9d73d3dcd2e727dc7cdb290ecf74d17a453c31..44e2e14545db02103bfe2fa2613f196937cfc558 100644 --- a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Repository/ConfigurableProduct/ConfigurableAttributesData.xml +++ b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Repository/ConfigurableProduct/ConfigurableAttributesData.xml @@ -440,6 +440,42 @@ </field> </dataset> + <dataset name="two_options_with_assigned_product_tier_price"> + <field name="attributes_data" xsi:type="array"> + <item name="attribute_key_0" xsi:type="array"> + <item name="options" xsi:type="array"> + <item name="option_key_0" xsi:type="array"> + <item name="label" xsi:type="string">option_key_1_%isolation%</item> + <item name="pricing_value" xsi:type="string">560</item> + <item name="include" xsi:type="string">Yes</item> + </item> + <item name="option_key_1" xsi:type="array"> + <item name="label" xsi:type="string">option_key_2_%isolation%</item> + <item name="pricing_value" xsi:type="string">10</item> + <item name="include" xsi:type="string">Yes</item> + </item> + </item> + </item> + </field> + <field name="attributes" xsi:type="array"> + <item name="attribute_key_0" xsi:type="string">catalogProductAttribute::attribute_type_dropdown_two_options</item> + </field> + <field name="products" xsi:type="array"> + <item name="attribute_key_0:option_key_0" xsi:type="string">catalogProductSimple::default</item> + <item name="attribute_key_0:option_key_1" xsi:type="string">catalogProductSimple::simple_with_tier_price</item> + </field> + <field name="matrix" xsi:type="array"> + <item name="attribute_key_0:option_key_0" xsi:type="array"> + <item name="qty" xsi:type="string">10</item> + <item name="weight" xsi:type="string">1</item> + </item> + <item name="attribute_key_0:option_key_1" xsi:type="array"> + <item name="qty" xsi:type="string">20</item> + <item name="weight" xsi:type="string">1</item> + </item> + </field> + </dataset> + <dataset name="color_and_size"> <field name="attributes_data" xsi:type="array"> <item name="attribute_key_0" xsi:type="array"> diff --git a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/TestCase/CreateConfigurableProductEntityTest.xml b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/TestCase/CreateConfigurableProductEntityTest.xml index 14ff24f18908da187a0631662cf74bfdaad5db6f..42277101cfbdaf5622efb6b4347dafb75bb113aa 100644 --- a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/TestCase/CreateConfigurableProductEntityTest.xml +++ b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/TestCase/CreateConfigurableProductEntityTest.xml @@ -159,5 +159,19 @@ <constraint name="Magento\Catalog\Test\Constraint\AssertProductSaveMessage" /> <constraint name="Magento\Catalog\Test\Constraint\AssertProductOnCustomWebsite" /> </variation> + <variation name="CreateConfigurableProductEntityTestVariation10" summary="Create configurable product with tier price for one item"> + <data name="product/data/url_key" xsi:type="string">configurable-product-%isolation%</data> + <data name="product/data/configurable_attributes_data/dataset" xsi:type="string">two_options_with_assigned_product_tier_price</data> + <data name="product/data/checkout_data/dataset" xsi:type="string">configurable_two_new_options_with_special_price</data> + <data name="product/data/name" xsi:type="string">Configurable Product %isolation%</data> + <data name="product/data/sku" xsi:type="string">configurable_sku_%isolation%</data> + <data name="product/data/price/value" xsi:type="string">1</data> + <data name="product/data/weight" xsi:type="string">2</data> + <data name="product/data/category_ids/dataset" xsi:type="string">default_subcategory</data> + <data name="product/data/short_description" xsi:type="string">Configurable short description</data> + <data name="product/data/description" xsi:type="string">Configurable Product description %isolation%</data> + <constraint name="Magento\Catalog\Test\Constraint\AssertProductSaveMessage" /> + <constraint name="Magento\ConfigurableProduct\Test\Constraint\AssertProductTierPriceOnProductPage" /> + </variation> </testCase> </config> diff --git a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/TestCase/CreateCreditMemoEntityTest.xml b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/TestCase/CreateCreditMemoEntityTest.xml index dd92edc82b3310ad9610c70138578a220e4358cd..8a8195db638d565564ae0e2bdf20ad46fbb05bbd 100644 --- a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/TestCase/CreateCreditMemoEntityTest.xml +++ b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/TestCase/CreateCreditMemoEntityTest.xml @@ -14,6 +14,7 @@ <data name="order/dataset" xsi:type="string">default</data> <data name="order/data/entity_id/products" xsi:type="string">configurableProduct::configurable_with_qty_1</data> <data name="order/data/price/dataset" xsi:type="string">full_refund</data> + <data name="configData" xsi:type="string"/> <constraint name="Magento\Sales\Test\Constraint\AssertRefundSuccessCreateMessage" /> <constraint name="Magento\ConfigurableProduct\Test\Constraint\AssertProductQtyDecreasedAfterCreditmemo" /> </variation> diff --git a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/TestCase/MoveRecentlyComparedProductsOnOrderPageTest.xml b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/TestCase/MoveRecentlyComparedProductsOnOrderPageTest.xml new file mode 100644 index 0000000000000000000000000000000000000000..aaa9b3e1f88f918aa63f852b28a5ac653f94cdef --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/TestCase/MoveRecentlyComparedProductsOnOrderPageTest.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + --> +<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../vendor/magento/mtf/etc/variations.xsd"> + <testCase name="Magento\Sales\Test\TestCase\MoveRecentlyComparedProductsOnOrderPageTest"> + <variation name="MoveRecentlyComparedProductsOnOrderPageTestVariationWithConfigurableProduct1"> + <data name="products/0" xsi:type="string">configurableProduct::configurable_with_qty_1</data> + <data name="products/1" xsi:type="string">configurableProduct::configurable_with_qty_1</data> + <constraint name="Magento\Sales\Test\Constraint\AssertProductInItemsOrderedGrid" /> + </variation> + </testCase> +</config> diff --git a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/etc/di.xml b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/etc/di.xml index 002ccfc4ed80ca48fb1b851558efa909b2e1c503..8bdf098cea58341cf83b081fca7bc946281e4884 100644 --- a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/etc/di.xml +++ b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/etc/di.xml @@ -26,4 +26,17 @@ <argument name="severity" xsi:type="string">high</argument> </arguments> </type> + <type name="Magento\Sales\Test\Block\Adminhtml\Order\Create\CustomerActivities\Sidebar\RecentlyComparedProducts"> + <arguments> + <argument name="config" xsi:type="array"> + <item name="renders" xsi:type="array"> + <item name="configurable" xsi:type="array"> + <item name="class" xsi:type="string">Magento\ConfigurableProduct\Test\Block\Adminhtml\Product\Composite\Configure</item> + <item name="locator" xsi:type="string">//ancestor::body//*[contains(@class, "modal-slide") and contains(@class, "_show")]</item> + <item name="strategy" xsi:type="string">xpath</item> + </item> + </item> + </argument> + </arguments> + </type> </config> diff --git a/dev/tests/functional/tests/app/Magento/CurrencySymbol/Test/Repository/ConfigData.xml b/dev/tests/functional/tests/app/Magento/CurrencySymbol/Test/Repository/ConfigData.xml index 3a099d79d370a97b9d75afb419bd36860e559a1a..77b311bd7a51f80b0347ba092dc700e467c2cf84 100644 --- a/dev/tests/functional/tests/app/Magento/CurrencySymbol/Test/Repository/ConfigData.xml +++ b/dev/tests/functional/tests/app/Magento/CurrencySymbol/Test/Repository/ConfigData.xml @@ -17,7 +17,6 @@ </item> </field> </dataset> - <dataset name="config_currency_symbols_usd_and_uah_rollback"> <field name="currency/options/allow" xsi:type="array"> <item name="scope" xsi:type="string">currency</item> @@ -83,7 +82,6 @@ <item name="value" xsi:type="string">CHF</item> </field> </dataset> - <dataset name="config_base_currency_ch_rollback"> <field name="currency/options/allow" xsi:type="array"> <item name="scope" xsi:type="string">currency</item> @@ -127,7 +125,6 @@ <item name="value" xsi:type="string">GBP</item> </field> </dataset> - <dataset name="config_base_currency_gb_rollback"> <field name="currency/options/allow" xsi:type="array"> <item name="scope" xsi:type="string">currency</item> @@ -150,6 +147,49 @@ </field> </dataset> + <dataset name="config_base_currency_aud"> + <field name="currency/options/allow" xsi:type="array"> + <item name="scope" xsi:type="string">currency</item> + <item name="scope_id" xsi:type="number">1</item> + <item name="value" xsi:type="array"> + <item name="Australian Dollar" xsi:type="string">AUD</item> + </item> + </field> + <field name="currency/options/base" xsi:type="array"> + <item name="scope" xsi:type="string">currency</item> + <item name="label" xsi:type="string">Australian Dollar</item> + <item name="scope_id" xsi:type="number">1</item> + <item name="value" xsi:type="string">AUD</item> + </field> + <field name="currency/options/default" xsi:type="array"> + <item name="scope" xsi:type="string">currency</item> + <item name="label" xsi:type="string">Australian Dollar</item> + <item name="scope_id" xsi:type="number">1</item> + <item name="value" xsi:type="string">AUD</item> + </field> + </dataset> + <dataset name="config_base_currency_aud_rollback"> + <field name="currency/options/allow" xsi:type="array"> + <item name="scope" xsi:type="string">currency</item> + <item name="scope_id" xsi:type="number">1</item> + <item name="value" xsi:type="array"> + <item name="US Dollar" xsi:type="string">USD</item> + </item> + </field> + <field name="currency/options/base" xsi:type="array"> + <item name="scope" xsi:type="string">currency</item> + <item name="label" xsi:type="string">US Dollar</item> + <item name="scope_id" xsi:type="number">1</item> + <item name="value" xsi:type="string">USD</item> + </field> + <field name="currency/options/default" xsi:type="array"> + <item name="scope" xsi:type="string">currency</item> + <item name="label" xsi:type="string">US Dollar</item> + <item name="scope_id" xsi:type="number">1</item> + <item name="value" xsi:type="string">USD</item> + </field> + </dataset> + <dataset name="config_currency_symbols_usd_and_eur"> <field name="currency/options/allow" xsi:type="array"> <item name="scope" xsi:type="string">currency</item> diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/Block/Address/Edit.php b/dev/tests/functional/tests/app/Magento/Customer/Test/Block/Address/Edit.php index b9d5f3c3af01e10559e2c942e546f4eeda6576c3..78eaf403826bc054996c570c2167600ac4fac0ff 100644 --- a/dev/tests/functional/tests/app/Magento/Customer/Test/Block/Address/Edit.php +++ b/dev/tests/functional/tests/app/Magento/Customer/Test/Block/Address/Edit.php @@ -61,4 +61,20 @@ class Edit extends Form { $this->_rootElement->find($this->saveAddress)->click(); } + + /** + * Fixture mapping. + * + * @param array|null $fields + * @param string|null $parent + * @return array + */ + protected function dataMapping(array $fields = null, $parent = null) + { + if (isset($fields['custom_attribute'])) { + $this->placeholders = ['attribute_code' => $fields['custom_attribute']['code']]; + $this->applyPlaceholders(); + } + return parent::dataMapping($fields, $parent); + } } diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/Page/CustomerAddressEdit.php b/dev/tests/functional/tests/app/Magento/Customer/Test/Page/CustomerAddressEdit.php deleted file mode 100644 index 4946f0825870974337a3724fae591e58b8d861be..0000000000000000000000000000000000000000 --- a/dev/tests/functional/tests/app/Magento/Customer/Test/Page/CustomerAddressEdit.php +++ /dev/null @@ -1,51 +0,0 @@ -<?php -/** - * Copyright © 2016 Magento. All rights reserved. - * See COPYING.txt for license details. - */ - -namespace Magento\Customer\Test\Page; - -use Magento\Mtf\Client\Locator; -use Magento\Mtf\Factory\Factory; -use Magento\Mtf\Page\Page; - -/** - * Customer Address Edit page. - */ -class CustomerAddressEdit extends Page -{ - /** - * URL for Customer Address Edit page. - */ - const MCA = 'customer/address/edit'; - - /** - * Customer Address Edit form. - * - * @var string - */ - protected $editForm = '#form-validate'; - - /** - * Init page. Set page url. - * - * @return void - */ - protected function initUrl() - { - $this->url = $_ENV['app_frontend_url'] . self::MCA; - } - - /** - * Get Customer Address Edit form. - * - * @return \Magento\Customer\Test\Block\Address\Edit - */ - public function getEditForm() - { - return Factory::getBlockFactory()->getMagentoCustomerAddressEdit( - $this->browser->find($this->editForm, Locator::SELECTOR_CSS) - ); - } -} diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/Page/CustomerAddressEdit.xml b/dev/tests/functional/tests/app/Magento/Customer/Test/Page/CustomerAddressEdit.xml new file mode 100644 index 0000000000000000000000000000000000000000..2f3738d05e5e3d0439496b2df70532613b9144d8 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Customer/Test/Page/CustomerAddressEdit.xml @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + --> +<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/pages.xsd"> + <page name="CustomerAddressEdit" mca="customer/address/edit" module="Magento_Customer"> + <block name="editForm" class="Magento\Customer\Test\Block\Address\Edit" locator="#form-validate" strategy="css selector" /> + </page> +</config> diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/Repository/Address.xml b/dev/tests/functional/tests/app/Magento/Customer/Test/Repository/Address.xml index 8baa7ce0d9310f7e2d7a17fab8c904530cf25629..6e7e76524557dd6ec875af966ef23e85bef6a73c 100644 --- a/dev/tests/functional/tests/app/Magento/Customer/Test/Repository/Address.xml +++ b/dev/tests/functional/tests/app/Magento/Customer/Test/Repository/Address.xml @@ -241,6 +241,40 @@ <field name="telephone" xsi:type="string">333-33-333-33</field> </dataset> + <dataset name="DE_address_Frankfurt"> + <field name="firstname" xsi:type="string">Jan</field> + <field name="lastname" xsi:type="string">Jansen</field> + <field name="company" xsi:type="string">Magento %isolation%</field> + <field name="city" xsi:type="string">Frankfurt</field> + <field name="street" xsi:type="string">Marzellenstrasse 13-17</field> + <field name="postcode" xsi:type="string">10789</field> + <field name="country_id" xsi:type="string">Germany</field> + <field name="region" xsi:type="string">Hessen</field> + <field name="telephone" xsi:type="string">333-33-333-33</field> + </dataset> + + <dataset name="KE_Nairobi"> + <field name="firstname" xsi:type="string">John</field> + <field name="lastname" xsi:type="string">Doe</field> + <field name="company" xsi:type="string">Magento %isolation%</field> + <field name="city" xsi:type="string">Nairobi</field> + <field name="street" xsi:type="string">6161 West Centinela Avenue</field> + <field name="telephone" xsi:type="string">555-55-555-55</field> + <field name="country_id" xsi:type="string">Kenya</field> + <field name="postcode" xsi:type="string">12345</field> + </dataset> + + <dataset name="KE_Mombasa"> + <field name="firstname" xsi:type="string">John</field> + <field name="lastname" xsi:type="string">Doe</field> + <field name="company" xsi:type="string">Magento %isolation%</field> + <field name="city" xsi:type="string">Mombasa</field> + <field name="street" xsi:type="string">6161 West Centinela Avenue</field> + <field name="telephone" xsi:type="string">555-55-555-55</field> + <field name="country_id" xsi:type="string">Kenya</field> + <field name="postcode" xsi:type="string">12345</field> + </dataset> + <dataset name="customer_UK_US_addresses"> <field name="firstname" xsi:type="string">John</field> <field name="lastname" xsi:type="string">Doe%isolation%</field> @@ -251,5 +285,29 @@ <item name="dataset" xsi:type="string">UK_address_default_billing, US_address_default_shipping</item> </field> </dataset> + + <dataset name="AVS_street_match_address"> + <field name="firstname" xsi:type="string">John</field> + <field name="lastname" xsi:type="string">Doe</field> + <field name="company" xsi:type="string">Magento %isolation%</field> + <field name="city" xsi:type="string">Culver City</field> + <field name="street" xsi:type="string">24285 Elm</field> + <field name="telephone" xsi:type="string">555-55-555-55</field> + <field name="country_id" xsi:type="string">United States</field> + <field name="region_id" xsi:type="string">California</field> + <field name="postcode" xsi:type="string">90230</field> + </dataset> + + <dataset name="AVS_street_does_not_match_address"> + <field name="firstname" xsi:type="string">John</field> + <field name="lastname" xsi:type="string">Doe</field> + <field name="company" xsi:type="string">Magento %isolation%</field> + <field name="city" xsi:type="string">Culver City</field> + <field name="street" xsi:type="string">49354 Main</field> + <field name="telephone" xsi:type="string">555-55-555-55</field> + <field name="country_id" xsi:type="string">United States</field> + <field name="region_id" xsi:type="string">California</field> + <field name="postcode" xsi:type="string">90230</field> + </dataset> </repository> </config> diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/GridFilteringTest.xml b/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/GridFilteringTest.xml index 918f723981faac5a3a919caaf99ac9e75b0bf1bd..42a3103ce33d7615fcbfd06084bebfa965769b60 100644 --- a/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/GridFilteringTest.xml +++ b/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/GridFilteringTest.xml @@ -8,6 +8,7 @@ <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd"> <testCase name="Magento\Ui\Test\TestCase\GridFilteringTest" summary="Grid UI Component Filtering" ticketId="MAGETWO-41329"> <variation name="CustomerGridFiltering"> + <data name="tag" xsi:type="string">severity:S2</data> <data name="description" xsi:type="string">Verify customer page grid filtering</data> <data name="itemsCount" xsi:type="string">2</data> <data name="fixtureName" xsi:type="string">customer</data> diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/GridFullTextSearchTest.xml b/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/GridFullTextSearchTest.xml index 00a2955be126a67b96d6ff8b03c706fe3b98d802..ef0bf7b7cea72e941840f103bb3700d66f06404c 100644 --- a/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/GridFullTextSearchTest.xml +++ b/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/GridFullTextSearchTest.xml @@ -8,6 +8,7 @@ <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd"> <testCase name="Magento\Ui\Test\TestCase\GridFullTextSearchTest" summary="Grid UI Component Full Text Search" ticketId="MAGETWO-41023"> <variation name="CustomerGridFullTextSearch"> + <data name="tag" xsi:type="string">severity:S2</data> <data name="description" xsi:type="string">Verify customer page grid full text search</data> <data name="itemsCount" xsi:type="string">2</data> <data name="fixtureName" xsi:type="string">customer</data> diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/GridSortingTest.xml b/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/GridSortingTest.xml index b967fbd184526fd1d71fcf2055799842d0d018f1..7d6e7f6d8f1b4f3a2402e0ae1b659f60c941c63d 100644 --- a/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/GridSortingTest.xml +++ b/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/GridSortingTest.xml @@ -8,6 +8,7 @@ <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd"> <testCase name="Magento\Ui\Test\TestCase\GridSortingTest" summary="Grid UI Component Sorting" ticketId="MAGETWO-41328"> <variation name="CustomerGridSorting"> + <data name="tag" xsi:type="string">severity:S2</data> <data name="tag" xsi:type="string">stable:no</data> <data name="description" xsi:type="string">Verify customer page grid sorting</data> <data name="columnsForSorting" xsi:type="array"> diff --git a/dev/tests/functional/tests/app/Magento/Dhl/Test/TestCase/CityBasedShippingRateTest.xml b/dev/tests/functional/tests/app/Magento/Dhl/Test/TestCase/CityBasedShippingRateTest.xml new file mode 100644 index 0000000000000000000000000000000000000000..e54439c8cd05c5537542d1769d58714d89fc4fb2 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Dhl/Test/TestCase/CityBasedShippingRateTest.xml @@ -0,0 +1,44 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + --> +<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd"> + <testCase name="Magento\Shipping\Test\TestCase\CityBasedShippingRateTest" summary="Shipping rates can be reloaded based on changes in City field value"> + <variation name="CityBasedShippingRateDHLTestVariation" summary="Shipping rates can be reloaded based on changes in City field value for DHL shipping method" ticketId="MAGETWO-56124"> + <data name="tag" xsi:type="string">test_type:3rd_party_test, severity:S1</data> + <data name="products/0" xsi:type="string">catalogProductSimple::default</data> + <data name="checkoutMethod" xsi:type="string">guest</data> + <data name="customer/dataset" xsi:type="string">default</data> + <data name="shippingMethod/shipping_service" xsi:type="string">DHL</data> + <data name="shippingMethod/shipping_method" xsi:type="string">Express easy</data> + <data name="clearShippingAddress/postcode" xsi:type="string" /> + <data name="clearShippingAddress/city" xsi:type="string" /> + <data name="clearShippingAddress/country_id" xsi:type="string" /> + <data name="shippingAddresses/0/country_id" xsi:type="string">Kenya</data> + <data name="shippingAddresses/1/country_id" xsi:type="string">Kenya</data> + <data name="shippingAddresses/1/postcode" xsi:type="string">12345</data> + <data name="shippingAddresses/2/country_id" xsi:type="string">Kenya</data> + <data name="shippingAddresses/2/postcode" xsi:type="string">12345</data> + <data name="shippingAddresses/2/city" xsi:type="string">Nairobi</data> + <data name="shippingAddresses/3/country_id" xsi:type="string">Kenya</data> + <data name="shippingAddresses/3/postcode" xsi:type="string">12345</data> + <data name="shippingAddresses/3/city" xsi:type="string">Mombasa</data> + <data name="shippingAddresses/4/country_id" xsi:type="string">Kenya</data> + <data name="shippingAddresses/4/city" xsi:type="string">Mombasa</data> + <data name="shippingAddresses/5/country_id" xsi:type="string">Kenya</data> + <data name="shippingAddresses/5/city" xsi:type="string">Nairobi</data> + <data name="isShippingAvailable" xsi:type="array"> + <item name="0" xsi:type="boolean">false</item> + <item name="1" xsi:type="boolean">false</item> + <item name="2" xsi:type="boolean">true</item> + <item name="3" xsi:type="boolean">true</item> + <item name="4" xsi:type="boolean">true</item> + <item name="5" xsi:type="boolean">true</item> + </data> + <data name="configData" xsi:type="string">dhl_eu, shipping_origin_CH, config_base_currency_ch</data> + </variation> + </testCase> +</config> diff --git a/dev/tests/functional/tests/app/Magento/Downloadable/Test/Fixture/Cart/Item.php b/dev/tests/functional/tests/app/Magento/Downloadable/Test/Fixture/Cart/Item.php index dd388ae11d2f66990e3f2bb54e83399ec7562d5c..1d0fabeceb771ebd61d73ee16bed79ba91efcc3a 100644 --- a/dev/tests/functional/tests/app/Magento/Downloadable/Test/Fixture/Cart/Item.php +++ b/dev/tests/functional/tests/app/Magento/Downloadable/Test/Fixture/Cart/Item.php @@ -6,9 +6,6 @@ namespace Magento\Downloadable\Test\Fixture\Cart; -use Magento\Downloadable\Test\Fixture\DownloadableProduct; -use Magento\Mtf\Fixture\FixtureInterface; - /** * Data for verify cart item block on checkout page. * @@ -18,17 +15,17 @@ use Magento\Mtf\Fixture\FixtureInterface; class Item extends \Magento\Catalog\Test\Fixture\Cart\Item { /** - * @constructor - * @param FixtureInterface $product + * Return prepared dataset. + * + * @param null|string $key + * @return array */ - public function __construct(FixtureInterface $product) + public function getData($key = null) { - parent::__construct($product); - - /** @var DownloadableProduct $product */ + parent::getData($key); $checkoutDownloadableOptions = []; - $checkoutData = $product->getCheckoutData(); - $downloadableOptions = $product->getDownloadableLinks(); + $checkoutData = $this->product->getCheckoutData(); + $downloadableOptions = $this->product->getDownloadableLinks(); foreach ($checkoutData['options']['links'] as $link) { $keyLink = str_replace('link_', '', $link['label']); $checkoutDownloadableOptions[] = [ @@ -38,5 +35,7 @@ class Item extends \Magento\Catalog\Test\Fixture\Cart\Item } $this->data['options'] += $checkoutDownloadableOptions; + + return $this->data; } } diff --git a/dev/tests/functional/tests/app/Magento/Fedex/Test/TestCase/CityBasedShippingRateTest.xml b/dev/tests/functional/tests/app/Magento/Fedex/Test/TestCase/CityBasedShippingRateTest.xml new file mode 100644 index 0000000000000000000000000000000000000000..b6a2fd5776a27d307e7c0f8372438b42f38fd7f5 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Fedex/Test/TestCase/CityBasedShippingRateTest.xml @@ -0,0 +1,44 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + --> +<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd"> + <testCase name="Magento\Shipping\Test\TestCase\CityBasedShippingRateTest" summary="Shipping rates can be reloaded based on changes in City field value"> + <variation name="CityBasedShippingRateFedexTestVariation" summary="Shipping rates can be reloaded based on changes in City field value for Fedex shipping method" ticketId="MAGETWO-56124"> + <data name="tag" xsi:type="string">test_type:3rd_party_test, severity:S1</data> + <data name="products/0" xsi:type="string">catalogProductSimple::default</data> + <data name="checkoutMethod" xsi:type="string">guest</data> + <data name="customer/dataset" xsi:type="string">default</data> + <data name="shippingMethod/shipping_service" xsi:type="string">Federal Express</data> + <data name="shippingMethod/shipping_method" xsi:type="string">International Economy</data> + <data name="clearShippingAddress/postcode" xsi:type="string" /> + <data name="clearShippingAddress/city" xsi:type="string" /> + <data name="clearShippingAddress/country_id" xsi:type="string" /> + <data name="shippingAddresses/0/country_id" xsi:type="string">Kenya</data> + <data name="shippingAddresses/1/country_id" xsi:type="string">Kenya</data> + <data name="shippingAddresses/1/postcode" xsi:type="string">12345</data> + <data name="shippingAddresses/2/country_id" xsi:type="string">Kenya</data> + <data name="shippingAddresses/2/postcode" xsi:type="string">12345</data> + <data name="shippingAddresses/2/city" xsi:type="string">Nairobi</data> + <data name="shippingAddresses/3/country_id" xsi:type="string">Kenya</data> + <data name="shippingAddresses/3/postcode" xsi:type="string">12345</data> + <data name="shippingAddresses/3/city" xsi:type="string">Mombasa</data> + <data name="shippingAddresses/4/country_id" xsi:type="string">Kenya</data> + <data name="shippingAddresses/4/city" xsi:type="string">Mombasa</data> + <data name="shippingAddresses/5/country_id" xsi:type="string">Kenya</data> + <data name="shippingAddresses/5/city" xsi:type="string">Nairobi</data> + <data name="isShippingAvailable" xsi:type="array"> + <item name="0" xsi:type="boolean">false</item> + <item name="1" xsi:type="boolean">true</item> + <item name="2" xsi:type="boolean">true</item> + <item name="3" xsi:type="boolean">true</item> + <item name="4" xsi:type="boolean">false</item> + <item name="5" xsi:type="boolean">false</item> + </data> + <data name="configData" xsi:type="string">fedex, shipping_origin_US_CA</data> + </variation> + </testCase> +</config> diff --git a/dev/tests/functional/tests/app/Magento/GiftMessage/Test/TestCase/CheckoutWithGiftMessagesTest.php b/dev/tests/functional/tests/app/Magento/GiftMessage/Test/TestCase/CheckoutWithGiftMessagesTest.php index e33adb68be4eb6eeb05753b072d394804acefb4a..40b622882d357a8c4770ace4b555230a134554f9 100644 --- a/dev/tests/functional/tests/app/Magento/GiftMessage/Test/TestCase/CheckoutWithGiftMessagesTest.php +++ b/dev/tests/functional/tests/app/Magento/GiftMessage/Test/TestCase/CheckoutWithGiftMessagesTest.php @@ -29,6 +29,7 @@ class CheckoutWithGiftMessagesTest extends Scenario { /* tags */ const MVP = 'no'; + const SEVERITY = 'S2'; const TO_MAINTAIN = 'yes'; // Consider variation #2 to work correctly with Virtual products /* end tags */ diff --git a/dev/tests/functional/tests/app/Magento/GiftMessage/Test/TestCase/CheckoutWithGiftMessagesTest.xml b/dev/tests/functional/tests/app/Magento/GiftMessage/Test/TestCase/CheckoutWithGiftMessagesTest.xml index 6226713f316c5f0a90f06291a3a8160a65ac912f..c4f03f0f3d317f3f8b4caa5eae6ad22ed0d475a9 100644 --- a/dev/tests/functional/tests/app/Magento/GiftMessage/Test/TestCase/CheckoutWithGiftMessagesTest.xml +++ b/dev/tests/functional/tests/app/Magento/GiftMessage/Test/TestCase/CheckoutWithGiftMessagesTest.xml @@ -8,6 +8,7 @@ <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd"> <testCase name="Magento\GiftMessage\Test\TestCase\CheckoutWithGiftMessagesTest" summary="One Page Checkout with Gift Messages" ticketId="MAGETWO-28978"> <variation name="CheckoutWithGiftMessagesTestVariation1"> + <data name="tag" xsi:type="string">severity:S2</data> <data name="products/0" xsi:type="string">catalogProductSimple::default</data> <data name="products/1" xsi:type="string">catalogProductVirtual::default</data> <data name="customer/dataset" xsi:type="string">default</data> @@ -27,7 +28,7 @@ <constraint name="Magento\GiftMessage\Test\Constraint\AssertGiftMessageInFrontendOrder" /> </variation> <variation name="CheckoutWithGiftMessagesTestVariation2"> - <data name="tag" xsi:type="string">to_maintain:yes</data> + <data name="tag" xsi:type="string">severity:S2,to_maintain:yes</data> <data name="products/0" xsi:type="string">catalogProductSimple::default</data> <data name="products/1" xsi:type="string">catalogProductVirtual::default</data> <data name="customer/dataset" xsi:type="string">default</data> diff --git a/dev/tests/functional/tests/app/Magento/GiftMessage/Test/TestCase/CreateGiftMessageOnBackendTest.php b/dev/tests/functional/tests/app/Magento/GiftMessage/Test/TestCase/CreateGiftMessageOnBackendTest.php new file mode 100644 index 0000000000000000000000000000000000000000..962d94ab6d59acf09f89c4b9b21a07dcf5e2cb92 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/GiftMessage/Test/TestCase/CreateGiftMessageOnBackendTest.php @@ -0,0 +1,43 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\GiftMessage\Test\TestCase; + +use Magento\Mtf\TestCase\Scenario; + +/** + * Preconditions: + * 1. Create Product according dataset. + * 2. Enable Gift Messages (Order/Items level). + * + * Steps: + * 1. Login to backend + * 2. Go to Sales >Orders + * 3. Create new order + * 4. Fill data form dataset + * 5. Perform all asserts + * + * @group Gift_Messages + * @ZephyrId MAGETWO-29642 + */ +class CreateGiftMessageOnBackendTest extends Scenario +{ + /* tags */ + const MVP = 'no'; + const SEVERITY = 'S2'; + const TO_MAINTAIN = 'yes'; + /* end tags */ + + /** + * Run CreateGiftMessageOnBackend test. + * + * @return void + */ + public function test() + { + $this->executeScenario(); + } +} diff --git a/dev/tests/functional/tests/app/Magento/GiftMessage/Test/TestCase/CreateGiftMessageOnBackendTest.xml b/dev/tests/functional/tests/app/Magento/GiftMessage/Test/TestCase/CreateGiftMessageOnBackendTest.xml new file mode 100644 index 0000000000000000000000000000000000000000..bc29b300b220e190e3ac6d00149520c44b493a7a --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/GiftMessage/Test/TestCase/CreateGiftMessageOnBackendTest.xml @@ -0,0 +1,73 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + --> +<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd"> + <testCase name="Magento\GiftMessage\Test\TestCase\CreateGiftMessageOnBackendTest" summary="Create Gift Message On Backend" ticketId="MAGETWO-29642"> + <variation name="CreateGiftMessageOnBackendTestVariation1"> + <data name="tag" xsi:type="string">severity:S2</data> + <data name="configData" xsi:type="string">cashondelivery, enable_gift_messages</data> + <data name="products/0" xsi:type="string">catalogProductSimple::default</data> + <data name="products/1" xsi:type="string">catalogProductVirtual::default</data> + <data name="customer/dataset" xsi:type="string">johndoe_with_addresses</data> + <data name="billingAddress/dataset" xsi:type="string">US_address_1_without_email</data> + <data name="shipping/shipping_service" xsi:type="string">Flat Rate</data> + <data name="shipping/shipping_method" xsi:type="string">Fixed</data> + <data name="giftMessage/data/allow_gift_options" xsi:type="string">Yes</data> + <data name="giftMessage/data/allow_gift_options_for_items" xsi:type="string">Yes</data> + <data name="giftMessage/data/sender" xsi:type="string">John Doe</data> + <data name="giftMessage/data/recipient" xsi:type="string">Jane Doe</data> + <data name="giftMessage/data/message" xsi:type="string">text_gift_message</data> + <data name="giftMessage/data/items/datasets" xsi:type="string">default</data> + <data name="payment/method" xsi:type="string">cashondelivery</data> + <constraint name="Magento\Sales\Test\Constraint\AssertOrderSuccessCreateMessage" /> + <constraint name="Magento\GiftMessage\Test\Constraint\AssertGiftMessageInBackendOrder" /> + <constraint name="Magento\GiftMessage\Test\Constraint\AssertGiftMessageInFrontendOrderItems" /> + </variation> + <variation name="CreateGiftMessageOnBackendTestVariation2"> + <data name="tag" xsi:type="string">severity:S2</data> + <data name="configData" xsi:type="string">cashondelivery, enable_gift_messages</data> + <data name="products/0" xsi:type="string">catalogProductSimple::default</data> + <data name="products/1" xsi:type="string">catalogProductVirtual::default</data> + <data name="customer/dataset" xsi:type="string">johndoe_with_addresses</data> + <data name="billingAddress/dataset" xsi:type="string">US_address_1_without_email</data> + <data name="shipping/shipping_service" xsi:type="string">Flat Rate</data> + <data name="shipping/shipping_method" xsi:type="string">Fixed</data> + <data name="giftMessage/data/allow_gift_options" xsi:type="string">Yes</data> + <data name="giftMessage/data/allow_gift_messages_for_order" xsi:type="string">Yes</data> + <data name="giftMessage/data/allow_gift_options_for_items" xsi:type="string">-</data> + <data name="giftMessage/data/sender" xsi:type="string">John Doe</data> + <data name="giftMessage/data/recipient" xsi:type="string">Jane Doe</data> + <data name="giftMessage/data/message" xsi:type="string">text_gift_message</data> + <data name="payment/method" xsi:type="string">cashondelivery</data> + <constraint name="Magento\Sales\Test\Constraint\AssertOrderSuccessCreateMessage" /> + <constraint name="Magento\GiftMessage\Test\Constraint\AssertGiftMessageInBackendOrder" /> + <constraint name="Magento\GiftMessage\Test\Constraint\AssertGiftMessageInFrontendOrder" /> + </variation> + <variation name="CreateGiftMessageOnBackendTestVariation3"> + <data name="tag" xsi:type="string">severity:S2</data> + <data name="configData" xsi:type="string">cashondelivery, enable_gift_messages</data> + <data name="products/0" xsi:type="string">catalogProductSimple::default</data> + <data name="products/1" xsi:type="string">catalogProductVirtual::default</data> + <data name="customer/dataset" xsi:type="string">johndoe_with_addresses</data> + <data name="billingAddress/dataset" xsi:type="string">US_address_1_without_email</data> + <data name="shipping/shipping_service" xsi:type="string">Flat Rate</data> + <data name="shipping/shipping_method" xsi:type="string">Fixed</data> + <data name="giftMessage/data/allow_gift_options" xsi:type="string">Yes</data> + <data name="giftMessage/data/allow_gift_messages_for_order" xsi:type="string">Yes</data> + <data name="giftMessage/data/allow_gift_options_for_items" xsi:type="string">Yes</data> + <data name="giftMessage/data/sender" xsi:type="string">John Doe</data> + <data name="giftMessage/data/recipient" xsi:type="string">Jane Doe</data> + <data name="giftMessage/data/message" xsi:type="string">text_gift_message</data> + <data name="giftMessage/data/items/datasets" xsi:type="string">default</data> + <data name="payment/method" xsi:type="string">cashondelivery</data> + <constraint name="Magento\Sales\Test\Constraint\AssertOrderSuccessCreateMessage" /> + <constraint name="Magento\GiftMessage\Test\Constraint\AssertGiftMessageInBackendOrder" /> + <constraint name="Magento\GiftMessage\Test\Constraint\AssertGiftMessageInFrontendOrder" /> + <constraint name="Magento\GiftMessage\Test\Constraint\AssertGiftMessageInFrontendOrderItems" /> + </variation> + </testCase> +</config> diff --git a/dev/tests/functional/tests/app/Magento/GiftMessage/Test/etc/di.xml b/dev/tests/functional/tests/app/Magento/GiftMessage/Test/etc/di.xml index bda2dc3ea97b95dead3597444f2a1438b88e2da7..a7ff131c0674637fd0c5c6c333d520649834b1cd 100644 --- a/dev/tests/functional/tests/app/Magento/GiftMessage/Test/etc/di.xml +++ b/dev/tests/functional/tests/app/Magento/GiftMessage/Test/etc/di.xml @@ -8,17 +8,17 @@ <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd"> <type name="Magento\GiftMessage\Test\Constraint\AssertGiftMessageInFrontendOrderItems"> <arguments> - <argument name="severity" xsi:type="string">high</argument> + <argument name="severity" xsi:type="string">S2</argument> </arguments> </type> <type name="Magento\GiftMessage\Test\Constraint\AssertGiftMessageInFrontendOrder"> <arguments> - <argument name="severity" xsi:type="string">high</argument> + <argument name="severity" xsi:type="string">S2</argument> </arguments> </type> <type name="Magento\GiftMessage\Test\Constraint\AssertGiftMessageInBackendOrder"> <arguments> - <argument name="severity" xsi:type="string">high</argument> + <argument name="severity" xsi:type="string">S2</argument> </arguments> </type> </config> diff --git a/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Block/Adminhtml/Product/Composite/Configure.xml b/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Block/Adminhtml/Product/Composite/Configure.xml index 04a918c3bf8d9598b74b0f53ebd41b9f477e778f..676ae6a64f3d820b4d65d821053d6d0ab7971542 100644 --- a/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Block/Adminhtml/Product/Composite/Configure.xml +++ b/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Block/Adminhtml/Product/Composite/Configure.xml @@ -8,7 +8,7 @@ <mapping strict="0"> <fields> <qty> - <selector>//tr[contains(.,"%product_name%")]//input[contains(@class,"qty")]</selector> + <selector>.//tr[contains(.,"%product_name%")]//input[contains(@class,"qty")]</selector> <strategy>xpath</strategy> </qty> </fields> diff --git a/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Block/Catalog/Product/View.php b/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Block/Catalog/Product/View.php index bd774f806053eb90b28ff70003cd703f315e1b2d..31ce18926b51ba89d70d8e5a73508562d405c9cf 100644 --- a/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Block/Catalog/Product/View.php +++ b/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Block/Catalog/Product/View.php @@ -94,4 +94,19 @@ class View extends ParentView { $this->getGroupedProductBlock()->fill($product); } + + /** + * Set quantity and click add to cart. + * @param FixtureInterface $product + * @param string|int $qty + */ + public function setQtyAndClickAddToCartGrouped(FixtureInterface $product, $qty) + { + $associatedProducts = $product->getAssociated()['products']; + $groupedProductBlock = $this->getGroupedProductBlock(); + foreach ($associatedProducts as $product) { + $groupedProductBlock->setQty($product->getId(), $qty); + } + $this->clickAddToCart(); + } } diff --git a/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Block/Catalog/Product/View/Type/Grouped.php b/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Block/Catalog/Product/View/Type/Grouped.php index 42b3b0dfcf76047bcd3c23ed1fcf117e497dcbf2..7498c3c56587dd1bace2b00727c90428af19435d 100644 --- a/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Block/Catalog/Product/View/Type/Grouped.php +++ b/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Block/Catalog/Product/View/Type/Grouped.php @@ -65,6 +65,18 @@ class Grouped extends Block return $this->_rootElement->find(sprintf($this->qtySubProductById, $subProductId))->getValue(); } + /** + * Set qty to subproduct block + * + * @param int $subProductId + * @param string|int $qty + * @return void + */ + public function setQty($subProductId, $qty) + { + $this->_rootElement->find(sprintf($this->qtySubProductById, $subProductId))->setValue($qty); + } + /** * Fill product options on view page. * diff --git a/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Block/Checkout/Cart/CartItem.php b/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Block/Checkout/Cart/CartItem.php index f843482eca1ca860869bb3a4413f71c632f05719..9db1477946df13464d6fabbb2a95cfed7a4046c6 100644 --- a/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Block/Checkout/Cart/CartItem.php +++ b/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Block/Checkout/Cart/CartItem.php @@ -8,6 +8,7 @@ namespace Magento\GroupedProduct\Test\Block\Checkout\Cart; use Magento\Checkout\Test\Block\Cart\AbstractCartItem; use Magento\Checkout\Test\Block\Cart\CartItem as CheckoutCartItem; +use Magento\Mtf\Client\Locator; /** * Class CartItem @@ -119,4 +120,57 @@ class CartItem extends AbstractCartItem $cartItem->removeItem(); } } + + /** + * Get product price including tax + * + * @return string|null + */ + public function getPriceInclTax() + { + return $this->getPriceByType($this->priceInclTax, Locator::SELECTOR_XPATH); + } + + /** + * Get product price excluding tax + * + * @return string|null + */ + public function getPriceExclTax() + { + return $this->getPriceByType($this->priceExclTax, Locator::SELECTOR_XPATH); + } + + /** + * Get sub-total excluding tax for the specified item in the cart + * + * @return string|null + */ + public function getSubtotalPriceExclTax() + { + return $this->getPriceByType($this->subTotalPriceExclTax); + } + + /** + * Get price for the specified item in the cart by the price type + * + * @return string|null + */ + public function getSubtotalPriceInclTax() + { + return $this->getPriceByType($this->subTotalPriceInclTax); + } + + /** + * @param string $priceType + * @param string $strategy + * @return mixed|null + */ + private function getPriceByType($priceType, $strategy = Locator::SELECTOR_CSS) + { + $cartProductPrice = $this->_rootElement->find($priceType, $strategy); + return $cartProductPrice->isVisible() + ? str_replace(',', '', $this->escapeCurrency($cartProductPrice->getText())) + : null; + } } diff --git a/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Constraint/AbstractAssertTaxRuleIsAppliedToAllPricesOnGroupedProductPage.php b/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Constraint/AbstractAssertTaxRuleIsAppliedToAllPricesOnGroupedProductPage.php new file mode 100644 index 0000000000000000000000000000000000000000..9fd3ebe177b3a2f5b0cfb10141f4a3e64f41a8b9 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Constraint/AbstractAssertTaxRuleIsAppliedToAllPricesOnGroupedProductPage.php @@ -0,0 +1,82 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\GroupedProduct\Test\Constraint; + +use Magento\Cms\Test\Page\CmsIndex; +use Magento\Catalog\Test\Page\Category\CatalogCategoryView; +use Magento\Catalog\Test\Page\Product\CatalogProductView; +use Magento\Checkout\Test\Page\CheckoutCart; +use Magento\Tax\Test\Constraint\AbstractAssertTaxRuleIsAppliedToAllPrices; +use Magento\Mtf\Fixture\FixtureFactory; +use Magento\Mtf\Fixture\FixtureInterface; +use Magento\Mtf\Fixture\InjectableFixture; + +/** + * Checks that prices excl tax on category, product and cart pages are equal to specified in dataset. + */ +abstract class AbstractAssertTaxRuleIsAppliedToAllPricesOnGroupedProductPage extends + AbstractAssertTaxRuleIsAppliedToAllPrices +{ + + /** + * Get grouped product view prices. + * + * @param FixtureInterface $product + * @param array $actualPrices + * @return array + */ + abstract protected function getGroupedProductPagePrices(FixtureInterface $product, array $actualPrices); + + /** + * Assert that specified prices are actual on category, product and cart pages. + * + * @param InjectableFixture $product + * @param array $prices + * @param int $qty + * @param CmsIndex $cmsIndex + * @param CatalogCategoryView $catalogCategoryView + * @param CatalogProductView $catalogProductView + * @param CheckoutCart $checkoutCart + * @param FixtureFactory $fixtureFactory + * @return void + */ + public function processAssert( + InjectableFixture $product, + array $prices, + $qty, + CmsIndex $cmsIndex, + CatalogCategoryView $catalogCategoryView, + CatalogProductView $catalogProductView, + CheckoutCart $checkoutCart, + FixtureFactory $fixtureFactory + ) { + $this->cmsIndex = $cmsIndex; + $this->catalogCategoryView = $catalogCategoryView; + $this->catalogProductView = $catalogProductView; + $this->checkoutCart = $checkoutCart; + //Preconditions + $address = $fixtureFactory->createByCode('address', ['dataset' => 'US_address_NY']); + $shipping = ['shipping_service' => 'Flat Rate', 'shipping_method' => 'Fixed']; + $actualPrices = []; + //Assertion steps + $productCategory = $product->getCategoryIds()[0]; + $this->openCategory($productCategory); + $actualPrices = $this->getCategoryPrices($product, $actualPrices); + $catalogCategoryView->getListProductBlock()->getProductItem($product)->open(); + $catalogProductView->getGroupedProductViewBlock()->fillOptions($product); + $actualPrices = $this->getGroupedProductPagePrices($product, $actualPrices); + $catalogProductView->getGroupedProductViewBlock()->setQtyAndClickAddToCartGrouped($product, $qty); + $catalogProductView->getMessagesBlock()->waitSuccessMessage(); + $this->checkoutCart->open(); + $this->fillEstimateBlock($address, $shipping); + $actualPrices = $this->getCartPrices($product, $actualPrices); + $actualPrices = $this->getTotals($actualPrices); + //Prices verification + $message = 'Prices from dataset should be equal to prices on frontend.'; + \PHPUnit_Framework_Assert::assertEquals($prices, $actualPrices, $message); + } +} diff --git a/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Constraint/AssertProductInItemsOrderedGrid.php b/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Constraint/AssertProductInItemsOrderedGrid.php new file mode 100644 index 0000000000000000000000000000000000000000..918c86f93340730e19ac576c1cda37255d86f0b3 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Constraint/AssertProductInItemsOrderedGrid.php @@ -0,0 +1,57 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\GroupedProduct\Test\Constraint; + +/** + * Assert product was added to Items Ordered grid in customer account on Order creation page backend. + */ +class AssertProductInItemsOrderedGrid extends \Magento\Sales\Test\Constraint\AssertProductInItemsOrderedGrid +{ + /** + * Prepare data. + * + * @param array $data + * @param \Magento\Sales\Test\Block\Adminhtml\Order\Create\Items $itemsBlock + * @return array + */ + protected function prepareData(array $data, \Magento\Sales\Test\Block\Adminhtml\Order\Create\Items $itemsBlock) + { + $fixtureData = []; + foreach ($data as $product) { + $fixtureData = array_merge($fixtureData, $this->getOptionsDetails($product)); + } + $pageData = $itemsBlock->getProductsDataByFields($this->fields); + $preparePageData = $this->arraySort($fixtureData, $pageData); + return ['fixtureData' => $fixtureData, 'pageData' => $preparePageData]; + } + + /** + * Get product options details. + * + * @param \Magento\Mtf\Fixture\FixtureInterface $product + * @return array + */ + private function getOptionsDetails(\Magento\Mtf\Fixture\FixtureInterface $product) + { + /** @var \Magento\GroupedProduct\Test\Fixture\GroupedProduct $product */ + $fixtureProducts = []; + $optionsPrices = $this->getProductPrice($product); + $optionsQtys = $product->getCheckoutData()['cartItem']['qty']; + $assignedProducts = $product->getAssociated()['assigned_products']; + + foreach ($assignedProducts as $key => $assignedProduct) { + $fixtureProducts[] = [ + 'name' => $assignedProduct['name'], + 'price' => number_format($optionsPrices['product_key_' . $key], 2), + 'checkout_data' => [ + 'qty' => $this->productsIsConfigured ? $optionsQtys['product_key_' . $key] : 1 + ] + ]; + } + return $fixtureProducts; + } +} diff --git a/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Constraint/AssertTaxRuleIsAppliedToAllPricesGroupedExcludingIncludingTax.php b/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Constraint/AssertTaxRuleIsAppliedToAllPricesGroupedExcludingIncludingTax.php new file mode 100644 index 0000000000000000000000000000000000000000..57853d344672b0e09a2f6aa9a821146108295cb4 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Constraint/AssertTaxRuleIsAppliedToAllPricesGroupedExcludingIncludingTax.php @@ -0,0 +1,74 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\GroupedProduct\Test\Constraint; + +use Magento\Mtf\Fixture\FixtureInterface; + +/** + * Checks that prices excl tax on category, product and cart pages are equal to specified in dataset. + */ +class AssertTaxRuleIsAppliedToAllPricesGroupedExcludingIncludingTax extends + AbstractAssertTaxRuleIsAppliedToAllPricesOnGroupedProductPage +{ + /** + * @inheritdoc + */ + public function getCategoryPrices(FixtureInterface $product, $actualPrices) + { + $priceBlock = $this->catalogCategoryView->getListProductBlock()->getProductItem($product)->getPriceBlock(); + $actualPrices['category_price_excl_tax'] = $priceBlock->getPriceExcludingTax(); + $actualPrices['category_price_incl_tax'] = $priceBlock->getPriceIncludingTax(); + + return $actualPrices; + } + + /** + * @inheritdoc + */ + public function getGroupedProductPagePrices(FixtureInterface $product, array $actualPrices) + { + $associatedProducts = $product->getAssociated(); + /** @var \Magento\GroupedProduct\Test\Block\Catalog\Product\View $groupedProductBlock */ + $this->catalogProductView = $this->catalogProductView->getGroupedProductViewBlock(); + foreach (array_keys($associatedProducts['products']) as $productIndex) { + //Process assertions + $this->catalogProductView ->itemPriceProductBlock(++$productIndex); + $actualPrices['sub_product_view_prices_' . $productIndex] = $this->getProductPagePrices($actualPrices); + } + return $actualPrices; + } + + /** + * @inheritdoc + */ + public function getProductPagePrices($actualPrices) + { + $priceBlock = $this->catalogProductView ->getPriceBlock(); + $productPrices['product_view_price_excl_tax'] = $priceBlock->getPriceExcludingTax(); + $productPrices['product_view_price_incl_tax'] = $priceBlock->getPriceIncludingTax(); + + return $productPrices; + } + + /** + * @inheritdoc + */ + public function getTotals($actualPrices) + { + $totalsBlock = $this->checkoutCart->getTotalsBlock(); + $actualPrices['subtotal_excl_tax'] = $totalsBlock->getSubtotalExcludingTax(); + $actualPrices['subtotal_incl_tax'] = $totalsBlock->getSubtotalIncludingTax(); + $actualPrices['discount'] = $totalsBlock->getDiscount(); + $actualPrices['shipping_excl_tax'] = $totalsBlock->getShippingPrice(); + $actualPrices['shipping_incl_tax'] = $totalsBlock->getShippingPriceInclTax(); + $actualPrices['tax'] = $totalsBlock->getTax(); + $actualPrices['grand_total_excl_tax'] = $totalsBlock->getGrandTotalExcludingTax(); + $actualPrices['grand_total_incl_tax'] = $totalsBlock->getGrandTotalIncludingTax(); + + return $actualPrices; + } +} diff --git a/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Fixture/Cart/Item.php b/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Fixture/Cart/Item.php index cc0cd2e9f09a49b04de46062905406bba68b7916..2aaf1253885a158f63a3a2aaf2df049d2c1ab105 100644 --- a/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Fixture/Cart/Item.php +++ b/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Fixture/Cart/Item.php @@ -6,9 +6,6 @@ namespace Magento\GroupedProduct\Test\Fixture\Cart; -use Magento\GroupedProduct\Test\Fixture\GroupedProduct; -use Magento\Mtf\Fixture\FixtureInterface; - /** * Data for verify cart item block on checkout page. * @@ -18,18 +15,19 @@ use Magento\Mtf\Fixture\FixtureInterface; class Item extends \Magento\Catalog\Test\Fixture\Cart\Item { /** - * @constructor - * @param FixtureInterface $product + * Return prepared dataset. + * + * @param null|string $key + * @return array */ - public function __construct(FixtureInterface $product) + public function getData($key = null) { - /** @var GroupedProduct $product */ - $checkoutData = $product->getCheckoutData(); + $checkoutData = $this->product->getCheckoutData(); $this->data = isset($checkoutData['cartItem']) ? $checkoutData['cartItem'] : []; $associatedProducts = []; $cartItem = []; - foreach ($product->getAssociated()['products'] as $key => $product) { + foreach ($this->product->getAssociated()['products'] as $key => $product) { $key = 'product_key_' . $key; $associatedProducts[$key] = $product; } @@ -51,5 +49,7 @@ class Item extends \Magento\Catalog\Test\Fixture\Cart\Item } $this->data = $cartItem; + + return $this->data; } } diff --git a/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Repository/GroupedProduct.xml b/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Repository/GroupedProduct.xml index bbdbc011ae8c9c8859d16dcfbd6b2e7428d46246..7f1fd69d8e784d08363b07837c35e9ec30c54ea0 100644 --- a/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Repository/GroupedProduct.xml +++ b/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Repository/GroupedProduct.xml @@ -33,6 +33,9 @@ <field name="attribute_set_id" xsi:type="array"> <item name="dataset" xsi:type="string">default</item> </field> + <field name="checkout_data" xsi:type="array"> + <item name="dataset" xsi:type="string">default</item> + </field> </dataset> <dataset name="grouped_product_out_of_stock"> @@ -125,5 +128,33 @@ <item name="dataset" xsi:type="string">grouped_three_simple_products</item> </field> </dataset> + + <dataset name="grouped_product_with_special_price"> + <field name="name" xsi:type="string">Test grouped product with special price %isolation%</field> + <field name="sku" xsi:type="string">sku_test_grouped_product_with_special_price_%isolation%</field> + <field name="category_ids" xsi:type="array"> + <item name="dataset" xsi:type="string">default</item> + </field> + <field name="associated" xsi:type="array"> + <item name="dataset" xsi:type="string">defaultSimpleProduct_with_specialPrice</item> + </field> + <field name="status" xsi:type="string">Yes</field> + <field name="visibility" xsi:type="string">Catalog, Search</field> + <field name="tax_class_id" xsi:type="array"> + <item name="dataset" xsi:type="string">taxable_goods</item> + </field> + <field name="url_key" xsi:type="string">test-grouped-product-with-special-price-%isolation%</field> + <field name="quantity_and_stock_status" xsi:type="array"> + <item name="is_in_stock" xsi:type="string">In Stock</item> + </field> + <field name="website_ids" xsi:type="array"> + <item name="0" xsi:type="array"> + <item name="dataset" xsi:type="string">default</item> + </item> + </field> + <field name="attribute_set_id" xsi:type="array"> + <item name="dataset" xsi:type="string">default</item> + </field> + </dataset> </repository> </config> diff --git a/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Repository/GroupedProduct/CheckoutData.xml b/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Repository/GroupedProduct/CheckoutData.xml index e6529d1afe6778f9c97396c20186be44f110545d..e2e17977b7dd6f43f68de86f0bfc2b060693a50e 100644 --- a/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Repository/GroupedProduct/CheckoutData.xml +++ b/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Repository/GroupedProduct/CheckoutData.xml @@ -7,6 +7,33 @@ --> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../vendor/magento/mtf/Magento/Mtf/Repository/etc/repository.xsd"> <repository class="Magento\GroupedProduct\Test\Repository\GroupedProduct\CheckoutData"> + <dataset name="default"> + <field name="options" xsi:type="array"> + <item name="0" xsi:type="array"> + <item name="name" xsi:type="string">product_key_0</item> + <item name="qty" xsi:type="string">2</item> + </item> + <item name="1" xsi:type="array"> + <item name="name" xsi:type="string">product_key_1</item> + <item name="qty" xsi:type="string">1</item> + </item> + </field> + <field name="cartItem" xsi:type="array"> + <item name="price" xsi:type="array"> + <item name="product_key_0" xsi:type="string">100</item> + <item name="product_key_1" xsi:type="string">560</item> + </item> + <item name="qty" xsi:type="array"> + <item name="product_key_0" xsi:type="string">2</item> + <item name="product_key_1" xsi:type="string">1</item> + </item> + <item name="subtotal" xsi:type="array"> + <item name="product_key_0" xsi:type="string">200</item> + <item name="product_key_1" xsi:type="string">560</item> + </item> + </field> + </dataset> + <dataset name="grouped_three_simple_products"> <field name="options" xsi:type="array"> <item name="0" xsi:type="array"> diff --git a/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/TestCase/MoveRecentlyComparedProductsOnOrderPageTest.xml b/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/TestCase/MoveRecentlyComparedProductsOnOrderPageTest.xml new file mode 100644 index 0000000000000000000000000000000000000000..1de8aeda4e9a4415b476d73c8b454b17ad4f5824 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/TestCase/MoveRecentlyComparedProductsOnOrderPageTest.xml @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + --> +<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../vendor/magento/mtf/etc/variations.xsd"> + <testCase name="Magento\Sales\Test\TestCase\MoveRecentlyComparedProductsOnOrderPageTest"> + <variation name="MoveRecentlyComparedProductsOnOrderPageTestVariationWithGroupedProduct1"> + <data name="products/0" xsi:type="string">groupedProduct::three_simple_products</data> + <data name="products/1" xsi:type="string">groupedProduct::three_simple_products</data> + <data name="productsIsConfigured" xsi:type="boolean">true</data> + <constraint name="Magento\GroupedProduct\Test\Constraint\AssertProductInItemsOrderedGrid" /> + </variation> + </testCase> +</config> diff --git a/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/TestCase/TaxCalculationTest.xml b/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/TestCase/TaxCalculationTest.xml new file mode 100644 index 0000000000000000000000000000000000000000..c57afc28b88683e3b08917ae2c1d8942a7c3b614 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/TestCase/TaxCalculationTest.xml @@ -0,0 +1,41 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + --> +<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd"> + <testCase name="Magento\Tax\Test\TestCase\TaxCalculationTest" summary="Apply Taxes for grouped products" ticketId="MAGETWO-60576"> + <variation name="TaxCalculationTestGroupedProduct"> + <data name="product" xsi:type="string">groupedProduct::grouped_product_with_special_price</data> + <data name="taxRule" xsi:type="string">us_full_tax_rule</data> + <data name="shippingAddress/dataset" xsi:type="string">US_address_1</data> + <data name="customer/dataset" xsi:type="string">johndoe_unique</data> + <data name="salesRule" xsi:type="string">active_sales_rule_for_all_groups_no_coupon</data> + <data name="catalogRule" xsi:type="string">-</data> + <data name="configData" xsi:type="string">total_cat_excl_ship_incl_after_disc_on_excl, display_excluding_including_tax</data> + <data name="flushCache" xsi:type="boolean">true</data> + <data name="qty" xsi:type="string">3</data> + <data name="prices/category_price_excl_tax" xsi:type="string">9.00</data> + <data name="prices/category_price_incl_tax" xsi:type="string">9.90</data> + <data name="prices/sub_product_view_prices_1/product_view_price_excl_tax" xsi:type="string">9.00</data> + <data name="prices/sub_product_view_prices_1/product_view_price_incl_tax" xsi:type="string">9.90</data> + <data name="prices/sub_product_view_prices_2/product_view_price_excl_tax" xsi:type="string">9.00</data> + <data name="prices/sub_product_view_prices_2/product_view_price_incl_tax" xsi:type="string">9.90</data> + <data name="prices/cart_item_price_excl_tax" xsi:type="string">9.00</data> + <data name="prices/cart_item_price_incl_tax" xsi:type="string">9.90</data> + <data name="prices/cart_item_subtotal_excl_tax" xsi:type="string">27.00</data> + <data name="prices/cart_item_subtotal_incl_tax" xsi:type="string">29.70</data> + <data name="prices/subtotal_excl_tax" xsi:type="string">54.00</data> + <data name="prices/subtotal_incl_tax" xsi:type="string">59.40</data> + <data name="prices/shipping_excl_tax" xsi:type="string">30.00</data> + <data name="prices/shipping_incl_tax" xsi:type="string">30.00</data> + <data name="prices/discount" xsi:type="string">27.00</data> + <data name="prices/tax" xsi:type="string">2.70</data> + <data name="prices/grand_total_excl_tax" xsi:type="string">57.00</data> + <data name="prices/grand_total_incl_tax" xsi:type="string">59.70</data> + <constraint name="Magento\GroupedProduct\Test\Constraint\AssertTaxRuleIsAppliedToAllPricesGroupedExcludingIncludingTax" /> + </variation> + </testCase> +</config> diff --git a/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/etc/di.xml b/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/etc/di.xml new file mode 100644 index 0000000000000000000000000000000000000000..5b12a012749fb6feb0e90b1910d964a19394ca8d --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/etc/di.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + --> +<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd"> + <type name="Magento\Sales\Test\Block\Adminhtml\Order\Create\CustomerActivities\Sidebar\RecentlyComparedProducts"> + <arguments> + <argument name="config" xsi:type="array"> + <item name="renders" xsi:type="array"> + <item name="grouped" xsi:type="array"> + <item name="class" xsi:type="string">\Magento\GroupedProduct\Test\Block\Adminhtml\Product\Composite\Configure</item> + <item name="locator" xsi:type="string">//ancestor::body//*[contains(@class, "modal-slide") and contains(@class, "_show")]</item> + <item name="strategy" xsi:type="string">xpath</item> + </item> + </item> + </argument> + </arguments> + </type> +</config> diff --git a/dev/tests/functional/tests/app/Magento/Integration/Test/TestCase/DeleteIntegrationEntityTest.xml b/dev/tests/functional/tests/app/Magento/Integration/Test/TestCase/DeleteIntegrationEntityTest.xml index 56431ee145d18d1fcae4df990a0a388a9e7f99f0..6594757fe15ee54f2d2b2e0f34344a3b40812a0b 100644 --- a/dev/tests/functional/tests/app/Magento/Integration/Test/TestCase/DeleteIntegrationEntityTest.xml +++ b/dev/tests/functional/tests/app/Magento/Integration/Test/TestCase/DeleteIntegrationEntityTest.xml @@ -8,6 +8,7 @@ <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd"> <testCase name="Magento\Integration\Test\TestCase\DeleteIntegrationEntityTest" summary="Delete Integration" ticketId="MAGETWO-26058"> <variation name="DeleteIntegrationEntityTestVariation1"> + <data name="integration/dataset" xsi:type="string">default</data> <constraint name="Magento\Integration\Test\Constraint\AssertIntegrationSuccessDeleteMessage" /> <constraint name="Magento\Integration\Test\Constraint\AssertIntegrationNotInGrid" /> </variation> diff --git a/dev/tests/functional/tests/app/Magento/Multishipping/Test/etc/di.xml b/dev/tests/functional/tests/app/Magento/Multishipping/Test/etc/di.xml index 2eac5848ace436ca634913d40d9b88cbeac67f7c..c792d650be0c1a4f8d2b094c78a8e59ee71346b4 100644 --- a/dev/tests/functional/tests/app/Magento/Multishipping/Test/etc/di.xml +++ b/dev/tests/functional/tests/app/Magento/Multishipping/Test/etc/di.xml @@ -8,7 +8,7 @@ <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd"> <type name="Magento\Multishipping\Test\Constraint\AssertMultishippingOrderSuccessPlacedMessage"> <arguments> - <argument name="severity" xsi:type="string">high</argument> + <argument name="severity" xsi:type="string">S3</argument> </arguments> </type> </config> diff --git a/dev/tests/functional/tests/app/Magento/Payment/Test/Block/Form/Cc.php b/dev/tests/functional/tests/app/Magento/Payment/Test/Block/Form/Cc.php deleted file mode 100644 index 3e8226d371ff4546d7b243834485d2b0dff37d8a..0000000000000000000000000000000000000000 --- a/dev/tests/functional/tests/app/Magento/Payment/Test/Block/Form/Cc.php +++ /dev/null @@ -1,17 +0,0 @@ -<?php -/** - * Copyright © 2016 Magento. All rights reserved. - * See COPYING.txt for license details. - */ - -namespace Magento\Payment\Test\Block\Form; - -use Magento\Mtf\Block\Form; - -/** - * Form for filling credit card data. - */ -class Cc extends Form -{ - // -} diff --git a/dev/tests/functional/tests/app/Magento/Payment/Test/Block/Form/PaymentCc.php b/dev/tests/functional/tests/app/Magento/Payment/Test/Block/Form/PaymentCc.php new file mode 100644 index 0000000000000000000000000000000000000000..474052114c4d396476f5c5083c53e42109f662e6 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Payment/Test/Block/Form/PaymentCc.php @@ -0,0 +1,34 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Payment\Test\Block\Form; + +use Magento\Mtf\Block\Form; +use Magento\Mtf\Client\Element\SimpleElement; +use Magento\Mtf\Fixture\FixtureInterface; + +/** + * Form for filling credit card data. + */ +class PaymentCc extends Form +{ + /** + * Fill credit card form. + * + * @param FixtureInterface $fixture + * @param SimpleElement|null $element + * @return $this + */ + public function fill(FixtureInterface $fixture, SimpleElement $element = null) + { + $data = $fixture->getData(); + unset($data['payment_code']); + $mapping = $this->dataMapping($data); + $this->_fill($mapping, $element); + + return $this; + } +} diff --git a/dev/tests/functional/tests/app/Magento/Payment/Test/Block/Form/Cc.xml b/dev/tests/functional/tests/app/Magento/Payment/Test/Block/Form/PaymentCc.xml similarity index 100% rename from dev/tests/functional/tests/app/Magento/Payment/Test/Block/Form/Cc.xml rename to dev/tests/functional/tests/app/Magento/Payment/Test/Block/Form/PaymentCc.xml diff --git a/dev/tests/functional/tests/app/Magento/Payment/Test/Constraint/AssertCardRequiredFields.php b/dev/tests/functional/tests/app/Magento/Payment/Test/Constraint/AssertCardRequiredFields.php index 2b1d9bdcf2df8fdb32869731b7b3af05d47bc417..c8b52ed317d0fe7454277464d638c63209556298 100644 --- a/dev/tests/functional/tests/app/Magento/Payment/Test/Constraint/AssertCardRequiredFields.php +++ b/dev/tests/functional/tests/app/Magento/Payment/Test/Constraint/AssertCardRequiredFields.php @@ -7,7 +7,7 @@ namespace Magento\Payment\Test\Constraint; use Magento\Mtf\Constraint\AbstractConstraint; -use Magento\Payment\Test\Repository\CreditCardAdmin; +use Magento\Payment\Test\Repository\CreditCard; use Magento\Sales\Test\Page\Adminhtml\OrderCreateIndex; /** @@ -30,10 +30,10 @@ class AssertCardRequiredFields extends AbstractConstraint /** * Assert required fields on credit card payment method in backend. * @param OrderCreateIndex $orderCreateIndex - * @param CreditCardAdmin $creditCard + * @param CreditCard $creditCard * @return void */ - public function processAssert(OrderCreateIndex $orderCreateIndex, CreditCardAdmin $creditCard) + public function processAssert(OrderCreateIndex $orderCreateIndex, CreditCard $creditCard) { $actualRequiredFields = $orderCreateIndex->getCreateBlock()->getBillingMethodBlock() ->getJsErrors(); diff --git a/dev/tests/functional/tests/app/Magento/Payment/Test/Fixture/CreditCard.xml b/dev/tests/functional/tests/app/Magento/Payment/Test/Fixture/CreditCard.xml index 6fd5d8675b8b0f38d929d1372dbde9b3aeb601b7..2fe0da150438a784742c3930a41ad5e0362e40a1 100644 --- a/dev/tests/functional/tests/app/Magento/Payment/Test/Fixture/CreditCard.xml +++ b/dev/tests/functional/tests/app/Magento/Payment/Test/Fixture/CreditCard.xml @@ -12,6 +12,8 @@ entity_type="credit_card" repository_class="Magento\Payment\Test\Repository\CreditCard" class="Magento\Payment\Test\Fixture\CreditCard"> + <field name="payment_code" /> + <field name="cc_type" /> <field name="cc_number" /> <field name="cc_exp_month" /> <field name="cc_exp_year" /> diff --git a/dev/tests/functional/tests/app/Magento/Payment/Test/Fixture/CreditCardAdmin.xml b/dev/tests/functional/tests/app/Magento/Payment/Test/Fixture/CreditCardAdmin.xml deleted file mode 100644 index 87e69cee86addd91d612fb66c594b1bfb89c2638..0000000000000000000000000000000000000000 --- a/dev/tests/functional/tests/app/Magento/Payment/Test/Fixture/CreditCardAdmin.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/** - * Copyright © 2016 Magento. All rights reserved. - * See COPYING.txt for license details. - */ - --> -<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/fixture.xsd"> - <fixture name="credit_card_admin" - module="Magento_Payment" - type="virtual" - entity_type="credit_card_admin" - repository_class="Magento\Payment\Test\Repository\CreditCardAdmin" - class="Magento\Payment\Test\Fixture\CreditCardAdmin"> - <field name="cc_type" /> - <field name="cc_number" /> - <field name="cc_exp_month" /> - <field name="cc_exp_year" /> - <field name="cc_cid" /> - </fixture> -</config> diff --git a/dev/tests/functional/tests/app/Magento/Payment/Test/Repository/CreditCard.xml b/dev/tests/functional/tests/app/Magento/Payment/Test/Repository/CreditCard.xml index 8e742ab30ba960dd022870fea86e08c74d71c3fd..80c337d0a8578fb9115ff6382fabba5f6b1b844b 100644 --- a/dev/tests/functional/tests/app/Magento/Payment/Test/Repository/CreditCard.xml +++ b/dev/tests/functional/tests/app/Magento/Payment/Test/Repository/CreditCard.xml @@ -14,6 +14,14 @@ <field name="cc_cid" xsi:type="string">123</field> </dataset> + <dataset name="visa_default_admin"> + <field name="cc_type" xsi:type="string">Visa</field> + <field name="cc_number" xsi:type="string">4111111111111111</field> + <field name="cc_exp_month" xsi:type="string">01 - January</field> + <field name="cc_exp_year" xsi:type="string">2020</field> + <field name="cc_cid" xsi:type="string">123</field> + </dataset> + <dataset name="visa_alt"> <field name="cc_number" xsi:type="string">4012888888881881</field> <field name="cc_exp_month" xsi:type="string">02 - February</field> @@ -34,5 +42,13 @@ <field name="cc_exp_year" xsi:type="string">2020</field> <field name="cc_cid" xsi:type="string">123</field> </dataset> + + <dataset name="visa_empty"> + <field name="cc_type" xsi:type="string" /> + <field name="cc_number" xsi:type="string" /> + <field name="cc_exp_month" xsi:type="string" /> + <field name="cc_exp_year" xsi:type="string" /> + <field name="cc_cid" xsi:type="string" /> + </dataset> </repository> </config> diff --git a/dev/tests/functional/tests/app/Magento/Payment/Test/Repository/CreditCardAdmin.xml b/dev/tests/functional/tests/app/Magento/Payment/Test/Repository/CreditCardAdmin.xml deleted file mode 100644 index 371c8f350c6af028ddc544c23142f2886d699dbd..0000000000000000000000000000000000000000 --- a/dev/tests/functional/tests/app/Magento/Payment/Test/Repository/CreditCardAdmin.xml +++ /dev/null @@ -1,32 +0,0 @@ -<?xml version="1.0" ?> -<!-- -/** - * Copyright © 2016 Magento. All rights reserved. - * See COPYING.txt for license details. - */ ---> -<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/Magento/Mtf/Repository/etc/repository.xsd"> - <repository class="Magento\Payment\Test\Repository\CreditCardAdmin"> - <dataset name="visa_default"> - <field name="cc_type" xsi:type="string">Visa</field> - <field name="cc_number" xsi:type="string">4111111111111111</field> - <field name="cc_exp_month" xsi:type="string">01 - January</field> - <field name="cc_exp_year" xsi:type="string">2020</field> - <field name="cc_cid" xsi:type="string">123</field> - </dataset> - - <dataset name="visa_direct"> - <field name="cc_type" xsi:type="string">Visa</field> - <field name="cc_number" xsi:type="string">4617747819866651</field> - <field name="cc_exp_month" xsi:type="string">01 - January</field> - <field name="cc_exp_year" xsi:type="string">2020</field> - <field name="cc_cid" xsi:type="string">123</field> - </dataset> - <dataset name="visa_empty"> - <field name="cc_type" xsi:type="string">Please Select</field> - <field name="cc_number" xsi:type="string" /> - <field name="cc_exp_month" xsi:type="string">Month</field> - <field name="cc_cid" xsi:type="string" /> - </dataset> - </repository> -</config> diff --git a/dev/tests/functional/tests/app/Magento/Paypal/Test/Block/Form/HostedPro/Cc.php b/dev/tests/functional/tests/app/Magento/Paypal/Test/Block/Form/HostedPro/Cc.php new file mode 100644 index 0000000000000000000000000000000000000000..53fd258b84cbb0ca65b588672eaeeaaf21f43041 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Paypal/Test/Block/Form/HostedPro/Cc.php @@ -0,0 +1,17 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Paypal\Test\Block\Form\HostedPro; + +use Magento\Payment\Test\Block\Form\PaymentCc as CreditCard; + +/** + * Form for filling credit card data for Hosted Pro payment method. + */ +class Cc extends CreditCard +{ + // +} diff --git a/dev/tests/functional/tests/app/Magento/Paypal/Test/Block/Form/HostedPro/Cc.xml b/dev/tests/functional/tests/app/Magento/Paypal/Test/Block/Form/HostedPro/Cc.xml new file mode 100644 index 0000000000000000000000000000000000000000..b6a0945a693a954bd2602031ebf0ae4f94b81beb --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Paypal/Test/Block/Form/HostedPro/Cc.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" ?> +<!-- +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<mapping strict="0"> + <fields> + <cc_type> + <input>select</input> + <selector>#credit_card_type</selector> + </cc_type> + <cc_number> + <selector>#credit_card_number</selector> + </cc_number> + <cc_exp_month> + <selector>[name=expiryMonth]</selector> + </cc_exp_month> + <cc_exp_year> + <selector>[name=expiryYear]</selector> + </cc_exp_year> + <cc_cid> + <selector>[name=cvv2]</selector> + </cc_cid> + </fields> +</mapping> diff --git a/dev/tests/functional/tests/app/Magento/Paypal/Test/Block/Form/PayflowLink/Cc.php b/dev/tests/functional/tests/app/Magento/Paypal/Test/Block/Form/PayflowLink/Cc.php new file mode 100644 index 0000000000000000000000000000000000000000..3f369efc7e829c2e427e883320183a51565006d4 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Paypal/Test/Block/Form/PayflowLink/Cc.php @@ -0,0 +1,17 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Paypal\Test\Block\Form\PayflowLink; + +use Magento\Payment\Test\Block\Form\PaymentCc as CreditCard; + +/** + * Form for filling credit card data for Payflow Link payment method. + */ +class Cc extends CreditCard +{ + // +} diff --git a/dev/tests/functional/tests/app/Magento/Paypal/Test/Block/Form/PayflowLink/Cc.xml b/dev/tests/functional/tests/app/Magento/Paypal/Test/Block/Form/PayflowLink/Cc.xml new file mode 100644 index 0000000000000000000000000000000000000000..1eaabeede0d49c5dc1387e7e27c560510e6db0a3 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Paypal/Test/Block/Form/PayflowLink/Cc.xml @@ -0,0 +1,23 @@ +<?xml version="1.0" ?> +<!-- +/** +* Copyright © 2016 Magento. All rights reserved. +* See COPYING.txt for license details. +*/ +--> +<mapping strict="0"> + <fields> + <cc_number> + <selector>#cc_number</selector> + </cc_number> + <cc_exp_month> + <selector>#expdate_month</selector> + </cc_exp_month> + <cc_exp_year> + <selector>#expdate_year</selector> + </cc_exp_year> + <cc_cid> + <selector>#cvv2_number</selector> + </cc_cid> + </fields> +</mapping> diff --git a/dev/tests/functional/tests/app/Magento/Paypal/Test/Block/Form/PaymentsAdvanced/Cc.php b/dev/tests/functional/tests/app/Magento/Paypal/Test/Block/Form/PaymentsAdvanced/Cc.php new file mode 100644 index 0000000000000000000000000000000000000000..a990a41cd69afa9e9969ed6668e17125647aee77 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Paypal/Test/Block/Form/PaymentsAdvanced/Cc.php @@ -0,0 +1,17 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Paypal\Test\Block\Form\PaymentsAdvanced; + +use Magento\Payment\Test\Block\Form\PaymentCc as CreditCard; + +/** + * Form for filling credit card data for Payments Advanced payment method. + */ +class Cc extends CreditCard +{ + // +} diff --git a/dev/tests/functional/tests/app/Magento/Paypal/Test/Block/Form/PaymentsAdvanced/Cc.xml b/dev/tests/functional/tests/app/Magento/Paypal/Test/Block/Form/PaymentsAdvanced/Cc.xml new file mode 100644 index 0000000000000000000000000000000000000000..1eaabeede0d49c5dc1387e7e27c560510e6db0a3 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Paypal/Test/Block/Form/PaymentsAdvanced/Cc.xml @@ -0,0 +1,23 @@ +<?xml version="1.0" ?> +<!-- +/** +* Copyright © 2016 Magento. All rights reserved. +* See COPYING.txt for license details. +*/ +--> +<mapping strict="0"> + <fields> + <cc_number> + <selector>#cc_number</selector> + </cc_number> + <cc_exp_month> + <selector>#expdate_month</selector> + </cc_exp_month> + <cc_exp_year> + <selector>#expdate_year</selector> + </cc_exp_year> + <cc_cid> + <selector>#cvv2_number</selector> + </cc_cid> + </fields> +</mapping> diff --git a/dev/tests/functional/tests/app/Magento/Paypal/Test/Block/Onepage/Payment/HostedPro.php b/dev/tests/functional/tests/app/Magento/Paypal/Test/Block/Onepage/Payment/HostedPro.php new file mode 100644 index 0000000000000000000000000000000000000000..f7ee9fc20947e5c4a7bf0acc5bf2ff829aad87c0 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Paypal/Test/Block/Onepage/Payment/HostedPro.php @@ -0,0 +1,20 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Paypal\Test\Block\Onepage\Payment; + +/** + * Hosted Pro credit card block. + */ +class HostedPro extends PaypalIframe +{ + /** + * Block for filling credit card data for Hosted Pro payment method. + * + * @var string + */ + protected $formBlockCc = \Magento\Paypal\Test\Block\Form\HostedPro\Cc::class; +} diff --git a/dev/tests/functional/tests/app/Magento/Paypal/Test/Block/Onepage/Payment/PayflowLink.php b/dev/tests/functional/tests/app/Magento/Paypal/Test/Block/Onepage/Payment/PayflowLink.php new file mode 100644 index 0000000000000000000000000000000000000000..c6b8d37dc3faa1634450e9152636171e44ec9139 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Paypal/Test/Block/Onepage/Payment/PayflowLink.php @@ -0,0 +1,20 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Paypal\Test\Block\Onepage\Payment; + +/** + * Payflow Link credit card block. + */ +class PayflowLink extends PaypalIframe +{ + /** + * Block for filling credit card data for Payflow Link payment method. + * + * @var string + */ + protected $formBlockCc = \Magento\Paypal\Test\Block\Form\PayflowLink\Cc::class; +} diff --git a/dev/tests/functional/tests/app/Magento/Paypal/Test/Block/Onepage/Payment/PaymentsAdvanced.php b/dev/tests/functional/tests/app/Magento/Paypal/Test/Block/Onepage/Payment/PaymentsAdvanced.php new file mode 100644 index 0000000000000000000000000000000000000000..bb80ab1ccfc3be3892813f744da23f56a0f11ac3 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Paypal/Test/Block/Onepage/Payment/PaymentsAdvanced.php @@ -0,0 +1,20 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Paypal\Test\Block\Onepage\Payment; + +/** + * Payments Advanced credit card block. + */ +class PaymentsAdvanced extends PaypalIframe +{ + /** + * Block for filling credit card data for Payments Advanced payment method. + * + * @var string + */ + protected $formBlockCc = \Magento\Paypal\Test\Block\Form\PaymentsAdvanced\Cc::class; +} diff --git a/dev/tests/functional/tests/app/Magento/Paypal/Test/Block/Onepage/Payment/PaypalIframe.php b/dev/tests/functional/tests/app/Magento/Paypal/Test/Block/Onepage/Payment/PaypalIframe.php new file mode 100644 index 0000000000000000000000000000000000000000..574dc256589b6afec1ea5d4f2252bf390b31a7e5 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Paypal/Test/Block/Onepage/Payment/PaypalIframe.php @@ -0,0 +1,98 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Paypal\Test\Block\Onepage\Payment; + +use Magento\Checkout\Test\Block\Onepage\Payment\Method; +use Magento\Mtf\Client\ElementInterface; +use Magento\Mtf\Fixture\FixtureInterface; + +/** + * Paypal Iframe block. + */ +class PaypalIframe extends Method +{ + /** + * 'Pay Now' button selector. + * + * @var string + */ + private $payNowButton = '#btn_pay_cc'; + + /** + * PayPal iframe selector. + * + * @var string + */ + private $paypalIframe = '.paypal.iframe'; + + /** + * Credit card form selector. + * + * @var string + */ + private $creditCardForm = '#formCreditCard'; + + /** + * Error message selector. + * + * @var string + */ + private $errorMessage = '#messageBox'; + + /** + * Block for filling credit card data for payment method. + * + * @var string + */ + protected $formBlockCc; + + /** + * Fill credit card data in PayPal iframe form. + * + * @param FixtureInterface $creditCard + * @return void + */ + public function fillPaymentData(FixtureInterface $creditCard) + { + $iframeRootElement = $this->switchToPaypalFrame(); + $formBlock = $this->blockFactory->create( + $this->formBlockCc, + ['element' => $this->_rootElement->find($this->creditCardForm)] + ); + $formBlock->fill($creditCard, $iframeRootElement); + $iframeRootElement->find($this->payNowButton)->click(); + $this->browser->switchToFrame(); + } + + /** + * Check if error message is appeared. + * + * @return bool + */ + public function isErrorMessageVisible() + { + $isErrorMessageVisible = false; + if ($this->_rootElement->find($this->paypalIframe)->isPresent()) { + $iframeRootElement = $this->switchToPaypalFrame(); + $isErrorMessageVisible = $iframeRootElement->find($this->errorMessage)->isVisible(); + $this->browser->switchToFrame(); + } + return $isErrorMessageVisible; + } + + /** + * Change the focus to a PayPal frame. + * + * @return ElementInterface + */ + private function switchToPaypalFrame() + { + $iframeLocator = $this->browser->find($this->paypalIframe)->getLocator(); + $this->browser->switchToFrame($iframeLocator); + return $this->browser->find('body'); + } +} diff --git a/dev/tests/functional/tests/app/Magento/Paypal/Test/Page/CheckoutOnepage.xml b/dev/tests/functional/tests/app/Magento/Paypal/Test/Page/CheckoutOnepage.xml new file mode 100644 index 0000000000000000000000000000000000000000..da37a44f9bf3db04ff42c1a14a0f36e0e499b9c7 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Paypal/Test/Page/CheckoutOnepage.xml @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + --> +<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/pages.xsd"> + <page name="CheckoutOnepage" mca="checkout" module="Magento_Checkout"> + <block name="payflowLinkBlock" class="Magento\Paypal\Test\Block\Onepage\Payment\PayflowLink" locator="#checkout-step-payment" strategy="css selector" /> + <block name="paymentsAdvancedBlock" class="Magento\Paypal\Test\Block\Onepage\Payment\PaymentsAdvanced" locator="#checkout-step-payment" strategy="css selector" /> + <block name="hostedProBlock" class="Magento\Paypal\Test\Block\Onepage\Payment\HostedPro" locator="#checkout-step-payment" strategy="css selector" /> + </page> +</config> diff --git a/dev/tests/functional/tests/app/Magento/Paypal/Test/Repository/ConfigData.xml b/dev/tests/functional/tests/app/Magento/Paypal/Test/Repository/ConfigData.xml index 0706f45beeb4bdfa39bfd65f6a76094ef77574e7..f1d041f0a5b344fb76e91acd57124eb03d9f6ae8 100644 --- a/dev/tests/functional/tests/app/Magento/Paypal/Test/Repository/ConfigData.xml +++ b/dev/tests/functional/tests/app/Magento/Paypal/Test/Repository/ConfigData.xml @@ -7,89 +7,177 @@ --> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/Magento/Mtf/Repository/etc/repository.xsd"> <repository class="Magento\Config\Test\Repository\ConfigData"> + <dataset name="merchant_country_gb"> + <field name="paypal/general/merchant_country" xsi:type="array"> + <item name="scope" xsi:type="string">payment</item> + <item name="scope_id" xsi:type="number">1</item> + <item name="label" xsi:type="string">United Kingdom</item> + <item name="value" xsi:type="string">GB</item> + </field> + </dataset> + <dataset name="merchant_country_gb_rollback"> + <field name="paypal/general/merchant_country" xsi:type="array"> + <item name="scope" xsi:type="string">payment</item> + <item name="scope_id" xsi:type="number">1</item> + <item name="label" xsi:type="string">United States</item> + <item name="value" xsi:type="string">US</item> + </field> + </dataset> + <dataset name="paypal_direct"> - <field name="payment/paypal_group_all_in_one/wpp_usuk/wpp_required_settings/wpp_and_express_checkout/business_account" xsi:type="array"> + <field name="payment/paypal_group_all_in_one/wpp_usuk/paypal_payflow_required/paypal_payflow_api_settings/business_account" xsi:type="array"> <item name="scope" xsi:type="string">payment</item> <item name="scope_id" xsi:type="number">1</item> - <item name="label" xsi:type="string">Yes</item> - <item name="value" xsi:type="string">PAYPAL_BUSINESS_ACCOUNT</item> + <item name="label" xsi:type="string">Email Associated with PayPal Merchant Account (Optional)</item> + <item name="value" xsi:type="string">%payflow_pro_business_account%</item> </field> - <field name="payment/paypal_group_all_in_one/wpp_usuk/wpp_required_settings/wpp_and_express_checkout/api_username" xsi:type="array"> + <field name="payment/paypal_group_all_in_one/wpp_usuk/paypal_payflow_required/paypal_payflow_api_settings/partner" xsi:type="array"> <item name="scope" xsi:type="string">payment</item> <item name="scope_id" xsi:type="number">1</item> - <item name="label" xsi:type="string"/> - <item name="value" xsi:type="string">PAYPAL_API_USERNAME</item> + <item name="label" xsi:type="string">Partner</item> + <item name="value" xsi:type="string">%payflow_pro_partner%</item> </field> - <field name="payment/paypal_group_all_in_one/wpp_usuk/wpp_required_settings/wpp_and_express_checkout/api_password" xsi:type="array"> + <field name="payment/paypal_group_all_in_one/wpp_usuk/paypal_payflow_required/paypal_payflow_api_settings/user" xsi:type="array"> <item name="scope" xsi:type="string">payment</item> <item name="scope_id" xsi:type="number">1</item> - <item name="label" xsi:type="string"/> - <item name="value" xsi:type="string">PAYPAL_API_PASSWORD</item> + <item name="label" xsi:type="string">User</item> + <item name="value" xsi:type="string">%payflow_pro_user%</item> + </field> + <field name="payment/paypal_group_all_in_one/wpp_usuk/paypal_payflow_required/paypal_payflow_api_settings/vendor" xsi:type="array"> + <item name="scope" xsi:type="string">payment</item> + <item name="scope_id" xsi:type="number">1</item> + <item name="label" xsi:type="string">Vendor</item> + <item name="value" xsi:type="string">%payflow_pro_vendor%</item> + </field> + <field name="payment/paypal_group_all_in_one/wpp_usuk/paypal_payflow_required/paypal_payflow_api_settings/pwd" xsi:type="array"> + <item name="scope" xsi:type="string">payment</item> + <item name="scope_id" xsi:type="number">1</item> + <item name="label" xsi:type="string">Password</item> + <item name="value" xsi:type="string">%payflow_pro_pwd%</item> + </field> + <field name="payment/paypal_group_all_in_one/wpp_usuk/paypal_payflow_required/paypal_payflow_api_settings/sandbox_flag" xsi:type="array"> + <item name="scope" xsi:type="string">payment</item> + <item name="scope_id" xsi:type="number">1</item> + <item name="label" xsi:type="string">Test Mode</item> + <item name="value" xsi:type="number">1</item> + </field> + <field name="payment/paypal_group_all_in_one/wpp_usuk/paypal_payflow_required/enable_paypal_payflow" xsi:type="array"> + <item name="scope" xsi:type="string">payment</item> + <item name="scope_id" xsi:type="number">1</item> + <item name="label" xsi:type="string">Enable this Solution</item> + <item name="value" xsi:type="number">1</item> + </field> + </dataset> + <dataset name="paypal_direct_rollback"> + <field name="payment/paypal_group_all_in_one/wpp_usuk/paypal_payflow_required/enable_paypal_payflow" xsi:type="array"> + <item name="scope" xsi:type="string">payment</item> + <item name="scope_id" xsi:type="number">1</item> + <item name="label" xsi:type="string">Enable this Solution</item> + <item name="value" xsi:type="number">0</item> + </field> + </dataset> + + <dataset name="payflowpro"> + <field name="payment/paypal_payment_gateways/paypal_payflowpro_with_express_checkout/paypal_payflow_required/paypal_payflow_api_settings/business_account" xsi:type="array"> + <item name="scope" xsi:type="string">payment</item> + <item name="scope_id" xsi:type="number">1</item> + <item name="label" xsi:type="string">Email Associated with PayPal Merchant Account (Optional)</item> + <item name="value" xsi:type="string">%payflow_pro_business_account%</item> + </field> + <field name="payment/paypal_payment_gateways/paypal_payflowpro_with_express_checkout/paypal_payflow_required/paypal_payflow_api_settings/partner" xsi:type="array"> + <item name="scope" xsi:type="string">payment</item> + <item name="scope_id" xsi:type="number">1</item> + <item name="label" xsi:type="string">Partner</item> + <item name="value" xsi:type="string">%payflow_pro_partner%</item> </field> - <field name="payment/paypal_group_all_in_one/wpp_usuk/wpp_required_settings/wpp_and_express_checkout/api_signature" xsi:type="array"> + <field name="payment/paypal_payment_gateways/paypal_payflowpro_with_express_checkout/paypal_payflow_required/paypal_payflow_api_settings/user" xsi:type="array"> + <item name="scope" xsi:type="string">payment</item> + <item name="scope_id" xsi:type="number">1</item> + <item name="label" xsi:type="string">User</item> + <item name="value" xsi:type="string">%payflow_pro_user%</item> + </field> + <field name="payment/paypal_payment_gateways/paypal_payflowpro_with_express_checkout/paypal_payflow_required/paypal_payflow_api_settings/pwd" xsi:type="array"> + <item name="scope" xsi:type="string">payment</item> + <item name="scope_id" xsi:type="number">1</item> + <item name="label" xsi:type="string">Password</item> + <item name="value" xsi:type="string">%payflow_pro_pwd%</item> + </field> + <field name="payment/paypal_payment_gateways/paypal_payflowpro_with_express_checkout/paypal_payflow_required/paypal_payflow_api_settings/vendor" xsi:type="array"> + <item name="scope" xsi:type="string">payment</item> + <item name="scope_id" xsi:type="number">1</item> + <item name="label" xsi:type="string">Vendor</item> + <item name="value" xsi:type="string">%payflow_pro_vendor%</item> + </field> + <field name="payment/paypal_payment_gateways/paypal_payflowpro_with_express_checkout/paypal_payflow_required/paypal_payflow_api_settings/sandbox_flag" xsi:type="array"> <item name="scope" xsi:type="string">payment</item> <item name="scope_id" xsi:type="number">1</item> <item name="label" xsi:type="string"/> - <item name="value" xsi:type="string">PAYPAL_API_SIGNATURE</item> + <item name="value" xsi:type="number">1</item> </field> - <field name="payment/paypal_group_all_in_one/wpp_usuk/wpp_required_settings/wpp_and_express_checkout/sandbox_flag" xsi:type="array"> + <field name="payment/payflowpro/debug" xsi:type="array"> <item name="scope" xsi:type="string">payment</item> <item name="scope_id" xsi:type="number">1</item> <item name="label" xsi:type="string">Yes</item> <item name="value" xsi:type="number">1</item> </field> - <field name="payment/paypal_direct/debug" xsi:type="array"> + <field name="payment/payflowpro/active" xsi:type="array"> <item name="scope" xsi:type="string">payment</item> <item name="scope_id" xsi:type="number">1</item> <item name="label" xsi:type="string">Yes</item> <item name="value" xsi:type="number">1</item> </field> - <field name="payment/paypal_direct/active" xsi:type="array"> + <field name="payment/payflow_express/debug" xsi:type="array"> <item name="scope" xsi:type="string">payment</item> <item name="scope_id" xsi:type="number">1</item> <item name="label" xsi:type="string">Yes</item> <item name="value" xsi:type="number">1</item> </field> - </dataset> - <dataset name="paypal_direct_rollback"> - <field name="payment/paypal_direct/active" xsi:type="array"> + <field name="payment/payflow_express/active" xsi:type="array"> <item name="scope" xsi:type="string">payment</item> <item name="scope_id" xsi:type="number">1</item> <item name="label" xsi:type="string">Yes</item> + <item name="value" xsi:type="number">1</item> + </field> + </dataset> + <dataset name="payflowpro_rollback"> + <field name="payment/payflowpro/active" xsi:type="array"> + <item name="scope" xsi:type="string">payment</item> + <item name="scope_id" xsi:type="number">1</item> + <item name="label" xsi:type="string">No</item> <item name="value" xsi:type="number">0</item> </field> </dataset> - <dataset name="payflowpro"> + <dataset name="payflowpro_fraud_filters_enabled"> <field name="payment/paypal_payment_gateways/paypal_payflowpro_with_express_checkout/paypal_payflow_required/paypal_payflow_api_settings/business_account" xsi:type="array"> <item name="scope" xsi:type="string">payment</item> <item name="scope_id" xsi:type="number">1</item> - <item name="label" xsi:type="string">Yes</item> - <item name="value" xsi:type="string">PAYPAL_BUSINESS_ACCOUNT</item> + <item name="label" xsi:type="string">Email Associated with PayPal Merchant Account (Optional)</item> + <item name="value" xsi:type="string">%payflow_pro_fraud_protection_enabled_business_account%</item> </field> <field name="payment/paypal_payment_gateways/paypal_payflowpro_with_express_checkout/paypal_payflow_required/paypal_payflow_api_settings/partner" xsi:type="array"> <item name="scope" xsi:type="string">payment</item> <item name="scope_id" xsi:type="number">1</item> - <item name="label" xsi:type="string"/> - <item name="value" xsi:type="string">PAYMENT_PAYFLOWPRO_PARTNER</item> + <item name="label" xsi:type="string">Partner</item> + <item name="value" xsi:type="string">%payflow_pro_fraud_protection_enabled_partner%</item> </field> <field name="payment/paypal_payment_gateways/paypal_payflowpro_with_express_checkout/paypal_payflow_required/paypal_payflow_api_settings/user" xsi:type="array"> <item name="scope" xsi:type="string">payment</item> <item name="scope_id" xsi:type="number">1</item> - <item name="label" xsi:type="string"/> - <item name="value" xsi:type="string">PAYMENT_PAYFLOWPRO_USER</item> + <item name="label" xsi:type="string">User</item> + <item name="value" xsi:type="string">%payflow_pro_fraud_protection_enabled_user%</item> </field> <field name="payment/paypal_payment_gateways/paypal_payflowpro_with_express_checkout/paypal_payflow_required/paypal_payflow_api_settings/pwd" xsi:type="array"> <item name="scope" xsi:type="string">payment</item> <item name="scope_id" xsi:type="number">1</item> - <item name="label" xsi:type="string"/> - <item name="value" xsi:type="string">PAYMENT_PAYFLOWPRO_PWD</item> + <item name="label" xsi:type="string">Password</item> + <item name="value" xsi:type="string">%payflow_pro_fraud_protection_enabled_pwd%</item> </field> <field name="payment/paypal_payment_gateways/paypal_payflowpro_with_express_checkout/paypal_payflow_required/paypal_payflow_api_settings/vendor" xsi:type="array"> <item name="scope" xsi:type="string">payment</item> <item name="scope_id" xsi:type="number">1</item> - <item name="label" xsi:type="string"/> - <item name="value" xsi:type="string">PAYMENT_PAYFLOWPRO_VENDOR</item> + <item name="label" xsi:type="string">Vendor</item> + <item name="value" xsi:type="string">%payflow_pro_fraud_protection_enabled_vendor%</item> </field> <field name="payment/paypal_payment_gateways/paypal_payflowpro_with_express_checkout/paypal_payflow_required/paypal_payflow_api_settings/sandbox_flag" xsi:type="array"> <item name="scope" xsi:type="string">payment</item> @@ -122,11 +210,81 @@ <item name="value" xsi:type="number">1</item> </field> </dataset> - <dataset name="payflowpro_rollback"> + <dataset name="payflowpro_fraud_filters_enabled_rollback"> <field name="payment/payflowpro/active" xsi:type="array"> + <item name="scope" xsi:type="string">payment</item> + <item name="scope_id" xsi:type="number">1</item> + <item name="label" xsi:type="string">No</item> + <item name="value" xsi:type="number">0</item> + </field> + </dataset> + + <dataset name="payflowpro_avs_street_does_not_match"> + <field name="payment/payflowpro/avs_street" xsi:type="array"> <item name="scope" xsi:type="string">payment</item> <item name="scope_id" xsi:type="number">1</item> <item name="label" xsi:type="string">Yes</item> + <item name="value" xsi:type="number">1</item> + </field> + </dataset> + <dataset name="payflowpro_avs_street_does_not_match_rollback"> + <field name="payment/payflowpro/avs_street" xsi:type="array"> + <item name="scope" xsi:type="string">payment</item> + <item name="scope_id" xsi:type="number">1</item> + <item name="label" xsi:type="string">No</item> + <item name="value" xsi:type="number">0</item> + </field> + </dataset> + + <dataset name="hosted_pro"> + <field name="payment/paypal_group_all_in_one/payments_pro_hosted_solution_with_express_checkout/pphs_required_settings/pphs_required_settings_pphs/business_account" xsi:type="array"> + <item name="scope" xsi:type="string">payment</item> + <item name="scope_id" xsi:type="number">1</item> + <item name="label" xsi:type="string">Yes</item> + <item name="value" xsi:type="string">HOSTED_PRO_BUSINESS_ACCOUNT</item> + </field> + <field name="payment/paypal_group_all_in_one/payments_pro_hosted_solution_with_express_checkout/pphs_required_settings/pphs_required_settings_pphs/api_username" xsi:type="array"> + <item name="scope" xsi:type="string">payment</item> + <item name="scope_id" xsi:type="number">1</item> + <item name="label" xsi:type="string"/> + <item name="value" xsi:type="string">HOSTED_PRO_API_USERNAME</item> + </field> + <field name="payment/paypal_group_all_in_one/payments_pro_hosted_solution_with_express_checkout/pphs_required_settings/pphs_required_settings_pphs/api_password" xsi:type="array"> + <item name="scope" xsi:type="string">payment</item> + <item name="scope_id" xsi:type="number">1</item> + <item name="label" xsi:type="string"/> + <item name="value" xsi:type="string">HOSTED_PRO_API_PASSWORD</item> + </field> + <field name="payment/paypal_group_all_in_one/payments_pro_hosted_solution_with_express_checkout/pphs_required_settings/pphs_required_settings_pphs/api_signature" xsi:type="array"> + <item name="scope" xsi:type="string">payment</item> + <item name="scope_id" xsi:type="number">1</item> + <item name="label" xsi:type="string"/> + <item name="value" xsi:type="string">HOSTED_PRO_API_SIGNATURE</item> + </field> + <field name="payment/paypal_group_all_in_one/payments_pro_hosted_solution_with_express_checkout/pphs_required_settings/pphs_required_settings_pphs/sandbox_flag" xsi:type="array"> + <item name="scope" xsi:type="string">payment</item> + <item name="scope_id" xsi:type="number">1</item> + <item name="label" xsi:type="string">Yes</item> + <item name="value" xsi:type="number">1</item> + </field> + <field name="payment/hosted_pro/debug" xsi:type="array"> + <item name="scope" xsi:type="string">payment</item> + <item name="scope_id" xsi:type="number">1</item> + <item name="label" xsi:type="string">Yes</item> + <item name="value" xsi:type="number">1</item> + </field> + <field name="payment/hosted_pro/active" xsi:type="array"> + <item name="scope" xsi:type="string">payment</item> + <item name="scope_id" xsi:type="number">1</item> + <item name="label" xsi:type="string">Yes</item> + <item name="value" xsi:type="number">1</item> + </field> + </dataset> + <dataset name="hosted_pro_rollback"> + <field name="payment/hosted_pro/active" xsi:type="array"> + <item name="scope" xsi:type="string">payment</item> + <item name="scope_id" xsi:type="number">1</item> + <item name="label" xsi:type="string">No</item> <item name="value" xsi:type="number">0</item> </field> </dataset> @@ -184,41 +342,100 @@ </field> </dataset> + <dataset name="payments_advanced"> + <field name="payment/paypal_group_all_in_one/payflow_advanced/required_settings/payments_advanced/business_account" xsi:type="array"> + <item name="scope" xsi:type="string">payment</item> + <item name="scope_id" xsi:type="number">1</item> + <item name="label" xsi:type="string">Email Associated with PayPal Merchant Account</item> + <item name="value" xsi:type="string">%payflow_link_business_account_email%</item> + </field> + <field name="payment/paypal_group_all_in_one/payflow_advanced/required_settings/payments_advanced/partner" xsi:type="array"> + <item name="scope" xsi:type="string">payment</item> + <item name="scope_id" xsi:type="number">1</item> + <item name="label" xsi:type="string">Partner</item> + <item name="value" xsi:type="string">%payflow_link_partner%</item> + </field> + <field name="payment/paypal_group_all_in_one/payflow_advanced/required_settings/payments_advanced/user" xsi:type="array"> + <item name="scope" xsi:type="string">payment</item> + <item name="scope_id" xsi:type="number">1</item> + <item name="label" xsi:type="string">User</item> + <item name="value" xsi:type="string">%payflow_link_user%</item> + </field> + <field name="payment/paypal_group_all_in_one/payflow_advanced/required_settings/payments_advanced/pwd" xsi:type="array"> + <item name="scope" xsi:type="string">payment</item> + <item name="scope_id" xsi:type="number">1</item> + <item name="label" xsi:type="string">Password</item> + <item name="value" xsi:type="string">%payflow_link_password%</item> + </field> + <field name="payment/paypal_group_all_in_one/payflow_advanced/required_settings/payments_advanced/vendor" xsi:type="array"> + <item name="scope" xsi:type="string">payment</item> + <item name="scope_id" xsi:type="number">1</item> + <item name="label" xsi:type="string">Vendor</item> + <item name="value" xsi:type="string">%payflow_link_vendor%</item> + </field> + <field name="payment/paypal_group_all_in_one/payflow_advanced/required_settings/payments_advanced/sandbox_flag" xsi:type="array"> + <item name="scope" xsi:type="string">payment</item> + <item name="scope_id" xsi:type="number">1</item> + <item name="label" xsi:type="string">Yes</item> + <item name="value" xsi:type="number">1</item> + </field> + <field name="payment/payflow_advanced/active" xsi:type="array"> + <item name="scope" xsi:type="string">payment</item> + <item name="scope_id" xsi:type="number">1</item> + <item name="label" xsi:type="string">Yes</item> + <item name="value" xsi:type="number">1</item> + </field> + </dataset> + <dataset name="payments_advanced_rollback"> + <field name="payment/payflow_advanced/active" xsi:type="array"> + <item name="scope" xsi:type="string">payment</item> + <item name="scope_id" xsi:type="number">1</item> + <item name="label" xsi:type="string">No</item> + <item name="value" xsi:type="number">0</item> + </field> + </dataset> + <dataset name="payflowlink"> <field name="payment/paypal_payment_gateways/payflow_link_us/payflow_link_required/payflow_link_payflow_link/business_account" xsi:type="array"> <item name="scope" xsi:type="string">payment</item> <item name="scope_id" xsi:type="number">1</item> - <item name="label" xsi:type="string">Yes</item> - <item name="value" xsi:type="string">PAYPAL_BUSINESS_ACCOUNT</item> + <item name="label" xsi:type="string">Email Associated with PayPal Merchant Account</item> + <item name="value" xsi:type="string">%payflow_link_business_account_email%</item> </field> <field name="payment/paypal_payment_gateways/payflow_link_us/payflow_link_required/payflow_link_payflow_link/partner" xsi:type="array"> <item name="scope" xsi:type="string">payment</item> <item name="scope_id" xsi:type="number">1</item> - <item name="label" xsi:type="string"/> - <item name="value" xsi:type="string">PAYMENT_PAYFLOWLINK_PARTNER</item> + <item name="label" xsi:type="string">Partner</item> + <item name="value" xsi:type="string">%payflow_link_partner%</item> </field> <field name="payment/paypal_payment_gateways/payflow_link_us/payflow_link_required/payflow_link_payflow_link/user" xsi:type="array"> <item name="scope" xsi:type="string">payment</item> <item name="scope_id" xsi:type="number">1</item> - <item name="label" xsi:type="string"/> - <item name="value" xsi:type="string">PAYMENT_PAYFLOWLINK_USER</item> + <item name="label" xsi:type="string">User</item> + <item name="value" xsi:type="string">%payflow_link_user%</item> </field> <field name="payment/paypal_payment_gateways/payflow_link_us/payflow_link_required/payflow_link_payflow_link/pwd" xsi:type="array"> <item name="scope" xsi:type="string">payment</item> <item name="scope_id" xsi:type="number">1</item> - <item name="label" xsi:type="string"/> - <item name="value" xsi:type="string">PAYMENT_PAYFLOWLINK_PWD</item> + <item name="label" xsi:type="string">Password</item> + <item name="value" xsi:type="string">%payflow_link_password%</item> </field> <field name="payment/paypal_payment_gateways/payflow_link_us/payflow_link_required/payflow_link_payflow_link/vendor" xsi:type="array"> <item name="scope" xsi:type="string">payment</item> <item name="scope_id" xsi:type="number">1</item> - <item name="label" xsi:type="string"/> - <item name="value" xsi:type="string">PAYMENT_PAYFLOWLINK_VENDOR</item> + <item name="label" xsi:type="string">Vendor</item> + <item name="value" xsi:type="string">%payflow_link_vendor%</item> </field> <field name="payment/paypal_payment_gateways/payflow_link_us/payflow_link_required/payflow_link_payflow_link/sandbox_flag" xsi:type="array"> <item name="scope" xsi:type="string">payment</item> <item name="scope_id" xsi:type="number">1</item> - <item name="label" xsi:type="string"/> + <item name="label" xsi:type="string">Yes</item> + <item name="value" xsi:type="number">1</item> + </field> + <field name="payment/paypal_payment_gateways/payflow_link_us/payflow_link_required/enable_payflow_link" xsi:type="array"> + <item name="scope" xsi:type="string">payment</item> + <item name="scope_id" xsi:type="number">1</item> + <item name="label" xsi:type="string">Yes</item> <item name="value" xsi:type="number">1</item> </field> <field name="payment/payflowlink/debug" xsi:type="array"> @@ -250,7 +467,7 @@ <field name="payment/payflowlink/active" xsi:type="array"> <item name="scope" xsi:type="string">payment</item> <item name="scope_id" xsi:type="number">1</item> - <item name="label" xsi:type="string">Yes</item> + <item name="label" xsi:type="string">No</item> <item name="value" xsi:type="number">0</item> </field> </dataset> diff --git a/dev/tests/functional/tests/app/Magento/Authorizenet/Test/Repository/CreditCard.xml b/dev/tests/functional/tests/app/Magento/Paypal/Test/Repository/CreditCard.xml similarity index 60% rename from dev/tests/functional/tests/app/Magento/Authorizenet/Test/Repository/CreditCard.xml rename to dev/tests/functional/tests/app/Magento/Paypal/Test/Repository/CreditCard.xml index c6b8eab58205e649e87e0acb760339bb9aafc273..9383dcd3faf4b40b23e665c4fb243cd45954e215 100644 --- a/dev/tests/functional/tests/app/Magento/Authorizenet/Test/Repository/CreditCard.xml +++ b/dev/tests/functional/tests/app/Magento/Paypal/Test/Repository/CreditCard.xml @@ -6,10 +6,11 @@ */ --> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/Magento/Mtf/Repository/etc/repository.xsd"> - <repository class="Magento\Authorizenet\Test\Repository\CreditCard"> - <dataset name="visa_authorizenet"> - <field name="cc_number" xsi:type="string">4111111111111111</field> - <field name="cc_exp_month" xsi:type="string">01 - January</field> + <repository class="Magento\Payment\Test\Repository\CreditCard"> + <dataset name="visa_hosted_pro"> + <field name="cc_type" xsi:type="string">V</field> + <field name="cc_number" xsi:type="string">4032034402702800</field> + <field name="cc_exp_month" xsi:type="string">01</field> <field name="cc_exp_year" xsi:type="string">2020</field> <field name="cc_cid" xsi:type="string">123</field> </dataset> diff --git a/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/CloseOrderTest.xml b/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/CloseOrderTest.xml new file mode 100644 index 0000000000000000000000000000000000000000..30385e1cd2006c5dd86f98a8f4da1a9d032c6efd --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/CloseOrderTest.xml @@ -0,0 +1,57 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + --> +<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd"> + <testCase name="Magento\Sales\Test\TestCase\CloseOrderTest" summary="Close order"> + <variation name="CloseOrderTestWithPayPalPaymentsPro" summary="Close order with PayPal Payments Pro" ticketId="MAGETWO-13015"> + <data name="products/0" xsi:type="string">catalogProductSimple::product_10_dollar</data> + <data name="customer/dataset" xsi:type="string">default</data> + <data name="shippingAddress/dataset" xsi:type="string">US_address_1_without_email</data> + <data name="checkoutMethod" xsi:type="string">guest</data> + <data name="shipping/shipping_service" xsi:type="string">Flat Rate</data> + <data name="shipping/shipping_method" xsi:type="string">Fixed</data> + <data name="payment/method" xsi:type="string">payflowpro</data> + <data name="prices" xsi:type="array"> + <item name="grandTotal" xsi:type="string">15.00</item> + </data> + <data name="capturedPrices" xsi:type="array"> + <item name="0" xsi:type="string">15.00</item> + </data> + <data name="creditCard/dataset" xsi:type="string">visa_default</data> + <data name="status" xsi:type="string">Complete</data> + <data name="configData" xsi:type="string">paypal_direct</data> + <data name="tag" xsi:type="string">test_type:3rd_party_test, severity:S0</data> + <constraint name="Magento\Sales\Test\Constraint\AssertCaptureInCommentsHistory" /> + <constraint name="Magento\Sales\Test\Constraint\AssertInvoiceItems" /> + <constraint name="Magento\Sales\Test\Constraint\AssertOrderStatusIsCorrect" /> + </variation> + <variation name="CloseOrderTestWithPayPalPayflowPro" summary="Close order with PayPal Payflow Pro" ticketId="MAGETWO-13020"> + <data name="products/0" xsi:type="string">catalogProductSimple::product_10_dollar</data> + <data name="customer/dataset" xsi:type="string">default</data> + <data name="shippingAddress/dataset" xsi:type="string">US_address_1_without_email</data> + <data name="checkoutMethod" xsi:type="string">guest</data> + <data name="shipping/shipping_service" xsi:type="string">Flat Rate</data> + <data name="shipping/shipping_method" xsi:type="string">Fixed</data> + <data name="payment/method" xsi:type="string">payflowpro</data> + <data name="order/data/price/dataset" xsi:type="string">full_invoice_with_product_10_dollar</data> + <data name="prices" xsi:type="array"> + <item name="grandTotal" xsi:type="string">15.00</item> + </data> + <data name="capturedPrices" xsi:type="array"> + <item name="0" xsi:type="string">15.00</item> + </data> + <data name="creditCard/dataset" xsi:type="string">visa_default</data> + <data name="status" xsi:type="string">Complete</data> + <data name="configData" xsi:type="string">payflowpro, payflowpro_use_vault</data> + <data name="tag" xsi:type="string">test_type:3rd_party_test, severity:S0</data> + <constraint name="Magento\Sales\Test\Constraint\AssertCaptureInCommentsHistory" /> + <constraint name="Magento\Sales\Test\Constraint\AssertInvoiceItems" /> + <constraint name="Magento\Sales\Test\Constraint\AssertInvoiceInInvoicesTab" /> + <constraint name="Magento\Sales\Test\Constraint\AssertOrderStatusIsCorrect" /> + </variation> + </testCase> +</config> \ No newline at end of file diff --git a/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/CloseSalesWithHostedProTest.php b/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/CloseSalesWithHostedProTest.php new file mode 100644 index 0000000000000000000000000000000000000000..11acf819c992692a856cf93c679c79a5c7a1aa8b --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/CloseSalesWithHostedProTest.php @@ -0,0 +1,44 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Paypal\Test\TestCase; + +use Magento\Mtf\TestCase\Scenario; + +/** + * Preconditions: + * 1. Order is placed via WPPHS. + * + * Steps: + * 1. Log in to Admin. + * 2. Go to Sales > Orders page. + * 3. Open order. + * 4. Click 'Ship' button and submit shipment. + * 5. Click 'Invoice' button. + * 6. Select Amount=Capture Online. + * 7. Click 'Submit Invoice' button. + * 11. Perform assertions. + * + * @group Paypal + * @ZephyrId MAGETWO-13016 + */ +class CloseSalesWithHostedProTest extends Scenario +{ + /* tags */ + const MVP = 'yes'; + const TEST_TYPE = '3rd_party_test'; + /* end tags */ + + /** + * Complete order paid PayPal Payments Pro Hosted Solution. + * + * @return void + */ + public function test() + { + $this->executeScenario(); + } +} diff --git a/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/CloseSalesWithHostedProTest.xml b/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/CloseSalesWithHostedProTest.xml new file mode 100644 index 0000000000000000000000000000000000000000..a7e058b4fba445c74febc19a71f7962c3b4af3b6 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/CloseSalesWithHostedProTest.xml @@ -0,0 +1,38 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + --> +<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd"> + <testCase name="Magento\Paypal\Test\TestCase\CloseSalesWithHostedProTest" summary="Complete order paid with PayPal Payments Pro Hosted Solution"> + <variation name="CloseSalesWithHostedProVariation1" summary="Complete order paid with PayPal Payments Pro Hosted Solution" ticketId="MAGETWO-13016"> + <data name="products/0" xsi:type="string">catalogProductSimple::product_10_dollar</data> + <data name="products/1" xsi:type="string">configurableProduct::with_one_option</data> + <data name="products/2" xsi:type="string">bundleProduct::bundle_fixed_100_dollar_product</data> + <data name="taxRule" xsi:type="string">us_ca_ny_rule</data> + <data name="customer/dataset" xsi:type="string">default</data> + <data name="shippingAddress/dataset" xsi:type="string">US_address_1_without_email</data> + <data name="checkoutMethod" xsi:type="string">guest</data> + <data name="shipping/shipping_service" xsi:type="string">Flat Rate</data> + <data name="shipping/shipping_method" xsi:type="string">Fixed</data> + <data name="payment/method" xsi:type="string">hosted_pro</data> + <data name="prices" xsi:type="array"> + <item name="grandTotal" xsi:type="string">145.98</item> + </data> + <data name="capturedPrices" xsi:type="array"> + <item name="0" xsi:type="string">145.98</item> + </data> + <data name="creditCardClass" xsi:type="string">credit_card_hostedpro</data> + <data name="creditCard/dataset" xsi:type="string">visa_hosted_pro</data> + <data name="isVaultPresent" xsi:type="boolean">false</data> + <data name="status" xsi:type="string">Complete</data> + <data name="configData" xsi:type="string">merchant_country_gb, hosted_pro, config_base_currency_gb</data> + <data name="tag" xsi:type="string">test_type:3rd_party_test, severity:S0</data> + <constraint name="Magento\Sales\Test\Constraint\AssertInvoiceItems" /> + <constraint name="Magento\Sales\Test\Constraint\AssertCaptureInCommentsHistory" /> + <constraint name="Magento\Sales\Test\Constraint\AssertOrderStatusIsCorrect" /> + </variation> + </testCase> +</config> diff --git a/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/CreateOnlineCreditMemoTest.xml b/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/CreateOnlineCreditMemoTest.xml new file mode 100644 index 0000000000000000000000000000000000000000..f859f579ecea45c5c992017a09df061b11b70bbc --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/CreateOnlineCreditMemoTest.xml @@ -0,0 +1,42 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + --> +<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd"> + <testCase name="Magento\Sales\Test\TestCase\CreateOnlineCreditMemoTest" summary="Create online credit memo for order placed with online payment method"> + <variation name="CreateCreditMemoPaymentsProTestVariation1" summary="Create Refund for Order Paid with PayPal Payments Pro" ticketId="MAGETWO-13059"> + <data name="products/0" xsi:type="string">catalogProductSimple::product_10_dollar</data> + <data name="customer/dataset" xsi:type="string">default</data> + <data name="checkoutMethod" xsi:type="string">guest</data> + <data name="refundedPrices" xsi:type="array"> + <item name="0" xsi:type="string">15.00</item> + </data> + <data name="shippingAddress/dataset" xsi:type="string">US_address_1_without_email</data> + <data name="shipping/shipping_service" xsi:type="string">Flat Rate</data> + <data name="shipping/shipping_method" xsi:type="string">Fixed</data> + <data name="payment/method" xsi:type="string">payflowpro</data> + <data name="configData" xsi:type="string">paypal_direct</data> + <data name="creditCard/dataset" xsi:type="string">visa_default</data> + <data name="data/items_data/0/qty" xsi:type="string">-</data> + <data name="data/form_data/do_shipment" xsi:type="string">Yes</data> + <data name="status" xsi:type="string">Closed</data> + <data name="transactions/Refund" xsi:type="array"> + <item name="transactionType" xsi:type="string">Refund</item> + <item name="statusIsClosed" xsi:type="string">Yes</item> + </data> + <data name="transactions/Capture" xsi:type="array"> + <item name="transactionType" xsi:type="string">Capture</item> + <item name="statusIsClosed" xsi:type="string">Yes</item> + </data> + <data name="tag" xsi:type="string">test_type:3rd_party_test, severity:S0</data> + <constraint name="Magento\Sales\Test\Constraint\AssertRefundSuccessCreateMessage" /> + <constraint name="Magento\Sales\Test\Constraint\AssertOrderStatusIsCorrect" /> + <constraint name="Magento\Sales\Test\Constraint\AssertRefundInCommentsHistory" /> + <constraint name="Magento\Sales\Test\Constraint\AssertRefundInCreditMemoTab" /> + <constraint name="Magento\Sales\Test\Constraint\AssertTransactionStatus" /> + </variation> + </testCase> +</config> diff --git a/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/CreatePayFlowOrderBackendNegativeTest.xml b/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/CreatePayFlowOrderBackendNegativeTest.xml index 4ad751de68a71f0330aa547bf74481c3e306f379..ea4dc7b7231466e1473fe4690d73a5ffe3af376b 100644 --- a/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/CreatePayFlowOrderBackendNegativeTest.xml +++ b/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/CreatePayFlowOrderBackendNegativeTest.xml @@ -19,7 +19,6 @@ <item name="grandTotal" xsi:type="string">15.00</item> </data> <data name="payment/method" xsi:type="string">payflowpro</data> - <data name="creditCardClass" xsi:type="string">credit_card_admin</data> <data name="creditCard/dataset" xsi:type="string">visa_empty</data> <data name="creditCardSave" xsi:type="string">Yes</data> <data name="configData" xsi:type="string">payflowpro, payflowpro_use_vault</data> diff --git a/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/CreateVaultOrderBackendTest.xml b/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/CreateVaultOrderBackendTest.xml index ca26ad42a020c80ab0540c21a2928b8a1874cae7..53e9c7b83900ac1c9422d0ed52ce761b05e24dc0 100644 --- a/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/CreateVaultOrderBackendTest.xml +++ b/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/CreateVaultOrderBackendTest.xml @@ -20,8 +20,7 @@ </data> <data name="payment/method" xsi:type="string">payflowpro</data> <data name="vault/method" xsi:type="string">payflowpro_cc_vault</data> - <data name="creditCardClass" xsi:type="string">credit_card_admin</data> - <data name="creditCard/dataset" xsi:type="string">visa_default</data> + <data name="creditCard/dataset" xsi:type="string">visa_default_admin</data> <data name="creditCardSave" xsi:type="string">Yes</data> <data name="configData" xsi:type="string">payflowpro, payflowpro_use_vault</data> <data name="status" xsi:type="string">Processing</data> diff --git a/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/ExpressCheckoutFromProductPageTest.xml b/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/ExpressCheckoutFromProductPageTest.xml index 1d92fa149efbc336eb0910a451a1740f2eda6c14..6005fe4008d7bb52308878e81a7d0211c5441a87 100644 --- a/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/ExpressCheckoutFromProductPageTest.xml +++ b/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/ExpressCheckoutFromProductPageTest.xml @@ -27,7 +27,7 @@ </data> <data name="payment/method" xsi:type="string">paypal_express</data> <data name="configData" xsi:type="string">paypal_express, freeshipping</data> - <data name="tag" xsi:type="string">test_type:3rd_party_test, severity:S0</data> + <data name="tag" xsi:type="string">test_type:3rd_party_test_deprecated, severity:S0</data> <constraint name="Magento\Checkout\Test\Constraint\AssertOrderSuccessPlacedMessage" /> <constraint name="Magento\Checkout\Test\Constraint\AssertMinicartEmpty" /> <constraint name="Magento\Sales\Test\Constraint\AssertOrderGrandTotal" /> diff --git a/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/ExpressCheckoutFromShoppingCartTest.xml b/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/ExpressCheckoutFromShoppingCartTest.xml index 38c876719bc3d82c772ff6f86cd507229ec5cf2b..233958afa1aa5605f922b105b2da85dee08960c8 100644 --- a/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/ExpressCheckoutFromShoppingCartTest.xml +++ b/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/ExpressCheckoutFromShoppingCartTest.xml @@ -28,7 +28,7 @@ <item name="grandTotal" xsi:type="string">145.98</item> </data> <data name="configData" xsi:type="string">payflowpro</data> - <data name="tag" xsi:type="string">test_type:3rd_party_test, severity:S0</data> + <data name="tag" xsi:type="string">test_type:3rd_party_test_deprecated, severity:S0</data> <constraint name="Magento\Checkout\Test\Constraint\AssertOrderSuccessPlacedMessage" /> <constraint name="Magento\Checkout\Test\Constraint\AssertMinicartEmpty" /> <constraint name="Magento\Sales\Test\Constraint\AssertOrderGrandTotal" /> diff --git a/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/ExpressCheckoutOnePageTest.xml b/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/ExpressCheckoutOnePageTest.xml index e52ed631ae46f983dc8860e7bf628f95a5a6a7fb..7de72c8ac9d93143dd3d59595a452981f2e15a89 100644 --- a/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/ExpressCheckoutOnePageTest.xml +++ b/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/ExpressCheckoutOnePageTest.xml @@ -26,7 +26,7 @@ </data> <data name="payment/method" xsi:type="string">paypal_express</data> <data name="configData" xsi:type="string">paypal_express</data> - <data name="tag" xsi:type="string">test_type:3rd_party_test, severity:S0</data> + <data name="tag" xsi:type="string">test_type:3rd_party_test_deprecated, severity:S0</data> <constraint name="Magento\Checkout\Test\Constraint\AssertOrderSuccessPlacedMessage" /> <constraint name="Magento\Checkout\Test\Constraint\AssertMinicartEmpty" /> <constraint name="Magento\Sales\Test\Constraint\AssertOrderGrandTotal" /> @@ -51,7 +51,7 @@ </data> <data name="payment/method" xsi:type="string">paypal_express</data> <data name="configData" xsi:type="string">payflowlink</data> - <data name="tag" xsi:type="string">test_type:3rd_party_test, severity:S0</data> + <data name="tag" xsi:type="string">test_type:3rd_party_test_deprecated, severity:S0</data> <constraint name="Magento\Checkout\Test\Constraint\AssertOrderSuccessPlacedMessage" /> <constraint name="Magento\Checkout\Test\Constraint\AssertMinicartEmpty" /> <constraint name="Magento\Sales\Test\Constraint\AssertOrderGrandTotal" /> @@ -76,7 +76,7 @@ </data> <data name="payment/method" xsi:type="string">paypal_express</data> <data name="configData" xsi:type="string">paypal_express</data> - <data name="tag" xsi:type="string">test_type:3rd_party_test</data> + <data name="tag" xsi:type="string">test_type:3rd_party_test_deprecated</data> <constraint name="Magento\Checkout\Test\Constraint\AssertOrderSuccessPlacedMessage" /> <constraint name="Magento\Checkout\Test\Constraint\AssertMinicartEmpty" /> <constraint name="Magento\Sales\Test\Constraint\AssertOrderGrandTotal" /> diff --git a/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/OnePageCheckoutDeclinedTest.xml b/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/OnePageCheckoutDeclinedTest.xml new file mode 100644 index 0000000000000000000000000000000000000000..e015e3ba566648ce05326e3fae03bf2a76eefc64 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/OnePageCheckoutDeclinedTest.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + --> +<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd"> + <testCase name="Magento\Checkout\Test\TestCase\OnePageCheckoutDeclinedTest" summary="Error message during OnePageCheckout"> + <variation name="OnePageCheckoutPayflowProWithAVSStreetDoesNotMatch" summary="Place Order via Payflow Pro with AVS Street verification fail" ticketId="MAGETWO-37480"> + <data name="tag" xsi:type="string">test_type:3rd_party_test, severity:S1</data> + <data name="products/0" xsi:type="string">catalogProductSimple::product_10_dollar</data> + <data name="customer/dataset" xsi:type="string">default</data> + <data name="shippingAddress/dataset" xsi:type="string">AVS_street_does_not_match_address</data> + <data name="checkoutMethod" xsi:type="string">guest</data> + <data name="shipping/shipping_service" xsi:type="string">Flat Rate</data> + <data name="shipping/shipping_method" xsi:type="string">Fixed</data> + <data name="payment/method" xsi:type="string">payflowpro</data> + <data name="creditCard/dataset" xsi:type="string">visa_default</data> + <data name="configData" xsi:type="string">payflowpro, payflowpro_avs_street_does_not_match</data> + <data name="expectedErrorMessage" xsi:type="string">An error occurred on the server. Please try to place the order again.</data> + <constraint name="Magento\Checkout\Test\Constraint\AssertCheckoutErrorMessage" /> + </variation> + </testCase> +</config> diff --git a/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/OnePageCheckoutHostedProTest.php b/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/OnePageCheckoutHostedProTest.php new file mode 100644 index 0000000000000000000000000000000000000000..12cedd4ffa458d3418f6834ea330a12c9b0c3c6b --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/OnePageCheckoutHostedProTest.php @@ -0,0 +1,51 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Paypal\Test\TestCase; + +use Magento\Mtf\TestCase\Scenario; + +/** + * Preconditions: + * 1. Configure shipping method. + * 2. Configure payment method. + * 3. Create products. + * 4. Create sales rule according to dataset. + * + * Steps: + * 1. Go to Storefront. + * 2. Add products to the cart. + * 3. Click the 'Go to Checkout' button. + * 4. Fill shipping information. + * 5. Select shipping method. + * 6. Click 'Next' button. + * 7. Select Hosted Pro method. + * 8. Click 'Continue' button. + * 9. Specify credit card data in Paypal iframe. + * 10. Click 'Pay Now' button. + * 11. Perform assertions. + * + * @group Paypal + * @ZephyrId MAGETWO-12971 + */ +class OnePageCheckoutHostedProTest extends Scenario +{ + /* tags */ + const MVP = 'yes'; + const TEST_TYPE = '3rd_party_test'; + const SEVERITY = 'S0'; + /* end tags */ + + /** + * Place order using PayPal Payments Pro Hosted Solution. + * + * @return void + */ + public function test() + { + $this->executeScenario(); + } +} diff --git a/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/OnePageCheckoutHostedProTest.xml b/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/OnePageCheckoutHostedProTest.xml new file mode 100644 index 0000000000000000000000000000000000000000..6583aa9cc873c9e3c8fc17255127a1fc62680cb5 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/OnePageCheckoutHostedProTest.xml @@ -0,0 +1,35 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + --> +<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd"> + <testCase name="Magento\Paypal\Test\TestCase\OnePageCheckoutHostedProTest" summary="Guest Checkout using PayPal Payments Pro Hosted Solution and Offline Shipping Method"> + <variation name="OnePageCheckoutHostedProVariation1" summary="Guest Checkout using PayPal Payments Pro Hosted Solution and Offline Shipping Method" ticketId="MAGETWO-12971"> + <data name="products/0" xsi:type="string">catalogProductSimple::product_10_dollar</data> + <data name="products/1" xsi:type="string">configurableProduct::with_one_option</data> + <data name="products/2" xsi:type="string">bundleProduct::bundle_fixed_100_dollar_product</data> + <data name="taxRule" xsi:type="string">us_ca_ny_rule</data> + <data name="customer/dataset" xsi:type="string">default</data> + <data name="shippingAddress/dataset" xsi:type="string">US_address_1_without_email</data> + <data name="checkoutMethod" xsi:type="string">guest</data> + <data name="shipping/shipping_service" xsi:type="string">Flat Rate</data> + <data name="shipping/shipping_method" xsi:type="string">Fixed</data> + <data name="payment/method" xsi:type="string">hosted_pro</data> + <data name="prices" xsi:type="array"> + <item name="grandTotal" xsi:type="string">145.98</item> + </data> + <data name="creditCardClass" xsi:type="string">credit_card_hostedpro</data> + <data name="creditCard/dataset" xsi:type="string">visa_hosted_pro</data> + <data name="isVaultPresent" xsi:type="boolean">false</data> + <data name="configData" xsi:type="string">merchant_country_gb, hosted_pro, config_base_currency_gb</data> + <data name="status" xsi:type="string">Processing</data> + <data name="tag" xsi:type="string">test_type:3rd_party_test, severity:S0</data> + <constraint name="Magento\Checkout\Test\Constraint\AssertOrderSuccessPlacedMessage" /> + <constraint name="Magento\Sales\Test\Constraint\AssertOrderGrandTotal" /> + <constraint name="Magento\Sales\Test\Constraint\AssertAuthorizationInCommentsHistory" /> + </variation> + </testCase> +</config> diff --git a/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/OnePageCheckoutPayflowLinkTest.php b/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/OnePageCheckoutPayflowLinkTest.php new file mode 100644 index 0000000000000000000000000000000000000000..726d6833660be0cfd2c838985724a88f680cea44 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/OnePageCheckoutPayflowLinkTest.php @@ -0,0 +1,51 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Paypal\Test\TestCase; + +use Magento\Mtf\TestCase\Scenario; + +/** + * Preconditions: + * 1. Configure shipping method. + * 2. Configure payment method. + * 3. Create products. + * 4. Create tax rule according to dataset. + * + * Steps: + * 1. Go to Storefront. + * 2. Add products to the cart. + * 3. Click the 'Go to Checkout' button. + * 4. Fill shipping information. + * 5. Select shipping method. + * 6. Click 'Next' button. + * 7. Select 'Credit Card' method. + * 8. Click 'Continue' button. + * 9. Specify credit card data in Paypal iframe. + * 10. Click 'Pay Now' button. + * 11. Perform assertions. + * + * @group Paypal + * @ZephyrId MAGETWO-12974 + */ +class OnePageCheckoutPayflowLinkTest extends Scenario +{ + /* tags */ + const MVP = 'yes'; + const TEST_TYPE = '3rd_party_test'; + const SEVERITY = 'S0'; + /* end tags */ + + /** + * Place order using PayPal Payflow Link Solution. + * + * @return void + */ + public function test() + { + $this->executeScenario(); + } +} diff --git a/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/OnePageCheckoutPayflowLinkTest.xml b/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/OnePageCheckoutPayflowLinkTest.xml new file mode 100644 index 0000000000000000000000000000000000000000..b23a1c6ae9d79e20bee3af1fcd81f2e116fd6d8e --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/OnePageCheckoutPayflowLinkTest.xml @@ -0,0 +1,34 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + --> +<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd"> + <testCase name="Magento\Paypal\Test\TestCase\OnePageCheckoutPayflowLinkTest" summary="Guest Checkout using PayPal Payflow Link and Flat Rate"> + <variation name="OnePageCheckoutPayflowLinkVariation1" summary="Guest Checkout using PayPal Payflow Link and Flat Rate" ticketId="MAGETWO-12974"> + <data name="products/0" xsi:type="string">catalogProductSimple::product_10_dollar</data> + <data name="products/1" xsi:type="string">configurableProduct::with_one_option</data> + <data name="products/2" xsi:type="string">bundleProduct::bundle_fixed_100_dollar_product</data> + <data name="taxRule" xsi:type="string">us_ca_ny_rule</data> + <data name="customer/dataset" xsi:type="string">default</data> + <data name="shippingAddress/dataset" xsi:type="string">US_address_1_without_email</data> + <data name="checkoutMethod" xsi:type="string">guest</data> + <data name="shipping/shipping_service" xsi:type="string">Flat Rate</data> + <data name="shipping/shipping_method" xsi:type="string">Fixed</data> + <data name="payment/method" xsi:type="string">payflow_link</data> + <data name="prices" xsi:type="array"> + <item name="grandTotal" xsi:type="string">145.98</item> + </data> + <data name="creditCard/dataset" xsi:type="string">visa_default</data> + <data name="isVaultPresent" xsi:type="boolean">false</data> + <data name="configData" xsi:type="string">payflowlink</data> + <data name="status" xsi:type="string">Processing</data> + <data name="tag" xsi:type="string">test_type:3rd_party_test, severity:S0</data> + <constraint name="Magento\Checkout\Test\Constraint\AssertOrderSuccessPlacedMessage" /> + <constraint name="Magento\Sales\Test\Constraint\AssertOrderGrandTotal" /> + <constraint name="Magento\Sales\Test\Constraint\AssertAuthorizationInCommentsHistory" /> + </variation> + </testCase> +</config> diff --git a/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/OnePageCheckoutPaymentsAdvancedTest.php b/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/OnePageCheckoutPaymentsAdvancedTest.php new file mode 100644 index 0000000000000000000000000000000000000000..789b5ddd27faaf2723e0feb909e1561e164df56d --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/OnePageCheckoutPaymentsAdvancedTest.php @@ -0,0 +1,51 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Paypal\Test\TestCase; + +use Magento\Mtf\TestCase\Scenario; + +/** + * Preconditions: + * 1. Configure shipping method. + * 2. Configure payment method. + * 3. Create products. + * 4. Create tax rule according to dataset. + * + * Steps: + * 1. Go to Storefront. + * 2. Add products to the cart. + * 3. Click the 'Go to Checkout' button. + * 4. Fill shipping information. + * 5. Select shipping method. + * 6. Click 'Next' button. + * 7. Select 'Credit Card' method. + * 8. Click 'Continue' button. + * 9. Specify credit card data in Paypal iframe. + * 10. Click 'Pay Now' button. + * 11. Perform assertions. + * + * @group Paypal + * @ZephyrId MAGETWO-12991 + */ +class OnePageCheckoutPaymentsAdvancedTest extends Scenario +{ + /* tags */ + const MVP = 'yes'; + const TEST_TYPE = '3rd_party_test'; + const SEVERITY = 'S0'; + /* end tags */ + + /** + * Place order using PayPal Payments Advanced Solution. + * + * @return void + */ + public function test() + { + $this->executeScenario(); + } +} diff --git a/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/OnePageCheckoutPaymentsAdvancedTest.xml b/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/OnePageCheckoutPaymentsAdvancedTest.xml new file mode 100644 index 0000000000000000000000000000000000000000..279a47689548ba0e3a08ba0d8070490bb417e09a --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/OnePageCheckoutPaymentsAdvancedTest.xml @@ -0,0 +1,34 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + --> +<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd"> + <testCase name="Magento\Paypal\Test\TestCase\OnePageCheckoutPaymentsAdvancedTest" summary="Guest Checkout using PayPal Payments Advanced and Flat Rate"> + <variation name="OnePageCheckoutPaymentsAdvancedVariation1" summary="Guest Checkout using PayPal Payments Advanced and Flat Rate" ticketId="MAGETWO-12991"> + <data name="products/0" xsi:type="string">catalogProductSimple::product_10_dollar</data> + <data name="products/1" xsi:type="string">configurableProduct::with_one_option</data> + <data name="products/2" xsi:type="string">bundleProduct::bundle_fixed_100_dollar_product</data> + <data name="taxRule" xsi:type="string">us_ca_ny_rule</data> + <data name="customer/dataset" xsi:type="string">default</data> + <data name="shippingAddress/dataset" xsi:type="string">US_address_1_without_email</data> + <data name="checkoutMethod" xsi:type="string">guest</data> + <data name="shipping/shipping_service" xsi:type="string">Flat Rate</data> + <data name="shipping/shipping_method" xsi:type="string">Fixed</data> + <data name="payment/method" xsi:type="string">payflow_advanced</data> + <data name="prices" xsi:type="array"> + <item name="grandTotal" xsi:type="string">145.98</item> + </data> + <data name="creditCard/dataset" xsi:type="string">visa_default</data> + <data name="isVaultPresent" xsi:type="boolean">false</data> + <data name="configData" xsi:type="string">payments_advanced</data> + <data name="status" xsi:type="string">Processing</data> + <data name="tag" xsi:type="string">test_type:3rd_party_test, severity:S0</data> + <constraint name="Magento\Checkout\Test\Constraint\AssertOrderSuccessPlacedMessage" /> + <constraint name="Magento\Sales\Test\Constraint\AssertOrderGrandTotal" /> + <constraint name="Magento\Sales\Test\Constraint\AssertAuthorizationInCommentsHistory" /> + </variation> + </testCase> +</config> \ No newline at end of file diff --git a/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/OnePageCheckoutTest.xml b/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/OnePageCheckoutTest.xml index f6ac4ac4f0a3c4591c12de7215600010c5fb857c..44577748f7b7a1abe37e6a9e562b3059820b0267 100644 --- a/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/OnePageCheckoutTest.xml +++ b/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/OnePageCheckoutTest.xml @@ -19,14 +19,85 @@ <data name="prices" xsi:type="array"> <item name="grandTotal" xsi:type="string">15.83</item> </data> - <data name="creditCardClass" xsi:type="string">credit_card</data> <data name="creditCard/dataset" xsi:type="string">visa_default</data> - <data name="isVaultEnabled" xsi:type="boolean">false</data> + <data name="isVaultPresent" xsi:type="boolean">false</data> <data name="configData" xsi:type="string">payflowpro</data> <data name="tag" xsi:type="string">test_type:3rd_party_test, severity:S1</data> <constraint name="Magento\Checkout\Test\Constraint\AssertOrderSuccessPlacedMessage" /> <constraint name="Magento\Sales\Test\Constraint\AssertOrderGrandTotal" /> <constraint name="Magento\Sales\Test\Constraint\AssertAuthorizationInCommentsHistory" /> </variation> + <variation name="OnePageCheckoutPayflowProWithInternationalAVSFilter" summary="Place order via Payflow Pro with fraud filters triggering" ticketId="MAGETWO-37476"> + <data name="tag" xsi:type="string">test_type:3rd_party_test, severity:S1</data> + <data name="products/0" xsi:type="string">catalogProductSimple::product_10_dollar</data> + <data name="customer/dataset" xsi:type="string">default</data> + <data name="billingAddress/dataset" xsi:type="string">US_address_1_without_email</data> + <data name="shippingAddress/dataset" xsi:type="string">UK_address_without_email</data> + <data name="checkoutMethod" xsi:type="string">guest</data> + <data name="shipping/shipping_service" xsi:type="string">Flat Rate</data> + <data name="shipping/shipping_method" xsi:type="string">Fixed</data> + <data name="payment/method" xsi:type="string">payflowpro</data> + <data name="prices" xsi:type="array"> + <item name="grandTotal" xsi:type="string">15.00</item> + </data> + <data name="creditCardClass" xsi:type="string">credit_card</data> + <data name="creditCard/dataset" xsi:type="string">visa_default</data> + <data name="isVaultPresent" xsi:type="boolean">false</data> + <data name="configData" xsi:type="string">payflowpro_fraud_filters_enabled</data> + <data name="paymentInfo" xsi:type="array"> + <item name="Triggered Fraud Filters" xsi:type="string">Under review by Fraud Service</item> + <item name="International AVS response" xsi:type="string">#N: No Details matched</item> + </data> + <data name="status" xsi:type="string">Processing</data> + <constraint name="Magento\Checkout\Test\Constraint\AssertOrderSuccessPlacedMessage" /> + <constraint name="Magento\Sales\Test\Constraint\AssertOrderStatusIsCorrect" /> + <constraint name="Magento\Sales\Test\Constraint\AssertOrderGrandTotal" /> + <constraint name="Magento\Sales\Test\Constraint\AssertAuthorizationInCommentsHistory" /> + <constraint name="Magento\Sales\Test\Constraint\AssertOrderPaymentInformation" /> + </variation> + <variation name="OnePageCheckoutPayflowProWithAVSStreetMatch" summary="Place Order via Payflow Pro with success AVS Street verification" ticketId="MAGETWO-37479"> + <data name="tag" xsi:type="string">test_type:3rd_party_test, severity:S1</data> + <data name="products/0" xsi:type="string">catalogProductSimple::product_10_dollar</data> + <data name="customer/dataset" xsi:type="string">default</data> + <data name="shippingAddress/dataset" xsi:type="string">AVS_street_match_address</data> + <data name="checkoutMethod" xsi:type="string">guest</data> + <data name="shipping/shipping_service" xsi:type="string">Flat Rate</data> + <data name="shipping/shipping_method" xsi:type="string">Fixed</data> + <data name="payment/method" xsi:type="string">payflowpro</data> + <data name="prices" xsi:type="array"> + <item name="grandTotal" xsi:type="string">15.00</item> + </data> + <data name="creditCardClass" xsi:type="string">credit_card</data> + <data name="creditCard/dataset" xsi:type="string">visa_default</data> + <data name="isVaultPresent" xsi:type="boolean">false</data> + <data name="configData" xsi:type="string">payflowpro_fraud_filters_enabled</data> + <data name="paymentInfo" xsi:type="array"> + <item name="AVS Street Match" xsi:type="string">#Y: Yes. Matched Address and five-didgit ZIP</item> + </data> + <data name="status" xsi:type="string">Processing</data> + <constraint name="Magento\Checkout\Test\Constraint\AssertOrderSuccessPlacedMessage" /> + <constraint name="Magento\Sales\Test\Constraint\AssertOrderInOrdersGrid" /> + <constraint name="Magento\Sales\Test\Constraint\AssertOrderStatusIsCorrect" /> + <constraint name="Magento\Sales\Test\Constraint\AssertOrderPaymentInformation" /> + </variation> + <variation name="OnePageCheckoutPayPalPaymentsPro" summary="Guest Checkout using PayPal Payments Pro and Flat Rate" ticketId="MAGETWO-62039"> + <data name="products/0" xsi:type="string">catalogProductSimple::product_10_dollar</data> + <data name="customer/dataset" xsi:type="string">default</data> + <data name="shippingAddress/dataset" xsi:type="string">US_address_1_without_email</data> + <data name="checkoutMethod" xsi:type="string">guest</data> + <data name="shipping/shipping_service" xsi:type="string">Flat Rate</data> + <data name="shipping/shipping_method" xsi:type="string">Fixed</data> + <data name="payment/method" xsi:type="string">payflowpro</data> + <data name="prices" xsi:type="array"> + <item name="grandTotal" xsi:type="string">15.00</item> + </data> + <data name="creditCard/dataset" xsi:type="string">visa_default</data> + <data name="configData" xsi:type="string">paypal_direct</data> + <data name="tag" xsi:type="string">test_type:3rd_party_test, severity:S1</data> + <constraint name="Magento\Checkout\Test\Constraint\AssertOrderSuccessPlacedMessage" /> + <constraint name="Magento\Checkout\Test\Constraint\AssertCartIsEmpty" /> + <constraint name="Magento\Sales\Test\Constraint\AssertOrderGrandTotal" /> + <constraint name="Magento\Sales\Test\Constraint\AssertAuthorizationInCommentsHistory" /> + </variation> </testCase> </config> diff --git a/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/ReorderUsingVaultTest.xml b/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/ReorderUsingVaultTest.xml index b1da43e473bc5d78d4bfaf0fbcbb718dac6acd3e..f5dd4b9604e0a1843c67cc470d607aaf93684eec 100644 --- a/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/ReorderUsingVaultTest.xml +++ b/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/ReorderUsingVaultTest.xml @@ -7,7 +7,7 @@ --> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd"> <testCase name="Magento\Vault\Test\TestCase\ReorderUsingVaultTest" summary="Reorder from Admin with saved within PayPal Payflow Pro credit card"> - <variation name="ReorderUsingVaultPayflowProTestVariation1" summary="Reorder from Admin with saved within PayPal Payflow Pro credit card for Guest Customer" ticketId="MAGETWO-54872"> + <variation name="ReorderUsingVaultPayflowProTestVariation1" summary="Reorder from Admin with saved within PayPal Payflow Pro credit card for Guest Customer" ticketId="MAGETWO-34217, MAGETWO-54872"> <data name="description" xsi:type="string">Reorder from Admin with saved within PayPal Payflow Pro credit card for Guest Customer</data> <data name="products/0" xsi:type="string">catalogProductSimple::product_10_dollar</data> <data name="customer/dataset" xsi:type="string">default</data> @@ -20,7 +20,6 @@ </data> <data name="payment/method" xsi:type="string">payflowpro</data> <data name="vault/method" xsi:type="string">payflowpro_cc_vault</data> - <data name="creditCardClass" xsi:type="string">credit_card</data> <data name="creditCard/dataset" xsi:type="string">visa_default</data> <data name="configData" xsi:type="string">payflowpro, payflowpro_use_vault</data> <data name="status" xsi:type="string">Processing</data> diff --git a/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/UseVaultOnCheckoutTest.xml b/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/UseVaultOnCheckoutTest.xml index 92b4be03b5937ffa318f9d3cd05f6e6d2290f6bc..b81d36ad33038279d0563ca704098b759e93773e 100644 --- a/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/UseVaultOnCheckoutTest.xml +++ b/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/UseVaultOnCheckoutTest.xml @@ -16,7 +16,6 @@ <data name="shipping/shipping_method" xsi:type="string">Fixed</data> <data name="payment/method" xsi:type="string">payflowpro</data> <data name="vault/method" xsi:type="string">payflowpro_cc_vault</data> - <data name="creditCardClass" xsi:type="string">credit_card</data> <data name="creditCard/dataset" xsi:type="string">visa_default</data> <data name="creditCardSave" xsi:type="string">Yes</data> <data name="configData" xsi:type="string">payflowpro, payflowpro_use_vault</data> diff --git a/dev/tests/functional/tests/app/Magento/Paypal/Test/TestStep/GetPlacedOrderIdStep.php b/dev/tests/functional/tests/app/Magento/Paypal/Test/TestStep/GetPlacedOrderIdStep.php deleted file mode 100644 index bb1e1416dc9339498c35fda85d1703b5fe62d69b..0000000000000000000000000000000000000000 --- a/dev/tests/functional/tests/app/Magento/Paypal/Test/TestStep/GetPlacedOrderIdStep.php +++ /dev/null @@ -1,44 +0,0 @@ -<?php -/** - * Copyright © 2016 Magento. All rights reserved. - * See COPYING.txt for license details. - */ - -namespace Magento\Paypal\Test\TestStep; - -use Magento\Mtf\TestStep\TestStepInterface; -use Magento\Checkout\Test\Page\CheckoutOnepageSuccess; - -/** - * Get success placed order id. - */ -class GetPlacedOrderIdStep implements TestStepInterface -{ - /** - * Order success page. - * - * @var CheckoutOnepageSuccess - */ - protected $checkoutOnepageSuccess; - - /** - * @constructor - * @param CheckoutOnepageSuccess $checkoutOnepageSuccess - */ - public function __construct(CheckoutOnepageSuccess $checkoutOnepageSuccess) - { - $this->checkoutOnepageSuccess = $checkoutOnepageSuccess; - } - - /** - * Get success placed order id. - * - * @return array - */ - public function run() - { - return [ - 'orderId' => $this->checkoutOnepageSuccess->getSuccessBlock()->getGuestOrderId(), - ]; - } -} diff --git a/dev/tests/functional/tests/app/Magento/Paypal/Test/TestStep/PlaceOrderWithHostedProStep.php b/dev/tests/functional/tests/app/Magento/Paypal/Test/TestStep/PlaceOrderWithHostedProStep.php new file mode 100644 index 0000000000000000000000000000000000000000..cf602190a6286d30a860633fc3fb61fca718fe3a --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Paypal/Test/TestStep/PlaceOrderWithHostedProStep.php @@ -0,0 +1,104 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Paypal\Test\TestStep; + +use Magento\Checkout\Test\Page\CheckoutOnepage; +use Magento\Mtf\Fixture\FixtureFactory; +use Magento\Mtf\Fixture\FixtureInterface; +use Magento\Mtf\TestStep\TestStepInterface; +use Magento\Payment\Test\Fixture\CreditCard; +use Magento\Sales\Test\Fixture\OrderInjectable; + +/** + * Place order using PayPal Payments Pro Hosted Solution during one page checkout. + */ +class PlaceOrderWithHostedProStep implements TestStepInterface +{ + /** + * Onepage checkout page. + * + * @var CheckoutOnepage + */ + private $checkoutOnepage; + + /** + * Fixture factory. + * + * @var FixtureFactory + */ + private $fixtureFactory; + + /** + * Products fixtures. + * + * @var FixtureInterface[] + */ + private $products; + + /** + * Payment information. + * + * @var string + */ + private $payment; + + /** + * Credit card information. + * + * @var string + */ + private $creditCard; + + /** + * @param CheckoutOnepage $checkoutOnepage + * @param FixtureFactory $fixtureFactory + * @param CreditCard $creditCard + * @param array $payment + * @param array $products + */ + public function __construct( + CheckoutOnepage $checkoutOnepage, + FixtureFactory $fixtureFactory, + CreditCard $creditCard, + array $payment, + array $products + ) { + $this->checkoutOnepage = $checkoutOnepage; + $this->fixtureFactory = $fixtureFactory; + $this->creditCard = $creditCard; + $this->payment = $payment; + $this->products = $products; + } + + /** + * Place order with Hosted Pro. + * + * @return array + */ + public function run() + { + $attempts = 1; + $this->checkoutOnepage->getPaymentBlock()->selectPaymentMethod($this->payment); + $this->checkoutOnepage->getPaymentBlock()->getSelectedPaymentMethodBlock()->clickPlaceOrder(); + $this->checkoutOnepage->getHostedProBlock()->fillPaymentData($this->creditCard); + // As Paypal Sandbox is not stable there are three attempts given to place order + while ($this->checkoutOnepage->getHostedProBlock()->isErrorMessageVisible() && $attempts <= 3) { + $this->checkoutOnepage->getHostedProBlock()->fillPaymentData($this->creditCard); + $attempts++; + } + /** @var OrderInjectable $order */ + $order = $this->fixtureFactory->createByCode( + 'orderInjectable', + [ + 'data' => [ + 'entity_id' => ['products' => $this->products] + ] + ] + ); + return ['order' => $order]; + } +} diff --git a/dev/tests/functional/tests/app/Magento/Paypal/Test/TestStep/PlaceOrderWithPayflowLinkStep.php b/dev/tests/functional/tests/app/Magento/Paypal/Test/TestStep/PlaceOrderWithPayflowLinkStep.php new file mode 100644 index 0000000000000000000000000000000000000000..926dabe9722b65e8c906cb18fb1a1e9df462dc4a --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Paypal/Test/TestStep/PlaceOrderWithPayflowLinkStep.php @@ -0,0 +1,98 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Paypal\Test\TestStep; + +use Magento\Checkout\Test\Page\CheckoutOnepage; +use Magento\Mtf\Fixture\FixtureFactory; +use Magento\Mtf\TestStep\TestStepInterface; +use Magento\Payment\Test\Fixture\CreditCard; +use Magento\Sales\Test\Fixture\OrderInjectable; + +/** + * Place order using PayPal Payflow Link Solution during one page checkout. + */ +class PlaceOrderWithPayflowLinkStep implements TestStepInterface +{ + /** + * Onepage checkout page. + * + * @var CheckoutOnepage + */ + private $checkoutOnepage; + + /** + * Fixture factory. + * + * @var FixtureFactory + */ + private $fixtureFactory; + + /** + * Products fixtures. + * + * @var array + */ + private $products; + + /** + * Payment information. + * + * @var array + */ + private $payment; + + /** + * Credit card information. + * + * @var CreditCard + */ + private $creditCard; + + /** + * @param CheckoutOnepage $checkoutOnepage + * @param FixtureFactory $fixtureFactory + * @param CreditCard $creditCard + * @param array $payment + * @param array $products + */ + public function __construct( + CheckoutOnepage $checkoutOnepage, + FixtureFactory $fixtureFactory, + CreditCard $creditCard, + array $payment, + array $products + ) { + $this->checkoutOnepage = $checkoutOnepage; + $this->fixtureFactory = $fixtureFactory; + $this->creditCard = $creditCard; + $this->payment = $payment; + $this->products = $products; + } + + /** + * Place order with Payflow Link. + * + * @return array + */ + public function run() + { + $this->checkoutOnepage->getPaymentBlock()->selectPaymentMethod($this->payment); + $this->checkoutOnepage->getPaymentBlock()->getSelectedPaymentMethodBlock()->clickPlaceOrder(); + $this->checkoutOnepage->getPayflowLinkBlock()->fillPaymentData($this->creditCard); + + /** @var OrderInjectable $order */ + $order = $this->fixtureFactory->createByCode( + 'orderInjectable', + [ + 'data' => [ + 'entity_id' => ['products' => $this->products] + ] + ] + ); + return ['order' => $order]; + } +} diff --git a/dev/tests/functional/tests/app/Magento/Paypal/Test/TestStep/PlaceOrderWithPaymentsAdvancedStep.php b/dev/tests/functional/tests/app/Magento/Paypal/Test/TestStep/PlaceOrderWithPaymentsAdvancedStep.php new file mode 100644 index 0000000000000000000000000000000000000000..c39a742c07c091cad853bdf716e7e3122f7c0965 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Paypal/Test/TestStep/PlaceOrderWithPaymentsAdvancedStep.php @@ -0,0 +1,98 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Paypal\Test\TestStep; + +use Magento\Checkout\Test\Page\CheckoutOnepage; +use Magento\Mtf\Fixture\FixtureFactory; +use Magento\Mtf\TestStep\TestStepInterface; +use Magento\Payment\Test\Fixture\CreditCard; +use Magento\Sales\Test\Fixture\OrderInjectable; + +/** + * Place order using PayPal Payments Advanced Solution during one page checkout. + */ +class PlaceOrderWithPaymentsAdvancedStep implements TestStepInterface +{ + /** + * Onepage checkout page. + * + * @var CheckoutOnepage + */ + private $checkoutOnepage; + + /** + * Fixture factory. + * + * @var FixtureFactory + */ + private $fixtureFactory; + + /** + * Products fixtures. + * + * @var array + */ + private $products; + + /** + * Payment information. + * + * @var array + */ + private $payment; + + /** + * Credit card information. + * + * @var CreditCard + */ + private $creditCard; + + /** + * @param CheckoutOnepage $checkoutOnepage + * @param FixtureFactory $fixtureFactory + * @param CreditCard $creditCard + * @param array $payment + * @param array $products + */ + public function __construct( + CheckoutOnepage $checkoutOnepage, + FixtureFactory $fixtureFactory, + CreditCard $creditCard, + array $payment, + array $products + ) { + $this->checkoutOnepage = $checkoutOnepage; + $this->fixtureFactory = $fixtureFactory; + $this->creditCard = $creditCard; + $this->payment = $payment; + $this->products = $products; + } + + /** + * Place order with Payments Advanced. + * + * @return array + */ + public function run() + { + $this->checkoutOnepage->getPaymentBlock()->selectPaymentMethod($this->payment); + $this->checkoutOnepage->getPaymentBlock()->getSelectedPaymentMethodBlock()->clickPlaceOrder(); + $this->checkoutOnepage->getPaymentsAdvancedBlock()->fillPaymentData($this->creditCard); + + /** @var OrderInjectable $order */ + $order = $this->fixtureFactory->createByCode( + 'orderInjectable', + [ + 'data' => [ + 'entity_id' => ['products' => $this->products] + ] + ] + ); + return ['order' => $order]; + } +} diff --git a/dev/tests/functional/tests/app/Magento/Paypal/Test/etc/testcase.xml b/dev/tests/functional/tests/app/Magento/Paypal/Test/etc/testcase.xml index 89cf35b73bc3ed292a152358fd5265a71d566983..e333b4b4ffefcf02ce59d632b9346831d974fb0b 100644 --- a/dev/tests/functional/tests/app/Magento/Paypal/Test/etc/testcase.xml +++ b/dev/tests/functional/tests/app/Magento/Paypal/Test/etc/testcase.xml @@ -13,7 +13,7 @@ <step name="addProductsToTheCart" module="Magento_Checkout" next="proceedToCheckout" /> <step name="proceedToCheckout" module="Magento_Checkout" next="createCustomer" /> <step name="createCustomer" module="Magento_Customer" next="selectCheckoutMethod" /> - <step name="selectCheckoutMethod" module="Magento_Checkout" next="fillShippingAddress"/> + <step name="selectCheckoutMethod" module="Magento_Checkout" next="fillShippingAddress" /> <step name="fillShippingAddress" module="Magento_Checkout" next="fillShippingMethod" /> <step name="fillShippingMethod" module="Magento_Checkout" next="selectPaymentMethod" /> <step name="selectPaymentMethod" module="Magento_Checkout" next="continueToPaypalInContext" /> @@ -59,7 +59,7 @@ <step name="selectPaymentMethod" module="Magento_Checkout" next="continueToPaypal" /> <step name="continueToPaypal" module="Magento_Paypal" next="continuePaypalCheckout" /> <step name="continuePaypalCheckout" module="Magento_Paypal" next="getPlacedOrderId" /> - <step name="getPlacedOrderId" module="Magento_Paypal" /> + <step name="getPlacedOrderId" module="Magento_Checkout" /> </scenario> <scenario name="ConflictResolutionTest" firstStep="checkExpressConfig"> <step name="checkExpressConfig" module="Magento_Paypal" next="checkBraintreeConfig" /> @@ -85,4 +85,58 @@ <step name="saveCreditCardOnBackend" module="Magento_Vault" next="submitOrderNegative" /> <step name="submitOrderNegative" module="Magento_Sales" /> </scenario> + <scenario name="OnePageCheckoutHostedProTest" firstStep="setupConfiguration"> + <step name="setupConfiguration" module="Magento_Config" next="createProducts" /> + <step name="createProducts" module="Magento_Catalog" next="createTaxRule" /> + <step name="createTaxRule" module="Magento_Tax" next="addProductsToTheCart" /> + <step name="addProductsToTheCart" module="Magento_Checkout" next="proceedToCheckout" /> + <step name="proceedToCheckout" module="Magento_Checkout" next="createCustomer" /> + <step name="createCustomer" module="Magento_Customer" next="selectCheckoutMethod" /> + <step name="selectCheckoutMethod" module="Magento_Checkout" next="fillShippingAddress" /> + <step name="fillShippingAddress" module="Magento_Checkout" next="fillShippingMethod" /> + <step name="fillShippingMethod" module="Magento_Checkout" next="placeOrderWithHostedPro" /> + <step name="placeOrderWithHostedPro" module="Magento_Paypal" next="getPlacedOrderId" /> + <step name="getPlacedOrderId" module="Magento_Checkout" /> + </scenario> + <scenario name="CloseSalesWithHostedProTest" firstStep="setupConfiguration"> + <step name="setupConfiguration" module="Magento_Config" next="createProducts" /> + <step name="createProducts" module="Magento_Catalog" next="createTaxRule" /> + <step name="createTaxRule" module="Magento_Tax" next="addProductsToTheCart" /> + <step name="addProductsToTheCart" module="Magento_Checkout" next="proceedToCheckout" /> + <step name="proceedToCheckout" module="Magento_Checkout" next="createCustomer" /> + <step name="createCustomer" module="Magento_Customer" next="selectCheckoutMethod" /> + <step name="selectCheckoutMethod" module="Magento_Checkout" next="fillShippingAddress"/> + <step name="fillShippingAddress" module="Magento_Checkout" next="fillShippingMethod" /> + <step name="fillShippingMethod" module="Magento_Checkout" next="placeOrderWithHostedPro" /> + <step name="placeOrderWithHostedPro" module="Magento_Paypal" next="getPlacedOrderId" /> + <step name="getPlacedOrderId" module="Magento_Checkout" next="createInvoice" /> + <step name="createInvoice" module="Magento_Sales" next="createShipment" /> + <step name="createShipment" module="Magento_Sales" /> + </scenario> + <scenario name="OnePageCheckoutPaymentsAdvancedTest" firstStep="setupConfiguration"> + <step name="setupConfiguration" module="Magento_Config" next="createProducts" /> + <step name="createProducts" module="Magento_Catalog" next="createTaxRule" /> + <step name="createTaxRule" module="Magento_Tax" next="addProductsToTheCart" /> + <step name="addProductsToTheCart" module="Magento_Checkout" next="proceedToCheckout" /> + <step name="proceedToCheckout" module="Magento_Checkout" next="createCustomer" /> + <step name="createCustomer" module="Magento_Customer" next="selectCheckoutMethod" /> + <step name="selectCheckoutMethod" module="Magento_Checkout" next="fillShippingAddress" /> + <step name="fillShippingAddress" module="Magento_Checkout" next="fillShippingMethod" /> + <step name="fillShippingMethod" module="Magento_Checkout" next="placeOrderWithPaymentsAdvanced" /> + <step name="placeOrderWithPaymentsAdvanced" module="Magento_Paypal" next="getPlacedOrderId" /> + <step name="getPlacedOrderId" module="Magento_Checkout" /> + </scenario> + <scenario name="OnePageCheckoutPayflowLinkTest" firstStep="setupConfiguration"> + <step name="setupConfiguration" module="Magento_Config" next="createProducts" /> + <step name="createProducts" module="Magento_Catalog" next="createTaxRule" /> + <step name="createTaxRule" module="Magento_Tax" next="addProductsToTheCart" /> + <step name="addProductsToTheCart" module="Magento_Checkout" next="proceedToCheckout" /> + <step name="proceedToCheckout" module="Magento_Checkout" next="createCustomer" /> + <step name="createCustomer" module="Magento_Customer" next="selectCheckoutMethod" /> + <step name="selectCheckoutMethod" module="Magento_Checkout" next="fillShippingAddress" /> + <step name="fillShippingAddress" module="Magento_Checkout" next="fillShippingMethod" /> + <step name="fillShippingMethod" module="Magento_Checkout" next="placeOrderWithPayflowLink" /> + <step name="placeOrderWithPayflowLink" module="Magento_Paypal" next="getPlacedOrderId" /> + <step name="getPlacedOrderId" module="Magento_Checkout" /> + </scenario> </config> diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/Block/Adminhtml/Order/AbstractItems.php b/dev/tests/functional/tests/app/Magento/Sales/Test/Block/Adminhtml/Order/AbstractItems.php index d76461b9ae5f071d8dcdddc2c473ebba01698bfc..38ad9139d4fdb2bf28c40d8420db890dcda77d3a 100644 --- a/dev/tests/functional/tests/app/Magento/Sales/Test/Block/Adminhtml/Order/AbstractItems.php +++ b/dev/tests/functional/tests/app/Magento/Sales/Test/Block/Adminhtml/Order/AbstractItems.php @@ -7,6 +7,7 @@ namespace Magento\Sales\Test\Block\Adminhtml\Order; use Magento\Mtf\Block\Block; +use Magento\Mtf\Client\ElementInterface; /** * Base Items block on Credit Memo, Invoice, Shipment view page. @@ -21,11 +22,18 @@ class AbstractItems extends Block protected $rowItem = 'tbody'; /** - * Locator for "Product" column. + * Locator for product sku column. * * @var string */ - protected $product = '.col-product'; + protected $sku = '.col-product .product-sku-block'; + + /** + * Locator for product title column. + * + * @var string + */ + protected $title = '.col-product .product-title'; /** * Locator for "Price" column. @@ -82,9 +90,10 @@ class AbstractItems extends Block foreach ($items as $item) { $itemData = []; - $itemData += $this->parseProductName($item->find($this->product)->getText()); + $itemData['product'] = preg_replace('/\n|\r/', '', $item->find($this->title)->getText()); + $itemData['sku'] = $this->getSku($item); $itemData['price'] = $this->escapePrice($item->find($this->price)->getText()); - $itemData['qty'] = $item->find($this->qty)->getText(); + $itemData['qty'] = $this->getQty($item); $itemData['subtotal'] = $this->escapePrice($item->find($this->subtotal)->getText()); $itemData['tax'] = $this->escapePrice($item->find($this->taxAmount)->getText()); $itemData['discount'] = $this->escapePrice($item->find($this->discountAmount)->getText()); @@ -97,18 +106,33 @@ class AbstractItems extends Block } /** - * Parse product name to title and sku product. + * Get product quantity. * - * @param string $product - * @return array + * @param ElementInterface $item + * @return null|int + */ + private function getQty(ElementInterface $item) + { + $qty = null; + $elements = $item->getElements($this->qty); + foreach ($elements as $element) { + $qty += (int) $element->getText(); + } + return $qty; + } + + /** + * Get product SKU. + * + * @param ElementInterface $item + * @return string */ - protected function parseProductName($product) + private function getSku(ElementInterface $item) { - $data = array_map('trim', explode('SKU:', str_replace("\n", '', $product))); - return [ - 'product' => $data[0], - 'sku' => isset($data[1]) ? $data[1] : '' - ]; + $itemContent = $item->find($this->sku)->getText(); + $itemContent = preg_replace('/\n|\r/', '', $itemContent); + $itemContent = str_replace('SKU: ', '', $itemContent); + return $itemContent; } /** @@ -117,7 +141,7 @@ class AbstractItems extends Block * @var string $price * @return string */ - protected function escapePrice($price) + private function escapePrice($price) { return preg_replace('[^0-9\.]', '', $price); } diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/Block/Adminhtml/Order/Create/Billing/Method.php b/dev/tests/functional/tests/app/Magento/Sales/Test/Block/Adminhtml/Order/Create/Billing/Method.php index 8477af0087fd47e07b8fee3e6c5138c690369d05..0d443eb1db9ff3c5e3eee8a4efcaffbea5d44df9 100644 --- a/dev/tests/functional/tests/app/Magento/Sales/Test/Block/Adminhtml/Order/Create/Billing/Method.php +++ b/dev/tests/functional/tests/app/Magento/Sales/Test/Block/Adminhtml/Order/Create/Billing/Method.php @@ -7,8 +7,8 @@ namespace Magento\Sales\Test\Block\Adminhtml\Order\Create\Billing; use Magento\Mtf\Block\Block; -use Magento\Mtf\Fixture\InjectableFixture; use Magento\Mtf\Client\Locator; +use Magento\Payment\Test\Fixture\CreditCard; /** * Adminhtml sales order create payment method block. @@ -20,66 +20,60 @@ class Method extends Block * * @var string */ - protected $paymentMethod = '#p_method_%s'; + private $paymentMethod = '#p_method_%s'; /** * Purchase order number selector. * * @var string */ - protected $purchaseOrderNumber = '#po_number'; - - /** - * Payment form. - * - * @var string - */ - protected $paymentForm = '#payment_form_%s'; + private $purchaseOrderNumber = '#po_number'; /** * Magento loader selector. * * @var string */ - protected $loader = '[data-role=loader]'; + private $loader = '[data-role=loader]'; /** * Field with Mage error. * * @var string */ - protected $mageErrorField = '//fieldset/*[contains(@class,"field ")][.//*[contains(@class,"error")]]'; + private $mageErrorField = './/*[contains(@name, "payment[")]/following-sibling::label[@class="mage-error"]'; /** - * Mage error text. + * Error label preceding field of credit card form. * * @var string */ - protected $mageErrorText = './/label[contains(@class,"error")]'; + private $errorLabelPrecedingField = './preceding-sibling::*[1][contains(@name, "payment")]'; /** * Select payment method. * - * @param array $paymentCode - * @param InjectableFixture|null $creditCard + * @param array $payment + * @param CreditCard|null $creditCard + * @return void */ - public function selectPaymentMethod(array $paymentCode, InjectableFixture $creditCard = null) + public function selectPaymentMethod(array $payment, CreditCard $creditCard = null) { - $paymentInput = $this->_rootElement->find(sprintf($this->paymentMethod, $paymentCode['method'])); + $paymentMethod = $payment['method']; + $paymentInput = $this->_rootElement->find(sprintf($this->paymentMethod, $paymentMethod)); if ($paymentInput->isVisible()) { $paymentInput->click(); $this->waitForElementNotVisible($this->loader); } - if (isset($paymentCode['po_number'])) { - $this->_rootElement->find($this->purchaseOrderNumber)->setValue($paymentCode['po_number']); + if (isset($payment['po_number'])) { + $this->_rootElement->find($this->purchaseOrderNumber)->setValue($payment['po_number']); } if ($creditCard !== null) { - $class = explode('\\', get_class($creditCard)); - $module = $class[1]; - /** @var \Magento\Payment\Test\Block\Form\Cc $formBlock */ + $module = $creditCard->hasData('payment_code') ? ucfirst($creditCard->getPaymentCode()) : 'Payment'; + /** @var \Magento\Payment\Test\Block\Form\PaymentCc $formBlock */ $formBlock = $this->blockFactory->create( - "\\Magento\\{$module}\\Test\\Block\\Form\\Cc", - ['element' => $this->_rootElement->find('#payment_form_' . $paymentCode['method'])] + "\\Magento\\{$module}\\Test\\Block\\Form\\{$module}Cc", + ['element' => $this->_rootElement->find('#payment_form_' . $paymentMethod)] ); $formBlock->fill($creditCard); } @@ -92,10 +86,9 @@ class Method extends Block { $data = []; $elements = $this->_rootElement->getElements($this->mageErrorField, Locator::SELECTOR_XPATH); - foreach ($elements as $element) { - $error = $element->find($this->mageErrorText, Locator::SELECTOR_XPATH); + foreach ($elements as $error) { if ($error->isVisible()) { - $label = $element->find('.//*[contains(@name,"payment")]', Locator::SELECTOR_XPATH); + $label = $error->find($this->errorLabelPrecedingField, Locator::SELECTOR_XPATH); $label = $label->getAttribute('name'); $label = preg_replace('/payment\[(.*)\]/u', '$1', $label); $data[$label] = $error->getText(); diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/Block/Adminhtml/Order/Create/CustomerActivities/Sidebar.php b/dev/tests/functional/tests/app/Magento/Sales/Test/Block/Adminhtml/Order/Create/CustomerActivities/Sidebar.php index 050f797d83825e99eaf08728c2dc69149f8faaae..3fc41e0db1785d06eb29bd58b7343b02a274ee00 100644 --- a/dev/tests/functional/tests/app/Magento/Sales/Test/Block/Adminhtml/Order/Create/CustomerActivities/Sidebar.php +++ b/dev/tests/functional/tests/app/Magento/Sales/Test/Block/Adminhtml/Order/Create/CustomerActivities/Sidebar.php @@ -21,6 +21,13 @@ abstract class Sidebar extends Block */ protected $addToOrder = './/tr[td[.="%s"]]//input[contains(@name,"add")]'; + /** + * 'Add to order' configure. + * + * @var string + */ + protected $addToOrderConfigure = './/tr[td[contains(.,"%s")]]//a[contains(@class, "icon-configure")]'; + /** * 'Add to order' checkbox. * @@ -39,9 +46,18 @@ abstract class Sidebar extends Block foreach ($products as $product) { $name = $product->getName(); $this->_rootElement->find(sprintf($this->addToOrderProductName, $name), Locator::SELECTOR_XPATH)->click(); - $this->_rootElement->click(); - $this->_rootElement->find(sprintf($this->addToOrder, $name), Locator::SELECTOR_XPATH, 'checkbox') - ->setValue('Yes'); + + $dataConfig = $product->getDataConfig(); + $typeId = isset($dataConfig['type_id']) ? $dataConfig['type_id'] : null; + + if ($this->hasRender($typeId)) { + $this->_rootElement->find(sprintf($this->addToOrderConfigure, $name), Locator::SELECTOR_XPATH)->click(); + $this->callRender($typeId, 'configProduct', ['product' => $product]); + } else { + $this->_rootElement->click(); + $this->_rootElement->find(sprintf($this->addToOrder, $name), Locator::SELECTOR_XPATH, 'checkbox') + ->setValue('Yes'); + } } } } diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/Block/Adminhtml/Order/Invoice/Totals.php b/dev/tests/functional/tests/app/Magento/Sales/Test/Block/Adminhtml/Order/Invoice/Totals.php index b6b14670c0f56ce8c6439c26fb606b2c35e85dc9..3433447222ccbbd92ee75f161c2c4f24dfb453c1 100644 --- a/dev/tests/functional/tests/app/Magento/Sales/Test/Block/Adminhtml/Order/Invoice/Totals.php +++ b/dev/tests/functional/tests/app/Magento/Sales/Test/Block/Adminhtml/Order/Invoice/Totals.php @@ -28,6 +28,13 @@ class Totals extends \Magento\Sales\Test\Block\Adminhtml\Order\Totals */ protected $capture = '[name="invoice[capture_case]"]'; + /** + * Offline capture text message selector. + * + * @var string + */ + private $captureOfflineMessage = './/input[@value="offline"]/following-sibling::div[1]'; + /** * Submit invoice * @@ -58,4 +65,15 @@ class Totals extends \Magento\Sales\Test\Block\Adminhtml\Order\Totals { $this->_rootElement->find($this->capture, Locator::SELECTOR_CSS, 'select')->setValue($option); } + + /** + * Get message that invoice can be created only offline. + * + * @return null|string + */ + public function getCaptureOfflineMessage() + { + $captureCaseMessage = $this->_rootElement->find($this->captureOfflineMessage, Locator::SELECTOR_XPATH); + return $captureCaseMessage->isVisible() ? $captureCaseMessage->getText() : null; + } } diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/Block/Adminhtml/Order/View/OrderForm.php b/dev/tests/functional/tests/app/Magento/Sales/Test/Block/Adminhtml/Order/View/OrderForm.php index 757a025605b9b69271e33848a019dd299f6034d9..2261257ca70fe093db941bca8a693d34ce813ae4 100644 --- a/dev/tests/functional/tests/app/Magento/Sales/Test/Block/Adminhtml/Order/View/OrderForm.php +++ b/dev/tests/functional/tests/app/Magento/Sales/Test/Block/Adminhtml/Order/View/OrderForm.php @@ -7,30 +7,11 @@ namespace Magento\Sales\Test\Block\Adminhtml\Order\View; use Magento\Backend\Test\Block\Widget\FormTabs; -use Magento\Sales\Test\Block\Adminhtml\Order\View\Tab\Info as OrderInformationBlock; /** - * Order view tabs + * Order view tabs. */ class OrderForm extends FormTabs { - /** - * Order information block. - * - * @var string - */ - protected $orderInfoBlock = '[data-ui-id="sales-order-tabs-tab-content-order-info"]'; - - /** - * Get order information block. - * - * @return OrderInformationBlock - */ - public function getOrderInfoBlock() - { - return $this->blockFactory->create( - \Magento\Sales\Test\Block\Adminhtml\Order\View\Tab\Info::class, - ['element' => $this->_rootElement->find($this->orderInfoBlock)] - ); - } + // } diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/Block/Adminhtml/Order/View/OrderForm.xml b/dev/tests/functional/tests/app/Magento/Sales/Test/Block/Adminhtml/Order/View/OrderForm.xml index 383dfb8b7b6aade39bf531312101387fc5c9bac7..0a5aa8e1993a8e84963b981849f18b19a8a22372 100644 --- a/dev/tests/functional/tests/app/Magento/Sales/Test/Block/Adminhtml/Order/View/OrderForm.xml +++ b/dev/tests/functional/tests/app/Magento/Sales/Test/Block/Adminhtml/Order/View/OrderForm.xml @@ -6,6 +6,11 @@ */ --> <tabs> + <info> + <class>Magento\Sales\Test\Block\Adminhtml\Order\View\Tab\Info</class> + <selector>#sales_order_view_tabs_order_info</selector> + <strategy>css selector</strategy> + </info> <invoices> <class>Magento\Sales\Test\Block\Adminhtml\Order\View\Tab\Invoices</class> <selector>#sales_order_view_tabs_order_invoices</selector> diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/Block/Adminhtml/Order/View/Tab/Info.php b/dev/tests/functional/tests/app/Magento/Sales/Test/Block/Adminhtml/Order/View/Tab/Info.php index 50c5a077e9b5511bd98d15306a5f3de15f6ad6a0..146e3facccb6196f154af1487053f8e8b17e1991 100644 --- a/dev/tests/functional/tests/app/Magento/Sales/Test/Block/Adminhtml/Order/View/Tab/Info.php +++ b/dev/tests/functional/tests/app/Magento/Sales/Test/Block/Adminhtml/Order/View/Tab/Info.php @@ -6,22 +6,30 @@ namespace Magento\Sales\Test\Block\Adminhtml\Order\View\Tab; -use Magento\Mtf\Block\Block; +use Magento\Backend\Test\Block\Widget\Tab; +use Magento\Sales\Test\Block\Adminhtml\Order\View\Tab\Info\PaymentInfoBlock; /** * Order information tab block. */ -class Info extends Block +class Info extends Tab { /** - * Order status selector + * Order status selector. * * @var string */ protected $orderStatus = '#order_status'; /** - * Get order status from info block + * Selector for 'Payment Information' block. + * + * @var string + */ + private $paymentInfoBlockSelector = '.order-payment-method'; + + /** + * Get order status from info block. * * @return array|string */ @@ -29,4 +37,17 @@ class Info extends Block { return $this->_rootElement->find($this->orderStatus)->getText(); } + + /** + * Returns Payment Information block. + * + * @return PaymentInfoBlock + */ + public function getPaymentInfoBlock() + { + return $this->blockFactory->create( + PaymentInfoBlock::class, + ['element' => $this->_rootElement->find($this->paymentInfoBlockSelector)] + ); + } } diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/Block/Adminhtml/Order/View/Tab/Info/PaymentInfoBlock.php b/dev/tests/functional/tests/app/Magento/Sales/Test/Block/Adminhtml/Order/View/Tab/Info/PaymentInfoBlock.php new file mode 100644 index 0000000000000000000000000000000000000000..818a9b9717cb989c5b352dfed121525f2b7bc4c3 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Sales/Test/Block/Adminhtml/Order/View/Tab/Info/PaymentInfoBlock.php @@ -0,0 +1,40 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Sales\Test\Block\Adminhtml\Order\View\Tab\Info; + +use Magento\Mtf\Block\Block; + +/** + * Order payment information block. + */ +class PaymentInfoBlock extends Block +{ + /** + * Payment info row selector. + * + * @var string + */ + private $info = 'tr'; + + /** + * Get payment information block data. + * + * @return array + */ + public function getData() + { + $result = []; + $elements = $this->_rootElement->getElements($this->info); + foreach ($elements as $row) { + $key = rtrim($row->find('th')->getText(), ':'); + $value = $row->find('td')->getText(); + $result[$key] = $value; + } + + return $result; + } +} diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/Block/Adminhtml/Order/View/Tab/Invoices/Grid.php b/dev/tests/functional/tests/app/Magento/Sales/Test/Block/Adminhtml/Order/View/Tab/Invoices/Grid.php index d1f27d14a6619f71fc2e459adad23888d4fb51b7..41fbd8979b58df8fb58f000e3ea79e0f289344c4 100644 --- a/dev/tests/functional/tests/app/Magento/Sales/Test/Block/Adminhtml/Order/View/Tab/Invoices/Grid.php +++ b/dev/tests/functional/tests/app/Magento/Sales/Test/Block/Adminhtml/Order/View/Tab/Invoices/Grid.php @@ -9,7 +9,7 @@ namespace Magento\Sales\Test\Block\Adminhtml\Order\View\Tab\Invoices; /** * Invoices grid on order view page. */ -class Grid extends \Magento\Backend\Test\Block\Widget\Grid +class Grid extends \Magento\Ui\Test\Block\Adminhtml\DataGrid { /** * Locator value for link in action column. @@ -25,6 +25,13 @@ class Grid extends \Magento\Backend\Test\Block\Widget\Grid */ protected $invoiceId = 'tbody td:nth-child(2)'; + /** + * Invoices data grid loader locator. + * + * @var string + */ + protected $loader = '[data-component="sales_order_view_invoice_grid"]'; + /** * Filters array mapping. * @@ -34,6 +41,9 @@ class Grid extends \Magento\Backend\Test\Block\Widget\Grid 'id' => [ 'selector' => 'input[name="increment_id"]', ], + 'order_id' => [ + 'selector' => 'input[name="order_increment_id"]', + ], 'status' => [ 'selector' => 'select[name="state"]', 'input' => 'select', @@ -54,6 +64,7 @@ class Grid extends \Magento\Backend\Test\Block\Widget\Grid public function getIds() { $result = []; + $this->waitForElementNotVisible($this->loader); $invoiceIds = $this->_rootElement->getElements($this->invoiceId); foreach ($invoiceIds as $invoiceId) { $result[] = trim($invoiceId->getText()); @@ -69,6 +80,7 @@ class Grid extends \Magento\Backend\Test\Block\Widget\Grid */ public function viewInvoice() { + $this->waitForElementNotVisible($this->loader); $this->_rootElement->find($this->invoiceId)->click(); } } diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AbstractAssertItems.php b/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AbstractAssertItems.php index 26978343fb2c26336e3e9902f46ca730a54ce6d8..fc9bd8275d650f19bedfebec0fe3f52c836d0623 100644 --- a/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AbstractAssertItems.php +++ b/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AbstractAssertItems.php @@ -6,25 +6,25 @@ namespace Magento\Sales\Test\Constraint; -use Magento\Catalog\Test\Fixture\CatalogProductSimple; -use Magento\Sales\Test\Fixture\OrderInjectable; +use Magento\Checkout\Test\Fixture\Cart; use Magento\Mtf\Constraint\AbstractAssertForm; +use Magento\Mtf\Fixture\FixtureFactory; +use Magento\Sales\Test\Fixture\OrderInjectable; /** - * Class AbstractAssertArchiveItems - * Assert items represented in order's entity view page + * Assert items represented in order's entity view page. */ abstract class AbstractAssertItems extends AbstractAssertForm { /** - * Key for sort data + * Key for sort data. * * @var string */ protected $sortKey = "::sku"; /** - * List compare fields + * List compare fields. * * @var array */ @@ -35,25 +35,29 @@ abstract class AbstractAssertItems extends AbstractAssertForm ]; /** - * Prepare order products + * Prepare order products. * * @param OrderInjectable $order * @param array|null $data [optional] + * @param Cart|null $cart [optional] * @return array */ - protected function prepareOrderProducts(OrderInjectable $order, array $data = null) + protected function prepareOrderProducts(OrderInjectable $order, array $data = null, Cart $cart = null) { - $products = $order->getEntityId()['products']; $productsData = []; - - /** @var CatalogProductSimple $product */ - foreach ($products as $key => $product) { + if ($cart === null) { + $cart['data']['items'] = ['products' => $order->getEntityId()['products']]; + $fixtureFactory = $this->objectManager->create(FixtureFactory::class); + $cart = $fixtureFactory->createByCode('cart', $cart); + } + /** @var \Magento\Catalog\Test\Fixture\Cart\Item $item */ + foreach ($cart->getItems() as $key => $item) { $productsData[] = [ - 'product' => $product->getName(), - 'sku' => $product->getSku(), + 'product' => $item->getData()['name'], + 'sku' => $item->getData()['sku'], 'qty' => (isset($data[$key]['qty']) && $data[$key]['qty'] != '-') ? $data[$key]['qty'] - : $product->getCheckoutData()['qty'], + : $item->getData()['qty'], ]; } @@ -61,7 +65,7 @@ abstract class AbstractAssertItems extends AbstractAssertForm } /** - * Prepare invoice data + * Prepare invoice data. * * @param array $itemsData * @return array diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertAuthorizationInCommentsHistory.php b/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertAuthorizationInCommentsHistory.php index a6b8e8983d2b617953b93490dc4c3a3e1079cec2..8b34837bc8df3efe77a348070abdcf12de71ac7f 100644 --- a/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertAuthorizationInCommentsHistory.php +++ b/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertAuthorizationInCommentsHistory.php @@ -6,8 +6,8 @@ namespace Magento\Sales\Test\Constraint; -use Magento\Sales\Test\Page\Adminhtml\SalesOrderView; use Magento\Sales\Test\Page\Adminhtml\OrderIndex; +use Magento\Sales\Test\Page\Adminhtml\SalesOrderView; use Magento\Mtf\Constraint\AbstractConstraint; /** @@ -16,9 +16,9 @@ use Magento\Mtf\Constraint\AbstractConstraint; class AssertAuthorizationInCommentsHistory extends AbstractConstraint { /** - * Message about authorized amount in order. + * Pattern of message about authorized amount in order. */ - const AUTHORIZED_AMOUNT = 'Authorized amount of $'; + const AUTHORIZED_AMOUNT_PATTERN = '/(IPN "Pending" )*Authorized amount of \w*\W{1,2}%s. Transaction ID: "[\w\-]*"/'; /** * Assert that comment about authorized amount exist in Comments History section on order page in Admin. @@ -37,11 +37,10 @@ class AssertAuthorizationInCommentsHistory extends AbstractConstraint ) { $salesOrder->open(); $salesOrder->getSalesOrderGrid()->searchAndOpen(['id' => $orderId]); - $actualAuthorizedAmount = $salesOrderView->getOrderHistoryBlock()->getAuthorizedAmount(); - \PHPUnit_Framework_Assert::assertContains( - self::AUTHORIZED_AMOUNT . $prices['grandTotal'], + \PHPUnit_Framework_Assert::assertRegExp( + sprintf(self::AUTHORIZED_AMOUNT_PATTERN, $prices['grandTotal']), $actualAuthorizedAmount, 'Incorrect authorized amount value for the order #' . $orderId ); diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertCaptureInCommentsHistory.php b/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertCaptureInCommentsHistory.php index c46a161cc63723b6fc4d2376e6f3160ed5e7eb54..90e0e7b091a11f51c04e8f719b3e1b4382080d61 100644 --- a/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertCaptureInCommentsHistory.php +++ b/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertCaptureInCommentsHistory.php @@ -6,6 +6,7 @@ namespace Magento\Sales\Test\Constraint; +use Magento\Sales\Test\Fixture\OrderInjectable; use Magento\Sales\Test\Page\Adminhtml\SalesOrderView; use Magento\Sales\Test\Page\Adminhtml\OrderIndex; use Magento\Mtf\Constraint\AbstractConstraint; @@ -16,9 +17,9 @@ use Magento\Mtf\Constraint\AbstractConstraint; class AssertCaptureInCommentsHistory extends AbstractConstraint { /** - * Message about captured amount in order. + * Pattern of message about captured amount in order. */ - const CAPTURED_AMOUNT = 'Captured amount of $'; + const CAPTURED_AMOUNT_PATTERN = '/^Captured amount of \w*\W{1,2}%s online. Transaction ID: "[\w\-]*"/'; /** * Assert that comment about captured amount exist in Comments History section on order page in Admin. @@ -40,8 +41,8 @@ class AssertCaptureInCommentsHistory extends AbstractConstraint $actualCapturedAmount = $salesOrderView->getOrderHistoryBlock()->getCapturedAmount(); foreach ($capturedPrices as $key => $capturedPrice) { - \PHPUnit_Framework_Assert::assertContains( - self::CAPTURED_AMOUNT . $capturedPrice, + \PHPUnit_Framework_Assert::assertRegExp( + sprintf(self::CAPTURED_AMOUNT_PATTERN, $capturedPrice), $actualCapturedAmount[$key], 'Incorrect captured amount value for the order #' . $orderId ); diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertInvoiceItems.php b/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertInvoiceItems.php index 9b43a3917aac199a5dc2e2255f6db5e2eb615dc6..cbcb725df05ffb0516497847f26440ee3f0790d7 100644 --- a/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertInvoiceItems.php +++ b/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertInvoiceItems.php @@ -6,6 +6,7 @@ namespace Magento\Sales\Test\Constraint; +use Magento\Checkout\Test\Fixture\Cart; use Magento\Sales\Test\Fixture\OrderInjectable; use Magento\Sales\Test\Page\Adminhtml\InvoiceIndex; use Magento\Sales\Test\Page\Adminhtml\SalesInvoiceView; @@ -23,6 +24,7 @@ class AssertInvoiceItems extends AbstractAssertItems * @param OrderInjectable $order * @param array $ids * @param array|null $data [optional] + * @param Cart|null $cart [optional] * @return void */ public function processAssert( @@ -30,10 +32,11 @@ class AssertInvoiceItems extends AbstractAssertItems SalesInvoiceView $salesInvoiceView, OrderInjectable $order, array $ids, - array $data = null + array $data = null, + Cart $cart = null ) { $orderId = $order->getId(); - $productsData = $this->prepareOrderProducts($order, $data['items_data']); + $productsData = $this->prepareOrderProducts($order, $data['items_data'], $cart); foreach ($ids['invoiceIds'] as $invoiceId) { $filter = [ 'order_id' => $orderId, diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertInvoiceStatusInOrdersGrid.php b/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertInvoiceStatusInOrdersGrid.php new file mode 100644 index 0000000000000000000000000000000000000000..6695786923b5c00c71e12101855421554e940281 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertInvoiceStatusInOrdersGrid.php @@ -0,0 +1,53 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Sales\Test\Constraint; + +use Magento\Sales\Test\Page\Adminhtml\SalesOrderView; +use Magento\Mtf\Constraint\AbstractConstraint; + +/** + * Assert invoice status on order page in Admin. + */ +class AssertInvoiceStatusInOrdersGrid extends AbstractConstraint +{ + /** + * Assert invoice status on order page in Admin. + * + * @param SalesOrderView $salesOrderView + * @param string $invoiceStatus + * @param string $orderId + * @return void + */ + public function processAssert( + SalesOrderView $salesOrderView, + $invoiceStatus, + $orderId + ) { + $salesOrderView->open(['order_id' => $orderId]); + $salesOrderView->getOrderForm()->openTab('invoices'); + /** @var \Magento\Sales\Test\Block\Adminhtml\Order\View\Tab\Invoices\Grid $grid */ + $grid = $salesOrderView->getOrderForm()->getTab('invoices')->getGridBlock(); + $filter = [ + 'order_id' => $orderId, + 'status' => $invoiceStatus, + ]; + \PHPUnit_Framework_Assert::assertTrue( + $grid->isRowVisible($filter), + 'Invoice status is incorrect.' + ); + } + + /** + * Returns a string representation of the object. + * + * @return string + */ + public function toString() + { + return 'Invoice status is correct.'; + } +} diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertOnlineInvoiceCannotBeCreated.php b/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertOnlineInvoiceCannotBeCreated.php new file mode 100644 index 0000000000000000000000000000000000000000..437dc8cc1be280f2edfd46baac79cad24e5748c0 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertOnlineInvoiceCannotBeCreated.php @@ -0,0 +1,59 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Sales\Test\Constraint; + +use Magento\Sales\Test\Page\Adminhtml\OrderInvoiceNew; +use Magento\Sales\Test\Page\Adminhtml\SalesOrderView; +use Magento\Sales\Test\Page\Adminhtml\OrderIndex; +use Magento\Mtf\Constraint\AbstractConstraint; + +/** + * Assert message that invoice can be created only offline is present. + */ +class AssertOnlineInvoiceCannotBeCreated extends AbstractConstraint +{ + /** + * Message that invoice can be created only offline. + */ + const OFFLINE_INVOICE_MESSAGE = 'The invoice will be created offline without the payment gateway.'; + + /** + * Assert message that invoice can be created only offline is present. + * + * @param SalesOrderView $salesOrderView + * @param OrderIndex $salesOrder + * @param OrderInvoiceNew $orderInvoiceNew + * @param string $orderId + * @return void + */ + public function processAssert( + SalesOrderView $salesOrderView, + OrderIndex $salesOrder, + OrderInvoiceNew $orderInvoiceNew, + $orderId + ) { + $salesOrder->open(); + $salesOrder->getSalesOrderGrid()->searchAndOpen(['id' => $orderId]); + $salesOrderView->getPageActions()->invoice(); + + \PHPUnit_Framework_Assert::assertEquals( + self::OFFLINE_INVOICE_MESSAGE, + $orderInvoiceNew->getTotalsBlock()->getCaptureOfflineMessage(), + 'Message incorrect or is not present.' + ); + } + + /** + * Returns string representation of successful assertion. + * + * @return string + */ + public function toString() + { + return "Message that invoice can be created only offline is present."; + } +} diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertOrderGrandTotal.php b/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertOrderGrandTotal.php index 4c30d5f68d208a2b53f54fd7607f7fec276c7c63..1de6de50612481e6bd90b209fcef59e5b3f68706 100644 --- a/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertOrderGrandTotal.php +++ b/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertOrderGrandTotal.php @@ -6,29 +6,29 @@ namespace Magento\Sales\Test\Constraint; -use Magento\Sales\Test\Page\Adminhtml\SalesOrderView; use Magento\Sales\Test\Page\Adminhtml\OrderIndex; +use Magento\Sales\Test\Page\Adminhtml\SalesOrderView; use Magento\Mtf\Constraint\AbstractConstraint; /** - * Assert that Order Grand Total is correct on order page in backend + * Assert that Order Grand Total is correct on order page in Admin. */ class AssertOrderGrandTotal extends AbstractConstraint { /** - * Assert that Order Grand Total is correct on order page in backend + * Assert that Order Grand Total is correct on order page in Admin. * * @param SalesOrderView $salesOrderView - * @param string $orderId * @param OrderIndex $salesOrder * @param array $prices + * @param string $orderId * @return void */ public function processAssert( SalesOrderView $salesOrderView, OrderIndex $salesOrder, - $orderId, - array $prices + array $prices, + $orderId ) { $salesOrder->open(); $salesOrder->getSalesOrderGrid()->searchAndOpen(['id' => $orderId]); @@ -41,7 +41,7 @@ class AssertOrderGrandTotal extends AbstractConstraint } /** - * Returns a string representation of the object + * Returns a string representation of the object. * * @return string */ diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertOrderPaymentInformation.php b/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertOrderPaymentInformation.php new file mode 100644 index 0000000000000000000000000000000000000000..18119ddbf95d6864311e750bd6844ba43062c73b --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertOrderPaymentInformation.php @@ -0,0 +1,55 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Sales\Test\Constraint; + +use Magento\Mtf\Constraint\AbstractConstraint; +use Magento\Sales\Test\Fixture\OrderInjectable; +use Magento\Sales\Test\Page\Adminhtml\OrderIndex; +use Magento\Sales\Test\Page\Adminhtml\SalesOrderView; + +/** + * Assert that payment information is valid and matches with expected values. + */ +class AssertOrderPaymentInformation extends AbstractConstraint +{ + /** + * Assert that payment information is valid and matches with expected values. + * + * @param OrderInjectable $order + * @param OrderIndex $orderIndex + * @param SalesOrderView $salesOrderView + * @param array $paymentInfo + * @return void + */ + public function processAssert( + OrderInjectable $order, + OrderIndex $orderIndex, + SalesOrderView $salesOrderView, + array $paymentInfo + ) { + $orderIndex->open(); + $orderIndex->getSalesOrderGrid()->searchAndOpen(['id' => $order->getId()]); + /** @var \Magento\Sales\Test\Block\Adminhtml\Order\View\Tab\Info $infoTab */ + $infoTab = $salesOrderView->getOrderForm()->openTab('info')->getTab('info'); + $actualPaymentInformation = $infoTab->getPaymentInfoBlock()->getData(); + + \PHPUnit_Framework_Assert::assertEmpty( + array_diff($paymentInfo, $actualPaymentInformation), + 'Payment Information missmatch with expected values.' + ); + } + + /** + * Returns a string representation of the object. + * + * @return string + */ + public function toString() + { + return 'Payment Information valid and matches with expected values.'; + } +} diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertOrderStatusIsCanceled.php b/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertOrderStatusIsCanceled.php new file mode 100644 index 0000000000000000000000000000000000000000..2547cb49b70a447382033b2d76f7606d5545f459 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertOrderStatusIsCanceled.php @@ -0,0 +1,53 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Sales\Test\Constraint; + +use Magento\Sales\Test\Page\Adminhtml\OrderIndex; +use Magento\Sales\Test\Page\Adminhtml\SalesOrderView; +use Magento\Mtf\Constraint\AbstractConstraint; + +/** + * Assert that status is Canceled. + */ +class AssertOrderStatusIsCanceled extends AbstractConstraint +{ + /** + * Assert that status is Canceled. + * + * @param OrderIndex $salesOrder + * @param SalesOrderView $salesOrderView + * @return void + */ + public function processAssert( + OrderIndex $salesOrder, + SalesOrderView $salesOrderView + ) { + $salesOrder->open(); + $grid = $salesOrder->getSalesOrderGrid(); + $grid->resetFilter(); + $grid->sortByColumn('ID'); + $grid->sortGridByField('ID'); + $grid->openFirstRow(); + + /** @var \Magento\Sales\Test\Block\Adminhtml\Order\View\Tab\Info $infoTab */ + $infoTab = $salesOrderView->getOrderForm()->openTab('info')->getTab('info'); + \PHPUnit_Framework_Assert::assertEquals( + $infoTab->getOrderStatus(), + 'Canceled' + ); + } + + /** + * Returns a string representation of the object. + * + * @return string + */ + public function toString() + { + return 'Order status is correct.'; + } +} diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertOrderStatusIsCorrect.php b/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertOrderStatusIsCorrect.php index 056e97c1b62626e0e10352d1bae9a078dea9021d..3623de40b06f165bf4f891d19d379f4d9104f336 100644 --- a/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertOrderStatusIsCorrect.php +++ b/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertOrderStatusIsCorrect.php @@ -11,13 +11,12 @@ use Magento\Sales\Test\Page\Adminhtml\SalesOrderView; use Magento\Mtf\Constraint\AbstractConstraint; /** - * Class AssertOrderStatusIsCorrect - * Assert that status is correct on order page in backend (same with value of orderStatus variable) + * Assert that status is correct on order page in admin panel (same with value of orderStatus variable). */ class AssertOrderStatusIsCorrect extends AbstractConstraint { /** - * Assert that status is correct on order page in backend (same with value of orderStatus variable) + * Assert that status is correct on order page in admin panel (same with value of orderStatus variable). * * @param string $status * @param string $orderId @@ -37,14 +36,16 @@ class AssertOrderStatusIsCorrect extends AbstractConstraint $salesOrder->getSalesOrderGrid()->searchAndOpen(['id' => $orderId]); $orderStatus = $statusToCheck == null ? $status : $statusToCheck; + /** @var \Magento\Sales\Test\Block\Adminhtml\Order\View\Tab\Info $infoTab */ + $infoTab = $salesOrderView->getOrderForm()->openTab('info')->getTab('info'); \PHPUnit_Framework_Assert::assertEquals( - $salesOrderView->getOrderForm()->getOrderInfoBlock()->getOrderStatus(), + $infoTab->getOrderStatus(), $orderStatus ); } /** - * Returns a string representation of the object + * Returns a string representation of the object. * * @return string */ diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertRefundInCommentsHistory.php b/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertRefundInCommentsHistory.php index 9cbb7b2c9ebbb684fcccbde61c7fc5e9bf82cee4..c0ce2a87fc1c3f62b1a934852c206358a3e76760 100644 --- a/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertRefundInCommentsHistory.php +++ b/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertRefundInCommentsHistory.php @@ -16,9 +16,9 @@ use Magento\Mtf\Constraint\AbstractConstraint; class AssertRefundInCommentsHistory extends AbstractConstraint { /** - * Message about refunded amount in order. + * Pattern of message about refunded amount in order. */ - const REFUNDED_AMOUNT = 'We refunded $'; + const REFUNDED_AMOUNT_PATTERN = '/^We refunded \w*\W{1,2}%s online. Transaction ID: "[\w\-]*"/'; /** * Assert that comment about refunded amount exist in Comments History section on order page in Admin. @@ -40,8 +40,8 @@ class AssertRefundInCommentsHistory extends AbstractConstraint $actualRefundedAmount = $salesOrderView->getOrderHistoryBlock()->getRefundedAmount(); foreach ($refundedPrices as $key => $refundedPrice) { - \PHPUnit_Framework_Assert::assertContains( - self::REFUNDED_AMOUNT . $refundedPrice, + \PHPUnit_Framework_Assert::assertRegExp( + sprintf(self::REFUNDED_AMOUNT_PATTERN, $refundedPrice), $actualRefundedAmount[$key], 'Incorrect refunded amount value for the order #' . $orderId ); diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertRefundOrderStatusInCommentsHistory.php b/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertRefundOrderStatusInCommentsHistory.php index 89faffc8ec0729082c81839ccd4762fdc335a8f3..557e29a0b9830200381f7651e3807cff39247040 100644 --- a/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertRefundOrderStatusInCommentsHistory.php +++ b/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertRefundOrderStatusInCommentsHistory.php @@ -11,7 +11,7 @@ use Magento\Mtf\Constraint\AbstractConstraint; use Magento\Sales\Test\Fixture\OrderInjectable; /** - * Class AssertRefundOrderStatusInCommentsHistory + * Assert that comment about refunded amount exist in Comments History section on order page in Admin. */ class AssertRefundOrderStatusInCommentsHistory extends AbstractConstraint { @@ -30,8 +30,11 @@ class AssertRefundOrderStatusInCommentsHistory extends AbstractConstraint ) { $salesOrder->open(); $salesOrder->getSalesOrderGrid()->searchAndOpen(['id' => $order->getId()]); + + /** @var \Magento\Sales\Test\Block\Adminhtml\Order\View\Tab\Info $infoTab */ + $infoTab = $salesOrderView->getOrderForm()->openTab('info')->getTab('info'); \PHPUnit_Framework_Assert::assertContains( - $salesOrderView->getOrderForm()->getOrderInfoBlock()->getOrderStatus(), + $infoTab->getOrderStatus(), $salesOrderView->getOrderHistoryBlock()->getStatus() ); } diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertReorderStatusIsCorrect.php b/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertReorderStatusIsCorrect.php index 804c607814a3da0cf081cbd9b5fa1b34617d0988..9c034d2ea7085d3aa35bfe5cf06af42edcd672a1 100644 --- a/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertReorderStatusIsCorrect.php +++ b/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertReorderStatusIsCorrect.php @@ -12,13 +12,12 @@ use Magento\Sales\Test\Page\Adminhtml\SalesOrderView; use Magento\Mtf\Constraint\AbstractConstraint; /** - * Class AssertReorderStatusIsCorrect - * Assert that status is correct on order page in backend + * Assert that status is correct on order page in admin panel. */ class AssertReorderStatusIsCorrect extends AbstractConstraint { /** - * Assert that status is correct on order page in backend (same with value of orderStatus variable) + * Assert that status is correct on order page in admin panel (same with value of orderStatus variable). * * @param string $previousOrderStatus * @param OrderInjectable $order @@ -35,15 +34,17 @@ class AssertReorderStatusIsCorrect extends AbstractConstraint $salesOrder->open(); $salesOrder->getSalesOrderGrid()->searchAndOpen(['id' => $order->getId()]); + /** @var \Magento\Sales\Test\Block\Adminhtml\Order\View\Tab\Info $infoTab */ + $infoTab = $salesOrderView->getOrderForm()->openTab('info')->getTab('info'); \PHPUnit_Framework_Assert::assertEquals( $previousOrderStatus, - $salesOrderView->getOrderForm()->getOrderInfoBlock()->getOrderStatus(), + $infoTab->getOrderStatus(), 'Order status is incorrect on order page in backend.' ); } /** - * Returns a string representation of the object + * Returns a string representation of the object. * * @return string */ diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/Repository/OrderInjectable/Price.xml b/dev/tests/functional/tests/app/Magento/Sales/Test/Repository/OrderInjectable/Price.xml index 3da1f91925e0a1274cbe317d36f2bc40271cbeb6..1b9a8b1465457d9d46d04f34774f42425450a7d9 100644 --- a/dev/tests/functional/tests/app/Magento/Sales/Test/Repository/OrderInjectable/Price.xml +++ b/dev/tests/functional/tests/app/Magento/Sales/Test/Repository/OrderInjectable/Price.xml @@ -19,6 +19,13 @@ </field> </dataset> + <dataset name="full_invoice_with_product_10_dollar"> + <field name="0" xsi:type="array"> + <item name="grand_order_total" xsi:type="string">15</item> + <item name="grand_invoice_total" xsi:type="string">15</item> + </field> + </dataset> + <dataset name="partial_invoice"> <field name="0" xsi:type="array"> <item name="grand_order_total" xsi:type="string">210</item> diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/CloseOrderTest.php b/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/CloseOrderTest.php new file mode 100644 index 0000000000000000000000000000000000000000..1594cad95eff98633a9b6b1e47a4705912059370 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/CloseOrderTest.php @@ -0,0 +1,45 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Sales\Test\TestCase; + +use Magento\Mtf\TestCase\Scenario; + +/** + * Preconditions: + * 1. Order is placed. + * + * Steps: + * 1. Log in to Admin. + * 2. Go to Sales > Orders page. + * 3. Open order. + * 4. Click 'Ship' button and submit shipment. + * 5. Click 'Invoice' button. + * 6. Select Amount=Capture Online. + * 7. Click 'Submit Invoice' button. + * 8. Perform assertions. + * + * @group Order_Management + * @ZephyrId MAGETWO-13015, MAGETWO-13020 + */ +class CloseOrderTest extends Scenario +{ + /* tags */ + const MVP = 'yes'; + const TEST_TYPE = '3rd_party_test'; + const SEVERITY = 'S0'; + /* end tags */ + + /** + * Close order. + * + * @return void + */ + public function test() + { + $this->executeScenario(); + } +} diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/CreateOnlineCreditMemoTest.php b/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/CreateOnlineCreditMemoTest.php new file mode 100644 index 0000000000000000000000000000000000000000..e11e1391a10e3442e1a92230615d7f1c0a2fbc4d --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/CreateOnlineCreditMemoTest.php @@ -0,0 +1,41 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Sales\Test\TestCase; + +use Magento\Mtf\TestCase\Scenario; + +/** + * Preconditions: + * 1. Complete a sales order with online payment method. + * + * Steps: + * 1. Log in to Admin. + * 2. Open order from preconditions. + * 3. Open created invoice. + * 3. Create credit memo. + * 4. Perform assertions. + * + * @group Order_Management + * @ZephyrId MAGETWO-13059 + */ +class CreateOnlineCreditMemoTest extends Scenario +{ + /* tags */ + const MVP = 'yes'; + const TEST_TYPE = '3rd_party_test'; + const SEVERITY = 'S0'; + /* end tags */ + + /** + * Runs test for online credit memo creation for order placed with online payment method. + * + * @return void + */ + public function test() + { + $this->executeScenario(); + } +} diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/GridFilteringTest.xml b/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/GridFilteringTest.xml index b4c3a7568a2a1dd4fb62fe0d013b6425d372d27d..78c2676765418ebcbbae5ed21a8b0b0cb9ab1da8 100644 --- a/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/GridFilteringTest.xml +++ b/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/GridFilteringTest.xml @@ -8,6 +8,7 @@ <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd"> <testCase name="Magento\Ui\Test\TestCase\GridFilteringTest" summary="Grid UI Component Filtering" ticketId="MAGETWO-41328"> <variation name="SalesOrderGridFiltering"> + <data name="tag" xsi:type="string">severity:S2</data> <data name="tag" xsi:type="string">stable:no</data> <data name="description" xsi:type="string">Verify sales order grid filtering</data> <data name="steps" xsi:type="array"> @@ -33,6 +34,7 @@ <constraint name="\Magento\Ui\Test\Constraint\AssertGridFiltering"/> </variation> <variation name="SalesInvoiceGridFiltering"> + <data name="tag" xsi:type="string">severity:S3</data> <data name="description" xsi:type="string">Verify sales invoice grid filtering</data> <data name="steps" xsi:type="array"> <item name="0" xsi:type="string">Magento\Sales\Test\TestStep\CreateInvoiceStep</item> @@ -56,6 +58,7 @@ <constraint name="Magento\Ui\Test\Constraint\AssertGridFiltering"/> </variation> <variation name="SalesShipmentGridFiltering"> + <data name="tag" xsi:type="string">severity:S3</data> <data name="description" xsi:type="string">Verify sales shipment grid filtering</data> <data name="steps" xsi:type="array"> <item name="0" xsi:type="string">Magento\Sales\Test\TestStep\CreateShipmentStep</item> @@ -79,6 +82,7 @@ <constraint name="Magento\Ui\Test\Constraint\AssertGridFiltering"/> </variation> <variation name="SalesCreditMemoGridFiltering"> + <data name="tag" xsi:type="string">severity:S3</data> <data name="description" xsi:type="string">Verify sales credit memo grid filtering</data> <data name="steps" xsi:type="array"> <item name="0" xsi:type="array"> diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/GridFullTextSearchTest.xml b/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/GridFullTextSearchTest.xml index 0979d0dcbff250a7f0bdb2d5151f60004f72efd0..86278c52a1e26f28c82b799de7a1f45a1f4273e9 100644 --- a/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/GridFullTextSearchTest.xml +++ b/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/GridFullTextSearchTest.xml @@ -8,7 +8,7 @@ <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd"> <testCase name="Magento\Ui\Test\TestCase\GridFullTextSearchTest" summary="Grid UI Component Full Text Search" ticketId="MAGETWO-41023"> <variation name="SalesOrderGridFullTextSearch"> - <data name="tag" xsi:type="string">stable:no</data> + <data name="tag" xsi:type="string">severity:S2, stable:no</data> <data name="description" xsi:type="string">Verify sales order grid full text search</data> <data name="steps" xsi:type="array"> <item name="0" xsi:type="string">-</item> @@ -24,7 +24,7 @@ <constraint name="Magento\Ui\Test\Constraint\AssertGridFullTextSearch"/> </variation> <variation name="SalesInvoiceGridFullTextSearch"> - <data name="tag" xsi:type="string">stable:no</data> + <data name="tag" xsi:type="string">severity:S3, stable:no</data> <data name="description" xsi:type="string">Verify sales invoice grid full text search</data> <data name="steps" xsi:type="array"> <item name="0" xsi:type="string">Magento\Sales\Test\TestStep\CreateInvoiceStep</item> @@ -41,6 +41,7 @@ <constraint name="Magento\Ui\Test\Constraint\AssertGridFullTextSearch"/> </variation> <variation name="SalesShipmentGridFullTextSearch"> + <data name="tag" xsi:type="string">severity:S3</data> <data name="description" xsi:type="string">Verify sales shipment grid full text search</data> <data name="steps" xsi:type="array"> <item name="0" xsi:type="string">Magento\Sales\Test\TestStep\CreateShipmentStep</item> @@ -57,7 +58,7 @@ <constraint name="Magento\Ui\Test\Constraint\AssertGridFullTextSearch"/> </variation> <variation name="SalesCreditMemoGridFullTextSearch"> - <data name="tag" xsi:type="string">stable:no</data> + <data name="tag" xsi:type="string">severity:S3, stable:no</data> <data name="description" xsi:type="string">Verify sales credit memo grid full text search</data> <data name="steps" xsi:type="array"> <item name="0" xsi:type="array"> diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/GridSortingTest.xml b/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/GridSortingTest.xml index f82f232625841ddfdd77e66812970a4de31efea6..75d5c7fd09d95200255119b7b00c7167eb8c0142 100644 --- a/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/GridSortingTest.xml +++ b/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/GridSortingTest.xml @@ -8,6 +8,7 @@ <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd"> <testCase name="Magento\Ui\Test\TestCase\GridSortingTest" summary="Grid UI Component Sorting" ticketId="MAGETWO-41328"> <variation name="SalesOrderGridSorting"> + <data name="tag" xsi:type="string">severity:S2</data> <data name="tag" xsi:type="string">to_maintain:yes</data> <data name="description" xsi:type="string">Verify sales order grid storting</data> <data name="steps" xsi:type="array"> @@ -27,6 +28,7 @@ <constraint name="\Magento\Ui\Test\Constraint\AssertGridSorting"/> </variation> <variation name="SalesInvoiceGridSorting"> + <data name="tag" xsi:type="string">severity:S3</data> <data name="tag" xsi:type="string">to_maintain:yes</data> <data name="description" xsi:type="string">Verify sales invoince grid storting</data> <data name="steps" xsi:type="array"> @@ -45,6 +47,7 @@ <constraint name="\Magento\Ui\Test\Constraint\AssertGridSorting"/> </variation> <variation name="SalesShipmentGridSorting"> + <data name="tag" xsi:type="string">severity:S3</data> <data name="tag" xsi:type="string">to_maintain:yes</data> <data name="description" xsi:type="string">Verify sales shipment grid storting</data> <data name="steps" xsi:type="array"> @@ -63,6 +66,7 @@ <constraint name="\Magento\Ui\Test\Constraint\AssertGridSorting"/> </variation> <variation name="SalesCreditMemoGridSorting"> + <data name="tag" xsi:type="string">severity:S3</data> <data name="tag" xsi:type="string">to_maintain:yes</data> <data name="description" xsi:type="string">Verify sales credit memo grid storting</data> <data name="steps" xsi:type="array"> diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/MoveRecentlyComparedProductsOnOrderPageTest.php b/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/MoveRecentlyComparedProductsOnOrderPageTest.php index 49487ff1b2e8ea9b9e23543a44a2878b797c4f2c..a501ec3cd228d8c60a5225027719e463dbf6c688 100644 --- a/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/MoveRecentlyComparedProductsOnOrderPageTest.php +++ b/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/MoveRecentlyComparedProductsOnOrderPageTest.php @@ -142,9 +142,10 @@ class MoveRecentlyComparedProductsOnOrderPageTest extends Injectable * * @param Customer $customer * @param string $products + * @param bool $productsIsConfigured * @return array */ - public function test(Customer $customer, $products) + public function test(Customer $customer, $products, $productsIsConfigured = false) { // Preconditions // Create product @@ -168,6 +169,6 @@ class MoveRecentlyComparedProductsOnOrderPageTest extends Injectable $activitiesBlock->getRecentlyComparedProductsBlock()->addProductsToOrder($products); $activitiesBlock->updateChanges(); - return ['products' => $products, 'productsIsConfigured' => false]; + return ['products' => $products, 'productsIsConfigured' => $productsIsConfigured]; } } diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/MoveRecentlyComparedProductsOnOrderPageTest.xml b/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/MoveRecentlyComparedProductsOnOrderPageTest.xml index 601f550e4588bfd3c613ef8a50e8615174b298ae..76282ff3eec53867d257029f5184b941899ac2db 100644 --- a/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/MoveRecentlyComparedProductsOnOrderPageTest.xml +++ b/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/MoveRecentlyComparedProductsOnOrderPageTest.xml @@ -7,17 +7,10 @@ --> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd"> <testCase name="Magento\Sales\Test\TestCase\MoveRecentlyComparedProductsOnOrderPageTest" summary="Add Products to Order from Recently Compared Products Section" ticketId="MAGETWO-28109"> - <variation name="MoveRecentlyComparedProductsOnOrderPageTestVariation1"> - <data name="tag" xsi:type="string">stable:no</data> + <variation name="MoveRecentlyComparedProductsOnOrderPageTestVariationWithSimpleProduct1"> <data name="products/0" xsi:type="string">catalogProductSimple::default</data> <data name="products/1" xsi:type="string">catalogProductSimple::default</data> <constraint name="Magento\Sales\Test\Constraint\AssertProductInItemsOrderedGrid" /> </variation> - <variation name="MoveRecentlyComparedProductsOnOrderPageTestVariation2"> - <data name="tag" xsi:type="string">to_maintain:yes</data> - <data name="products/0" xsi:type="string">configurableProduct::configurable_with_qty_1</data> - <data name="products/1" xsi:type="string">configurableProduct::configurable_with_qty_1</data> - <constraint name="Magento\Sales\Test\Constraint\AssertProductInItemsOrderedGrid" /> - </variation> </testCase> </config> diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/TestStep/AddProductsStep.php b/dev/tests/functional/tests/app/Magento/Sales/Test/TestStep/AddProductsStep.php index 594f7098e45592f61ba83544f80a742f9eeb5b2e..0caeb235119c86debf0cc6de86e69cbb0f6b3883 100644 --- a/dev/tests/functional/tests/app/Magento/Sales/Test/TestStep/AddProductsStep.php +++ b/dev/tests/functional/tests/app/Magento/Sales/Test/TestStep/AddProductsStep.php @@ -6,44 +6,55 @@ namespace Magento\Sales\Test\TestStep; +use Magento\Mtf\Fixture\FixtureFactory; use Magento\Sales\Test\Page\Adminhtml\OrderCreateIndex; use Magento\Mtf\TestStep\TestStepInterface; /** - * Class AddProductsStep - * Add Products Step + * Add Products Step. */ class AddProductsStep implements TestStepInterface { /** - * Sales order create index page + * Sales order create index page. * * @var OrderCreateIndex */ - protected $orderCreateIndex; + private $orderCreateIndex; /** - * Array products + * Array products. * * @var array */ - protected $products; + private $products; + + /** + * Fixture factory. + * + * @var FixtureFactory + */ + private $fixtureFactory; /** - * @constructor * @param OrderCreateIndex $orderCreateIndex + * @param FixtureFactory $fixtureFactory * @param array $products */ - public function __construct(OrderCreateIndex $orderCreateIndex, array $products) - { + public function __construct( + OrderCreateIndex $orderCreateIndex, + FixtureFactory $fixtureFactory, + array $products + ) { $this->orderCreateIndex = $orderCreateIndex; $this->products = $products; + $this->fixtureFactory = $fixtureFactory; } /** - * Add product to sales + * Add product to sales. * - * @return void + * @return array */ public function run() { @@ -58,5 +69,8 @@ class AddProductsStep implements TestStepInterface } $createBlock->addSelectedProductsToOrder(); $createBlock->getTemplateBlock()->waitLoader(); + + $cart['data']['items'] = ['products' => $this->products]; + return ['cart' => $this->fixtureFactory->createByCode('cart', $cart)]; } } diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/TestStep/SelectPaymentMethodForOrderStep.php b/dev/tests/functional/tests/app/Magento/Sales/Test/TestStep/SelectPaymentMethodForOrderStep.php index c05dfc4fac2dcbb8bea98ec39c705c9ff419e559..fa0a62d79625e1e23602aed9f37ab153f8d2ee76 100644 --- a/dev/tests/functional/tests/app/Magento/Sales/Test/TestStep/SelectPaymentMethodForOrderStep.php +++ b/dev/tests/functional/tests/app/Magento/Sales/Test/TestStep/SelectPaymentMethodForOrderStep.php @@ -6,7 +6,6 @@ namespace Magento\Sales\Test\TestStep; -use Magento\Mtf\Fixture\FixtureFactory; use Magento\Sales\Test\Page\Adminhtml\OrderCreateIndex; use Magento\Mtf\TestStep\TestStepInterface; use Magento\Payment\Test\Fixture\CreditCard; @@ -38,29 +37,22 @@ class SelectPaymentMethodForOrderStep implements TestStepInterface private $creditCard; /** - * @constructor * @param OrderCreateIndex $orderCreateIndex * @param array $payment - * @param FixtureFactory $fixtureFactory - * @param string $creditCardClass - * @param array|CreditCard|null $creditCard + * @param CreditCard|null $creditCard */ public function __construct( OrderCreateIndex $orderCreateIndex, array $payment, - FixtureFactory $fixtureFactory, - $creditCardClass = 'credit_card', - array $creditCard = null + CreditCard $creditCard = null ) { $this->orderCreateIndex = $orderCreateIndex; $this->payment = $payment; - if (isset($creditCard['dataset'])) { - $this->creditCard = $fixtureFactory->createByCode($creditCardClass, ['dataset' => $creditCard['dataset']]); - } + $this->creditCard = $creditCard; } /** - * Fill Payment data + * Fill Payment data. * * @return void */ diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/etc/di.xml b/dev/tests/functional/tests/app/Magento/Sales/Test/etc/di.xml index f42c97e1a6614a927da685f9cd5e1f8c84ff0c32..e9670a1d727f72b2d7ea853fd38e4b0a2bb1c218 100644 --- a/dev/tests/functional/tests/app/Magento/Sales/Test/etc/di.xml +++ b/dev/tests/functional/tests/app/Magento/Sales/Test/etc/di.xml @@ -11,6 +11,11 @@ <argument name="severity" xsi:type="string">S0</argument> </arguments> </type> + <type name="Magento\Sales\Test\Constraint\AssertInvoiceStatusInOrdersGrid"> + <arguments> + <argument name="severity" xsi:type="string">S1</argument> + </arguments> + </type> <type name="Magento\Sales\Test\Constraint\AssertOrderStatusDuplicateStatus"> <arguments> <argument name="severity" xsi:type="string">S0</argument> @@ -86,4 +91,24 @@ <argument name="severity" xsi:type="string">S0</argument> </arguments> </type> + <type name="Magento\Sales\Test\Constraint\AssertOnlineInvoiceCannotBeCreated"> + <arguments> + <argument name="severity" xsi:type="string">S1</argument> + </arguments> + </type> + <type name="Magento\Sales\Test\Constraint\AssertOrderPaymentInformation"> + <arguments> + <argument name="severity" xsi:type="string">S1</argument> + </arguments> + </type> + <type name="Magento\Sales\Test\Constraint\AssertOnlineInvoiceCannotBeCreated"> + <arguments> + <argument name="severity" xsi:type="string">S1</argument> + </arguments> + </type> + <type name="Magento\Sales\Test\Constraint\AssertOrderStatusIsCanceled"> + <arguments> + <argument name="severity" xsi:type="string">S0</argument> + </arguments> + </type> </config> diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/etc/testcase.xml b/dev/tests/functional/tests/app/Magento/Sales/Test/etc/testcase.xml index 030b0f4f32df0eacd76c99cbe55537df1c734cf5..fa4329137b0272a5ae59cefdf217baa894c2cd28 100644 --- a/dev/tests/functional/tests/app/Magento/Sales/Test/etc/testcase.xml +++ b/dev/tests/functional/tests/app/Magento/Sales/Test/etc/testcase.xml @@ -86,4 +86,33 @@ <step name="submitOrder" module="Magento_Sales" next="createInvoice" /> <step name="createInvoice" module="Magento_Sales" /> </scenario> + <scenario name="CreateOnlineCreditMemoTest" firstStep="setupConfiguration"> + <step name="setupConfiguration" module="Magento_Config" next="createProducts" /> + <step name="createProducts" module="Magento_Catalog" next="addProductsToTheCart" /> + <step name="addProductsToTheCart" module="Magento_Checkout" next="createCustomer" /> + <step name="createCustomer" module="Magento_Customer" next="proceedToCheckout" /> + <step name="proceedToCheckout" module="Magento_Checkout" next="selectCheckoutMethod" /> + <step name="selectCheckoutMethod" module="Magento_Checkout" next="fillShippingAddress" /> + <step name="fillShippingAddress" module="Magento_Checkout" next="fillShippingMethod" /> + <step name="fillShippingMethod" module="Magento_Checkout" next="selectPaymentMethod" /> + <step name="selectPaymentMethod" module="Magento_Checkout" next="placeOrder" /> + <step name="placeOrder" module="Magento_Checkout" next="createInvoice" /> + <step name="createInvoice" module="Magento_Sales" next="createOnlineCreditMemo" /> + <step name="createOnlineCreditMemo" module="Magento_Sales" /> + </scenario> + <scenario name="CloseOrderTest" firstStep="setupConfiguration"> + <step name="setupConfiguration" module="Magento_Config" next="createProducts" /> + <step name="createProducts" module="Magento_Catalog" next="createTaxRule" /> + <step name="createTaxRule" module="Magento_Tax" next="addProductsToTheCart" /> + <step name="addProductsToTheCart" module="Magento_Checkout" next="proceedToCheckout" /> + <step name="proceedToCheckout" module="Magento_Checkout" next="createCustomer" /> + <step name="createCustomer" module="Magento_Customer" next="selectCheckoutMethod" /> + <step name="selectCheckoutMethod" module="Magento_Checkout" next="fillShippingAddress"/> + <step name="fillShippingAddress" module="Magento_Checkout" next="fillShippingMethod" /> + <step name="fillShippingMethod" module="Magento_Checkout" next="selectPaymentMethod" /> + <step name="selectPaymentMethod" module="Magento_Checkout" next="placeOrder" /> + <step name="placeOrder" module="Magento_Checkout" next="createInvoice" /> + <step name="createInvoice" module="Magento_Sales" next="createShipment" /> + <step name="createShipment" module="Magento_Sales" /> + </scenario> </config> diff --git a/dev/tests/functional/tests/app/Magento/Shipping/Test/Constraint/AssertCityBasedShippingRateChanged.php b/dev/tests/functional/tests/app/Magento/Shipping/Test/Constraint/AssertCityBasedShippingRateChanged.php new file mode 100644 index 0000000000000000000000000000000000000000..a10b47a2f9950f311d4c8ebcbdd3babb46faf6a8 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Shipping/Test/Constraint/AssertCityBasedShippingRateChanged.php @@ -0,0 +1,50 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Shipping\Test\Constraint; + +use Magento\Checkout\Test\Page\CheckoutOnepage; +use Magento\Mtf\Constraint\AbstractConstraint; + +/** + * Check that Shipping rate changes due to City change. + */ +class AssertCityBasedShippingRateChanged extends AbstractConstraint +{ + /** + * Assert that Shipping rate changed on City change. + * + * @param CheckoutOnepage $checkoutOnepage + * @param array $shippingMethod + * @param bool $isShippingAvailable + * @return void + */ + public function processAssert(CheckoutOnepage $checkoutOnepage, $shippingMethod, $isShippingAvailable) + { + if ($isShippingAvailable) { + \PHPUnit_Framework_Assert::assertTrue( + $checkoutOnepage->getShippingMethodBlock()->isLoaderAppeared(), + 'Shipping rate has not been changed.' + ); + } + $shippingAvaialability = $isShippingAvailable ? 'avaiable' : 'unavailable'; + \PHPUnit_Framework_Assert::assertEquals( + $isShippingAvailable, + $checkoutOnepage->getShippingMethodBlock()->isShippingMethodAvaiable($shippingMethod), + "Shipping rates for {$shippingMethod['shipping_service']} should be $shippingAvaialability." + ); + } + + /** + * Returns a string representation of successful assertion. + * + * @return string + */ + public function toString() + { + return "Shipping rate has been changed."; + } +} diff --git a/dev/tests/functional/tests/app/Magento/Shipping/Test/TestCase/CityBasedShippingRateTest.php b/dev/tests/functional/tests/app/Magento/Shipping/Test/TestCase/CityBasedShippingRateTest.php new file mode 100644 index 0000000000000000000000000000000000000000..294cf129c607308425fc6e9a3574b047d8b2ff18 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Shipping/Test/TestCase/CityBasedShippingRateTest.php @@ -0,0 +1,44 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Shipping\Test\TestCase; + +use Magento\Mtf\TestCase\Scenario; + +/** + * Preconditions: + * 1. Configure shipping method. + * 2. Create products. + * 3. Create and setup customer. + * + * Steps: + * 1. Go to Frontend. + * 2. Add products to the cart. + * 3. Click the 'Proceed to Checkout' button. + * 4. Fill shipping information. + * 5. Perform assertions. + * + * @group Shipping + * @ZephyrId MAGETWO-56124 + */ +class CityBasedShippingRateTest extends Scenario +{ + /* tags */ + const MVP = 'yes'; + const TEST_TYPE = '3rd_party_test'; + const SEVERITY = 'S1'; + /* end tags */ + + /** + * Runs City Based Shipping Rate test. + * + * @return void + */ + public function test() + { + $this->executeScenario(); + } +} diff --git a/dev/tests/functional/tests/app/Magento/Shipping/Test/TestStep/FillShippingAddressesStep.php b/dev/tests/functional/tests/app/Magento/Shipping/Test/TestStep/FillShippingAddressesStep.php new file mode 100644 index 0000000000000000000000000000000000000000..8a0f5ea7e269d71234e3cdacbc8c570c6bb040ed --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Shipping/Test/TestStep/FillShippingAddressesStep.php @@ -0,0 +1,98 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Shipping\Test\TestStep; + +use Magento\Mtf\Fixture\FixtureFactory; +use Magento\Mtf\TestStep\TestStepInterface; +use Magento\Customer\Test\Fixture\Address; +use Magento\Checkout\Test\Page\CheckoutOnepage; +use Magento\Shipping\Test\Constraint\AssertCityBasedShippingRateChanged; + +/** + * Fill shipping addresses and assert rates relouding. + */ +class FillShippingAddressesStep implements TestStepInterface +{ + /** + * Onepage checkout page. + * + * @var CheckoutOnepage + */ + private $checkoutOnepage; + + /** + * Address fixture. + * + * @var Address[] + */ + private $shippingAddresses; + + /** + * Assert City based Shipping rate. + * + * @var array + */ + private $assertRate; + + /** + * @var array + */ + private $isShippingAvailable; + + /** + * Shipping method. + * + * @var array + */ + private $shippingMethod; + + /** + * @param CheckoutOnepage $checkoutOnepage + * @param FixtureFactory $fixtureFactory + * @param AssertCityBasedShippingRateChanged $assertRate + * @param array $shippingMethod + * @param array $shippingAddresses + * @param array $clearShippingAddress + * @param array $isShippingAvailable + */ + public function __construct( + CheckoutOnepage $checkoutOnepage, + FixtureFactory $fixtureFactory, + AssertCityBasedShippingRateChanged $assertRate, + array $shippingMethod, + array $shippingAddresses, + array $clearShippingAddress, + array $isShippingAvailable + ) { + $this->checkoutOnepage = $checkoutOnepage; + $this->assertRate = $assertRate; + + foreach ($shippingAddresses as $address) { + $data = array_merge($clearShippingAddress, $address); + $this->shippingAddresses[] = $fixtureFactory->createByCode('address', ['data' => $data]); + } + $this->isShippingAvailable = $isShippingAvailable; + $this->shippingMethod = $shippingMethod; + } + + /** + * Fill shipping address and assert if the shipping rates is reloaded. + * + * @return void + */ + public function run() + { + foreach ($this->shippingAddresses as $key => $shippingAddress) { + $this->checkoutOnepage->getShippingBlock()->fill($shippingAddress); + $this->assertRate->processAssert( + $this->checkoutOnepage, + $this->shippingMethod, + $this->isShippingAvailable[$key] + ); + } + } +} diff --git a/dev/tests/functional/tests/app/Magento/Shipping/Test/etc/di.xml b/dev/tests/functional/tests/app/Magento/Shipping/Test/etc/di.xml new file mode 100644 index 0000000000000000000000000000000000000000..d0d24b810fb44bd0caa7dec1e6b302006904b102 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Shipping/Test/etc/di.xml @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + --> +<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd"> + <type name="Magento\Shipping\Test\Constraint\AssertCityBasedShippingRateChanged"> + <arguments> + <argument name="severity" xsi:type="string">S1</argument> + </arguments> + </type> +</config> diff --git a/dev/tests/functional/tests/app/Magento/Shipping/Test/etc/testcase.xml b/dev/tests/functional/tests/app/Magento/Shipping/Test/etc/testcase.xml new file mode 100644 index 0000000000000000000000000000000000000000..b1fabed80066b6933f58f89e69aa59ea20042d65 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Shipping/Test/etc/testcase.xml @@ -0,0 +1,18 @@ +<?xml version="1.0"?> +<!-- +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/Magento/Mtf/TestCase/etc/testcase.xsd"> + <scenario name="CityBasedShippingRateTest" firstStep="setupConfiguration"> + <step name="setupConfiguration" module="Magento_Config" next="createProducts" /> + <step name="createProducts" module="Magento_Catalog" next="addProductsToTheCart" /> + <step name="addProductsToTheCart" module="Magento_Checkout" next="proceedToCheckout" /> + <step name="proceedToCheckout" module="Magento_Checkout" next="createCustomer" /> + <step name="createCustomer" module="Magento_Customer" next="selectCheckoutMethod" /> + <step name="selectCheckoutMethod" module="Magento_Checkout" next="fillShippingAddresses" /> + <step name="fillShippingAddresses" module="Magento_Shipping" /> + </scenario> +</config> diff --git a/dev/tests/functional/tests/app/Magento/Ui/Test/Block/Adminhtml/DataGrid.php b/dev/tests/functional/tests/app/Magento/Ui/Test/Block/Adminhtml/DataGrid.php index c5968c8e936f8a5bead20016d9c70d699b8c1a0c..b913a1c6804e63b136fdf1b497071dd173f35088 100644 --- a/dev/tests/functional/tests/app/Magento/Ui/Test/Block/Adminhtml/DataGrid.php +++ b/dev/tests/functional/tests/app/Magento/Ui/Test/Block/Adminhtml/DataGrid.php @@ -389,6 +389,8 @@ class DataGrid extends Grid } /** + * Sort grid by column. + * * @param string $columnLabel */ public function sortByColumn($columnLabel) @@ -396,6 +398,7 @@ class DataGrid extends Grid $this->waitLoader(); $this->getTemplateBlock()->waitForElementNotVisible($this->loader); $this->_rootElement->find(sprintf($this->columnHeader, $columnLabel), Locator::SELECTOR_XPATH)->click(); + $this->waitLoader(); } /** diff --git a/dev/tests/functional/tests/app/Magento/Ui/Test/TestCase/GridFilteringTest.php b/dev/tests/functional/tests/app/Magento/Ui/Test/TestCase/GridFilteringTest.php index 4b923dd4344a93be0e2bf3491c30eecf823f76ba..7a3da9b3fa7cd1d74bf0cc707f8b0be2ddc1214e 100644 --- a/dev/tests/functional/tests/app/Magento/Ui/Test/TestCase/GridFilteringTest.php +++ b/dev/tests/functional/tests/app/Magento/Ui/Test/TestCase/GridFilteringTest.php @@ -28,6 +28,7 @@ use Magento\Ui\Test\Block\Adminhtml\DataGrid; class GridFilteringTest extends Injectable { /* tags */ + const SEVERITY = 'S2'; const STABLE = 'no'; const MVP = 'no'; /* end tags */ diff --git a/dev/tests/functional/tests/app/Magento/Ui/Test/TestCase/GridFullTextSearchTest.php b/dev/tests/functional/tests/app/Magento/Ui/Test/TestCase/GridFullTextSearchTest.php index 510d2d61c0acd2100b295ee1422015b1833d9c36..a16d61e112a83a2b008f49d9b95e072aec06d7ec 100644 --- a/dev/tests/functional/tests/app/Magento/Ui/Test/TestCase/GridFullTextSearchTest.php +++ b/dev/tests/functional/tests/app/Magento/Ui/Test/TestCase/GridFullTextSearchTest.php @@ -28,6 +28,7 @@ use Magento\Ui\Test\Block\Adminhtml\DataGrid; class GridFullTextSearchTest extends Injectable { /* tags */ + const SEVERITY = 'S2'; const STABLE = 'no'; const MVP = 'no'; /* end tags */ diff --git a/dev/tests/functional/tests/app/Magento/Ui/Test/TestCase/GridSortingTest.php b/dev/tests/functional/tests/app/Magento/Ui/Test/TestCase/GridSortingTest.php index d1f543c7b989137c209bdbd63e6c4755644e9e8b..319ef215bcb142677d847a2c3e6ce0af6ba80199 100644 --- a/dev/tests/functional/tests/app/Magento/Ui/Test/TestCase/GridSortingTest.php +++ b/dev/tests/functional/tests/app/Magento/Ui/Test/TestCase/GridSortingTest.php @@ -28,6 +28,7 @@ use Magento\Ui\Test\Block\Adminhtml\DataGrid; class GridSortingTest extends Injectable { /* tags */ + const SEVERITY = 'S2'; const MVP = 'no'; /* end tags */ diff --git a/dev/tests/functional/tests/app/Magento/Ui/Test/etc/di.xml b/dev/tests/functional/tests/app/Magento/Ui/Test/etc/di.xml new file mode 100644 index 0000000000000000000000000000000000000000..8982c1966306252a5d0113ac49e8efdb011e8ddb --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Ui/Test/etc/di.xml @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + --> +<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd"> + <type name="Magento\Ui\Test\Constraint\AssertGridFiltering"> + <arguments> + <argument name="severity" xsi:type="string">S2</argument> + </arguments> + </type> + <type name="Magento\Ui\Test\Constraint\AssertGridFullTextSearch"> + <arguments> + <argument name="severity" xsi:type="string">S2</argument> + </arguments> + </type> + <type name="Magento\Ui\Test\Constraint\AssertGridSorting"> + <arguments> + <argument name="severity" xsi:type="string">S2</argument> + </arguments> + </type> +</config> diff --git a/dev/tests/functional/tests/app/Magento/Vault/Test/TestCase/DeleteSavedCreditCardTest.php b/dev/tests/functional/tests/app/Magento/Vault/Test/TestCase/DeleteSavedCreditCardTest.php index e6462e4697aa612c1239b92b3c7b7e847bd252ba..37aa17e95b2ff4803d95d7865f4892190f940e15 100644 --- a/dev/tests/functional/tests/app/Magento/Vault/Test/TestCase/DeleteSavedCreditCardTest.php +++ b/dev/tests/functional/tests/app/Magento/Vault/Test/TestCase/DeleteSavedCreditCardTest.php @@ -6,6 +6,7 @@ namespace Magento\Vault\Test\TestCase; use Magento\Checkout\Test\Page\CheckoutOnepage; +use Magento\Customer\Test\Fixture\Customer; use Magento\Mtf\ObjectManager; use Magento\Mtf\TestCase\Injectable; use Magento\Vault\Test\Constraint\AssertCreditCardNotPresentOnCheckout; @@ -95,7 +96,7 @@ class DeleteSavedCreditCardTest extends Injectable if ($key >= 2) { // if this order will be placed via stored credit card $this->useSavedCreditCard($payment['vault']); } else { - $this->selectPaymentMethod($payment, $payment['creditCardClass'], $payment['creditCard']); + $this->selectPaymentMethod($payment, $payment['creditCard']); $this->saveCreditCard($payment, $creditCardSave); } $this->placeOrder(); @@ -105,8 +106,7 @@ class DeleteSavedCreditCardTest extends Injectable for ($i = 2; $i < $paymentsCount; $i++) { $deletedCard = $this->deleteCreditCardFromMyAccount( $customer, - $payments[$i]['creditCard'], - $payments[$i]['creditCardClass'] + $payments[$i]['creditCard'] ); $this->addToCart($products); $this->proceedToCheckout(); @@ -119,9 +119,12 @@ class DeleteSavedCreditCardTest extends Injectable } /** + * Setup configuration step. + * * @param $configData + * @return void */ - protected function setupConfiguration($configData) + private function setupConfiguration($configData) { $setupConfigurationStep = ObjectManager::getInstance()->create( \Magento\Config\Test\TestStep\SetupConfigurationStep::class, @@ -132,7 +135,7 @@ class DeleteSavedCreditCardTest extends Injectable } /** - * Create products + * Create products step. * * @param string $productList * @return array @@ -149,6 +152,8 @@ class DeleteSavedCreditCardTest extends Injectable } /** + * Add to cart step. + * * @param array $products * @return void */ @@ -162,6 +167,8 @@ class DeleteSavedCreditCardTest extends Injectable } /** + * Proceed to checkout step. + * * @return void */ protected function proceedToCheckout() @@ -173,7 +180,10 @@ class DeleteSavedCreditCardTest extends Injectable } /** + * Create customer step. + * * @param array $customer + * @return Customer */ protected function createCustomer(array $customer) { @@ -186,8 +196,11 @@ class DeleteSavedCreditCardTest extends Injectable } /** + * Select Checkout method step. + * * @param $checkoutMethod * @param $customer + * @return void */ protected function selectCheckoutMethod($checkoutMethod, $customer) { @@ -202,7 +215,10 @@ class DeleteSavedCreditCardTest extends Injectable } /** + * Fill shipping address step. + * * @param array $shippingAddress + * @return void */ protected function fillShippingAddress(array $shippingAddress) { @@ -214,9 +230,10 @@ class DeleteSavedCreditCardTest extends Injectable } /** - * Add products to cart + * Add products to cart. * * @param array $shipping + * @return void */ protected function fillShippingMethod(array $shipping) { @@ -228,17 +245,18 @@ class DeleteSavedCreditCardTest extends Injectable } /** + * Select payment method step. + * * @param array $payment - * @param $creditCardClass * @param array $creditCard + * @return void */ - protected function selectPaymentMethod(array $payment, $creditCardClass, array $creditCard) + protected function selectPaymentMethod(array $payment, array $creditCard) { $selectPaymentMethodStep = ObjectManager::getInstance()->create( \Magento\Checkout\Test\TestStep\SelectPaymentMethodStep::class, [ 'payment' => $payment, - 'creditCardClass' => $creditCardClass, 'creditCard' => $creditCard, ] ); @@ -250,6 +268,7 @@ class DeleteSavedCreditCardTest extends Injectable * * @param $payment * @param $creditCardSave + * @return void */ protected function saveCreditCard($payment, $creditCardSave) { @@ -264,6 +283,8 @@ class DeleteSavedCreditCardTest extends Injectable } /** + * Fill billing information step. + * * @return void */ protected function fillBillingInformation() @@ -275,6 +296,8 @@ class DeleteSavedCreditCardTest extends Injectable } /** + * Place order step. + * * @return void */ protected function placeOrder() @@ -286,7 +309,10 @@ class DeleteSavedCreditCardTest extends Injectable } /** + * Use saved credit card step. + * * @param $payment + * @return void */ protected function useSavedCreditCard($payment) { @@ -298,18 +324,19 @@ class DeleteSavedCreditCardTest extends Injectable } /** + * Delete credit card from My Account step. + * * @param $customer * @param $creditCard - * @param $creditCardClass + * @return array */ - protected function deleteCreditCardFromMyAccount($customer, $creditCard, $creditCardClass) + protected function deleteCreditCardFromMyAccount($customer, $creditCard) { $deleteCreditCardFromMyAccountStep = ObjectManager::getInstance()->create( \Magento\Vault\Test\TestStep\DeleteCreditCardFromMyAccountStep::class, [ 'customer' => $customer, - 'creditCard' => $creditCard, - 'creditCardClass' => $creditCardClass + 'creditCard' => $creditCard ] ); $deletedCard = $deleteCreditCardFromMyAccountStep->run(); diff --git a/dev/tests/functional/tests/app/Magento/Vault/Test/TestCase/DeleteSavedCreditCardTest.xml b/dev/tests/functional/tests/app/Magento/Vault/Test/TestCase/DeleteSavedCreditCardTest.xml index 2cafc815fed1dfc1865d1f2627f536d1ba909563..c6daa6ac89d58c68f9edc9c7e9372780107f56a7 100644 --- a/dev/tests/functional/tests/app/Magento/Vault/Test/TestCase/DeleteSavedCreditCardTest.xml +++ b/dev/tests/functional/tests/app/Magento/Vault/Test/TestCase/DeleteSavedCreditCardTest.xml @@ -17,23 +17,29 @@ <data name="payments" xsi:type="array"> <item name="0" xsi:type="array"> <item name="method" xsi:type="string">braintree</item> - <item name="creditCardClass" xsi:type="string">credit_card_braintree</item> <item name="creditCard" xsi:type="array"> - <item name="dataset" xsi:type="string">visa_braintree</item> + <item name="dataset" xsi:type="string">visa_default</item> + <item name="data" xsi:type="array"> + <item name="payment_code" xsi:type="string">braintree</item> + </item> </item> </item> <item name="1" xsi:type="array"> <item name="method" xsi:type="string">payflowpro</item> - <item name="creditCardClass" xsi:type="string">credit_card</item> <item name="creditCard" xsi:type="array"> <item name="dataset" xsi:type="string">visa_alt</item> + <item name="data" xsi:type="array"> + <item name="payment_code" xsi:type="string">payment</item> + </item> </item> </item> <item name="2" xsi:type="array"> <item name="method" xsi:type="string">braintree</item> - <item name="creditCardClass" xsi:type="string">credit_card_braintree</item> <item name="creditCard" xsi:type="array"> - <item name="dataset" xsi:type="string">visa_braintree</item> + <item name="dataset" xsi:type="string">visa_default</item> + <item name="data" xsi:type="array"> + <item name="payment_code" xsi:type="string">braintree</item> + </item> </item> <item name="vault" xsi:type="array"> <item name="method" xsi:type="string">braintree_cc_vault</item> @@ -41,9 +47,11 @@ </item> <item name="3" xsi:type="array"> <item name="method" xsi:type="string">payflowpro</item> - <item name="creditCardClass" xsi:type="string">credit_card</item> <item name="creditCard" xsi:type="array"> <item name="dataset" xsi:type="string">visa_alt</item> + <item name="data" xsi:type="array"> + <item name="payment_code" xsi:type="string">payment</item> + </item> </item> <item name="vault" xsi:type="array"> <item name="method" xsi:type="string">payflowpro_cc_vault</item> diff --git a/dev/tests/functional/tests/app/Magento/Vault/Test/TestStep/CheckSaveCreditCardOptionStep.php b/dev/tests/functional/tests/app/Magento/Vault/Test/TestStep/CheckSaveCreditCardOptionStep.php index b0f33872103f27ffe00e2b1323574fa0fdc6b88a..eee0f1be86ef79198a7864df8be90e8a225ea840 100644 --- a/dev/tests/functional/tests/app/Magento/Vault/Test/TestStep/CheckSaveCreditCardOptionStep.php +++ b/dev/tests/functional/tests/app/Magento/Vault/Test/TestStep/CheckSaveCreditCardOptionStep.php @@ -36,28 +36,28 @@ class CheckSaveCreditCardOptionStep implements TestStepInterface private $payment; /** - * If vault is enabled for payment method. + * If 'Save for later use' checkbox is present in credit card form. * * @var null|bool */ - private $isVaultEnabled; + private $isVaultPresent; /** * @param CheckoutOnepage $checkoutOnepage * @param AssertSaveCreditCardOptionNotPresent $assertSaveCreditCardOptionNotPresent * @param array $payment - * @param null|bool $isVaultEnabled + * @param null|bool $isVaultPresent */ public function __construct( CheckoutOnepage $checkoutOnepage, AssertSaveCreditCardOptionNotPresent $assertSaveCreditCardOptionNotPresent, array $payment, - $isVaultEnabled = null + $isVaultPresent = null ) { $this->checkoutOnepage = $checkoutOnepage; $this->assertSaveCreditCardOptionNotPresent = $assertSaveCreditCardOptionNotPresent; $this->payment = $payment; - $this->isVaultEnabled = $isVaultEnabled; + $this->isVaultPresent = $isVaultPresent; } /** @@ -67,7 +67,7 @@ class CheckSaveCreditCardOptionStep implements TestStepInterface */ public function run() { - if ($this->isVaultEnabled === false) { + if ($this->isVaultPresent === false) { $this->assertSaveCreditCardOptionNotPresent->processAssert( $this->checkoutOnepage, $this->payment['method'] diff --git a/dev/tests/functional/tests/app/Magento/Vault/Test/TestStep/DeleteCreditCardFromMyAccountStep.php b/dev/tests/functional/tests/app/Magento/Vault/Test/TestStep/DeleteCreditCardFromMyAccountStep.php index c3cb46347dd8c50bfa372b84df66231086e054a5..f751108d28b16600c0b61050923174f81a98678c 100644 --- a/dev/tests/functional/tests/app/Magento/Vault/Test/TestStep/DeleteCreditCardFromMyAccountStep.php +++ b/dev/tests/functional/tests/app/Magento/Vault/Test/TestStep/DeleteCreditCardFromMyAccountStep.php @@ -7,86 +7,87 @@ namespace Magento\Vault\Test\TestStep; use Magento\Customer\Test\Fixture\Customer; use Magento\Customer\Test\Page\CustomerAccountIndex; -use Magento\Mtf\Fixture\FixtureFactory; -use Magento\Mtf\Fixture\InjectableFixture; use Magento\Mtf\ObjectManager; use Magento\Mtf\TestStep\TestStepInterface; +use Magento\Payment\Test\Fixture\CreditCard; use Magento\Vault\Test\Constraint\AssertStoredPaymentDeletedMessage; use Magento\Vault\Test\Page\StoredPaymentMethods; /** + * Delete credit card from My Account step. + * * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class DeleteCreditCardFromMyAccountStep implements TestStepInterface { /** + * Customer Fixture. + * * @var Customer */ private $customer; /** + * Object manager. + * * @var ObjectManager */ private $objectManager; /** + * Customer account index page. + * * @var CustomerAccountIndex */ private $customerAccountIndex; /** - * @var FixtureFactory - */ - private $fixtureFactory; - - /** - * @var \Magento\Mtf\Fixture\FixtureInterface + * Credit card fixture. + * + * @var CreditCard */ private $creditCard; /** + * Assert message of success deletion of stored payment method. + * * @var AssertStoredPaymentDeletedMessage */ private $assertStoredPaymentDeletedMessage; /** + * Stored payment methods page. + * * @var StoredPaymentMethods */ private $storedPaymentMethodsPage; /** - * DeleteCreditCardFromMyAccountStep constructor. - * * @param StoredPaymentMethods $storedPaymentMethodsPage * @param Customer $customer * @param ObjectManager $objectManager * @param CustomerAccountIndex $customerAccountIndex - * @param FixtureFactory $fixtureFactory * @param AssertStoredPaymentDeletedMessage $assertStoredPaymentDeletedMessage - * @param array $creditCard - * @param string $creditCardClass + * @param CreditCard $creditCard */ public function __construct( StoredPaymentMethods $storedPaymentMethodsPage, Customer $customer, ObjectManager $objectManager, CustomerAccountIndex $customerAccountIndex, - FixtureFactory $fixtureFactory, AssertStoredPaymentDeletedMessage $assertStoredPaymentDeletedMessage, - array $creditCard, - $creditCardClass = 'credit_card' + CreditCard $creditCard ) { $this->storedPaymentMethodsPage = $storedPaymentMethodsPage; $this->customer = $customer; $this->objectManager = $objectManager; $this->customerAccountIndex = $customerAccountIndex; - $this->fixtureFactory = $fixtureFactory; $this->assertStoredPaymentDeletedMessage = $assertStoredPaymentDeletedMessage; - $this->creditCard = $fixtureFactory->createByCode($creditCardClass, ['dataset' => $creditCard['dataset']]); + $this->creditCard = $creditCard; } /** - * @inheritdoc + * Run Delete credit card from My Account step. * * @return array */ diff --git a/dev/tests/functional/tests/app/Magento/Vault/Test/TestStep/SaveCreditCardOnBackendStep.php b/dev/tests/functional/tests/app/Magento/Vault/Test/TestStep/SaveCreditCardOnBackendStep.php index 24d1c76c01621fa9b6ce892aa8fd3262e3f7090a..3a378633bd4036737f391185ecd1bebb697609f1 100644 --- a/dev/tests/functional/tests/app/Magento/Vault/Test/TestStep/SaveCreditCardOnBackendStep.php +++ b/dev/tests/functional/tests/app/Magento/Vault/Test/TestStep/SaveCreditCardOnBackendStep.php @@ -5,13 +5,12 @@ */ namespace Magento\Vault\Test\TestStep; -use Magento\Mtf\Fixture\FixtureFactory; use Magento\Mtf\TestStep\TestStepInterface; use Magento\Payment\Test\Fixture\CreditCard; use Magento\Sales\Test\Page\Adminhtml\OrderCreateIndex; /** - * Class SaveCreditCardOnBackendStep + * Save credit card during order placement from Admin. */ class SaveCreditCardOnBackendStep implements TestStepInterface { @@ -44,22 +43,18 @@ class SaveCreditCardOnBackendStep implements TestStepInterface /** * @param OrderCreateIndex $orderCreateIndex * @param array $payment - * @param FixtureFactory $fixtureFactory - * @param $creditCardClass - * @param array $creditCard + * @param CreditCard $creditCard * @param string $creditCardSave */ public function __construct( OrderCreateIndex $orderCreateIndex, array $payment, - FixtureFactory $fixtureFactory, - $creditCardClass, - array $creditCard, + CreditCard $creditCard, $creditCardSave = 'No' ) { $this->orderCreatePage = $orderCreateIndex; $this->payment = $payment; - $this->creditCard = $fixtureFactory->createByCode($creditCardClass, ['dataset' => $creditCard['dataset']]); + $this->creditCard = $creditCard; $this->creditCardSave = $creditCardSave; } diff --git a/dev/tests/functional/tests/app/Magento/Vault/Test/etc/testcase.xml b/dev/tests/functional/tests/app/Magento/Vault/Test/etc/testcase.xml index 6289a8392ee7544777959e8afffe9fd999388713..ee55d7ef5ba905973cbbfb38effab1ccc7f750e0 100644 --- a/dev/tests/functional/tests/app/Magento/Vault/Test/etc/testcase.xml +++ b/dev/tests/functional/tests/app/Magento/Vault/Test/etc/testcase.xml @@ -56,7 +56,8 @@ <step name="selectCheckoutMethod" module="Magento_Checkout" next="fillShippingAddress" /> <step name="fillShippingAddress" module="Magento_Checkout" next="fillShippingMethod" /> <step name="fillShippingMethod" module="Magento_Checkout" next="selectPaymentMethod" /> - <step name="selectPaymentMethod" module="Magento_Checkout" next="fillBillingInformation" /> + <step name="selectPaymentMethod" module="Magento_Checkout" next="checkSaveCreditCardOption" /> + <step name="checkSaveCreditCardOption" module="Magento_Vault" next="fillBillingInformation" /> <step name="fillBillingInformation" module="Magento_Checkout" next="placeOrder" /> <step name="placeOrder" module="Magento_Checkout" next="openOrder" /> <step name="openOrder" module="Magento_Sales" next="reorder" /> diff --git a/dev/tests/functional/tests/app/Magento/Widget/Test/Constraint/AssertWidgetRecentlyComparedProducts.php b/dev/tests/functional/tests/app/Magento/Widget/Test/Constraint/AssertWidgetRecentlyComparedProducts.php index 745c3afe0aa91cc794d99e7312b620128d3306b4..c32ba27b671655a47a8400391f5fc7a7671d7083 100644 --- a/dev/tests/functional/tests/app/Magento/Widget/Test/Constraint/AssertWidgetRecentlyComparedProducts.php +++ b/dev/tests/functional/tests/app/Magento/Widget/Test/Constraint/AssertWidgetRecentlyComparedProducts.php @@ -118,6 +118,7 @@ class AssertWidgetRecentlyComparedProducts extends AbstractConstraint protected function removeCompareProducts() { $this->cmsIndex->open(); + $this->cmsIndex->getCompareLinkBlock()->waitForCompareProductsLinks(); $this->cmsIndex->getLinksBlock()->openLink("Compare Products"); $this->catalogProductCompare->getCompareProductsBlock()->removeAllProducts(); } diff --git a/dev/tests/functional/tests/app/Magento/Widget/Test/TestCase/CreateWidgetEntityTest.xml b/dev/tests/functional/tests/app/Magento/Widget/Test/TestCase/CreateWidgetEntityTest.xml index 225759df91f179dbd911fca662c05476c4830a69..57920ead79a7d113e37123d3603462759728393c 100644 --- a/dev/tests/functional/tests/app/Magento/Widget/Test/TestCase/CreateWidgetEntityTest.xml +++ b/dev/tests/functional/tests/app/Magento/Widget/Test/TestCase/CreateWidgetEntityTest.xml @@ -42,7 +42,7 @@ <constraint name="Magento\Widget\Test\Constraint\AssertWidgetRecentlyViewedProducts" /> </variation> <variation name="CreateWidgetEntityTestVariation4"> - <data name="tag" xsi:type="string">severity:S1, stable:no</data> + <data name="tag" xsi:type="string">severity:S1</data> <data name="widget/data/code" xsi:type="string">Recently Compared Products</data> <data name="widget/data/theme_id" xsi:type="string">Magento Luma</data> <data name="widget/data/title" xsi:type="string">Title_%isolation%</data> diff --git a/dev/tests/functional/utils/command.php b/dev/tests/functional/utils/command.php index 4061b07c783e4b0e8cbf4a7e4daa08d445834f68..a149be72a1ca48fbb7531b74d3dc84b687c5f737 100644 --- a/dev/tests/functional/utils/command.php +++ b/dev/tests/functional/utils/command.php @@ -8,5 +8,5 @@ if (isset($_GET['command'])) { $command = urldecode($_GET['command']); exec('php -f ../../../../bin/magento ' . $command); } else { - throw new \Exception("Command GET parameter is not set."); + throw new \InvalidArgumentException("Command GET parameter is not set."); } diff --git a/dev/tests/functional/utils/export.php b/dev/tests/functional/utils/export.php new file mode 100644 index 0000000000000000000000000000000000000000..062e8de6cbe7d6453f75d48b4faaf208ebffddc5 --- /dev/null +++ b/dev/tests/functional/utils/export.php @@ -0,0 +1,27 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +if (!isset($_GET['template'])) { + throw new \InvalidArgumentException('Argument "template" must be set.'); +} + +$varDir = '../../../../var/'; +$template = urldecode($_GET['template']); +$fileList = scandir($varDir, SCANDIR_SORT_NONE); +$files = []; + +foreach ($fileList as $fileName) { + if (preg_match("`$template`", $fileName) === 1) { + $filePath = $varDir . $fileName; + $files[] = [ + 'content' => file_get_contents($filePath), + 'name' => $fileName, + 'date' => filectime($filePath), + ]; + } +} + +echo serialize($files); diff --git a/dev/tests/functional/utils/generate.php b/dev/tests/functional/utils/generate.php index e374dae4ccfc2fec002e7be5d63782f7b9c357e3..d53ac44451376dd8d8a4dd0c69d5802a2ce6f1fe 100644 --- a/dev/tests/functional/utils/generate.php +++ b/dev/tests/functional/utils/generate.php @@ -3,12 +3,17 @@ * Copyright © 2016 Magento. All rights reserved. * See COPYING.txt for license details. */ +use Magento\Framework\App\Filesystem\DirectoryList; +use Magento\Framework\Filesystem; + require_once dirname(__FILE__) . '/' . 'bootstrap.php'; // Generate fixtures $magentoObjectManagerFactory = \Magento\Framework\App\Bootstrap::createObjectManagerFactory(BP, $_SERVER); $magentoObjectManager = $magentoObjectManagerFactory->create($_SERVER); - +// Remove previously generated static classes +$fs = $magentoObjectManager->create(Filesystem::class); +$fs->getDirectoryWrite(DirectoryList::ROOT)->delete('dev/tests/functional/generated/'); // Generate factories for old end-to-end tests $magentoObjectManager->create(\Magento\Mtf\Util\Generate\Factory::class)->launch(); 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/Helper/CacheCleaner.php b/dev/tests/integration/framework/Magento/TestFramework/Helper/CacheCleaner.php new file mode 100644 index 0000000000000000000000000000000000000000..5d7748f0b1fd91db302a33b5ff84086f8fb11b23 --- /dev/null +++ b/dev/tests/integration/framework/Magento/TestFramework/Helper/CacheCleaner.php @@ -0,0 +1,50 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\TestFramework\Helper; + +use Magento\Framework\App\Cache\Frontend\Pool; + +/** + * Helper for cleaning cache + */ +class CacheCleaner +{ + /** + * Clean cache by specified types + * + * @param array $cacheTypes + */ + public static function clean(array $cacheTypes = []) + { + $cachePool = self::getCachePool(); + foreach ($cacheTypes as $cacheType) { + $cachePool->get($cacheType)->getBackend()->clean(); + } + } + + /** + * Clean all cache + */ + public static function cleanAll() + { + $cachePool = self::getCachePool(); + foreach ($cachePool as $cacheType) { + $cacheType->getBackend()->clean(); + } + } + + /** + * Get cache pool + * + * @return Pool + */ + private static function getCachePool() + { + return Bootstrap::getObjectManager() + ->get(Pool::class); + } +} diff --git a/dev/tests/integration/framework/Magento/TestFramework/Interception/PluginList.php b/dev/tests/integration/framework/Magento/TestFramework/Interception/PluginList.php index 9e8901c91fd7587378713afd7abea020cb82fa83..18cdc66cb3f2ea28436692cf55c5bfae1df42ac4 100644 --- a/dev/tests/integration/framework/Magento/TestFramework/Interception/PluginList.php +++ b/dev/tests/integration/framework/Magento/TestFramework/Interception/PluginList.php @@ -5,6 +5,11 @@ */ namespace Magento\TestFramework\Interception; +use Magento\Framework\Serialize\SerializerInterface; + +/** + * Provides plugin list configuration + */ class PluginList extends \Magento\Framework\Interception\PluginList\PluginList { /** @@ -13,6 +18,8 @@ class PluginList extends \Magento\Framework\Interception\PluginList\PluginList protected $_originScopeScheme = []; /** + * Constructor + * * @param \Magento\Framework\Config\ReaderInterface $reader * @param \Magento\Framework\Config\ScopeInterface $configScope * @param \Magento\Framework\Config\CacheInterface $cache @@ -22,8 +29,8 @@ class PluginList extends \Magento\Framework\Interception\PluginList\PluginList * @param \Magento\Framework\ObjectManagerInterface $objectManager * @param \Magento\Framework\ObjectManager\DefinitionInterface $classDefinitions * @param array $scopePriorityScheme - * @param string $cacheId - * + * @param string|null $cacheId + * @param SerializerInterface|null $serializer * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( @@ -36,7 +43,8 @@ class PluginList extends \Magento\Framework\Interception\PluginList\PluginList \Magento\Framework\ObjectManagerInterface $objectManager, \Magento\Framework\ObjectManager\DefinitionInterface $classDefinitions, array $scopePriorityScheme, - $cacheId = 'plugins' + $cacheId = 'plugins', + SerializerInterface $serializer = null ) { parent::__construct( $reader, @@ -48,7 +56,8 @@ class PluginList extends \Magento\Framework\Interception\PluginList\PluginList $objectManager, $classDefinitions, $scopePriorityScheme, - $cacheId + $cacheId, + $serializer ); $this->_originScopeScheme = $this->_scopePriorityScheme; } 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/Authorizenet/Model/Directpost/RequestTest.php b/dev/tests/integration/testsuite/Magento/Authorizenet/Model/Directpost/RequestTest.php new file mode 100644 index 0000000000000000000000000000000000000000..ab35c27985da8f13fb2fd4362c719fe0d3267315 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Authorizenet/Model/Directpost/RequestTest.php @@ -0,0 +1,102 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Authorizenet\Model\Directpost; + +use Magento\Authorizenet\Model\Directpost; +use Magento\Framework\Api\FilterBuilder; +use Magento\Framework\Api\SearchCriteriaBuilder; +use Magento\Framework\App\ObjectManager; +use Magento\Sales\Api\Data\OrderInterface; +use Magento\Sales\Api\OrderRepositoryInterface; +use Magento\Sales\Model\Order; +use Magento\TestFramework\Helper\Bootstrap; +use PHPUnit_Framework_MockObject_MockObject as MockObject; + +/** + * Class contains tests for Authorize.net Direct Post request handler + */ +class RequestTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var Order + */ + private $order; + + /** + * @var Request + */ + private $request; + + /** + * @var ObjectManager + */ + private $objectManager; + + protected function setUp() + { + $this->objectManager = Bootstrap::getObjectManager(); + + $this->order = $this->getOrder(); + $this->request = $this->objectManager->get(Request::class); + } + + /** + * @covers \Magento\Authorizenet\Model\Directpost\Request::setDataFromOrder + * @magentoDataFixture Magento/Authorizenet/_files/order.php + */ + public function testSetDataFromOrder() + { + $customerEmail = 'john.doe@example.com'; + $merchantEmail = 'merchant@example.com'; + + /** @var Directpost|MockObject $payment */ + $payment = $this->getMockBuilder(Directpost::class) + ->disableOriginalConstructor() + ->setMethods(['getConfigData']) + ->getMock(); + + $payment->expects(static::exactly(2)) + ->method('getConfigData') + ->willReturnMap([ + ['email_customer', null, $customerEmail], + ['merchant_email', null, $merchantEmail] + ]); + + $result = $this->request->setDataFromOrder($this->order, $payment); + + static::assertEquals('US', $result->getXCountry()); + static::assertEquals('UK', $result->getXShipToCountry()); + static::assertEquals($customerEmail, $result->getXEmailCustomer()); + static::assertEquals($merchantEmail, $result->getXMerchantEmail()); + } + + /** + * Get stored order + * @return Order + */ + private function getOrder() + { + /** @var FilterBuilder $filterBuilder */ + $filterBuilder = $this->objectManager->get(FilterBuilder::class); + $filters = [ + $filterBuilder->setField(OrderInterface::INCREMENT_ID) + ->setValue('100000002') + ->create() + ]; + + /** @var SearchCriteriaBuilder $searchCriteriaBuilder */ + $searchCriteriaBuilder = $this->objectManager->get(SearchCriteriaBuilder::class); + $searchCriteria = $searchCriteriaBuilder->addFilters($filters) + ->create(); + + $orderRepository = $this->objectManager->get(OrderRepositoryInterface::class); + $orders = $orderRepository->getList($searchCriteria) + ->getItems(); + + /** @var OrderInterface $order */ + return array_pop($orders); + } +} diff --git a/dev/tests/integration/testsuite/Magento/Authorizenet/Model/DirectpostTest.php b/dev/tests/integration/testsuite/Magento/Authorizenet/Model/DirectpostTest.php new file mode 100644 index 0000000000000000000000000000000000000000..c20db43c127b4a9c058cb206cde14822f9aafd84 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Authorizenet/Model/DirectpostTest.php @@ -0,0 +1,129 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Authorizenet\Model; + +use Magento\Framework\Api\FilterBuilder; +use Magento\Framework\Api\SearchCriteriaBuilder; +use Magento\Framework\App\ObjectManager; +use Magento\Framework\HTTP\ZendClient; +use Magento\Framework\HTTP\ZendClientFactory; +use Magento\Sales\Api\Data\OrderInterface; +use Magento\Sales\Api\OrderRepositoryInterface; +use Magento\Sales\Model\Order\Payment; +use Magento\TestFramework\Helper\Bootstrap; +use PHPUnit_Framework_MockObject_MockObject as MockObject; +use Zend_Http_Response; + +/** + * Class contains tests for Direct Post integration + */ +class DirectpostTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var ObjectManager + */ + private $objectManager; + + /** + * @var ZendClientFactory|MockObject + */ + private $httpClientFactory; + + /** + * @var Directpost + */ + private $directPost; + + protected function setUp() + { + $this->objectManager = Bootstrap::getObjectManager(); + + $this->httpClientFactory = $this->getMockBuilder(ZendClientFactory::class) + ->disableOriginalConstructor() + ->setMethods(['create']) + ->getMock(); + + $this->directPost = $this->objectManager->create(Directpost::class, [ + 'httpClientFactory' => $this->httpClientFactory + ]); + } + + /** + * @covers \Magento\Authorizenet\Model\Directpost::capture + * @magentoDataFixture Magento/Authorizenet/_files/order.php + */ + public function testCapture() + { + $amount = 120.15; + /** @var Payment $payment */ + $payment = $this->getPayment(); + $transactionId = '106235225'; + + /** @var ZendClient|MockObject $httpClient */ + $httpClient = $this->getMockBuilder(ZendClient::class) + ->disableOriginalConstructor() + ->setMethods(['setUri', 'setConfig', 'setParameterPost', 'setMethod', 'request']) + ->getMock(); + + $this->httpClientFactory->expects(static::once()) + ->method('create') + ->willReturn($httpClient); + + $response = $this->getMockBuilder(Zend_Http_Response::class) + ->disableOriginalConstructor() + ->setMethods(['getBody']) + ->getMock(); + $response->expects(static::once()) + ->method('getBody') + ->willReturn( + "1(~)1(~)1(~)This transaction has been approved.(~)AWZFTG(~)P(~){$transactionId}(~)100000002(~) + (~)120.15(~)CC(~)prior_auth_capture(~)(~)Anthony(~)Nealy(~)(~)Pearl St(~)Los Angeles(~)California + (~)10020(~)US(~)22-333-44(~)(~)customer@example.com(~)John(~)Doe(~) + (~)Bourne St(~)London(~)(~)DW23W(~)UK(~)0.00(~)(~){$amount}(~)(~) + (~)74B5D54ADFE98093A0FF6446(~)(~)(~)(~)(~)(~)(~)(~)(~)(~)(~)(~)(~)XXXX1111(~)Visa(~)(~)(~)(~)(~) + (~)(~)(~)(~)(~)(~)(~)(~)(~)(~)(~)(~)" + ); + + $httpClient->expects(static::once()) + ->method('request') + ->willReturn($response); + + $this->directPost->capture($payment, $amount); + + static::assertEquals($transactionId, $payment->getTransactionId()); + static::assertFalse($payment->getIsTransactionClosed()); + static::assertEquals('US', $payment->getOrder()->getBillingAddress()->getCountryId()); + static::assertEquals('UK', $payment->getOrder()->getShippingAddress()->getCountryId()); + } + + /** + * Get order payment + * @return Payment + */ + private function getPayment() + { + /** @var FilterBuilder $filterBuilder */ + $filterBuilder = $this->objectManager->get(FilterBuilder::class); + $filters = [ + $filterBuilder->setField(OrderInterface::INCREMENT_ID) + ->setValue('100000002') + ->create() + ]; + + /** @var SearchCriteriaBuilder $searchCriteriaBuilder */ + $searchCriteriaBuilder = $this->objectManager->get(SearchCriteriaBuilder::class); + $searchCriteria = $searchCriteriaBuilder->addFilters($filters) + ->create(); + + $orderRepository = $this->objectManager->get(OrderRepositoryInterface::class); + $orders = $orderRepository->getList($searchCriteria) + ->getItems(); + + /** @var OrderInterface $order */ + $order = array_pop($orders); + return $order->getPayment(); + } +} diff --git a/dev/tests/integration/testsuite/Magento/Authorizenet/_files/order.php b/dev/tests/integration/testsuite/Magento/Authorizenet/_files/order.php new file mode 100644 index 0000000000000000000000000000000000000000..564ab84a8f8527c61bf8e79f7a57ad53b971089f --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Authorizenet/_files/order.php @@ -0,0 +1,70 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +use Magento\Sales\Api\OrderRepositoryInterface; +use Magento\Sales\Model\Order; +use Magento\Sales\Model\Order\Address; +use Magento\Sales\Model\Order\Payment; +use Magento\TestFramework\Helper\Bootstrap; + +$objectManager = Bootstrap::getObjectManager(); + +$amount = 120.15; + +/** @var Payment $payment */ +$payment = $objectManager->get(Payment::class); +$payment + ->setMethod('authorizenet_directpost') + ->setAnetTransType('AUTH_ONLY') + ->setBaseAmountAuthorized($amount) + ->setPoNumber('10101200'); + +/** @var Address\ $billingAddress */ +$billingAddress = $objectManager->create(Address::class, [ + 'data' => [ + 'firstname' => 'John', + 'lastname' => 'Doe', + 'email' => 'customer@example.com', + 'street' => 'Pearl St', + 'city' => 'Los Angeles', + 'region' => 'CA', + 'postcode' => '10020', + 'country_id' => 'US', + 'telephone' => '22-333-44', + 'address_type' => 'billing' + ] +]); + +$shippingAddress = $objectManager->create(Address::class, [ + 'data' => [ + 'firstname' => 'John', + 'lastname' => 'Doe', + 'email' => 'customer@example.com', + 'street' => 'Bourne St', + 'city' => 'London', + 'postcode' => 'DW23W', + 'country_id' => 'UK', + 'telephone' => '22-333-44', + 'address_type' => 'billing' + ] +]); + +/** @var Order $order */ +$order = $objectManager->create(Order::class); +$order->setIncrementId('100000002') + ->setQuoteId(2) + ->setIncrementId('100000002') + ->setBaseGrandTotal($amount) + ->setBaseCurrencyCode('USD') + ->setBaseTaxAmount($amount) + ->setBaseShippingAmount($amount) + ->setCustomerEmail('customer@example.com') + ->setBillingAddress($billingAddress) + ->setShippingAddress($shippingAddress) + ->setPayment($payment); + +/** @var OrderRepositoryInterface $orderRepository */ +$orderRepository = $objectManager->get(OrderRepositoryInterface::class); +$orderRepository->save($order); diff --git a/dev/tests/integration/testsuite/Magento/Backend/Block/Widget/Grid/Column/Renderer/TextTest.php b/dev/tests/integration/testsuite/Magento/Backend/Block/Widget/Grid/Column/Renderer/TextTest.php new file mode 100644 index 0000000000000000000000000000000000000000..9d2875716156e83b48502be84a4ef1a86ef46772 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Backend/Block/Widget/Grid/Column/Renderer/TextTest.php @@ -0,0 +1,142 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Backend\Block\Widget\Grid\Column\Renderer; + +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\ObjectManager; +use Magento\Backend\Block\Widget\Grid\Column; +use Magento\Framework\DataObject; +use Magento\Framework\Phrase; +use Magento\Framework\Phrase\RendererInterface; + +class TextTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var ObjectManager + */ + private $objectManager; + + /** + * @var RendererInterface + */ + private $origRenderer; + + protected function setUp() + { + $this->objectManager = Bootstrap::getObjectManager(); + $this->origRenderer = Phrase::getRenderer(); + /** @var RendererInterface|PHPUnit_Framework_MockObject_MockObject $rendererMock */ + $rendererMock = $this->getMock(RendererInterface::class); + $rendererMock->expects($this->any()) + ->method('render') + ->willReturnCallback( + function ($input) { + return end($input) . ' translated'; + } + ); + Phrase::setRenderer($rendererMock); + } + + protected function tearDown() + { + Phrase::setRenderer($this->origRenderer); + } + + /** + * @param array $columnData + * @param array $rowData + * @param string $expected + * @dataProvider renderDataProvider + */ + public function testRender($columnData, $rowData, $expected) + { + /** @var Text $renderer */ + $renderer = $this->objectManager->create(Text::class); + /** @var Column $column */ + $column = $this->objectManager->create( + Column::class, + [ + 'data' => $columnData + ] + ); + /** @var DataObject $row */ + $row = $this->objectManager->create( + DataObject::class, + [ + 'data' => $rowData + ] + ); + $this->assertEquals( + $expected, + $renderer->setColumn($column)->render($row) + ); + } + + /** + * @return array + */ + public function renderDataProvider() + { + return [ + [ + [ + 'index' => 'title', + 'translate' => true + ], + [ + 'title' => 'String' + ], + 'String translated' + ], + [ + [ + 'index' => 'title' + ], + [ + 'title' => 'Doesn\'t need to be translated' + ], + 'Doesn't need to be translated' + ], + [ + [ + 'format' => '#$subscriber_id $customer_name ($subscriber_email)' + ], + [ + 'subscriber_id' => '10', + 'customer_name' => 'John Doe', + 'subscriber_email' => 'john@doe.com' + ], + '#10 John Doe (john@doe.com)' + ], + [ + [ + 'format' => '$customer_name, email: $subscriber_email', + 'translate' => true + ], + [ + 'customer_name' => 'John Doe', + 'subscriber_email' => 'john@doe.com' + ], + 'John Doe, email: john@doe.com translated' + ], + [ + [ + 'format' => 'String', + 'translate' => true + ], + [], + 'String translated' + ], + [ + [ + 'format' => 'Doesn\'t need to be translated' + ], + [], + 'Doesn't need to be translated' + ] + ]; + } +} diff --git a/dev/tests/integration/testsuite/Magento/Backend/Block/Widget/Grid/MassactionTest.php b/dev/tests/integration/testsuite/Magento/Backend/Block/Widget/Grid/MassactionTest.php index 1bbf40ca6dc72999e4d2bd0c65987d25ee2e6f2a..8c0a7dd201d62abd7e823de4c31c2e9aec57f954 100644 --- a/dev/tests/integration/testsuite/Magento/Backend/Block/Widget/Grid/MassactionTest.php +++ b/dev/tests/integration/testsuite/Magento/Backend/Block/Widget/Grid/MassactionTest.php @@ -3,11 +3,10 @@ * Copyright © 2016 Magento. All rights reserved. * See COPYING.txt for license details. */ - -// @codingStandardsIgnoreFile - namespace Magento\Backend\Block\Widget\Grid; +use Magento\TestFramework\App\State; + /** * @magentoAppArea adminhtml * @magentoComponentsDir Magento/Backend/Block/_files/design @@ -25,18 +24,43 @@ class MassactionTest extends \PHPUnit_Framework_TestCase */ protected $_layout; + /** + * @var \Magento\Framework\ObjectManagerInterface + */ + private $objectManager; + + /** + * @var string + */ + private $mageMode; + protected function setUp() { - $this->markTestIncomplete('MAGETWO-6406'); - parent::setUp(); - $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); + $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); + + $this->mageMode = $this->objectManager->get(State::class)->getMode(); + /** @var \Magento\Theme\Model\Theme\Registration $registration */ - $registration = $objectManager->get(\Magento\Theme\Model\Theme\Registration::class); + $registration = $this->objectManager->get(\Magento\Theme\Model\Theme\Registration::class); $registration->register(); - $objectManager->get(\Magento\Framework\View\DesignInterface::class)->setDesignTheme('BackendTest/test_default'); - $this->_layout = $objectManager->create( + $this->objectManager->get(\Magento\Framework\View\DesignInterface::class) + ->setDesignTheme('BackendTest/test_default'); + } + + protected function tearDown() + { + $this->objectManager->get(State::class)->setMode($this->mageMode); + } + + /** + * @param string $mageMode + */ + private function loadLayout($mageMode = State::MODE_DEVELOPER) + { + $this->objectManager->get(State::class)->setMode($mageMode); + $this->_layout = $this->objectManager->create( \Magento\Framework\View\LayoutInterface::class, ['area' => 'adminhtml'] ); @@ -48,20 +72,14 @@ class MassactionTest extends \PHPUnit_Framework_TestCase $this->assertNotFalse($this->_block, 'Could not load the block for testing'); } - /** - * @covers \Magento\Backend\Block\Widget\Grid\Massaction::getItems - * @covers \Magento\Backend\Block\Widget\Grid\Massaction::getCount - * @covers \Magento\Backend\Block\Widget\Grid\Massaction::getItemsJson - * @covers \Magento\Backend\Block\Widget\Grid\Massaction::isAvailable - */ public function testMassactionDefaultValues() { + $this->loadLayout(); + /** @var $blockEmpty \Magento\Backend\Block\Widget\Grid\Massaction */ - $blockEmpty = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get( - \Magento\Framework\View\LayoutInterface::class - )->createBlock( - \Magento\Backend\Block\Widget\Grid\Massaction::class - ); + $blockEmpty = \Magento\TestFramework\Helper\Bootstrap::getObjectManager() + ->get(\Magento\Framework\View\LayoutInterface::class) + ->createBlock(\Magento\Backend\Block\Widget\Grid\Massaction::class); $this->assertEmpty($blockEmpty->getItems()); $this->assertEquals(0, $blockEmpty->getCount()); $this->assertSame('[]', $blockEmpty->getItemsJson()); @@ -71,6 +89,8 @@ class MassactionTest extends \PHPUnit_Framework_TestCase public function testGetJavaScript() { + $this->loadLayout(); + $javascript = $this->_block->getJavaScript(); $expectedItemFirst = '#"option_id1":{"label":"Option One",' . @@ -86,6 +106,8 @@ class MassactionTest extends \PHPUnit_Framework_TestCase public function testGetJavaScriptWithAddedItem() { + $this->loadLayout(); + $input = [ 'id' => 'option_id3', 'label' => 'Option Three', @@ -100,20 +122,49 @@ class MassactionTest extends \PHPUnit_Framework_TestCase $this->assertRegExp($expected, $this->_block->getJavaScript()); } - public function testGetCount() + /** + * @param string $mageMode + * @param int $expectedCount + * @dataProvider getCountDataProvider + */ + public function testGetCount($mageMode, $expectedCount) { - $this->assertEquals(2, $this->_block->getCount()); + $this->loadLayout($mageMode); + $this->assertEquals($expectedCount, $this->_block->getCount()); + } + + /** + * @return array + */ + public function getCountDataProvider() + { + return [ + [ + 'mageMode' => State::MODE_DEVELOPER, + 'expectedCount' => 3, + ], + [ + 'mageMode' => State::MODE_DEFAULT, + 'expectedCount' => 3, + ], + [ + 'mageMode' => State::MODE_PRODUCTION, + 'expectedCount' => 2, + ], + ]; } /** - * @param $itemId - * @param $expectedItem + * @param string $itemId + * @param array $expectedItem * @dataProvider getItemsDataProvider */ public function testGetItems($itemId, $expectedItem) { + $this->loadLayout(); + $items = $this->_block->getItems(); - $this->assertCount(2, $items); + $this->assertCount(3, $items); $this->assertArrayHasKey($itemId, $items); $actualItem = $items[$itemId]; @@ -149,19 +200,29 @@ class MassactionTest extends \PHPUnit_Framework_TestCase 'selected' => false, 'blockname' => '' ] + ], + [ + 'option_id3', + [ + 'id' => 'option_id3', + 'label' => 'Option Three', + 'url' => '#http:\/\/localhost\/index\.php\/(?:key\/([\w\d]+)\/)?#', + 'selected' => false, + 'blockname' => '' + ] ] ]; } public function testGridContainsMassactionColumn() { + $this->loadLayout(); $this->_layout->getBlock('admin.test.grid')->toHtml(); - $gridMassactionColumn = $this->_layout->getBlock( - 'admin.test.grid' - )->getColumnSet()->getChildBlock( - 'massaction' - ); + $gridMassactionColumn = $this->_layout->getBlock('admin.test.grid') + ->getColumnSet() + ->getChildBlock('massaction'); + $this->assertNotNull($gridMassactionColumn, 'Massaction column does not exist in the grid column set'); $this->assertInstanceOf( \Magento\Backend\Block\Widget\Grid\Column::class, diff --git a/dev/tests/integration/testsuite/Magento/Backend/Block/_files/design/adminhtml/Magento/test_default/Magento_Backend/layout/layout_test_grid_handle.xml b/dev/tests/integration/testsuite/Magento/Backend/Block/_files/design/adminhtml/Magento/test_default/Magento_Backend/layout/layout_test_grid_handle.xml index 5f9a80a5a3dbda9a86915c99aefce1066074ffb6..c072532a1c27c3471602abbb2442611fa49c6a59 100644 --- a/dev/tests/integration/testsuite/Magento/Backend/Block/_files/design/adminhtml/Magento/test_default/Magento_Backend/layout/layout_test_grid_handle.xml +++ b/dev/tests/integration/testsuite/Magento/Backend/Block/_files/design/adminhtml/Magento/test_default/Magento_Backend/layout/layout_test_grid_handle.xml @@ -6,60 +6,68 @@ */ --> <layout xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> - <block class="Magento\Backend\Block\Widget\Grid" name="admin.test.grid" Output="1"> + <block class="Magento\Backend\Block\Widget\Grid" name="admin.test.grid"> <arguments> - <dataSource type="object">Magento\Framework\Data\Collection</dataSource> + <argument name="dataSource" xsi:type="object">Magento\Framework\Data\Collection</argument> </arguments> - <block class="Magento\Backend\Block\Widget\Grid\ColumnSet" as="grid.columnSet" name="admin.test.grid.columnSet" Output="1"> - <block class="Magento\Backend\Block\Widget\Grid\Column" as="product_name" Output="1"> + <block class="Magento\Backend\Block\Widget\Grid\ColumnSet" as="grid.columnSet" name="admin.test.grid.columnSet"> + <block class="Magento\Backend\Block\Widget\Grid\Column" as="product_name"> <arguments> - <header>Product name 1</header> - <index>product_name</index> - <type>text</type> + <argument name="header" xsi:type="string" translate="true">Product name 1</argument> + <argument name="id" xsi:type="string">product_name</argument> + <argument name="index" xsi:type="string">product_name</argument> + <argument name="type" xsi:type="string">text</argument> </arguments> </block> - <block class="Magento\Backend\Block\Widget\Grid\Column" as="description" output="1"> + <block class="Magento\Backend\Block\Widget\Grid\Column" as="description"> <arguments> - <header>User Description</header> - <index>description</index> - <type>text</type> + <argument name="header" xsi:type="string" translate="true">User Description</argument> + <argument name="id" xsi:type="string">description</argument> + <argument name="index" xsi:type="string">description</argument> + <argument name="type" xsi:type="string">text</argument> </arguments> </block> - <block class="Magento\Backend\Block\Widget\Grid\Column" as="qty" output="1"> + <block class="Magento\Backend\Block\Widget\Grid\Column" as="qty"> <arguments> - <header>Qty</header> - <index>qty</index> - <type>number</type> - <width>60px</width> + <argument name="header" xsi:type="string" translate="true">Qty</argument> + <argument name="id" xsi:type="string">qty</argument> + <argument name="index" xsi:type="string">qty</argument> + <argument name="type" xsi:type="string">number</argument> + <argument name="width" xsi:type="string">60</argument> </arguments> </block> - <block class="Magento\Backend\Block\Widget\Grid\Column" as="added_at" output="1"> + <block class="Magento\Backend\Block\Widget\Grid\Column" as="added_at"> <arguments> - <header>Date Added</header> - <index>added_at</index> - <gmtoffset>1</gmtoffset> - <type>date</type> + <argument name="header" xsi:type="string" translate="true">Date Added</argument> + <argument name="id" xsi:type="string">added_at</argument> + <argument name="index" xsi:type="string">added_at</argument> + <argument name="type" xsi:type="string">date</argument> + <argument name="gmtoffset" xsi:type="string">1</argument> </arguments> </block> </block> - <block class="Magento\Backend\Block\Widget\Grid\Massaction" as="grid.massaction" name='admin.test.grid.massaction' output="1"> + <block class="Magento\Backend\Block\Widget\Grid\Massaction" as="grid.massaction" name='admin.test.grid.massaction'> <arguments> - <massaction_id_field>test_id</massaction_id_field> - <massaction_id_filter>test_id</massaction_id_filter> - <form_field_name>test</form_field_name> - <use_select_all>1</use_select_all> - <options> - <option_id1> - <label>Option One</label> - <url>*/*/option1</url> - <complete>Test</complete> - </option_id1> - <option_id2> - <label>Option Two</label> - <url>*/*/option2</url> - <confirm>Are you sure?</confirm> - </option_id2> - </options> + <argument name="massaction_id_field" xsi:type="string">test_id</argument> + <argument name="form_field_name" xsi:type="string">test_id</argument> + <argument name="use_select_all" xsi:type="string">1</argument> + <argument name="options" xsi:type="array"> + <item name="option_id1" xsi:type="array"> + <item name="label" xsi:type="string" translate="true">Option One</item> + <item name="url" xsi:type="string">*/*/option1</item> + <item name="complete" xsi:type="string">Test</item> + </item> + <item name="option_id2" xsi:type="array"> + <item name="label" xsi:type="string" translate="true">Option Two</item> + <item name="url" xsi:type="string">*/*/option2</item> + <item name="confirm" xsi:type="string">Are you sure?</item> + </item> + <item name="option_id3" xsi:type="array"> + <item name="label" xsi:type="string" translate="true">Option Three</item> + <item name="url" xsi:type="string">*/*/option3</item> + <item name="visible" xsi:type="object">Magento\Backend\Block\Cache\Grid\Massaction\ProductionModeVisibilityChecker</item> + </item> + </argument> </arguments> </block> </block> diff --git a/dev/tests/integration/testsuite/Magento/Backend/Controller/Adminhtml/Cache/MassActionTest.php b/dev/tests/integration/testsuite/Magento/Backend/Controller/Adminhtml/Cache/MassActionTest.php index e9fbb76f513d545eb4d710423bfd58a0cbb3d03e..a1034643ae3dcd6064caea87cf13f052db967f0f 100644 --- a/dev/tests/integration/testsuite/Magento/Backend/Controller/Adminhtml/Cache/MassActionTest.php +++ b/dev/tests/integration/testsuite/Magento/Backend/Controller/Adminhtml/Cache/MassActionTest.php @@ -3,13 +3,13 @@ * Copyright © 2016 Magento. All rights reserved. * See COPYING.txt for license details. */ - namespace Magento\Backend\Controller\Adminhtml\Cache; use Magento\Framework\App\Cache\State; use Magento\TestFramework\Helper\Bootstrap; use Magento\Framework\Config\File\ConfigFilePool; use Magento\Framework\App\Filesystem\DirectoryList; +use Magento\TestFramework\App\State as AppState; class MassActionTest extends \Magento\TestFramework\TestCase\AbstractBackendController { @@ -20,6 +20,11 @@ class MassActionTest extends \Magento\TestFramework\TestCase\AbstractBackendCont */ private static $typesConfig; + /** + * @var string + */ + private $mageState; + public static function setUpBeforeClass() { /** @var \Magento\Framework\App\DeploymentConfig $config */ @@ -27,8 +32,15 @@ class MassActionTest extends \Magento\TestFramework\TestCase\AbstractBackendCont self::$typesConfig = $config->get(State::CACHE_KEY); } + protected function setUp() + { + parent::setUp(); + $this->mageState = Bootstrap::getObjectManager()->get(AppState::class)->getMode(); + } + protected function tearDown() { + Bootstrap::getObjectManager()->get(AppState::class)->setMode($this->mageState); /** @var $cacheState \Magento\Framework\App\Cache\StateInterface */ $cacheState = Bootstrap::getObjectManager()->get(\Magento\Framework\App\Cache\StateInterface::class); foreach (self::$typesConfig as $type => $value) { @@ -42,7 +54,7 @@ class MassActionTest extends \Magento\TestFramework\TestCase\AbstractBackendCont * @dataProvider massActionsDataProvider * @param array $typesToEnable */ - public function testMassEnableAction($typesToEnable = []) + public function testMassEnableActionDeveloperMode($typesToEnable = []) { $this->setAll(false); @@ -53,16 +65,33 @@ class MassActionTest extends \Magento\TestFramework\TestCase\AbstractBackendCont if (in_array($cacheType, $typesToEnable)) { $this->assertEquals(1, $cacheState, "Type '{$cacheType}' has not been enabled"); } else { - $this->assertEquals(0, $cacheState, "Type '{$cacheType}' has not been enabled"); + $this->assertEquals(0, $cacheState, "Type '{$cacheType}' must remain disabled"); } } } + /** + * @dataProvider massActionsDataProvider + * @param array $typesToEnable + */ + public function testMassEnableActionProductionMode($typesToEnable = []) + { + Bootstrap::getObjectManager()->get(AppState::class)->setMode(AppState::MODE_PRODUCTION); + $this->setAll(false); + + $this->getRequest()->setParams(['types' => $typesToEnable]); + $this->dispatch('backend/admin/cache/massEnable'); + + foreach ($this->getCacheStates() as $cacheType => $cacheState) { + $this->assertEquals(0, $cacheState, "Type '{$cacheType}' must remain disabled"); + } + } + /** * @dataProvider massActionsDataProvider * @param array $typesToDisable */ - public function testMassDisableAction($typesToDisable = []) + public function testMassDisableActionDeveloperMode($typesToDisable = []) { $this->setAll(true); @@ -78,6 +107,23 @@ class MassActionTest extends \Magento\TestFramework\TestCase\AbstractBackendCont } } + /** + * @dataProvider massActionsDataProvider + * @param array $typesToDisable + */ + public function testMassDisableActionProductionMode($typesToDisable = []) + { + Bootstrap::getObjectManager()->get(AppState::class)->setMode(AppState::MODE_PRODUCTION); + $this->setAll(true); + + $this->getRequest()->setParams(['types' => $typesToDisable]); + $this->dispatch('backend/admin/cache/massDisable'); + + foreach ($this->getCacheStates() as $cacheType => $cacheState) { + $this->assertEquals(1, $cacheState, "Type '{$cacheType}' must remain enabled"); + } + } + /** * Retrieve cache states (enabled/disabled) information * diff --git a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/DynamicBundleWithTierPriceCalculatorTest.php b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/DynamicBundleWithTierPriceCalculatorTest.php index 0be5adcb304f772218e588795f3f6ef26ce0721c..c2c62aa2ce093e3b52502ec5c234d3932cdbe3b4 100644 --- a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/DynamicBundleWithTierPriceCalculatorTest.php +++ b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/DynamicBundleWithTierPriceCalculatorTest.php @@ -201,7 +201,8 @@ class DynamicBundleWithTierPriceCalculatorTest extends BundlePriceAbstract $tierPriceData = [ 'customer_group_id' => \Magento\Customer\Model\Group::NOT_LOGGED_IN_ID, 'qty' => 1, - 'value' => 50 + 'value' => 50, + 'extension_attributes' => new \Magento\Framework\DataObject(['percentage_value' => 50]) ]; return [ @@ -239,7 +240,8 @@ class DynamicBundleWithTierPriceCalculatorTest extends BundlePriceAbstract $tierPriceData = [ 'customer_group_id' => \Magento\Customer\Model\Group::NOT_LOGGED_IN_ID, 'qty' => 1, - 'value' => 50 + 'value' => 50, + 'extension_attributes' => new \Magento\Framework\DataObject(['percentage_value' => 50]) ]; return [ @@ -281,7 +283,8 @@ class DynamicBundleWithTierPriceCalculatorTest extends BundlePriceAbstract $tierPriceData = [ 'customer_group_id' => \Magento\Customer\Model\Group::NOT_LOGGED_IN_ID, 'qty' => 1, - 'value' => 50 + 'value' => 50, + 'extension_attributes' => new \Magento\Framework\DataObject(['percentage_value' => 50]) ]; return [ @@ -323,7 +326,8 @@ class DynamicBundleWithTierPriceCalculatorTest extends BundlePriceAbstract $tierPriceData = [ 'customer_group_id' => \Magento\Customer\Model\Group::NOT_LOGGED_IN_ID, 'qty' => 1, - 'value' => 50 + 'value' => 50, + 'extension_attributes' => new \Magento\Framework\DataObject(['percentage_value' => 50]) ]; return [ @@ -365,7 +369,8 @@ class DynamicBundleWithTierPriceCalculatorTest extends BundlePriceAbstract $tierPriceData = [ 'customer_group_id' => \Magento\Customer\Model\Group::NOT_LOGGED_IN_ID, 'qty' => 1, - 'value' => 50 + 'value' => 50, + 'extension_attributes' => new \Magento\Framework\DataObject(['percentage_value' => 50]) ]; return [ @@ -422,7 +427,8 @@ class DynamicBundleWithTierPriceCalculatorTest extends BundlePriceAbstract $tierPriceData = [ 'customer_group_id' => \Magento\Customer\Model\Group::NOT_LOGGED_IN_ID, 'qty' => 1, - 'value' => 50 + 'value' => 50, + 'extension_attributes' => new \Magento\Framework\DataObject(['percentage_value' => 50]) ]; return [ @@ -479,7 +485,8 @@ class DynamicBundleWithTierPriceCalculatorTest extends BundlePriceAbstract $tierPriceData = [ 'customer_group_id' => \Magento\Customer\Model\Group::NOT_LOGGED_IN_ID, 'qty' => 1, - 'value' => 50 + 'value' => 50, + 'extension_attributes' => new \Magento\Framework\DataObject(['percentage_value' => 50]) ]; return [ @@ -536,7 +543,8 @@ class DynamicBundleWithTierPriceCalculatorTest extends BundlePriceAbstract $tierPriceData = [ 'customer_group_id' => \Magento\Customer\Model\Group::NOT_LOGGED_IN_ID, 'qty' => 1, - 'value' => 50 + 'value' => 50, + 'extension_attributes' => new \Magento\Framework\DataObject(['percentage_value' => 50]) ]; return [ @@ -578,7 +586,8 @@ class DynamicBundleWithTierPriceCalculatorTest extends BundlePriceAbstract $tierPriceData = [ 'customer_group_id' => \Magento\Customer\Model\Group::NOT_LOGGED_IN_ID, 'qty' => 1, - 'value' => 50 + 'value' => 50, + 'extension_attributes' => new \Magento\Framework\DataObject(['percentage_value' => 50]) ]; $tierPriceSimpleProductData = [ diff --git a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/FixedBundleWithTierPriceCalculatorTest.php b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/FixedBundleWithTierPriceCalculatorTest.php index bd148080631aea892cccb0fab6fd0321d08c231b..aa020fe1f5a2b89e6d1e1eb922c0dee8412f4de7 100644 --- a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/FixedBundleWithTierPriceCalculatorTest.php +++ b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/FixedBundleWithTierPriceCalculatorTest.php @@ -495,7 +495,8 @@ class FixedBundleWithTierPriceCalculatorTest extends BundlePriceAbstract $tierPriceData = [ 'customer_group_id' => \Magento\Customer\Model\Group::NOT_LOGGED_IN_ID, 'qty' => 1, - 'value' => 50 + 'value' => 50, + 'extension_attributes' => new \Magento\Framework\DataObject(['percentage_value' => 50]) ]; return [ @@ -544,7 +545,8 @@ class FixedBundleWithTierPriceCalculatorTest extends BundlePriceAbstract $tierPriceData = [ 'customer_group_id' => \Magento\Customer\Model\Group::NOT_LOGGED_IN_ID, 'qty' => 1, - 'value' => 50 + 'value' => 50, + 'extension_attributes' => new \Magento\Framework\DataObject(['percentage_value' => 50]) ]; return [ @@ -601,7 +603,8 @@ class FixedBundleWithTierPriceCalculatorTest extends BundlePriceAbstract $tierPriceData = [ 'customer_group_id' => \Magento\Customer\Model\Group::NOT_LOGGED_IN_ID, 'qty' => 1, - 'value' => 50 + 'value' => 50, + 'extension_attributes' => new \Magento\Framework\DataObject(['percentage_value' => 50]) ]; return [ @@ -664,7 +667,8 @@ class FixedBundleWithTierPriceCalculatorTest extends BundlePriceAbstract $tierPriceData = [ 'customer_group_id' => \Magento\Customer\Model\Group::NOT_LOGGED_IN_ID, 'qty' => 1, - 'value' => 50 + 'value' => 50, + 'extension_attributes' => new \Magento\Framework\DataObject(['percentage_value' => 50]) ]; return [ @@ -727,7 +731,8 @@ class FixedBundleWithTierPriceCalculatorTest extends BundlePriceAbstract $tierPriceData = [ 'customer_group_id' => \Magento\Customer\Model\Group::NOT_LOGGED_IN_ID, 'qty' => 1, - 'value' => 50 + 'value' => 50, + 'extension_attributes' => new \Magento\Framework\DataObject(['percentage_value' => 50]) ]; return [ @@ -790,7 +795,8 @@ class FixedBundleWithTierPriceCalculatorTest extends BundlePriceAbstract $tierPriceData = [ 'customer_group_id' => \Magento\Customer\Model\Group::NOT_LOGGED_IN_ID, 'qty' => 1, - 'value' => 50 + 'value' => 50, + 'extension_attributes' => new \Magento\Framework\DataObject(['percentage_value' => 50]) ]; return [ @@ -872,7 +878,8 @@ class FixedBundleWithTierPriceCalculatorTest extends BundlePriceAbstract $tierPriceData = [ 'customer_group_id' => \Magento\Customer\Model\Group::NOT_LOGGED_IN_ID, 'qty' => 1, - 'value' => 50 + 'value' => 50, + 'extension_attributes' => new \Magento\Framework\DataObject(['percentage_value' => 50]) ]; return [ diff --git a/dev/tests/integration/testsuite/Magento/Bundle/_files/product_with_tier_pricing.php b/dev/tests/integration/testsuite/Magento/Bundle/_files/product_with_tier_pricing.php index 6d6d10ce4d220fc45047d140621a784ea44413c6..9574948dae900e292e38d55a306d4a7fe8706955 100644 --- a/dev/tests/integration/testsuite/Magento/Bundle/_files/product_with_tier_pricing.php +++ b/dev/tests/integration/testsuite/Magento/Bundle/_files/product_with_tier_pricing.php @@ -41,18 +41,21 @@ $product->setTypeId('bundle') 'cust_group' => \Magento\Customer\Model\GroupManagement::CUST_GROUP_ALL, 'price_qty' => 2, 'price' => 8, + 'percentage_value' => 8 ], [ 'website_id' => 0, 'cust_group' => \Magento\Customer\Model\GroupManagement::CUST_GROUP_ALL, 'price_qty' => 5, 'price' => 30, + 'percentage_value' => 30 ], [ 'website_id' => 0, 'cust_group' => \Magento\Customer\Model\GroupManagement::NOT_LOGGED_IN_ID, 'price_qty' => 3, 'price' => 20, + 'percentage_value' => 20 ], ] ) diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/Action/AttributeTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/Action/AttributeTest.php index fc2763aea017dee37b05216a1b881665a29dc551..c17553629ae59a3b0c8ef7c1643112743cd82bf8 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/Action/AttributeTest.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/Action/AttributeTest.php @@ -45,6 +45,47 @@ class AttributeTest extends \Magento\TestFramework\TestCase\AbstractBackendContr $this->assertTrue($isRedirectPresent); } + /** + * @covers \Magento\Catalog\Controller\Adminhtml\Product\Action\Attribute\Save::execute + * + * @dataProvider saveActionVisibilityAttrDataProvider + * @param array $attributes + * @magentoDataFixture Magento/Catalog/_files/product_simple.php + */ + public function testSaveActionChangeVisibility($attributes) + { + $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); + $repository = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create( + \Magento\Catalog\Model\ProductRepository::class + ); + $product = $repository->get('simple'); + $product->setOrigData(); + $product->setVisibility(\Magento\Catalog\Model\Product\Visibility::VISIBILITY_NOT_VISIBLE); + $product->save(); + + /** @var $session \Magento\Backend\Model\Session */ + $session = $objectManager->get(\Magento\Backend\Model\Session::class); + $session->setProductIds([$product->getId()]); + $this->getRequest()->setParam('attributes', $attributes); + + $this->dispatch('backend/catalog/product_action_attribute/save/store/0'); + /** @var \Magento\Catalog\Model\Category $category */ + $categoryFactory = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get( + \Magento\Catalog\Model\CategoryFactory::class + ); + /** @var \Magento\Catalog\Block\Product\ListProduct $listProduct */ + $listProduct = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get( + \Magento\Catalog\Block\Product\ListProduct::class + ); + + $category = $categoryFactory->create()->load(2); + $layer = $listProduct->getLayer(); + $layer->setCurrentCategory($category); + $productCollection = $layer->getProductCollection(); + $productItem = $productCollection->getFirstItem(); + $this->assertEquals($session->getProductIds(), [$productItem->getId()]); + } + /** * @covers \Magento\Catalog\Controller\Adminhtml\Product\Action\Attribute\Validate::execute * @@ -97,4 +138,17 @@ class AttributeTest extends \Magento\TestFramework\TestCase\AbstractBackendContr ] ]; } + + /** + * Data Provider for save with visibility attribute + * + * @return array + */ + public function saveActionVisibilityAttrDataProvider() + { + return [ + ['arguments' => ['visibility' => \Magento\Catalog\Model\Product\Visibility::VISIBILITY_BOTH]], + ['arguments' => ['visibility' => \Magento\Catalog\Model\Product\Visibility::VISIBILITY_IN_CATALOG]] + ]; + } } 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/ConfigTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Model/ConfigTest.php new file mode 100644 index 0000000000000000000000000000000000000000..178107e487e9292b90226e838e5767deef47d1d8 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Catalog/Model/ConfigTest.php @@ -0,0 +1,61 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Catalog\Model; + +use Magento\Catalog\Model\Config; +use Magento\TestFramework\ObjectManager; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\Helper\CacheCleaner; + +class ConfigTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var Config + */ + private $config; + + /** + * @var ObjectManager + */ + private $objectManager; + + protected function setUp() + { + $this->objectManager = Bootstrap::getObjectManager(); + $this->config = $this->objectManager->get(Config::class); + } + + public function testGetEntityAttributeCodes() + { + $entityType = 'catalog_product'; + CacheCleaner::cleanAll(); + $this->assertEquals( + $this->config->getEntityAttributeCodes($entityType), + $this->config->getEntityAttributeCodes($entityType) + ); + } + + public function testGetAttribute() + { + $entityType = 'catalog_product'; + $attributeCode = 'color'; + CacheCleaner::cleanAll(); + $this->assertEquals( + $this->config->getAttribute($entityType, $attributeCode), + $this->config->getAttribute($entityType, $attributeCode) + ); + } + + public function testGetEntityType() + { + $entityType = 'catalog_product'; + CacheCleaner::cleanAll(); + $this->assertEquals( + $this->config->getEntityType($entityType), + $this->config->getEntityType($entityType) + ); + } +} diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Model/Product/Attribute/Source/CountryofmanufactureTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Model/Product/Attribute/Source/CountryofmanufactureTest.php new file mode 100644 index 0000000000000000000000000000000000000000..34fd3b678a0866af7ce5bcec53cf6d6fe496bbfc --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Catalog/Model/Product/Attribute/Source/CountryofmanufactureTest.php @@ -0,0 +1,32 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Catalog\Model\Product\Attribute\Source; + +use Magento\TestFramework\Helper\CacheCleaner; + +class CountryofmanufactureTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var \Magento\Catalog\Model\Product\Attribute\Source\Countryofmanufacture + */ + private $model; + + protected function setUp() + { + $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); + $this->model = $objectManager->create( + \Magento\Catalog\Model\Product\Attribute\Source\Countryofmanufacture::class + ); + } + + public function testGetAllOptions() + { + CacheCleaner::cleanAll(); + $allOptions = $this->model->getAllOptions(); + $cachedAllOptions = $this->model->getAllOptions(); + $this->assertEquals($allOptions, $cachedAllOptions); + } +} diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Model/Product/Gallery/ProcessorTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Model/Product/Gallery/ProcessorTest.php index 9c9e564939070e99b097477a221f445811a25ef1..ae954fdc7cfbb7bdc7c66dfb4ab9a25e977e8fae 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/Model/Product/Gallery/ProcessorTest.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/Model/Product/Gallery/ProcessorTest.php @@ -146,15 +146,15 @@ class ProcessorTest extends \PHPUnit_Framework_TestCase ); $product->setData(['image' => 'test1', 'small_image' => 'test2', 'thumbnail' => 'test3']); - $this->assertNotEmpty($product->getData('image')); + $this->assertNotEquals('no_selection', $product->getData('image')); $this->_model->clearMediaAttribute($product, 'image'); - $this->assertNull($product->getData('image')); + $this->assertEquals('no_selection', $product->getData('image')); - $this->assertNotEmpty($product->getData('small_image')); - $this->assertNotEmpty($product->getData('thumbnail')); + $this->assertNotEquals('no_selection', $product->getData('small_image')); + $this->assertNotEquals('no_selection', $product->getData('thumbnail')); $this->_model->clearMediaAttribute($product, ['small_image', 'thumbnail']); - $this->assertNull($product->getData('small_image')); - $this->assertNull($product->getData('thumbnail')); + $this->assertEquals('no_selection', $product->getData('small_image')); + $this->assertEquals('no_selection', $product->getData('thumbnail')); } public function testSetMediaAttribute() diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Model/Product/ImageTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Model/Product/ImageTest.php index 88fd7797e768fb5fb227a8fc888ad481794d4347..8b0d1b393f467641bd87bc65fb425dbe8000bff6 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/Model/Product/ImageTest.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/Model/Product/ImageTest.php @@ -23,8 +23,15 @@ class ImageTest extends \PHPUnit_Framework_TestCase $model = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create( \Magento\Catalog\Model\Product\Image::class ); - $model->setDestinationSubdir('image')->setBaseFile(''); - $this->assertEmpty($model->getBaseFile()); + /** @var \Magento\Catalog\Model\View\Asset\Placeholder $defualtPlaceholder */ + $defualtPlaceholder = \Magento\TestFramework\Helper\Bootstrap::getObjectManager() + ->create(\Magento\Catalog\Model\View\Asset\Placeholder::class, + ['type' => 'image'] + ); + + $model->setDestinationSubdir('image'); + $model->setBaseFile(''); + $this->assertEquals($defualtPlaceholder->getSourceFile(), $model->getBaseFile()); return $model; } 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/Ui/DataProvider/Product/Form/Modifier/CategoriesTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/CategoriesTest.php new file mode 100644 index 0000000000000000000000000000000000000000..b01d1e6d38655fac502d16e4be7f6d117202078d --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/CategoriesTest.php @@ -0,0 +1,50 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Catalog\Ui\DataProvider\Product\Form\Modifier; + +use Magento\TestFramework\Helper\CacheCleaner; + +/** + * @magentoAppArea adminhtml + * @magentoDataFixture Magento/Catalog/_files/categories.php + * @magentoDbIsolation enabled + * @magentoAppIsolation enabled + */ +class CategoriesTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var Categories + */ + private $object; + + protected function setUp() + { + $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); + $registry = $objectManager->get(\Magento\Framework\Registry::class); + /** @var $store \Magento\Store\Model\Store */ + $store = $objectManager->create(\Magento\Store\Model\Store::class); + $store->load('admin'); + $registry->register('current_store', $store); + $this->object = $objectManager->create(Categories::class); + } + + public function testModifyMeta() + { + $inputMeta = include __DIR__ . '/_files/input_meta_for_categories.php'; + $expectedCategories = include __DIR__ . '/_files/expected_categories.php'; + CacheCleaner::cleanAll(); + $this->assertCategoriesInMeta($expectedCategories, $this->object->modifyMeta($inputMeta)); + // Verify cached data + $this->assertCategoriesInMeta($expectedCategories, $this->object->modifyMeta($inputMeta)); + } + + private function assertCategoriesInMeta(array $expectedCategories, array $meta) + { + $categoriesElement = $meta['product-details']['children']['container_category_ids']['children']['category_ids']; + $this->assertEquals($expectedCategories, $categoriesElement['arguments']['data']['config']['options']); + } +} diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/_files/expected_categories.php b/dev/tests/integration/testsuite/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/_files/expected_categories.php new file mode 100644 index 0000000000000000000000000000000000000000..ed30676e16b07dd54cae708b2f7942511fe8fb6c --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/_files/expected_categories.php @@ -0,0 +1,89 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +return [ + 0 => + [ + 'value' => '2', + 'is_active' => '1', + 'label' => 'Default Category', + 'optgroup' => + [ + 0 => + [ + 'value' => '3', + 'is_active' => '1', + 'label' => 'Category 1', + 'optgroup' => + [ + 0 => + [ + 'value' => '4', + 'is_active' => '1', + 'label' => 'Category 1.1', + 'optgroup' => + [ + 0 => + [ + 'value' => '5', + 'is_active' => '1', + 'label' => 'Category 1.1.1', + ], + ], + ], + 1 => + [ + 'value' => '13', + 'is_active' => '1', + 'label' => 'Category 1.2', + ], + ], + ], + 1 => + [ + 'value' => '6', + 'is_active' => '1', + 'label' => 'Category 2', + ], + 2 => + [ + 'value' => '7', + 'is_active' => '1', + 'label' => 'Movable', + ], + 3 => + [ + 'value' => '8', + 'is_active' => '0', + 'label' => 'Inactive', + ], + 4 => + [ + 'value' => '9', + 'is_active' => '1', + 'label' => 'Movable Position 1', + ], + 5 => + [ + 'value' => '10', + 'is_active' => '1', + 'label' => 'Movable Position 2', + ], + 6 => + [ + 'value' => '11', + 'is_active' => '1', + 'label' => 'Movable Position 3', + ], + 7 => + [ + 'value' => '12', + 'is_active' => '1', + 'label' => 'Category 12', + ], + ], + ], +]; diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/_files/input_meta_for_categories.php b/dev/tests/integration/testsuite/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/_files/input_meta_for_categories.php new file mode 100644 index 0000000000000000000000000000000000000000..f43e9c916fcd25723a65f9dd6fde0018f026cd66 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/_files/input_meta_for_categories.php @@ -0,0 +1,56 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +return [ + 'product-details' => + [ + 'children' => + ['container_category_ids' => + [ + 'arguments' => + [ + 'data' => + [ + 'config' => + [ + 'formElement' => 'container', + 'componentType' => 'container', + 'breakLine' => false, + 'label' => 'Categories', + 'required' => '0', + 'sortOrder' => 70, + ], + ], + ], + 'children' => + [ + 'category_ids' => + [ + 'arguments' => + [ + 'data' => + [ + 'config' => + [ + 'dataType' => 'text', + 'formElement' => 'input', + 'visible' => '1', + 'required' => '0', + 'notice' => null, + 'default' => null, + 'label' => 'Categories', + 'code' => 'category_ids', + 'source' => 'product-details', + 'scopeLabel' => '[GLOBAL]', + 'globalScope' => true, + 'sortOrder' => 70, + 'componentType' => 'field', + ], + ], + ], + ], + ], + ]]]]; 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/Config/Model/Config/Processor/EnvironmentPlaceholderTest.php b/dev/tests/integration/testsuite/Magento/Config/Model/Config/Processor/EnvironmentPlaceholderTest.php new file mode 100644 index 0000000000000000000000000000000000000000..1e2b6aacc931446cee8f42accb17d684c4bb413c --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Config/Model/Config/Processor/EnvironmentPlaceholderTest.php @@ -0,0 +1,103 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Config\Model\Config\Processor; + +use Magento\Framework\ObjectManagerInterface; + +class EnvironmentPlaceholderTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var ObjectManagerInterface + */ + private $objectManager; + + /** + * @var EnvironmentPlaceholder + */ + private $model; + + /** + * @var array + */ + private $env = []; + + protected function setUp() + { + $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); + $this->model = $this->objectManager->get(EnvironmentPlaceholder::class); + $this->env = $_ENV; + } + + public function testProcess() + { + $_ENV = array_merge( + $_ENV, + [ + 'CONFIG__DEFAULT__WEB__UNSECURE__BASE_URL' => 'http://expected.local', + 'CONFIG__TEST__TEST__DESIGN__HEADER__WELCOME' => 'Expected header', + 'TEST__TEST__WEB__SECURE__BASE_URL' => 'http://wrong_pattern.local', + 'CONFIG__DEFAULT__GENERAL__REGION__DISPLAY_ALL' => 1 + ] + ); + $expected = [ + 'default' => [ + 'web' => [ + 'unsecure' => [ + 'base_url' => 'http://expected.local' + ], + 'secure' => [ + 'base_url' => 'https://original.local' + ] + ], + 'general' => [ + 'region' => [ + 'display_all' => 1 + ], + ], + ], + 'test' => [ + 'test' => [ + 'design' => [ + 'header' => [ + 'welcome' => 'Expected header' + ] + ], + ], + ] + ]; + $config = [ + 'default' => [ + 'web' => [ + 'unsecure' => [ + 'base_url' => 'http://original.local', + ], + 'secure' => [ + 'base_url' => 'https://original.local' + ] + ] + ], + 'test' => [ + 'test' => [ + 'design' => [ + 'header' => [ + 'welcome' => 'Original header' + ] + ], + ], + ] + ]; + + $this->assertSame( + $expected, + $this->model->process($config) + ); + } + + protected function tearDown() + { + $_ENV = $this->env; + } +} 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/Model/ResourceModel/Product/Indexer/Price/ConfigurableTest.php b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/Model/ResourceModel/Product/Indexer/Price/ConfigurableTest.php index 5db97cc36614924ae915b7b924b2c7a1f575e344..2e339e4347cf65ad13474de26ba61c3237cfafe9 100644 --- a/dev/tests/integration/testsuite/Magento/ConfigurableProduct/Model/ResourceModel/Product/Indexer/Price/ConfigurableTest.php +++ b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/Model/ResourceModel/Product/Indexer/Price/ConfigurableTest.php @@ -67,4 +67,40 @@ class ConfigurableTest extends \PHPUnit_Framework_TestCase ->getFirstItem(); $this->assertEquals(20, $configurableProduct->getMinimalPrice()); } + + /** + * @magentoDataFixture Magento/ConfigurableProduct/_files/product_configurable.php + */ + public function testGetProductFinalPriceIfOneOfChildIsDisabledPerStore() + { + /** @var Collection $collection */ + $collection = Bootstrap::getObjectManager()->get(CollectionFactory::class) + ->create(); + $configurableProduct = $collection + ->addIdFilter([1]) + ->addMinimalPrice() + ->load() + ->getFirstItem(); + $this->assertEquals(10, $configurableProduct->getMinimalPrice()); + + $childProduct = $this->productRepository->getById(10, false, null, true); + $childProduct->setStatus(Status::STATUS_DISABLED); + + // update in default store scope + $currentStoreId = $this->storeManager->getStore()->getId(); + $defaultStore = $this->storeManager->getDefaultStoreView(); + $this->storeManager->setCurrentStore($defaultStore->getId()); + $this->productRepository->save($childProduct); + $this->storeManager->setCurrentStore($currentStoreId); + + /** @var Collection $collection */ + $collection = Bootstrap::getObjectManager()->get(CollectionFactory::class) + ->create(); + $configurableProduct = $collection + ->addIdFilter([1]) + ->addMinimalPrice() + ->load() + ->getFirstItem(); + $this->assertEquals(20, $configurableProduct->getMinimalPrice()); + } } diff --git a/dev/tests/integration/testsuite/Magento/ConfigurableProduct/Pricing/Price/LowestPriceOptionProviderTest.php b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/Pricing/Price/LowestPriceOptionProviderTest.php index 50787c7962412b0611edf093825563061da67119..58df9f50f7f0c10a8750c1fdf31c68561b6fdb87 100644 --- a/dev/tests/integration/testsuite/Magento/ConfigurableProduct/Pricing/Price/LowestPriceOptionProviderTest.php +++ b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/Pricing/Price/LowestPriceOptionProviderTest.php @@ -68,6 +68,38 @@ class LowestPriceOptionProviderTest extends \PHPUnit_Framework_TestCase $this->assertEquals(20, $lowestPriceChildrenProduct->getPrice()); } + /** + * @magentoDataFixture Magento/ConfigurableProduct/_files/product_configurable.php + */ + public function testGetProductsIfOneOfChildIsDisabledPerStore() + { + $configurableProduct = $this->productRepository->getById(1, false, null, true); + $lowestPriceChildrenProducts = $this->lowestPriceOptionsProvider->getProducts($configurableProduct); + $this->assertCount(1, $lowestPriceChildrenProducts); + $lowestPriceChildrenProduct = reset($lowestPriceChildrenProducts); + $this->assertEquals(10, $lowestPriceChildrenProduct->getPrice()); + + // load full aggregation root + $lowestPriceChildProduct = $this->productRepository->get( + $lowestPriceChildrenProduct->getSku(), + false, + null, + true + ); + $lowestPriceChildProduct->setStatus(Status::STATUS_DISABLED); + // update in default store scope + $currentStoreId = $this->storeManager->getStore()->getId(); + $defaultStore = $this->storeManager->getDefaultStoreView(); + $this->storeManager->setCurrentStore($defaultStore->getId()); + $this->productRepository->save($lowestPriceChildProduct); + $this->storeManager->setCurrentStore($currentStoreId); + + $lowestPriceChildrenProducts = $this->lowestPriceOptionsProvider->getProducts($configurableProduct); + $this->assertCount(1, $lowestPriceChildrenProducts); + $lowestPriceChildrenProduct = reset($lowestPriceChildrenProducts); + $this->assertEquals(20, $lowestPriceChildrenProduct->getPrice()); + } + /** * @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..170d186e20af812a1c40bc4937559c6d5342942a --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Deploy/Console/Command/App/ApplicationDumpCommandTest.php @@ -0,0 +1,111 @@ +<?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\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 ObjectManagerInterface + */ + private $objectManager; + + /** + * @var DeploymentConfig\Reader + */ + private $reader; + + public function setUp() + { + $this->objectManager = Bootstrap::getObjectManager(); + $this->reader = $this->objectManager->get(DeploymentConfig\Reader::class); + } + + /** + * @magentoDbIsolation enabled + * @magentoDataFixture Magento/Deploy/_files/config_data.php + */ + public function testExecute() + { + $this->objectManager->configure([ + \Magento\Config\Model\Config\Export\ExcludeList::class => [ + 'arguments' => [ + 'configs' => [ + 'web/test/test_value_1' => '', + 'web/test/test_value_2' => '', + 'web/test/test_sensitive' => '1', + ], + ], + ], + ]); + + $comment = 'The configuration file doesn\'t contain sensitive data for security reasons. ' + . 'Sensitive data can be stored in the following environment variables:' + . "\nCONFIG__DEFAULT__WEB__TEST__TEST_SENSITIVE for web/test/test_sensitive"; + $outputMock = $this->getMock(OutputInterface::class); + $outputMock->expects($this->at(0)) + ->method('writeln') + ->with(['system' => $comment]); + $outputMock->expects($this->at(1)) + ->method('writeln') + ->with('<info>Done.</info>'); + + /** @var ApplicationDumpCommand command */ + $command = $this->objectManager->create(ApplicationDumpCommand::class); + $command->run($this->getMock(InputInterface::class), $outputMock); + + $config = $this->reader->loadConfigFile(ConfigFilePool::APP_CONFIG, $this->getFileName()); + + $this->assertArrayHasKey( + 'test_value_1', + $config['system']['default']['web']['test'] + ); + $this->assertArrayHasKey( + 'test_value_2', + $config['system']['default']['web']['test'] + ); + $this->assertArrayNotHasKey( + 'test_sensitive', + $config['system']['default']['web']['test'] + ); + } + + public function tearDown() + { + $file = $this->getFileName(); + /** @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(); + } + + /** + * @return string + */ + private function getFileName() + { + /** @var ConfigFilePool $configFilePool */ + $configFilePool = $this->objectManager->get(ConfigFilePool::class); + $filePool = $configFilePool->getInitialFilePools(); + + return $filePool[ConfigFilePool::LOCAL][ConfigFilePool::APP_CONFIG]; + } +} diff --git a/dev/tests/integration/testsuite/Magento/Deploy/_files/config_data.php b/dev/tests/integration/testsuite/Magento/Deploy/_files/config_data.php new file mode 100644 index 0000000000000000000000000000000000000000..bd8e69262e1e03f98b3ce41735bbf2264e234292 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Deploy/_files/config_data.php @@ -0,0 +1,33 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +$configData = [ + 'default' => [ + '' => [ + 'web/test/test_value_1' => 'http://local2.test/', + 'web/test/test_value_2' => 5, + 'web/test/test_sensitive' => 10, + ] + ], +]; + +$objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); +$configFactory = $objectManager->create(\Magento\Config\Model\Config\Factory::class); + +foreach ($configData as $scope => $data) { + foreach ($data as $scopeCode => $scopeData) { + foreach ($scopeData as $path => $value) { + $config = $configFactory->create(); + $config->setCope($scope); + + if ($scopeCode) { + $config->setScopeCode($scopeCode); + } + + $config->setDataByPath($path, $value); + $config->save(); + } + } +} diff --git a/dev/tests/integration/testsuite/Magento/Directory/Block/DataTest.php b/dev/tests/integration/testsuite/Magento/Directory/Block/DataTest.php new file mode 100644 index 0000000000000000000000000000000000000000..b0c08ed1792fc8f17b42d263436b4701bf865d7c --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Directory/Block/DataTest.php @@ -0,0 +1,38 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Directory\Block; + +use Magento\TestFramework\Helper\CacheCleaner; + +class DataTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var \Magento\Directory\Block\Data + */ + private $block; + + protected function setUp() + { + $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); + $this->block = $objectManager->get(\Magento\Directory\Block\Data::class); + } + + public function testGetCountryHtmlSelect() + { + CacheCleaner::cleanAll(); + $result = $this->block->getCountryHtmlSelect(); + $resultTwo = $this->block->getCountryHtmlSelect(); + $this->assertEquals($result, $resultTwo); + } + + public function testGetRegionHtmlSelect() + { + CacheCleaner::cleanAll(); + $result = $this->block->getRegionHtmlSelect(); + $resultTwo = $this->block->getRegionHtmlSelect(); + $this->assertEquals($result, $resultTwo); + } +} diff --git a/dev/tests/integration/testsuite/Magento/Directory/Model/ObserverTest.php b/dev/tests/integration/testsuite/Magento/Directory/Model/ObserverTest.php index 389fd4b253eb7c8e8a89237f1b7a20be9aa777fe..95fd6110bb432e72daa2af66d7b65f7abbdb3d0f 100644 --- a/dev/tests/integration/testsuite/Magento/Directory/Model/ObserverTest.php +++ b/dev/tests/integration/testsuite/Magento/Directory/Model/ObserverTest.php @@ -62,12 +62,12 @@ class ObserverTest extends \PHPUnit_Framework_TestCase { //skipping test if service is unavailable $url = str_replace('{{CURRENCY_FROM}}', 'USD', - \Magento\Directory\Model\Currency\Import\Webservicex::CURRENCY_CONVERTER_URL + \Magento\Directory\Model\Currency\Import\Webservicex::CURRENCY_CONVERTER_URL ); $url = str_replace('{{CURRENCY_TO}}', 'GBP', $url); try { file_get_contents($url); - } catch (\PHPUnit_Framework_Error_Warning $e) { + } catch (\PHPUnit_Framework_Exception $e) { $this->markTestSkipped('http://www.webservicex.net is unavailable '); } diff --git a/dev/tests/integration/testsuite/Magento/DownloadableImportExport/Model/Import/Product/Type/DownloadableTest.php b/dev/tests/integration/testsuite/Magento/DownloadableImportExport/Model/Import/Product/Type/DownloadableTest.php index 8db369facf97f4d61dd8468dd34db67b5250bf13..d25e0406882377e1ef5e6ab89c21bf5a1368496c 100644 --- a/dev/tests/integration/testsuite/Magento/DownloadableImportExport/Model/Import/Product/Type/DownloadableTest.php +++ b/dev/tests/integration/testsuite/Magento/DownloadableImportExport/Model/Import/Product/Type/DownloadableTest.php @@ -5,9 +5,7 @@ */ namespace Magento\DownloadableImportExport\Model\Import\Product\Type; -use Magento\Framework\App\Bootstrap; use Magento\Framework\App\Filesystem\DirectoryList; -use Magento\ImportExport\Model\Import; /** * @magentoAppArea adminhtml diff --git a/dev/tests/integration/testsuite/Magento/Eav/Model/ConfigTest.php b/dev/tests/integration/testsuite/Magento/Eav/Model/ConfigTest.php new file mode 100644 index 0000000000000000000000000000000000000000..4cb90c2c98c56185f99f3b1e1759fc40aa73d179 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Eav/Model/ConfigTest.php @@ -0,0 +1,40 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Eav\Model; + +use Magento\Eav\Model\Config; +use Magento\TestFramework\ObjectManager; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\Helper\CacheCleaner; + +class ConfigTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var Config + */ + private $config; + + /** + * @var ObjectManager + */ + private $objectManager; + + protected function setUp() + { + $this->objectManager = Bootstrap::getObjectManager(); + $this->config = $this->objectManager->get(Config::class); + } + + public function testGetEntityAttributeCodes() + { + $entityType = 'catalog_product'; + CacheCleaner::cleanAll(); + $this->assertEquals( + $this->config->getEntityAttributeCodes($entityType), + $this->config->getEntityAttributeCodes($entityType) + ); + } +} 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/App/Config/InitialTest.php b/dev/tests/integration/testsuite/Magento/Framework/App/Config/InitialTest.php new file mode 100644 index 0000000000000000000000000000000000000000..a98704a130b3bb74c2fc14df9d7b2d4efa0205f8 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Framework/App/Config/InitialTest.php @@ -0,0 +1,55 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Framework\App\Config; + +use Magento\TestFramework\Helper\CacheCleaner; +use Magento\TestFramework\ObjectManager; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\Framework\App\Config\Initial as Config; + +class InitialTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var ObjectManager + */ + private $objectManager; + + protected function setUp() + { + $this->objectManager = Bootstrap::getObjectManager(); + } + + public function testGetMetadata() + { + CacheCleaner::cleanAll(); + $this->assertEquals( + $this->objectManager->create(Config::class)->getMetadata(), + $this->objectManager->create(Config::class)->getMetadata() + ); + } + + /** + * @param string $scope + * @dataProvider getDataDataProvider + */ + public function testGetData($scope) + { + CacheCleaner::cleanAll(); + $this->assertEquals( + $this->objectManager->create(Config::class)->getData($scope), + $this->objectManager->create(Config::class)->getData($scope) + ); + } + + public function getDataDataProvider() + { + return [ + ['default'], + ['stores|default'], + ['websites|default'] + ]; + } +} diff --git a/dev/tests/integration/testsuite/Magento/Framework/App/ObjectManager/ConfigLoaderTest.php b/dev/tests/integration/testsuite/Magento/Framework/App/ObjectManager/ConfigLoaderTest.php new file mode 100644 index 0000000000000000000000000000000000000000..30e9c09e9b4c5b834a4e071ed3d74be1c6d27029 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Framework/App/ObjectManager/ConfigLoaderTest.php @@ -0,0 +1,33 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Framework\App\ObjectManager; + +use Magento\TestFramework\Helper\CacheCleaner; + +class ConfigLoaderTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var \Magento\Framework\App\ObjectManager\ConfigLoader + */ + private $object; + + protected function setUp() + { + $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); + $this->object = $objectManager->create( + \Magento\Framework\App\ObjectManager\ConfigLoader::class + ); + } + + public function testLoad() + { + CacheCleaner::cleanAll(); + $data = $this->object->load('global'); + $this->assertNotEmpty($data); + $cachedData = $this->object->load('global'); + $this->assertEquals($data, $cachedData); + } +} diff --git a/dev/tests/integration/testsuite/Magento/Framework/App/Route/ConfigTest.php b/dev/tests/integration/testsuite/Magento/Framework/App/Route/ConfigTest.php new file mode 100644 index 0000000000000000000000000000000000000000..d0c4b562952ba0f0b36ba88088430eb87fdb40d7 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Framework/App/Route/ConfigTest.php @@ -0,0 +1,45 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Framework\App\Route; + +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\Helper\CacheCleaner; +use Magento\TestFramework\ObjectManager; + +class ConfigTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var ObjectManager + */ + private $objectManager; + + protected function setUp() + { + $this->objectManager = Bootstrap::getObjectManager(); + } + + /** + * @param string $route + * @param string $scope + * @dataProvider getRouteFrontNameDataProvider + */ + public function testGetRouteFrontName($route, $scope) + { + CacheCleaner::cleanAll(); + $this->assertEquals( + $this->objectManager->create(Config::class)->getRouteFrontName($route, $scope), + $this->objectManager->create(Config::class)->getRouteFrontName($route, $scope) + ); + } + + public function getRouteFrontNameDataProvider() + { + return [ + ['adminhtml', 'adminhtml'], + ['catalog', 'frontend'], + ]; + } +} diff --git a/dev/tests/integration/testsuite/Magento/Framework/Interception/AbstractPlugin.php b/dev/tests/integration/testsuite/Magento/Framework/Interception/AbstractPlugin.php index 5c0406ec372a5b0055bca2ef1171ea0d7841282f..43b962851c3bfb68fe9aa0e0a20711266f50aebc 100644 --- a/dev/tests/integration/testsuite/Magento/Framework/Interception/AbstractPlugin.php +++ b/dev/tests/integration/testsuite/Magento/Framework/Interception/AbstractPlugin.php @@ -71,6 +71,7 @@ abstract class AbstractPlugin extends \PHPUnit_Framework_TestCase $definitions ); $interceptionDefinitions = new Definition\Runtime(); + $json = new \Magento\Framework\Serialize\Serializer\Json(); $sharedInstances = [ \Magento\Framework\Config\CacheInterface::class => $cache, \Magento\Framework\Config\ScopeInterface::class => $configScope, @@ -79,7 +80,8 @@ abstract class AbstractPlugin extends \PHPUnit_Framework_TestCase \Magento\Framework\ObjectManager\ConfigInterface::class => $config, \Magento\Framework\Interception\ObjectManager\ConfigInterface::class => $config, \Magento\Framework\ObjectManager\DefinitionInterface::class => $definitions, - \Magento\Framework\Interception\DefinitionInterface::class => $interceptionDefinitions + \Magento\Framework\Interception\DefinitionInterface::class => $interceptionDefinitions, + \Magento\Framework\Serialize\SerializerInterface::class => $json, ]; $this->_objectManager = new \Magento\Framework\ObjectManager\ObjectManager( $factory, diff --git a/dev/tests/integration/testsuite/Magento/Framework/Reflection/MethodsMapTest.php b/dev/tests/integration/testsuite/Magento/Framework/Reflection/MethodsMapTest.php new file mode 100644 index 0000000000000000000000000000000000000000..992b6a59382e7c3b5e67e6f8e3b6df6dfbaad2ab --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Framework/Reflection/MethodsMapTest.php @@ -0,0 +1,48 @@ +<?php +/** + * Test case for \Magento\Framework\Profiler + * + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Framework\Reflection; + +use Magento\TestFramework\Helper\CacheCleaner; + +class MethodsMapTest extends \PHPUnit_Framework_TestCase +{ + /** @var \Magento\Framework\Reflection\MethodsMap */ + private $object; + + protected function setUp() + { + $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); + $this->object = $objectManager->create( + \Magento\Framework\Reflection\MethodsMap::class + ); + } + + public function testGetMethodsMap() + { + CacheCleaner::cleanAll(); + $data = $this->object->getMethodsMap(\Magento\Framework\Reflection\MethodsMap::class); + $this->assertArrayHasKey('getMethodsMap', $data); + $cachedData = $this->object->getMethodsMap(\Magento\Framework\Reflection\MethodsMap::class); + $this->assertEquals($data, $cachedData); + } + + public function testGetMethodParams() + { + CacheCleaner::cleanAll(); + $data = $this->object->getMethodParams( + \Magento\Framework\Reflection\MethodsMap::class, + 'getMethodParams' + ); + $this->assertCount(2, $data); + $cachedData = $this->object->getMethodParams( + \Magento\Framework\Reflection\MethodsMap::class, + 'getMethodParams' + ); + $this->assertEquals($data, $cachedData); + } +} 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..93043a5deb12ae36c324ee56208124b1d5bccfd9 100644 --- a/dev/tests/integration/testsuite/Magento/Framework/TranslateTest.php +++ b/dev/tests/integration/testsuite/Magento/Framework/TranslateTest.php @@ -6,13 +6,18 @@ namespace Magento\Framework; use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\Helper\CacheCleaner; /** + * @magentoAppIsolation enabled * @magentoCache all disabled * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class TranslateTest extends \PHPUnit_Framework_TestCase { + /** @var \Magento\Framework\Translate */ + private $translate; + protected function setUp() { /** @var \Magento\Framework\View\FileSystem $viewFileSystem */ @@ -36,6 +41,7 @@ class TranslateTest extends \PHPUnit_Framework_TestCase $viewFileSystem->expects($this->any())->method('getDesignTheme')->will($this->returnValue($theme)); + /** @var \Magento\TestFramework\ObjectManager $objectManager */ $objectManager = Bootstrap::getObjectManager(); $objectManager->addSharedInstance($viewFileSystem, \Magento\Framework\View\FileSystem::class); @@ -71,19 +77,31 @@ class TranslateTest extends \PHPUnit_Framework_TestCase $objectManager->addSharedInstance($designModel, \Magento\Theme\Model\View\Design\Proxy::class); - $model = $objectManager->create(\Magento\Framework\Translate::class); - $objectManager->addSharedInstance($model, \Magento\Framework\Translate::class); + $this->translate = $objectManager->create(\Magento\Framework\Translate::class); + $objectManager->addSharedInstance($this->translate, \Magento\Framework\Translate::class); $objectManager->removeSharedInstance(\Magento\Framework\Phrase\Renderer\Composite::class); $objectManager->removeSharedInstance(\Magento\Framework\Phrase\Renderer\Translate::class); - \Magento\Framework\Phrase::setRenderer($objectManager->get(\Magento\Framework\Phrase\RendererInterface::class)); - $model->loadData(\Magento\Framework\App\Area::AREA_FRONTEND); + \Magento\Framework\Phrase::setRenderer( + $objectManager->get(\Magento\Framework\Phrase\RendererInterface::class) + ); + } + + public function testLoadData() + { + $data = $this->translate->loadData(null, true)->getData(); + CacheCleaner::cleanAll(); + $this->translate->loadData()->getData(); + $dataCached = $this->translate->loadData()->getData(); + $this->assertEquals($data, $dataCached); } /** + * @magentoCache all disabled * @dataProvider translateDataProvider */ public function testTranslate($inputText, $expectedTranslation) { + $this->translate->loadData(\Magento\Framework\App\Area::AREA_FRONTEND); $actualTranslation = new \Magento\Framework\Phrase($inputText); $this->assertEquals($expectedTranslation, $actualTranslation); } diff --git a/dev/tests/integration/testsuite/Magento/Framework/View/Element/UiComponent/Config/Provider/TemplateTest.php b/dev/tests/integration/testsuite/Magento/Framework/View/Element/UiComponent/Config/Provider/TemplateTest.php new file mode 100644 index 0000000000000000000000000000000000000000..d2e5ab7215ff00fa76428d027d8289f7bb2dc3bb --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Framework/View/Element/UiComponent/Config/Provider/TemplateTest.php @@ -0,0 +1,79 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Framework\View\Element\UiComponent\Config\Provider; + +use \Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\Helper\CacheCleaner; + +/** + * @magentoComponentsDir Magento/Framework/View/_files/UiComponent/theme + * @magentoAppIsolation enabled + * @magentoDbIsolation enabled + */ +class TemplateTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var \Magento\Framework\ObjectManagerInterface + */ + private $objectManager; + + /** + * @var \Magento\Framework\View\Element\UiComponent\Config\Provider\Template + */ + private $model; + + protected function setUp() + { + $this->objectManager = Bootstrap::getObjectManager(); + $this->registerThemes(); + $this->objectManager->addSharedInstance( + $this->objectManager->create( + \Magento\Framework\App\Arguments\ValidationState::class, + ['appMode' => 'default'] + ), + \Magento\Framework\App\Arguments\ValidationState::class + ); + $this->model = $this->objectManager->create( + \Magento\Framework\View\Element\UiComponent\Config\Provider\Template::class + ); + } + + public function testGetTemplate() + { + $expected = file_get_contents(__DIR__ . '/../../../../_files/UiComponent/expected/config.xml'); + + \Magento\TestFramework\Helper\Bootstrap::getInstance()->loadArea('adminhtml'); + $this->objectManager->get(\Magento\Framework\View\DesignInterface::class) + ->setDesignTheme('FrameworkViewUiComponent/default'); + CacheCleaner::cleanAll(); + + $resultOne = $this->model->getTemplate('test.xml'); + $resultTwo = $this->model->getTemplate('test.xml'); + + $this->assertXmlStringEqualsXmlString($expected, $resultOne); + $this->assertXmlStringEqualsXmlString($expected, $resultTwo); + } + + /** + * Register themes in the fixture folder + */ + protected function registerThemes() + { + /** @var \Magento\Theme\Model\Theme\Registration $registration */ + $registration = $this->objectManager->get( + \Magento\Theme\Model\Theme\Registration::class + ); + $registration->register(); + } + + protected function tearDown() + { + $this->objectManager->removeSharedInstance( + \Magento\Framework\App\Arguments\ValidationState::class + ); + } +} diff --git a/dev/tests/integration/testsuite/Magento/Framework/View/_files/UiComponent/expected/config.xml b/dev/tests/integration/testsuite/Magento/Framework/View/_files/UiComponent/expected/config.xml new file mode 100644 index 0000000000000000000000000000000000000000..467afb2004cbe9d85b92ef8aba0778abec26a420 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Framework/View/_files/UiComponent/expected/config.xml @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<form xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Ui:etc/ui_configuration.xsd"> + <argument name="data" xsi:type="array" type="array"> + <item name="buttons" xsi:type="array"> + <item name="save" xsi:type="string">Magento\Catalog\Block\Adminhtml\Product\Edit\Button\CreateCategory</item> + </item> + <item name="js_config" xsi:type="array"> + <item name="provider" xsi:type="string">new_category_form.new_category_form_data_source</item> + </item> + </argument> +</form> diff --git a/dev/tests/integration/testsuite/Magento/Framework/View/_files/UiComponent/theme/Magento_Catalog/ui_component/test.xml b/dev/tests/integration/testsuite/Magento/Framework/View/_files/UiComponent/theme/Magento_Catalog/ui_component/test.xml new file mode 100644 index 0000000000000000000000000000000000000000..e0bd296bfda2b1d9096b115e2176b2df17059648 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Framework/View/_files/UiComponent/theme/Magento_Catalog/ui_component/test.xml @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<form xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Ui:etc/ui_configuration.xsd"> + <argument name="data" xsi:type="array"> + <item name="js_config" xsi:type="array"> + <item name="provider" xsi:type="string">new_category_form.new_category_form_data_source</item> + </item> + </argument> +</form> diff --git a/dev/tests/integration/testsuite/Magento/Framework/View/_files/UiComponent/theme/Magento_Customer/ui_component/test.xml b/dev/tests/integration/testsuite/Magento/Framework/View/_files/UiComponent/theme/Magento_Customer/ui_component/test.xml new file mode 100644 index 0000000000000000000000000000000000000000..c1e0d46aee53e82eba40994f545231974c2b3523 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Framework/View/_files/UiComponent/theme/Magento_Customer/ui_component/test.xml @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<form xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Ui:etc/ui_configuration.xsd"> + <argument name="data" xsi:type="array"> + <item name="buttons" xsi:type="array"> + <item name="save" xsi:type="string">Magento\Catalog\Block\Adminhtml\Product\Edit\Button\CreateCategory</item> + </item> + </argument> +</form> diff --git a/dev/tests/integration/testsuite/Magento/Framework/View/_files/UiComponent/theme/registration.php b/dev/tests/integration/testsuite/Magento/Framework/View/_files/UiComponent/theme/registration.php new file mode 100644 index 0000000000000000000000000000000000000000..42145b38953bdf25371d3a8eaf83b9889c7e27d1 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Framework/View/_files/UiComponent/theme/registration.php @@ -0,0 +1,11 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +\Magento\Framework\Component\ComponentRegistrar::register( + \Magento\Framework\Component\ComponentRegistrar::THEME, + 'adminhtml/FrameworkViewUiComponent/default', + __DIR__ +); diff --git a/dev/tests/integration/testsuite/Magento/Framework/View/_files/UiComponent/theme/theme.xml b/dev/tests/integration/testsuite/Magento/Framework/View/_files/UiComponent/theme/theme.xml new file mode 100644 index 0000000000000000000000000000000000000000..96de1f7bebee0d46e22e984e97ae61983e6cd5ca --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Framework/View/_files/UiComponent/theme/theme.xml @@ -0,0 +1,9 @@ +<!-- +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<theme xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Config/etc/theme.xsd"> + <title>Test theme</title> +</theme> diff --git a/dev/tests/integration/testsuite/Magento/Paypal/Model/Express/CheckoutTest.php b/dev/tests/integration/testsuite/Magento/Paypal/Model/Express/CheckoutTest.php index c64500fa6cfec3aed4a33cbcbc262befa1621d5c..c2bc02893e042de06cce4023d943110a693aeeca 100644 --- a/dev/tests/integration/testsuite/Magento/Paypal/Model/Express/CheckoutTest.php +++ b/dev/tests/integration/testsuite/Magento/Paypal/Model/Express/CheckoutTest.php @@ -34,7 +34,7 @@ class CheckoutTest extends \PHPUnit_Framework_TestCase /** * Verify that an order placed with an existing customer can re-use the customer addresses. * - * @magentoDataFixture Magento/Paypal/_files/quote_payment_express_with_customer.php + * @magentoDataFixture Magento/Paypal/_files/quote_express_with_customer.php * @magentoAppIsolation enabled * @magentoDbIsolation enabled */ @@ -74,7 +74,7 @@ class CheckoutTest extends \PHPUnit_Framework_TestCase /** * Verify that after placing the order, addresses are associated with the order and the quote is a guest quote. * - * @magentoDataFixture Magento/Paypal/_files/quote_payment_express.php + * @magentoDataFixture Magento/Paypal/_files/quote_express.php * @magentoAppIsolation enabled * @magentoDbIsolation enabled */ diff --git a/dev/tests/integration/testsuite/Magento/Paypal/_files/quote_express.php b/dev/tests/integration/testsuite/Magento/Paypal/_files/quote_express.php new file mode 100644 index 0000000000000000000000000000000000000000..0be18cdcaf9e42e2beb792596d0819b3c7a46182 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Paypal/_files/quote_express.php @@ -0,0 +1,95 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +\Magento\TestFramework\Helper\Bootstrap::getInstance()->loadArea('adminhtml'); +\Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get( + \Magento\Framework\App\Config\MutableScopeConfigInterface::class +)->setValue( + 'carriers/flatrate/active', + 1, + \Magento\Store\Model\ScopeInterface::SCOPE_STORE +); +\Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get( + \Magento\Framework\App\Config\MutableScopeConfigInterface::class +)->setValue( + 'payment/paypal_express/active', + 1, + \Magento\Store\Model\ScopeInterface::SCOPE_STORE +); +$objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); +/** @var $product \Magento\Catalog\Model\Product */ +$product = $objectManager->create(\Magento\Catalog\Model\Product::class); +$product->setTypeId('simple') + ->setId(1) + ->setAttributeSetId(4) + ->setName('Simple Product') + ->setSku('simple') + ->setPrice(10) + ->setVisibility(\Magento\Catalog\Model\Product\Visibility::VISIBILITY_BOTH) + ->setStatus(\Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_ENABLED) + ->setStockData( + [ + 'qty' => 100, + 'is_in_stock' => 1, + ] + )->save(); +$product->load(1); + +$billingData = [ + 'firstname' => 'testname', + 'lastname' => 'lastname', + 'company' => '', + 'email' => 'test@com.com', + 'street' => [ + 0 => 'test1', + 1 => '', + ], + 'city' => 'Test', + 'region_id' => '1', + 'region' => '', + 'postcode' => '9001', + 'country_id' => 'US', + 'telephone' => '11111111', + 'fax' => '', + 'confirm_password' => '', + 'save_in_address_book' => '1', + 'use_for_shipping' => '1', +]; + +$billingAddress = \Magento\TestFramework\Helper\Bootstrap::getObjectManager() + ->create(\Magento\Quote\Model\Quote\Address::class, ['data' => $billingData]); +$billingAddress->setAddressType('billing'); + +$shippingAddress = clone $billingAddress; +$shippingAddress->setId(null)->setAddressType('shipping'); +$shippingAddress->setShippingMethod('flatrate_flatrate'); +$shippingAddress->setCollectShippingRates(true); + +/** @var $quote \Magento\Quote\Model\Quote */ +$quote = $objectManager->create(\Magento\Quote\Model\Quote::class); +$quote->setCustomerIsGuest( + true +)->setStoreId( + $objectManager->get( + \Magento\Store\Model\StoreManagerInterface::class + )->getStore()->getId() +)->setReservedOrderId( + '100000002' +)->setBillingAddress( + $billingAddress +)->setShippingAddress( + $shippingAddress +)->addProduct( + $product, + 10 +); +$quote->getShippingAddress()->setShippingMethod('flatrate_flatrate'); +$quote->getShippingAddress()->setCollectShippingRates(true); +$quote->getPayment()->setMethod(\Magento\Paypal\Model\Config::METHOD_WPS_EXPRESS); + +$quoteRepository = $objectManager->get(\Magento\Quote\Api\CartRepositoryInterface::class); +$quoteRepository->save($quote); +$quote = $quoteRepository->get($quote->getId()); +$quote->setCustomerEmail('admin@example.com'); diff --git a/dev/tests/integration/testsuite/Magento/Paypal/_files/quote_express_with_customer.php b/dev/tests/integration/testsuite/Magento/Paypal/_files/quote_express_with_customer.php new file mode 100644 index 0000000000000000000000000000000000000000..c319e298d1e50d56cdc886dd789d6c36941e8a4e --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Paypal/_files/quote_express_with_customer.php @@ -0,0 +1,77 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +require __DIR__ . '/../../Customer/_files/customer.php'; +require __DIR__ . '/../../Customer/_files/customer_two_addresses.php'; + +\Magento\TestFramework\Helper\Bootstrap::getInstance()->loadArea('adminhtml'); + +$objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); + +$objectManager->get( + \Magento\Framework\App\Config\MutableScopeConfigInterface::class +)->setValue('carriers/flatrate/active', 1, \Magento\Store\Model\ScopeInterface::SCOPE_STORE); +$objectManager->get(\Magento\Framework\App\Config\MutableScopeConfigInterface::class) + ->setValue('payment/paypal_express/active', 1, \Magento\Store\Model\ScopeInterface::SCOPE_STORE); + +/** @var \Magento\Customer\Api\CustomerRepositoryInterface $customerRepository */ +$customerRepository = $objectManager->create(\Magento\Customer\Api\CustomerRepositoryInterface::class); +$customer = $customerRepository->getById(1); + +/** @var $product \Magento\Catalog\Model\Product */ +$product = $objectManager->create(\Magento\Catalog\Model\Product::class); +$product->setTypeId('simple') + ->setId(1) + ->setAttributeSetId(4) + ->setName('Simple Product') + ->setSku('simple') + ->setPrice(10) + ->setStockData([ + 'use_config_manage_stock' => 1, + 'qty' => 100, + 'is_qty_decimal' => 0, + 'is_in_stock' => 100, + ]) + ->setVisibility(\Magento\Catalog\Model\Product\Visibility::VISIBILITY_BOTH) + ->setStatus(\Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_ENABLED) + ->save(); +$product->load(1); + +$customerBillingAddress = $objectManager->create(\Magento\Customer\Model\Address::class); +$customerBillingAddress->load(1); +$billingAddressDataObject = $customerBillingAddress->getDataModel(); +$billingAddress = $objectManager->create(\Magento\Quote\Model\Quote\Address::class); +$billingAddress->importCustomerAddressData($billingAddressDataObject); +$billingAddress->setAddressType('billing'); + +/** @var \Magento\Customer\Model\Address $customerShippingAddress */ +$customerShippingAddress = $objectManager->create(\Magento\Customer\Model\Address::class); +$customerShippingAddress->load(2); +$shippingAddressDataObject = $customerShippingAddress->getDataModel(); +$shippingAddress = $objectManager->create(\Magento\Quote\Model\Quote\Address::class); +$shippingAddress->importCustomerAddressData($shippingAddressDataObject); +$shippingAddress->setAddressType('shipping'); + +$shippingAddress->setShippingMethod('flatrate_flatrate'); +$shippingAddress->setCollectShippingRates(true); + +/** @var $quote \Magento\Quote\Model\Quote */ +$quote = $objectManager->create(\Magento\Quote\Model\Quote::class); +$quote->setCustomerIsGuest(false) + ->setCustomerId($customer->getId()) + ->setCustomer($customer) + ->setStoreId($objectManager->get(\Magento\Store\Model\StoreManagerInterface::class)->getStore()->getId()) + ->setReservedOrderId('test02') + ->setBillingAddress($billingAddress) + ->setShippingAddress($shippingAddress) + ->addProduct($product, 10); +$quote->getShippingAddress()->setShippingMethod('flatrate_flatrate'); +$quote->getShippingAddress()->setCollectShippingRates(true); +$quote->getPayment()->setMethod(\Magento\Paypal\Model\Config::METHOD_WPS_EXPRESS); + +/** @var \Magento\Quote\Api\CartRepositoryInterface $quoteRepository */ +$quoteRepository = $objectManager->create(\Magento\Quote\Api\CartRepositoryInterface::class); +$quoteRepository->save($quote); +$quote = $quoteRepository->get($quote->getId()); diff --git a/dev/tests/integration/testsuite/Magento/Paypal/_files/quote_payment_express.php b/dev/tests/integration/testsuite/Magento/Paypal/_files/quote_payment_express.php index fa234cc444a0730a580d35400483c0f2ee92e416..90f1102e0ec7639910c83dd76d37d0b0e36eef25 100644 --- a/dev/tests/integration/testsuite/Magento/Paypal/_files/quote_payment_express.php +++ b/dev/tests/integration/testsuite/Magento/Paypal/_files/quote_payment_express.php @@ -3,96 +3,7 @@ * Copyright © 2016 Magento. All rights reserved. * See COPYING.txt for license details. */ -\Magento\TestFramework\Helper\Bootstrap::getInstance()->loadArea('adminhtml'); -\Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get( - \Magento\Framework\App\Config\MutableScopeConfigInterface::class -)->setValue( - 'carriers/flatrate/active', - 1, - \Magento\Store\Model\ScopeInterface::SCOPE_STORE -); -\Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get( - \Magento\Framework\App\Config\MutableScopeConfigInterface::class -)->setValue( - 'payment/paypal_express/active', - 1, - \Magento\Store\Model\ScopeInterface::SCOPE_STORE -); -$objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); -/** @var $product \Magento\Catalog\Model\Product */ -$product = $objectManager->create(\Magento\Catalog\Model\Product::class); -$product->setTypeId('simple') - ->setId(1) - ->setAttributeSetId(4) - ->setName('Simple Product') - ->setSku('simple') - ->setPrice(10) - ->setVisibility(\Magento\Catalog\Model\Product\Visibility::VISIBILITY_BOTH) - ->setStatus(\Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_ENABLED) - ->setStockData( - [ - 'qty' => 100, - 'is_in_stock' => 1, - ] - )->save(); -$product->load(1); - -$billingData = [ - 'firstname' => 'testname', - 'lastname' => 'lastname', - 'company' => '', - 'email' => 'test@com.com', - 'street' => [ - 0 => 'test1', - 1 => '', - ], - 'city' => 'Test', - 'region_id' => '1', - 'region' => '', - 'postcode' => '9001', - 'country_id' => 'US', - 'telephone' => '11111111', - 'fax' => '', - 'confirm_password' => '', - 'save_in_address_book' => '1', - 'use_for_shipping' => '1', -]; - -$billingAddress = \Magento\TestFramework\Helper\Bootstrap::getObjectManager() - ->create(\Magento\Quote\Model\Quote\Address::class, ['data' => $billingData]); -$billingAddress->setAddressType('billing'); - -$shippingAddress = clone $billingAddress; -$shippingAddress->setId(null)->setAddressType('shipping'); -$shippingAddress->setShippingMethod('flatrate_flatrate'); -$shippingAddress->setCollectShippingRates(true); - -/** @var $quote \Magento\Quote\Model\Quote */ -$quote = $objectManager->create(\Magento\Quote\Model\Quote::class); -$quote->setCustomerIsGuest( - true -)->setStoreId( - $objectManager->get( - \Magento\Store\Model\StoreManagerInterface::class - )->getStore()->getId() -)->setReservedOrderId( - '100000002' -)->setBillingAddress( - $billingAddress -)->setShippingAddress( - $shippingAddress -)->addProduct( - $product, - 10 -); -$quote->getShippingAddress()->setShippingMethod('flatrate_flatrate'); -$quote->getShippingAddress()->setCollectShippingRates(true); -$quote->getPayment()->setMethod(\Magento\Paypal\Model\Config::METHOD_WPS_EXPRESS); - -$quoteRepository = $objectManager->get(\Magento\Quote\Api\CartRepositoryInterface::class); -$quoteRepository->save($quote); -$quote = $quoteRepository->get($quote->getId()); -$quote->setCustomerEmail('admin@example.com'); +require __DIR__ . '/quote_express.php'; /** @var $service \Magento\Quote\Api\CartManagementInterface */ $service = \Magento\TestFramework\Helper\Bootstrap::getObjectManager() diff --git a/dev/tests/integration/testsuite/Magento/Paypal/_files/quote_payment_express_with_customer.php b/dev/tests/integration/testsuite/Magento/Paypal/_files/quote_payment_express_with_customer.php index 1c6793f05dea95644067521332900cc647a3648e..eaf444be13367f8769d28e34245c007122b79bf1 100644 --- a/dev/tests/integration/testsuite/Magento/Paypal/_files/quote_payment_express_with_customer.php +++ b/dev/tests/integration/testsuite/Magento/Paypal/_files/quote_payment_express_with_customer.php @@ -3,79 +3,7 @@ * Copyright © 2016 Magento. All rights reserved. * See COPYING.txt for license details. */ - -require __DIR__ . '/../../Customer/_files/customer.php'; -require __DIR__ . '/../../Customer/_files/customer_two_addresses.php'; - -\Magento\TestFramework\Helper\Bootstrap::getInstance()->loadArea('adminhtml'); - -$objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); - -$objectManager->get( - \Magento\Framework\App\Config\MutableScopeConfigInterface::class -)->setValue('carriers/flatrate/active', 1, \Magento\Store\Model\ScopeInterface::SCOPE_STORE); -$objectManager->get(\Magento\Framework\App\Config\MutableScopeConfigInterface::class) - ->setValue('payment/paypal_express/active', 1, \Magento\Store\Model\ScopeInterface::SCOPE_STORE); - -/** @var \Magento\Customer\Api\CustomerRepositoryInterface $customerRepository */ -$customerRepository = $objectManager->create(\Magento\Customer\Api\CustomerRepositoryInterface::class); -$customer = $customerRepository->getById(1); - -/** @var $product \Magento\Catalog\Model\Product */ -$product = $objectManager->create(\Magento\Catalog\Model\Product::class); -$product->setTypeId('simple') - ->setId(1) - ->setAttributeSetId(4) - ->setName('Simple Product') - ->setSku('simple') - ->setPrice(10) - ->setStockData([ - 'use_config_manage_stock' => 1, - 'qty' => 100, - 'is_qty_decimal' => 0, - 'is_in_stock' => 100, -]) - ->setVisibility(\Magento\Catalog\Model\Product\Visibility::VISIBILITY_BOTH) - ->setStatus(\Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_ENABLED) - ->save(); -$product->load(1); - -$customerBillingAddress = $objectManager->create(\Magento\Customer\Model\Address::class); -$customerBillingAddress->load(1); -$billingAddressDataObject = $customerBillingAddress->getDataModel(); -$billingAddress = $objectManager->create(\Magento\Quote\Model\Quote\Address::class); -$billingAddress->importCustomerAddressData($billingAddressDataObject); -$billingAddress->setAddressType('billing'); - -/** @var \Magento\Customer\Model\Address $customerShippingAddress */ -$customerShippingAddress = $objectManager->create(\Magento\Customer\Model\Address::class); -$customerShippingAddress->load(2); -$shippingAddressDataObject = $customerShippingAddress->getDataModel(); -$shippingAddress = $objectManager->create(\Magento\Quote\Model\Quote\Address::class); -$shippingAddress->importCustomerAddressData($shippingAddressDataObject); -$shippingAddress->setAddressType('shipping'); - -$shippingAddress->setShippingMethod('flatrate_flatrate'); -$shippingAddress->setCollectShippingRates(true); - -/** @var $quote \Magento\Quote\Model\Quote */ -$quote = $objectManager->create(\Magento\Quote\Model\Quote::class); -$quote->setCustomerIsGuest(false) - ->setCustomerId($customer->getId()) - ->setCustomer($customer) - ->setStoreId($objectManager->get(\Magento\Store\Model\StoreManagerInterface::class)->getStore()->getId()) - ->setReservedOrderId('test02') - ->setBillingAddress($billingAddress) - ->setShippingAddress($shippingAddress) - ->addProduct($product, 10); -$quote->getShippingAddress()->setShippingMethod('flatrate_flatrate'); -$quote->getShippingAddress()->setCollectShippingRates(true); -$quote->getPayment()->setMethod(\Magento\Paypal\Model\Config::METHOD_WPS_EXPRESS); - -/** @var \Magento\Quote\Api\CartRepositoryInterface $quoteRepository */ -$quoteRepository = $objectManager->create(\Magento\Quote\Api\CartRepositoryInterface::class); -$quoteRepository->save($quote); -$quote = $quoteRepository->get($quote->getId()); +require __DIR__ . '/quote_express_with_customer.php'; /** @var $service \Magento\Quote\Api\CartManagementInterface */ $service = $objectManager->create(\Magento\Quote\Api\CartManagementInterface::class); 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/Model/StoreManagerTest.php b/dev/tests/integration/testsuite/Magento/Store/Model/StoreManagerTest.php new file mode 100644 index 0000000000000000000000000000000000000000..c42856d865649d5206df2c76de323fff521c5482 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Store/Model/StoreManagerTest.php @@ -0,0 +1,48 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Store\Model; + +use Magento\Framework\ObjectManagerInterface as ObjectManager; +use Magento\Store\Model\Store; +use Magento\Store\Model\StoreManagerInterface; +use Magento\TestFramework\Helper\Bootstrap; + +class StoreManagerTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var StoreManagerInterface + */ + private $storeManager; + + /** + * @var ObjectManager + */ + private $objectManager; + + /** + * Class dependencies initialization + * + * @return void + */ + protected function setUp() + { + $this->objectManager = Bootstrap::getObjectManager(); + $this->storeManager = $this->objectManager->get(StoreManagerInterface::class); + } + + /** + * Check that behavior of setting and getting store into StoreManager is correct + * Setting: Magento\Store\Model\StoreManagerInterface::setCurrentStore + * Getting: Magento\Store\Model\StoreManagerInterface::getStore + * + * @return void + */ + public function testDefaultStoreIdIsSetCorrectly() + { + $this->storeManager->setCurrentStore(Store::DEFAULT_STORE_ID); + $this->assertEquals(Store::DEFAULT_STORE_ID, $this->storeManager->getStore()->getId()); + } +} diff --git a/dev/tests/integration/testsuite/Magento/Store/Model/StoreResolverTest.php b/dev/tests/integration/testsuite/Magento/Store/Model/StoreResolverTest.php new file mode 100644 index 0000000000000000000000000000000000000000..b2aa803bc010599cc6a02554b9c23b36ad47b8f2 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Store/Model/StoreResolverTest.php @@ -0,0 +1,37 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Store\Model; + +use Magento\TestFramework\Helper\CacheCleaner; + +class StoreResolverTest extends \PHPUnit_Framework_TestCase +{ + /** @var \Magento\TestFramework\ObjectManager */ + private $objectManager; + + protected function setUp() + { + $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); + $this->block = $this->objectManager->get(\Magento\Directory\Block\Data::class); + } + + public function testGetStoreData() + { + $methodGetStoresData = new \ReflectionMethod(\Magento\Store\Model\StoreResolver::class, 'getStoresData'); + $methodGetStoresData->setAccessible(true); + $methodReadStoresData = new \ReflectionMethod(\Magento\Store\Model\StoreResolver::class, 'readStoresData'); + $methodReadStoresData->setAccessible(true); + + $storeResolver = $this->objectManager->get(\Magento\Store\Model\StoreResolver::class); + + $storesDataRead = $methodReadStoresData->invoke($storeResolver); + CacheCleaner::cleanAll(); + $storesData = $methodGetStoresData->invoke($storeResolver); + $storesDataCached = $methodGetStoresData->invoke($storeResolver); + $this->assertEquals($storesDataRead, $storesData); + $this->assertEquals($storesDataRead, $storesDataCached); + } +} 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/Tax/Model/Sales/Total/Quote/SubtotalTest.php b/dev/tests/integration/testsuite/Magento/Tax/Model/Sales/Total/Quote/SubtotalTest.php index 383cc31a84228631d62864e9e2f6c2d78551d9d5..41b0fdaff08c5b0b8b7291347a2a121cf0a4c68b 100644 --- a/dev/tests/integration/testsuite/Magento/Tax/Model/Sales/Total/Quote/SubtotalTest.php +++ b/dev/tests/integration/testsuite/Magento/Tax/Model/Sales/Total/Quote/SubtotalTest.php @@ -125,6 +125,7 @@ class SubtotalTest extends \PHPUnit_Framework_TestCase $this->assertEquals($expected['subtotal'], $total->getSubtotal()); $this->assertEquals($expected['subtotal'] + $expected['tax_amount'], $total->getSubtotalInclTax()); + $this->assertEquals($expected['subtotal'] + $expected['tax_amount'], $address->getBaseSubtotalTotalInclTax()); $this->assertEquals($expected['discount_amount'], $total->getDiscountAmount()); $items = $address->getAllItems(); /** @var \Magento\Quote\Model\Quote\Address\Item $item */ diff --git a/dev/tests/integration/testsuite/Magento/Theme/Model/DesignTest.php b/dev/tests/integration/testsuite/Magento/Theme/Model/DesignTest.php index 6cd9746daca3325eafcf730a462b9c0226db9ba0..f450f1b3d0cbe2309611ee673493bfdddfad9f5d 100644 --- a/dev/tests/integration/testsuite/Magento/Theme/Model/DesignTest.php +++ b/dev/tests/integration/testsuite/Magento/Theme/Model/DesignTest.php @@ -5,6 +5,9 @@ */ namespace Magento\Theme\Model; +use Magento\Backend\Block\Widget\Grid\Serializer; +use Magento\Framework\Serialize\SerializerInterface; + class DesignTest extends \PHPUnit_Framework_TestCase { /** @@ -121,7 +124,8 @@ class DesignTest extends \PHPUnit_Framework_TestCase )->load( $cacheId ); - $cachedDesign = unserialize($cachedDesign); + $serializer = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get(SerializerInterface::class); + $cachedDesign = $serializer->unserialize($cachedDesign); $this->assertInternalType('array', $cachedDesign); $this->assertArrayHasKey('design', $cachedDesign); @@ -139,7 +143,8 @@ class DesignTest extends \PHPUnit_Framework_TestCase )->load( $cacheId ); - $cachedDesign = unserialize($cachedDesign); + + $cachedDesign = $serializer->unserialize($cachedDesign); $this->assertTrue(is_array($cachedDesign)); $this->assertEquals($cachedDesign['design'], $design->getDesign()); 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/js/jasmine/tests/app/code/Magento/Review/view/frontend/web/js/process-review.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Review/view/frontend/web/js/process-review.test.js new file mode 100644 index 0000000000000000000000000000000000000000..66c9ccccb23bea8565ec37477056b69b320d092b --- /dev/null +++ b/dev/tests/js/jasmine/tests/app/code/Magento/Review/view/frontend/web/js/process-review.test.js @@ -0,0 +1,76 @@ +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +/*eslint max-nested-callbacks: 0*/ +/*jscs:disable jsDoc*/ + +define([ + 'jquery', + 'Magento_Review/js/process-reviews' +], function ($, reviewProcessor) { + 'use strict'; + + describe('Test product page reviews processor', function () { + var element, + config = { + reviewsTabSelector: '#review-tab' + }; + + beforeEach(function () { + element = $('<div id="review-tab" role="tab"></div>'); + + $('body').append(element); + }); + + afterEach(function () { + element.remove(); + }); + + it('Should automatically load reviews after page load if review tab is active', function () { + element.addClass('active'); + + spyOn($, 'ajax').and.callFake(function () { + var d = $.Deferred(); + + d.promise().complete = function () {}; + + return d.promise(); + }); + + reviewProcessor(config, null); + + expect($.ajax).toHaveBeenCalled(); + }); + + it('Should not automatically load reviews after page load if review tab is not active', function () { + spyOn($, 'ajax').and.callFake(function () { + var d = $.Deferred(); + + d.promise().complete = function () {}; + + return d.promise(); + }); + + reviewProcessor(config, null); + + expect($.ajax).not.toHaveBeenCalled(); + }); + + it('Should load reviews if non active review tab was opened', function () { + spyOn($, 'ajax').and.callFake(function () { + var d = $.Deferred(); + + d.promise().complete = function () {}; + + return d.promise(); + }); + + reviewProcessor(config, null); + element.trigger('beforeOpen'); + + expect($.ajax).toHaveBeenCalled(); + }); + }); +}); diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/element/date.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/element/date.test.js index de6b83eaf2005d06c324c3b7da997b541d305522..51a998e6eb2a04ea2e63c64933a90335dadd96cc 100644 --- a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/element/date.test.js +++ b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/element/date.test.js @@ -6,8 +6,9 @@ /*eslint max-nested-callbacks: 0*/ define([ - 'Magento_Ui/js/form/element/date' -], function (DateElement) { + 'Magento_Ui/js/form/element/date', + 'mageUtils' +], function (DateElement, utils) { 'use strict'; describe('Magento_Ui/js/form/element/date', function () { @@ -19,5 +20,12 @@ define([ }; model = new DateElement(params); }); + + it('Check prepareDateTimeFormats function', function () { + spyOn(utils, 'convertToMomentFormat'); + model.prepareDateTimeFormats(); + expect(utils.convertToMomentFormat).toHaveBeenCalled(); + }); + }); }); diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/element/select.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/element/select.test.js index db5855b0a692bb7ac0c9b75de35d228abe309016..5d75b8c595366169166d3964bbd95d988b1d5606 100644 --- a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/element/select.test.js +++ b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/element/select.test.js @@ -121,7 +121,7 @@ define([ { value: 'valLast' }]; - model.caption = false; + model.caption(''); expect(model.normalizeData('')).toEqual('valFirst'); }); }); diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/lib/ko/bind/datepicker.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/lib/ko/bind/datepicker.test.js index a8c06b7b34cc055ce052f73d0a231613f8944f1c..e5f90863ec63071f191b82b0df7fdbba0ac411fa 100644 --- a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/lib/ko/bind/datepicker.test.js +++ b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/lib/ko/bind/datepicker.test.js @@ -7,21 +7,32 @@ define([ 'ko', 'jquery', 'moment', + 'mageUtils', 'Magento_Ui/js/lib/knockout/bindings/datepicker' -], function (ko, $, moment) { +], function (ko, $, moment, utils) { 'use strict'; describe('Datepicker binding', function () { var observable, - element; + element, + config; beforeEach(function () { element = $('<input />'); observable = ko.observable(); + config = { + options : { + dateFormat: 'M/d/yy', + 'storeLocale': 'en_US', + 'timeFormat': 'h:mm: a' + }, + storage:ko.observable(moment().format('MM/DD/YYYY')) + }; + $(document.body).append(element); - ko.applyBindingsToNode(element[0], { datepicker: observable }); + ko.applyBindingsToNode(element[0], { datepicker: config }); }); afterEach(function () { @@ -29,22 +40,18 @@ define([ }); it('writes picked date\'s value to assigned observable', function () { - var openBtn, - todayBtn, - todayDate, - dateFormat, - result; + var todayDate, + momentFormat, + result, + inputFormat; - dateFormat = element.datepicker('option', 'dateFormat'); - todayDate = moment().format(dateFormat); + inputFormat = 'M/d/yy'; - openBtn = $('img.ui-datepicker-trigger'); - todayBtn = $('[data-handler="today"]'); + momentFormat = utils.convertToMomentFormat(inputFormat); - openBtn.click(); - todayBtn.click(); + todayDate = moment().format(momentFormat); - result = moment(observable()).format(dateFormat); + result = $('input:last').val(); expect(todayDate).toEqual(result); }); diff --git a/dev/tests/js/jasmine/tests/lib/mage/misc.test.js b/dev/tests/js/jasmine/tests/lib/mage/misc.test.js new file mode 100644 index 0000000000000000000000000000000000000000..a9ea5ed90192fa46e3e223802d872be0a32afba2 --- /dev/null +++ b/dev/tests/js/jasmine/tests/lib/mage/misc.test.js @@ -0,0 +1,638 @@ +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +define([ + 'mageUtils', + 'moment' +], function (utils, moment) { + 'use strict'; + + describe('mageUtils', function () { + + it('Check convertToMomentFormat function', function () { + var format, momentFormat; + + format = 'M/d/yy'; + momentFormat = 'MM/DD/YYYY'; + expect(utils.convertToMomentFormat(format)).toBe(momentFormat); + }); + + it('Check convertToMomentFormat function for all Magento supported locales', function () { + + var fixture, + localeValues, + format, + expectedValue, + momentFormat, + dt, + m, + p; + + fixture = { + 'af_ZA': { + 'locale': 'af_ZA', + 'localeInfo': { + 'format': 'y-MM-dd', + 'expectedValue': '2016-11-17' + } + }, + 'az_Latn_AZ': { + 'locale': 'az_Latn_AZ', + 'localeInfo': { + 'format': 'dd.MM.yy', + 'expectedValue': '17.11.2016' + } + }, + 'id_ID': { + 'locale': 'id_ID', + 'localeInfo': { + 'format': 'dd/MM/yy', + 'expectedValue': '17/11/2016' + } + }, + 'ms_Latn_MY': { + 'locale': 'ms_Latn_MY', + 'localeInfo': { + 'format': 'd/MM/yy', + 'expectedValue': '17/11/2016' + } + }, + 'bs_Latn_BA': { + 'locale': 'bs_Latn_BA', + 'localeInfo': { + 'format': 'dd.MM.yy.', + 'expectedValue': '17.11.2016.' + } + }, + 'ca_ES': { + 'locale': 'ca_ES', + 'localeInfo': { + 'format': 'd/M/yy', + 'expectedValue': '17/11/2016' + } + }, + 'cy_GB': { + 'locale': 'cy_GB', + 'localeInfo': { + 'format': 'dd/MM/yy', + 'expectedValue': '17/11/2016' + } + }, + 'da_DK': { + 'locale': 'da_DK', + 'localeInfo': { + 'format': 'dd/MM/y', + 'expectedValue': '17/11/2016' + } + }, + 'de_DE': { + 'locale': 'de_DE', + 'localeInfo': { + 'format': 'dd.MM.yy', + 'expectedValue': '17.11.2016' + } + }, + 'de_CH': { + 'locale': 'de_CH', + 'localeInfo': { + 'format': 'dd.MM.yy', + 'expectedValue': '17.11.2016' + } + }, + 'de_AT': { + 'locale': 'de_AT', + 'localeInfo': { + 'format': 'dd.MM.yy', + 'expectedValue': '17.11.2016' + } + }, + 'et_EE': { + 'locale': 'et_EE', + 'localeInfo': { + 'format': 'dd.MM.yy', + 'expectedValue': '17.11.2016' + } + }, + 'en_AU': { + 'locale': 'en_AU', + 'localeInfo': { + 'format': 'd/MM/y', + 'expectedValue': '17/11/2016' + } + }, + 'en_CA': { + 'locale': 'en_CA', + 'localeInfo': { + 'format': 'y-MM-dd', + 'expectedValue': '2016-11-17' + } + }, + 'en_IE': { + 'locale': 'en_IE', + 'localeInfo': { + 'format': 'dd/MM/y', + 'expectedValue': '17/11/2016' + } + }, + 'en_NZ': { + 'locale': 'en_NZ', + 'localeInfo': { + 'format': 'd/MM/yy', + 'expectedValue': '17/11/2016' + } + }, + 'en_GB': { + 'locale': 'en_GB', + 'localeInfo': { + 'format': 'dd/MM/y', + 'expectedValue': '17/11/2016' + } + }, + 'en_US': { + 'locale': 'en_US', + 'localeInfo': { + 'format': 'M/d/yy', + 'expectedValue': '11/17/2016' + } + }, + 'es_AR': { + 'locale': 'es_AR', + 'localeInfo': { + 'format': 'd/M/yy', + 'expectedValue': '17/11/2016' + } + }, + 'es_CL': { + 'locale': 'es_CL', + 'localeInfo': { + 'format': 'dd-MM-yy', + 'expectedValue': '17-11-2016' + } + }, + 'es_CO': { + 'locale': 'es_CO', + 'localeInfo': { + 'format': 'd/MM/yy', + 'expectedValue': '17/11/2016' + } + }, + 'es_CR': { + 'locale': 'es_CR', + 'localeInfo': { + 'format': 'd/M/yy', + 'expectedValue': '17/11/2016' + } + }, + 'es_ES': { + 'locale': 'es_ES', + 'localeInfo': { + 'format': 'd/M/yy', + 'expectedValue': '17/11/2016' + } + }, + 'es_MX': { + 'locale': 'es_MX', + 'localeInfo': { + 'format': 'dd/MM/yy', + 'expectedValue': '17/11/2016' + } + }, + 'es_PA': { + 'locale': 'es_PA', + 'localeInfo': { + 'format': 'MM/dd/yy', + 'expectedValue': '11/17/2016' + } + }, + 'es_PE': { + 'locale': 'es_PE', + 'localeInfo': { + 'format': 'd/MM/yy', + 'expectedValue': '17/11/2016' + } + }, + 'es_VE': { + 'locale': 'es_VE', + 'localeInfo': { + 'format': 'd/M/yy', + 'expectedValue': '17/11/2016' + } + }, + 'eu_ES': { + 'locale': 'eu_ES', + 'localeInfo': { + 'format': 'y/MM/dd', + 'expectedValue': '2016/11/17' + } + }, + 'fil_PH': { + 'locale': 'fil_PH', + 'localeInfo': { + 'format': 'M/d/yy', + 'expectedValue': '11/17/2016' + } + }, + 'fr_BE': { + 'locale': 'fr_BE', + 'localeInfo': { + 'format': 'd/MM/yy', + 'expectedValue': '17/11/2016' + } + }, + 'fr_CA': { + 'locale': 'fr_CA', + 'localeInfo': { + 'format': 'yy-MM-dd', + 'expectedValue': '2016-11-17' + } + }, + 'fr_FR': { + 'locale': 'fr_FR', + 'localeInfo': { + 'format': 'dd/MM/y', + 'expectedValue': '17/11/2016' + } + }, + 'gl_ES': { + 'locale': 'gl_ES', + 'localeInfo': { + 'format': 'dd/MM/yy', + 'expectedValue': '17/11/2016' + } + }, + 'hr_HR': { + 'locale': 'hr_HR', + 'localeInfo': { + 'format': 'dd.MM.y.', + 'expectedValue': '17.11.2016.' + } + }, + 'it_IT': { + 'locale': 'it_IT', + 'localeInfo': { + 'format': 'dd/MM/yy', + 'expectedValue': '17/11/2016' + } + }, + 'it_CH': { + 'locale': 'it_CH', + 'localeInfo': { + 'format': 'dd.MM.yy', + 'expectedValue': '17.11.2016' + } + }, + 'sw_KE': { + 'locale': 'sw_KE', + 'localeInfo': { + 'format': 'dd/MM/y', + 'expectedValue': '17/11/2016' + } + }, + 'lv_LV': { + 'locale': 'lv_LV', + 'localeInfo': { + 'format': 'dd.MM.yy', + 'expectedValue': '17.11.2016' + } + }, + 'lt_LT': { + 'locale': 'lt_LT', + 'localeInfo': { + 'format': 'y-MM-dd', + 'expectedValue': '2016-11-17' + } + }, + 'hu_HU': { + 'locale': 'hu_HU', + 'localeInfo': { + 'format': 'y. MM. dd.', + 'expectedValue': '2016. 11. 17.' + } + }, + 'nl_BE': { + 'locale': 'nl_BE', + 'localeInfo': { + 'format': 'd/MM/yy', + 'expectedValue': '17/11/2016' + } + }, + 'nl_NL': { + 'locale': 'nl_NL', + 'localeInfo': { + 'format': 'dd-MM-yy', + 'expectedValue': '17-11-2016' + } + }, + 'nb_NO': { + 'locale': 'nb_NO', + 'localeInfo': { + 'format': 'dd.MM.y', + 'expectedValue': '17.11.2016' + } + }, + 'nn_NO': { + 'locale': 'nn_NO', + 'localeInfo': { + 'format': 'dd.MM.y', + 'expectedValue': '17.11.2016' + } + }, + 'pl_PL': { + 'locale': 'pl_PL', + 'localeInfo': { + 'format': 'dd.MM.y', + 'expectedValue': '17.11.2016' + } + }, + 'pt_BR': { + 'locale': 'pt_BR', + 'localeInfo': { + 'format': 'dd/MM/yy', + 'expectedValue': '17/11/2016' + } + }, + 'pt_PT': { + 'locale': 'pt_PT', + 'localeInfo': { + 'format': 'dd/MM/yy', + 'expectedValue': '17/11/2016' + } + }, + 'ro_RO': { + 'locale': 'ro_RO', + 'localeInfo': { + 'format': 'dd.MM.y', + 'expectedValue': '17.11.2016' + } + }, + 'sq_AL': { + 'locale': 'sq_AL', + 'localeInfo': { + 'format': 'd.M.yy', + 'expectedValue': '17.11.2016' + } + }, + 'sk_SK': { + 'locale': 'sk_SK', + 'localeInfo': { + 'format': 'dd.MM.yy', + 'expectedValue': '17.11.2016' + } + }, + 'sl_SI': { + 'locale': 'sl_SI', + 'localeInfo': { + 'format': 'd. MM. yy', + 'expectedValue': '17. 11. 2016' + } + }, + 'fi_FI': { + 'locale': 'fi_FI', + 'localeInfo': { + 'format': 'd.M.y', + 'expectedValue': '17.11.2016' + } + }, + 'sv_SE': { + 'locale': 'sv_SE', + 'localeInfo': { + 'format': 'y-MM-dd', + 'expectedValue': '2016-11-17' + } + }, + 'vi_VN': { + 'locale': 'vi_VN', + 'localeInfo': { + 'format': 'dd/MM/y', + 'expectedValue': '17/11/2016' + } + }, + 'tr_TR': { + 'locale': 'tr_TR', + 'localeInfo': { + 'format': 'd.MM.y', + 'expectedValue': '17.11.2016' + } + }, + 'is_IS': { + 'locale': 'is_IS', + 'localeInfo': { + 'format': 'd.M.y', + 'expectedValue': '17.11.2016' + } + }, + 'cs_CZ': { + 'locale': 'cs_CZ', + 'localeInfo': { + 'format': 'dd.MM.yy', + 'expectedValue': '17.11.2016' + } + }, + 'el_GR': { + 'locale': 'el_GR', + 'localeInfo': { + 'format': 'd/M/yy', + 'expectedValue': '17/11/2016' + } + }, + 'be_BY': { + 'locale': 'be_BY', + 'localeInfo': { + 'format': 'd.M.yy', + 'expectedValue': '17.11.2016' + } + }, + 'bg_BG': { + 'locale': 'bg_BG', + 'localeInfo': { + 'format': 'd.MM.yy г.', + 'expectedValue': '17.11.2016 г.' + } + }, + 'mk_MK': { + 'locale': 'mk_MK', + 'localeInfo': { + 'format': 'dd.M.yy', + 'expectedValue': '17.11.2016' + } + }, + 'mn_Cyrl_MN': { + 'locale': 'mn_Cyrl_MN', + 'localeInfo': { + 'format': 'y-MM-dd', + 'expectedValue': '2016-11-17' + } + }, + 'ru_RU': { + 'locale': 'ru_RU', + 'localeInfo': { + 'format': 'dd.MM.yy', + 'expectedValue': '17.11.2016' + } + }, + 'sr_Cyrl_RS': { + 'locale': 'sr_Cyrl_RS', + 'localeInfo': { + 'format': 'd.M.yy.', + 'expectedValue': '17.11.2016.' + } + }, + 'uk_UA': { + 'locale': 'uk_UA', + 'localeInfo': { + 'format': 'dd.MM.yy', + 'expectedValue': '17.11.2016' + } + }, + 'he_IL': { + 'locale': 'he_IL', + 'localeInfo': { + 'format': 'd.M.y', + 'expectedValue': '17.11.2016' + } + }, + 'ar_DZ': { + 'locale': 'ar_DZ', + 'localeInfo': { + 'format': 'dâ€/Mâ€/y', + 'expectedValue': '17â€/11â€/2016' + } + }, + 'ar_KW': { + 'locale': 'ar_KW', + 'localeInfo': { + 'format': 'dâ€/Mâ€/y', + 'expectedValue': '17â€/11â€/2016' + } + }, + 'ar_MA': { + 'locale': 'ar_MA', + 'localeInfo': { + 'format': 'dâ€/Mâ€/y', + 'expectedValue': '17â€/11â€/2016' + } + }, + 'ar_SA': { + 'locale': 'ar_SA', + 'localeInfo': { + 'format': 'dâ€/Mâ€/y', + 'expectedValue': '17â€/11â€/2016' + } + }, + 'ar_EG': { + 'locale': 'ar_EG', + 'localeInfo': { + 'format': 'dâ€/Mâ€/y', + 'expectedValue': '17â€/11â€/2016' + } + }, + 'fa_IR': { + 'locale': 'fa_IR', + 'localeInfo': { + 'format': 'y/M/d G', + 'expectedValue': '2016/11/17 G' + } + }, + 'hi_IN': { + 'locale': 'hi_IN', + 'localeInfo': { + 'format': 'd/M/yy', + 'expectedValue': '17/11/2016' + } + }, + 'bn_BD': { + 'locale': 'bn_BD', + 'localeInfo': { + 'format': 'd/M/yy', + 'expectedValue': '17/11/2016' + } + }, + 'gu_IN': { + 'locale': 'gu_IN', + 'localeInfo': { + 'format': 'd/M/yy', + 'expectedValue': '17/11/2016' + } + }, + 'th_TH': { + 'locale': 'th_TH', + 'localeInfo': { + 'format': 'd/M/yy', + 'expectedValue': '17/11/2016' + } + }, + 'lo_LA': { + 'locale': 'lo_LA', + 'localeInfo': { + 'format': 'd/M/y', + 'expectedValue': '17/11/2016' + } + }, + 'ka_GE': { + 'locale': 'ka_GE', + 'localeInfo': { + 'format': 'dd.MM.yy', + 'expectedValue': '17.11.2016' + } + }, + 'km_KH': { + 'locale': 'km_KH', + 'localeInfo': { + 'format': 'd/M/yy', + 'expectedValue': '17/11/2016' + } + }, + 'zh_Hans_CN': { + 'locale': 'zh_Hans_CN', + 'localeInfo': { + 'format': 'yy/M/d', + 'expectedValue': '2016/11/17' + } + }, + 'zh_Hant_HK': { + 'locale': 'zh_Hant_HK', + 'localeInfo': { + 'format': 'd/M/yy', + 'expectedValue': '17/11/2016' + } + }, + 'zh_Hant_TW': { + 'locale': 'zh_Hant_TW', + 'localeInfo': { + 'format': 'y/M/d', + 'expectedValue': '2016/11/17' + } + }, + 'ja_JP': { + 'locale': 'ja_JP', + 'localeInfo': { + 'format': 'y/MM/dd', + 'expectedValue': '2016/11/17' + } + }, + 'ko_KR': { + 'locale': 'ko_KR', + 'localeInfo': { + 'format': 'yy. M. d.', + 'expectedValue': '2016. 11. 17.' + } + } + }; + + for (p in fixture) { + if (fixture.hasOwnProperty(p)) { + localeValues = fixture[p]; + format = localeValues.localeInfo.format; + expectedValue = localeValues.localeInfo.expectedValue; + momentFormat = utils.convertToMomentFormat(format); + dt = moment('2016-11-17'); + m = moment(dt, momentFormat); + + expect(m.format(momentFormat)).toBe(expectedValue); + } + } + }); + }); +}); diff --git a/dev/tests/static/framework/Magento/Sniffs/Translation/ConstantUsageSniff.php b/dev/tests/static/framework/Magento/Sniffs/Translation/ConstantUsageSniff.php index 260f731aecf1ce30d60cbd5dee1c2fb0f20074d2..4f9082aa4eb2124072b3c9fe39ddd50a901b7bd1 100644 --- a/dev/tests/static/framework/Magento/Sniffs/Translation/ConstantUsageSniff.php +++ b/dev/tests/static/framework/Magento/Sniffs/Translation/ConstantUsageSniff.php @@ -5,12 +5,10 @@ */ namespace Magento\Sniffs\Translation; -use PHP_CodeSniffer_File; - /** * Make sure that constants are not used as the first argument of translation function. */ -class ConstantUsageSniff extends \Generic_Sniffs_Files_LineLengthSniff +class ConstantUsageSniff implements \PHP_CodeSniffer_Sniff { /** * Having previous line content allows to process multi-line declaration. @@ -20,24 +18,73 @@ class ConstantUsageSniff extends \Generic_Sniffs_Files_LineLengthSniff protected $previousLineContent = ''; /** - * {@inheritdoc} + * {@inheritDoc} + */ + public function register() + { + return [T_OPEN_TAG]; + + } + + /** + * Copied from \Generic_Sniffs_Files_LineLengthSniff, minor changes made + * + * {@inheritDoc} */ - protected function checkLineLength(\PHP_CodeSniffer_File $phpcsFile, $stackPtr, $lineContent) + public function process(\PHP_CodeSniffer_File $phpcsFile, $stackPtr) { - $previousLineRegexp = '~__\($|Phrase\($~'; - $currentLineRegexp = '~__\(.+\)|Phrase\(.+\)~'; + $tokens = $phpcsFile->getTokens(); + + // Make sure this is the first open tag + $previousOpenTag = $phpcsFile->findPrevious(T_OPEN_TAG, ($stackPtr - 1)); + if ($previousOpenTag !== false) { + return; + } + + $tokenCount = 0; + $currentLineContent = ''; + $currentLine = 1; + + for (; $tokenCount < $phpcsFile->numTokens; $tokenCount++) { + if ($tokens[$tokenCount]['line'] === $currentLine) { + $currentLineContent .= $tokens[$tokenCount]['content']; + } else { + $this->checkIfFirstArgumentConstant($phpcsFile, ($tokenCount - 1), $currentLineContent); + $currentLineContent = $tokens[$tokenCount]['content']; + $currentLine++; + } + } + + $this->checkIfFirstArgumentConstant($phpcsFile, ($tokenCount - 1), $currentLineContent); + } + + /** + * Checks if first argument of \Magento\Framework\Phrase or translation function is a constant + * + * @param \PHP_CodeSniffer_File $phpcsFile + * @param int $stackPtr + * @param string $lineContent + * @return void + */ + private function checkIfFirstArgumentConstant( + \PHP_CodeSniffer_File $phpcsFile, + $stackPtr, + $lineContent + ) { + $previousLineRegexp = '/(__|Phrase)\($/im'; + $currentLineRegexp = '/(__|Phrase)\(.+\)/'; $currentLineMatch = preg_match($currentLineRegexp, $lineContent) !== 0; $previousLineMatch = preg_match($previousLineRegexp, $this->previousLineContent) !== 0; $this->previousLineContent = $lineContent; $error = 'Constants are not allowed as the first argument of translation function, use string literal instead'; - $constantRegexp = '[^\'"]+::[A-Z_0-9]+.*'; + $constantRegexp = '[^\$\'"]+::[A-Z_0-9]+.*'; if ($currentLineMatch) { - $variableRegexp = "~__\({$constantRegexp}\)|Phrase\({$constantRegexp}\)~"; + $variableRegexp = "/(__|Phrase)\({$constantRegexp}\)/"; if (preg_match($variableRegexp, $lineContent) !== 0) { $phpcsFile->addError($error, $stackPtr, 'VariableTranslation'); } } else if ($previousLineMatch) { - $variableRegexp = "~^\s+{$constantRegexp}~"; + $variableRegexp = "/^{$constantRegexp}/"; if (preg_match($variableRegexp, $lineContent) !== 0) { $phpcsFile->addError($error, $stackPtr, 'VariableTranslation'); } diff --git a/dev/tests/static/framework/Magento/TestFramework/Utility/ChangedFiles.php b/dev/tests/static/framework/Magento/TestFramework/Utility/ChangedFiles.php index d71c03eb0f85d01634f6f3a28c185c37e84bc1b2..a25b16c2277f3e7052840e9cf1fbbe2660cc4462 100644 --- a/dev/tests/static/framework/Magento/TestFramework/Utility/ChangedFiles.php +++ b/dev/tests/static/framework/Magento/TestFramework/Utility/ChangedFiles.php @@ -7,6 +7,7 @@ namespace Magento\TestFramework\Utility; use Magento\Framework\App\Utility\Files; +use Magento\TestFramework\Utility\File\RegexIteratorFactory; /** * A helper to gather various changed files @@ -15,6 +16,11 @@ use Magento\Framework\App\Utility\Files; */ class ChangedFiles { + /** + * File path with changed files content. + */ + const CHANGED_FILES_CONTENT_FILE = '/dev/tests/static/testsuite/Magento/Test/_files/changed_%s_files_content.json'; + /** * Returns array of PHP-files, that use or declare Magento application classes and Magento libs * @@ -23,7 +29,7 @@ class ChangedFiles */ public static function getPhpFiles($changedFilesList) { - $fileHelper = \Magento\Framework\App\Utility\Files::init(); + $fileUtilities = new File(Files::init(), new RegexIteratorFactory()); if (isset($_ENV['INCREMENTAL_BUILD'])) { $phpFiles = []; foreach (glob($changedFilesList) as $listFile) { @@ -36,29 +42,45 @@ class ChangedFiles } ); if (!empty($phpFiles)) { - $phpFiles = \Magento\Framework\App\Utility\Files::composeDataSets($phpFiles); - $phpFiles = array_intersect_key($phpFiles, $fileHelper->getPhpFiles( - Files::INCLUDE_APP_CODE - | Files::INCLUDE_PUB_CODE - | Files::INCLUDE_LIBS - | Files::INCLUDE_TEMPLATES - | Files::INCLUDE_TESTS - | Files::AS_DATA_SET - | Files::INCLUDE_NON_CLASSES - )); + $phpFiles = Files::composeDataSets($phpFiles); + $phpFiles = array_intersect_key($phpFiles, $fileUtilities->getPhpFiles()); } } else { - $phpFiles = $fileHelper->getPhpFiles( - Files::INCLUDE_APP_CODE - | Files::INCLUDE_PUB_CODE - | Files::INCLUDE_LIBS - | Files::INCLUDE_TEMPLATES - | Files::INCLUDE_TESTS - | Files::AS_DATA_SET - | Files::INCLUDE_NON_CLASSES - ); + $phpFiles = $fileUtilities->getPhpFiles(); } return $phpFiles; } + + /** + * Get changed content. + * + * @param string $fileName + * @return string + */ + public static function getChangedContent($fileName) + { + $data = []; + $extension = self::getFileExtension($fileName); + $fileName = ltrim(str_replace(BP, '', $fileName), DIRECTORY_SEPARATOR); + $changedFilesContentFile = BP . sprintf(self::CHANGED_FILES_CONTENT_FILE, $extension); + if (file_exists($changedFilesContentFile)) { + $changedContent = file_get_contents($changedFilesContentFile); + $data = json_decode($changedContent, true); + } + + return isset($data[$fileName]) ? $data[$fileName] : ''; + } + + /** + * Get file extension. + * + * @param string $fileName + * @return string + */ + public static function getFileExtension($fileName) + { + $fileInfo = pathinfo($fileName); + return isset($fileInfo['extension']) ? $fileInfo['extension'] : 'unknown'; + } } diff --git a/dev/tests/static/framework/Magento/TestFramework/Utility/File.php b/dev/tests/static/framework/Magento/TestFramework/Utility/File.php new file mode 100644 index 0000000000000000000000000000000000000000..7a8e02e5143a0808867a4b9c1d1d01b2da7b34f9 --- /dev/null +++ b/dev/tests/static/framework/Magento/TestFramework/Utility/File.php @@ -0,0 +1,80 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\TestFramework\Utility; + +use Magento\Framework\App\Utility\Files; +use Magento\TestFramework\Utility\File\RegexIteratorFactory; + +/** + * Get list of PHP files including files in setup application + */ +class File +{ + /** + * @var RegexIteratorFactory + */ + private $regexIteratorFactory; + + /** + * @var Files + */ + private $fileUtilities; + + /** + * Constructor + * + * @param Files $fileUtilities + * @param RegexIteratorFactory $regexIteratorFactory + */ + public function __construct( + Files $fileUtilities, + RegexIteratorFactory $regexIteratorFactory + ) { + $this->fileUtilities = $fileUtilities; + $this->regexIteratorFactory = $regexIteratorFactory; + } + + /** + * Get list of PHP files + * + * @return array + * @throws \Exception + */ + public function getPhpFiles() + { + $files = array_merge( + $this->fileUtilities->getPhpFiles( + Files::INCLUDE_APP_CODE + | Files::INCLUDE_PUB_CODE + | Files::INCLUDE_LIBS + | Files::INCLUDE_TEMPLATES + | Files::INCLUDE_TESTS + | Files::INCLUDE_NON_CLASSES + ), + $this->getSetupPhpFiles() + ); + return Files::composeDataSets($files); + } + + /** + * Get list of PHP files in setup application + * + * @param int $flags + * @return array + */ + private function getSetupPhpFiles() + { + $files = []; + $regexIterator = $this->regexIteratorFactory->create( + BP . '/setup', + '/.*php^/' + ); + foreach ($regexIterator as $file) { + $files = array_merge($files, [$file]); + } + return $files; + } +} diff --git a/dev/tests/static/framework/Magento/TestFramework/Utility/File/RegexIteratorFactory.php b/dev/tests/static/framework/Magento/TestFramework/Utility/File/RegexIteratorFactory.php new file mode 100644 index 0000000000000000000000000000000000000000..d2e5768414f06f13138ba83ebcf34ce7535783e6 --- /dev/null +++ b/dev/tests/static/framework/Magento/TestFramework/Utility/File/RegexIteratorFactory.php @@ -0,0 +1,26 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\TestFramework\Utility\File; + +/** + * Factory for \RegexIterator + */ +class RegexIteratorFactory +{ + /** + * Create instance of \RegexIterator + * + * @param string $directoryPath + * @param string $regexp + * @return \RegexIterator + */ + public function create($directoryPath, $regexp) + { + $directory = new \RecursiveDirectoryIterator($directoryPath); + $recursiveIterator = new \RecursiveIteratorIterator($directory); + return new \RegexIterator($recursiveIterator, $regexp, \RegexIterator::GET_MATCH); + } +} diff --git a/dev/tests/static/framework/Magento/TestFramework/Utility/FunctionDetector.php b/dev/tests/static/framework/Magento/TestFramework/Utility/FunctionDetector.php new file mode 100644 index 0000000000000000000000000000000000000000..69162d3dfba2e6d67acb9c9bad48dbb03fc3c41a --- /dev/null +++ b/dev/tests/static/framework/Magento/TestFramework/Utility/FunctionDetector.php @@ -0,0 +1,113 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\TestFramework\Utility; + +/** + * Check if one or more functions are used in the file + */ +class FunctionDetector +{ + /** + * Detect functions in given file + * + * return result in this format: + * [ + * line_number => [ + * function_name_1, + * function_name_2, + * function_name_3, + * ], + * line_number => [ + * function_name_1, + * function_name_2, + * function_name_3, + * ], + * ] + * + * @param string $filePath + * @param string[] $functions + * @return array + */ + public function detect($filePath, $functions) + { + $result = []; + $regexp = $this->composeRegexp($functions); + + if (!$regexp) { + return $result; + } + + $fileContent = \Magento\TestFramework\Utility\ChangedFiles::getChangedContent($filePath); + $file = file($filePath); + + return $fileContent + ? $this->grepChangedContent($file, $regexp, $functions, $fileContent) + : $this->grepFile($file, $regexp); + } + + /** + * Grep only changed content. + * + * @param array $file + * @param string $regexp + * @param string[] $functions + * @param string $fileContent + * @return array + */ + public function grepChangedContent(array $file, $regexp, $functions, $fileContent) + { + $result = []; + $matches = preg_grep($regexp, explode("\n", $fileContent)); + if (!empty($matches)) { + foreach ($matches as $line) { + $actualFunctions = []; + foreach ($functions as $function) { + if (false !== strpos($line, $function)) { + $actualFunctions[] = $function; + } + } + $result[array_search($line . "\n", $file) + 1] = $actualFunctions; + } + } + + return $result; + } + + /** + * Grep File. + * + * @param array $file + * @param string $regexp + * @return array + */ + public function grepFile(array $file, $regexp) + { + $result = []; + array_unshift($file, ''); + $lines = preg_grep($regexp, $file); + foreach ($lines as $lineNumber => $line) { + if (preg_match_all($regexp, $line, $matches)) { + $result[$lineNumber] = $matches[1]; + } + } + + return $result; + } + + /** + * Compose regular expression + * + * @param array $functions + * @return string + */ + private function composeRegexp(array $functions) + { + if (empty($functions)) { + return ''; + } + return '/(?<!function |->|::)\b(' . join('|', $functions) . ')\s*\(/i'; + } +} diff --git a/dev/tests/static/framework/tests/unit/testsuite/Magento/Sniffs/Translation/ConstantUsageSniffTest.php b/dev/tests/static/framework/tests/unit/testsuite/Magento/Sniffs/Translation/ConstantUsageSniffTest.php new file mode 100644 index 0000000000000000000000000000000000000000..a64d47054ede9bc1f695514aa8f3ef95fc1e8eeb --- /dev/null +++ b/dev/tests/static/framework/tests/unit/testsuite/Magento/Sniffs/Translation/ConstantUsageSniffTest.php @@ -0,0 +1,96 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Sniffs\Translation; + +class ConstantUsageSniffTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var \PHP_CodeSniffer_File|\PHPUnit_Framework_MockObject_MockObject + */ + private $fileMock; + + /** + * @var ConstantUsageSniff + */ + private $constantUsageSniff; + + protected function setUp() + { + $this->fileMock = $this->getMock(\PHP_CodeSniffer_File::class, [], [], '', false); + $this->constantUsageSniff = new ConstantUsageSniff(); + } + + /** + * @param string $file + * @param int $numIncorrectUsages + * @dataProvider processDataProvider + */ + public function testProcessIncorrectArguments($file, $numIncorrectUsages) + { + $stackPtr = 10; + $fileContent = file_get_contents(__DIR__ . '/_files/' . $file); + $tokens = $this->tokenizeString($fileContent); + $this->fileMock->expects($this->once()) + ->method('findPrevious') + ->with( + T_OPEN_TAG, + $stackPtr - 1 + ) + ->willReturn(false); + $this->fileMock->expects($this->once()) + ->method('getTokens') + ->willReturn($tokens); + $this->fileMock->numTokens = count($tokens); + $this->fileMock->expects($this->exactly($numIncorrectUsages)) + ->method('addError') + ->with( + 'Constants are not allowed as the first argument of translation function, use string literal instead', + $this->anything(), + 'VariableTranslation' + ); + $this->constantUsageSniff->process($this->fileMock, $stackPtr); + } + + /** + * Get tokens for a string + * + * @param string $fileContent + * @return array + */ + private function tokenizeString($fileContent) + { + $lineNumber = 1; + $tokens = token_get_all($fileContent); + $snifferTokens = []; + for ($i = 0; $i < count($tokens); $i++) { + $content = is_array($tokens[$i]) ? $tokens[$i][1] : $tokens[$i]; + $snifferTokens[$i]['line'] = $lineNumber; + $snifferTokens[$i]['content'] = $content; + $trimmedContent = trim($content, ' '); + if ($trimmedContent == PHP_EOL || $trimmedContent == PHP_EOL . PHP_EOL) { + $lineNumber++; + } + } + return $snifferTokens; + } + + /** + * @return array + */ + public function processDataProvider() + { + return [ + [ + 'incorrect_arguments.txt', + 9 + ], + [ + 'correct_arguments.txt', + 0 + ] + ]; + } +} diff --git a/dev/tests/static/framework/tests/unit/testsuite/Magento/Sniffs/Translation/_files/correct_arguments.txt b/dev/tests/static/framework/tests/unit/testsuite/Magento/Sniffs/Translation/_files/correct_arguments.txt new file mode 100644 index 0000000000000000000000000000000000000000..536029811fd87972da11ca531cd6787fa59921a4 --- /dev/null +++ b/dev/tests/static/framework/tests/unit/testsuite/Magento/Sniffs/Translation/_files/correct_arguments.txt @@ -0,0 +1,29 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +__($variable) + +__($variable[Class::CONSTANT]) + +__($variable[\Namespace\Class::CONSTANT]) + +__($variable['value']) + +__( + $variable +) + +Phrase($variable) + +Phrase($variable[Class::CONSTANT]) + +Phrase($variable[\Namespace\Class::CONSTANT]) + +\Magento\Framework\Phrase($variable['value']) + +\Magento\Framework\Phrase( + $variable[Class::CONSTANT] +) diff --git a/dev/tests/static/framework/tests/unit/testsuite/Magento/Sniffs/Translation/_files/incorrect_arguments.txt b/dev/tests/static/framework/tests/unit/testsuite/Magento/Sniffs/Translation/_files/incorrect_arguments.txt new file mode 100644 index 0000000000000000000000000000000000000000..6112ce567ce14cc200e4bb648e828fc51d0dbc77 --- /dev/null +++ b/dev/tests/static/framework/tests/unit/testsuite/Magento/Sniffs/Translation/_files/incorrect_arguments.txt @@ -0,0 +1,27 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +__(Class::CONSTANT) + +__(self::CONSTANT) + +__(\Namespace\Class::CONSTANT) + +__( + Class::CONSTANT +) + +Phrase(Class::CONSTANT) + +Phrase(self::CONSTANT) + +Phrase(\Namespace\Class::CONSTANT) + +\Magento\Framework\Phrase(Class::CONSTANT) + +\Magento\Framework\Phrase( + Class::CONSTANT +) diff --git a/dev/tests/static/framework/tests/unit/testsuite/Magento/TestFramework/Utility/FileTest.php b/dev/tests/static/framework/tests/unit/testsuite/Magento/TestFramework/Utility/FileTest.php new file mode 100644 index 0000000000000000000000000000000000000000..be8b246a9330495fd5b859a4feb2552772492e21 --- /dev/null +++ b/dev/tests/static/framework/tests/unit/testsuite/Magento/TestFramework/Utility/FileTest.php @@ -0,0 +1,83 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\TestFramework\Utility; + +use Magento\Framework\App\Utility\Files; +use Magento\TestFramework\Utility\File\RegexIteratorFactory; +use Magento\TestFramework\Utility\File; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; + +class FileTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var Files|PHPUnit_Framework_MockObject_MockObject + */ + private $fileUtilitiesMock; + + /** + * @var RegexIteratorFactory|PHPUnit_Framework_MockObject_MockObject + */ + private $regexIteratorFactoryMock; + + /** + * @var ObjectManager + */ + private $objectManager; + + /** + * @var File + */ + private $file; + + protected function setUp() + { + $this->objectManager = new ObjectManager($this); + $this->fileUtilitiesMock = $this->getMock(Files::class, [], [], '', false); + $this->regexIteratorFactoryMock = $this->getMock(RegexIteratorFactory::class, [], [], '', false); + $this->file = $this->objectManager->getObject( + File::class, + [ + 'fileUtilities' => $this->fileUtilitiesMock, + 'regexIteratorFactory' => $this->regexIteratorFactoryMock + ] + ); + } + + public function testGetPhpFiles() + { + $appFiles = [ + 'file1', + 'file2' + ]; + $setupFiles = [ + 'file3' + ]; + $expected = [ + 'file1' => ['file1'], + 'file2' => ['file2'], + 'file3' => ['file3'] + ]; + $iteratorMock = $this->getMock(\IteratorAggregate::class, [], [], '', false); + $iteratorMock->expects($this->any()) + ->method('getIterator') + ->willReturn(new \ArrayIterator($setupFiles)); + $this->regexIteratorFactoryMock->expects($this->once()) + ->method('create') + ->willReturn($iteratorMock); + $this->fileUtilitiesMock->expects($this->once()) + ->method('getPhpFiles') + ->with( + Files::INCLUDE_APP_CODE + | Files::INCLUDE_PUB_CODE + | Files::INCLUDE_LIBS + | Files::INCLUDE_TEMPLATES + | Files::INCLUDE_TESTS + | Files::INCLUDE_NON_CLASSES + ) + ->willReturn($appFiles); + $this->assertEquals($expected, $this->file->getPhpFiles()); + } +} diff --git a/dev/tests/static/framework/tests/unit/testsuite/Magento/TestFramework/Utility/FunctionDetectorTest.php b/dev/tests/static/framework/tests/unit/testsuite/Magento/TestFramework/Utility/FunctionDetectorTest.php new file mode 100644 index 0000000000000000000000000000000000000000..a356aaa3cc83b48e4bf310b31d2556ec4c63bc12 --- /dev/null +++ b/dev/tests/static/framework/tests/unit/testsuite/Magento/TestFramework/Utility/FunctionDetectorTest.php @@ -0,0 +1,22 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\TestFramework\Utility; + +class FunctionDetectorTest extends \PHPUnit_Framework_TestCase +{ + public function testDetectFunctions() + { + $fixturePath = __DIR__ . '/_files/test.txt'; + $expectedResults = [ + 1 => ['strtoupper', 'strtolower'], + 3 => ['foo'], + 4 => ['foo'], + ]; + $functionDetector = new FunctionDetector(); + $lines = $functionDetector->detect($fixturePath, ['foo', 'strtoupper', 'test', 'strtolower']); + $this->assertEquals($expectedResults, $lines); + } +} diff --git a/dev/tests/static/framework/tests/unit/testsuite/Magento/TestFramework/Utility/_files/test.txt b/dev/tests/static/framework/tests/unit/testsuite/Magento/TestFramework/Utility/_files/test.txt new file mode 100644 index 0000000000000000000000000000000000000000..c2feb8284b2373bc94f9c16f7b5383fbc60f711a --- /dev/null +++ b/dev/tests/static/framework/tests/unit/testsuite/Magento/TestFramework/Utility/_files/test.txt @@ -0,0 +1,9 @@ +strtoupper(strtolower($foo . $bar)) +function foo($merchantMd5, $merchantApiLogin) +$this->generateHash(foo($bar), $foo) +foo( + 'bar' +) +Foo::bar($foo, $this->getData('bar')) +$this->foo('bar') +Foo::foo() diff --git a/dev/tests/static/get_github_changes.php b/dev/tests/static/get_github_changes.php index f332208cd17d0861dd1b28bd7096a0b3fe0066a5..16a4f7d8e090de40c4881f1e3a60015bb377396b 100644 --- a/dev/tests/static/get_github_changes.php +++ b/dev/tests/static/get_github_changes.php @@ -34,6 +34,8 @@ if (!validateInput($options, $requiredOptions)) { $fileExtensions = explode(',', isset($options['file-extensions']) ? $options['file-extensions'] : 'php'); +include_once __DIR__ . '/framework/autoload.php'; + $mainline = 'mainline_' . (string)rand(0, 9999); $repo = getRepo($options, $mainline); $branches = $repo->getBranches('--remotes'); @@ -41,8 +43,27 @@ generateBranchesList($options['output-file'], $branches, $options['branch']); $changes = retrieveChangesAcrossForks($mainline, $repo, $options['branch']); $changedFiles = getChangedFiles($changes, $fileExtensions); generateChangedFilesList($options['output-file'], $changedFiles); +saveChangedFileContent($repo); cleanup($repo, $mainline); +/** + * Save changed file content. + * + * @param GitRepo $repo + * @return void + */ +function saveChangedFileContent(GitRepo $repo) +{ + $changedFilesContentFileName = BP . Magento\TestFramework\Utility\ChangedFiles::CHANGED_FILES_CONTENT_FILE; + foreach ($repo->getChangedContentFiles() as $key => $changedContentFile) { + $filePath = sprintf($changedFilesContentFileName, $key); + $oldContent = file_exists($filePath) ? file_get_contents($filePath) : '{}'; + $oldData = json_decode($oldContent, true); + $data = array_merge($oldData, $changedContentFile); + file_put_contents($filePath, json_encode($data)); + } +} + /** * Generates a file containing changed files * @@ -170,6 +191,18 @@ class GitRepo */ private $remoteList = []; + /** + * Array of changed content files. + * + * Example: + * 'extension' => + * 'path_to_file/filename' => 'Content that was edited', + * 'path_to_file/filename2' => 'Content that was edited', + * + * @var array + */ + private $changedContentFiles = []; + /** * @param string $workTree absolute path to git project */ @@ -285,6 +318,9 @@ class GitRepo 'diff HEAD %s/%s -- %s', $remoteAlias, $remoteBranch, $this->workTree . '/' . $fileName) ); if ($result) { + if (!(isset($this->changedContentFiles[$fileName]))) { + $this->setChangedContentFile($result, $fileName); + } $filteredChanges[] = $fileName; } } @@ -295,6 +331,38 @@ class GitRepo return $filteredChanges; } + /** + * Set changed content for file. + * + * @param array $content + * @param string $fileName + * @return void + */ + private function setChangedContentFile(array $content, $fileName) + { + $changedContent = ''; + $extension = Magento\TestFramework\Utility\ChangedFiles::getFileExtension($fileName); + + foreach ($content as $item) { + if (strpos($item, '---') !== 0 && strpos($item, '-') === 0 && $line = ltrim($item, '-')) { + $changedContent .= $line . "\n"; + } + } + if ($changedContent !== '') { + $this->changedContentFiles[$extension][$fileName] = $changedContent; + } + } + + /** + * Get changed content files collection. + * + * @return array + */ + public function getChangedContentFiles() + { + return $this->changedContentFiles; + } + /** * Makes call ro git cli * diff --git a/dev/tests/static/testsuite/Magento/Test/Integrity/ApiAnnotationTest.php b/dev/tests/static/testsuite/Magento/Test/Integrity/ApiAnnotationTest.php deleted file mode 100644 index a1e7c25e3d6008cff744a090c0c01a810efad8a4..0000000000000000000000000000000000000000 --- a/dev/tests/static/testsuite/Magento/Test/Integrity/ApiAnnotationTest.php +++ /dev/null @@ -1,40 +0,0 @@ -<?php -/** - * Scan source code for unmarked API interfaces - * - * Copyright © 2016 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Test\Integrity; - -use Magento\Framework\App\Utility\Files; -use Magento\Framework\Component\ComponentRegistrar; - -class ApiAnnotationTest extends \PHPUnit_Framework_TestCase -{ - /** - * API annotation pattern - */ - private $apiAnnotation = '~/\*{2}(.*@api.*)\*/\s+(?=interface)~s'; - - public function testApiAnnotations() - { - $modulePaths = array_map(function ($path) { - return $path . DIRECTORY_SEPARATOR . 'Api'; - }, (new ComponentRegistrar())->getPaths(ComponentRegistrar::MODULE)); - - foreach (Files::init()->getFiles($modulePaths, '*.php', true) as $file) { - $fileContent = file_get_contents($file); - if (!preg_match($this->apiAnnotation, $fileContent)) { - $result[] = $file; - } - } - if (!empty($result)) { - $this->fail(sprintf( - 'Found %s file(s) without @api annotations under Api namespace: %s', - count($result), - PHP_EOL . implode(PHP_EOL, $result) - )); - } - } -} diff --git a/dev/tests/static/testsuite/Magento/Test/Integrity/ObserverImplementationTest.php b/dev/tests/static/testsuite/Magento/Test/Integrity/ObserverImplementationTest.php index 037069e8fd2ca551a216a1e3fe349e1793aa8768..6c4bc5f52c0c06b08f44f2a70554fd3d11c9bca7 100644 --- a/dev/tests/static/testsuite/Magento/Test/Integrity/ObserverImplementationTest.php +++ b/dev/tests/static/testsuite/Magento/Test/Integrity/ObserverImplementationTest.php @@ -22,29 +22,6 @@ class ObserverImplementationTest extends \PHPUnit_Framework_TestCase */ protected static $observerClasses = []; - /** - * @var array - */ - protected static $blackList = [ - // not support of virtual types - 'SalesOrderIndexGridAsyncInsertObserver', - 'SalesInvoiceIndexGridAsyncInsertObserver', - 'SalesShipmentIndexGridAsyncInsertObserver', - 'SalesCreditmemoIndexGridAsyncInsertObserver', - 'SalesOrderIndexGridSyncInsert', - 'SalesInvoiceIndexGridSyncInsert', - 'SalesShipmentIndexGridSyncInsert', - 'SalesCreditmemoIndexGridSyncInsert', - 'SalesOrderIndexGridSyncRemove', - 'SalesInvoiceIndexGridSyncRemove', - 'SalesShipmentIndexGridSyncRemove', - 'SalesCreditmemoIndexGridSyncRemove', - 'SalesOrderSendEmailsObserver', - 'SalesOrderInvoiceSendEmailsObserver', - 'SalesOrderShipmentSendEmailsObserver', - 'SalesOrderCreditmemoSendEmailsObserver', - ]; - public static function setUpBeforeClass() { self::$observerClasses = array_merge( @@ -116,9 +93,18 @@ class ObserverImplementationTest extends \PHPUnit_Framework_TestCase } } } + + $blacklistFiles = str_replace('\\', '/', realpath(__DIR__)) . '/_files/blacklist/observers*.txt'; + $blacklistExceptions = []; + foreach (glob($blacklistFiles) as $fileName) { + $blacklistExceptions = array_merge( + $blacklistExceptions, + file($fileName, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES) + ); + } return array_diff( array_unique($observerClasses), - self::$blackList + $blacklistExceptions ); } } diff --git a/dev/tests/static/testsuite/Magento/Test/Integrity/_files/blacklist/observers.txt b/dev/tests/static/testsuite/Magento/Test/Integrity/_files/blacklist/observers.txt new file mode 100644 index 0000000000000000000000000000000000000000..3e9b19322cb09773f161b0e502ed7d84e7826a7e --- /dev/null +++ b/dev/tests/static/testsuite/Magento/Test/Integrity/_files/blacklist/observers.txt @@ -0,0 +1,16 @@ +SalesOrderIndexGridAsyncInsertObserver +SalesInvoiceIndexGridAsyncInsertObserver +SalesShipmentIndexGridAsyncInsertObserver +SalesCreditmemoIndexGridAsyncInsertObserver +SalesOrderIndexGridSyncInsert +SalesInvoiceIndexGridSyncInsert +SalesShipmentIndexGridSyncInsert +SalesCreditmemoIndexGridSyncInsert +SalesOrderIndexGridSyncRemove +SalesInvoiceIndexGridSyncRemove +SalesShipmentIndexGridSyncRemove +SalesCreditmemoIndexGridSyncRemove +SalesOrderSendEmailsObserver +SalesOrderInvoiceSendEmailsObserver +SalesOrderShipmentSendEmailsObserver +SalesOrderCreditmemoSendEmailsObserver diff --git a/dev/tests/static/testsuite/Magento/Test/Js/_files/blacklist/magento.txt b/dev/tests/static/testsuite/Magento/Test/Js/_files/blacklist/magento.txt index 29b5280ec6693f70c8d65a1f40e25c644897ace1..4f27497305353e0903207a48ed81d22885e66120 100644 --- a/dev/tests/static/testsuite/Magento/Test/Js/_files/blacklist/magento.txt +++ b/dev/tests/static/testsuite/Magento/Test/Js/_files/blacklist/magento.txt @@ -923,7 +923,6 @@ vendor/magento/module-ui/view/base/web/js/form/components/html.js vendor/magento/module-ui/view/base/web/js/form/components/tab_group.js vendor/magento/module-ui/view/base/web/js/form/components/tab.js vendor/magento/module-ui/view/base/web/js/form/element/abstract.js -vendor/magento/module-ui/view/base/web/js/form/element/date.js vendor/magento/module-ui/view/base/web/js/form/element/helpers/options.js vendor/magento/module-ui/view/base/web/js/form/element/multiselect.js vendor/magento/module-ui/view/base/web/js/form/element/post-code.js 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/RestrictedCodeTest.php b/dev/tests/static/testsuite/Magento/Test/Legacy/RestrictedCodeTest.php index 0c4c6eba49efa33c997b2dc62c70bd49434540e8..68c2d166448ab6fb4c39354b92ddb9f803d500f1 100644 --- a/dev/tests/static/testsuite/Magento/Test/Legacy/RestrictedCodeTest.php +++ b/dev/tests/static/testsuite/Magento/Test/Legacy/RestrictedCodeTest.php @@ -3,14 +3,13 @@ * Copyright © 2016 Magento. All rights reserved. * See COPYING.txt for license details. */ - -/** - * Tests to find usage of restricted code - */ namespace Magento\Test\Legacy; use Magento\Framework\Component\ComponentRegistrar; +/** + * Tests to find usage of restricted code + */ class RestrictedCodeTest extends \PHPUnit_Framework_TestCase { /**@#+ @@ -18,17 +17,29 @@ class RestrictedCodeTest extends \PHPUnit_Framework_TestCase * * @var array */ - protected static $_classes = []; + private static $_classes = []; /**#@-*/ /** * List of fixtures that contain restricted classes and should not be tested + * * @var array */ - protected static $_fixtureFiles = []; + private static $_fixtureFiles = []; + + /** + * @var ComponentRegistrar + */ + private $componentRegistrar; + + protected function setUp() + { + $this->componentRegistrar = new ComponentRegistrar(); + } /** * Read fixtures into memory as arrays + * * @return void */ public static function setUpBeforeClass() @@ -69,6 +80,7 @@ class RestrictedCodeTest extends \PHPUnit_Framework_TestCase /** * Test that restricted entities are not used in PHP files + * * @return void */ public function testPhpFiles() @@ -97,15 +109,13 @@ class RestrictedCodeTest extends \PHPUnit_Framework_TestCase protected function _testRestrictedClasses($file) { $content = file_get_contents($file); - $componentRegistrar = new ComponentRegistrar(); foreach (self::$_classes as $restrictedClass => $classRules) { foreach ($classRules['exclude'] as $skippedPathInfo) { - $skippedPath = $componentRegistrar->getPath($skippedPathInfo['type'], $skippedPathInfo['name']) - . '/' . $skippedPathInfo['path']; - if (strpos($file, $skippedPath) === 0) { + if (strpos($file, $this->getExcludedFilePath($skippedPathInfo)) === 0) { continue 2; } } + $this->assertFalse( \Magento\TestFramework\Utility\CodeCheck::isClassUsed($restrictedClass, $content), sprintf( @@ -117,4 +127,18 @@ class RestrictedCodeTest extends \PHPUnit_Framework_TestCase ); } } + + /** + * Get full path for excluded file + * + * @param array $pathInfo + * @return string + */ + private function getExcludedFilePath($pathInfo) + { + if ($pathInfo['type'] != 'setup') { + return $this->componentRegistrar->getPath($pathInfo['type'], $pathInfo['name']) . '/' . $pathInfo['path']; + } + return BP . '/setup/' . $pathInfo['path']; + } } diff --git a/dev/tests/static/testsuite/Magento/Test/Legacy/UnsecureFunctionsUsageTest.php b/dev/tests/static/testsuite/Magento/Test/Legacy/UnsecureFunctionsUsageTest.php index e5263713d71d7af374ea1f32c2d765d3639e56ce..44eb7fa78d8ac7099bfbfb6c14eae050c5e578e1 100644 --- a/dev/tests/static/testsuite/Magento/Test/Legacy/UnsecureFunctionsUsageTest.php +++ b/dev/tests/static/testsuite/Magento/Test/Legacy/UnsecureFunctionsUsageTest.php @@ -6,12 +6,28 @@ namespace Magento\Test\Legacy; use Magento\Framework\App\Utility\Files; +use Magento\Framework\Component\ComponentRegistrar; +use Magento\TestFramework\Utility\FunctionDetector; /** * Tests to detect unsecure functions usage */ class UnsecureFunctionsUsageTest extends \PHPUnit_Framework_TestCase { + /** + * Php unsecure functions + * + * @var array + */ + private static $phpUnsecureFunctions = []; + + /** + * JS unsecure functions + * + * @var array + */ + private static $jsUnsecureFunctions = []; + /** * File extensions pattern to search for * @@ -20,25 +36,54 @@ class UnsecureFunctionsUsageTest extends \PHPUnit_Framework_TestCase private $fileExtensions = '/\.(php|phtml|js)$/'; /** - * Php unsecure functions to detect + * Read fixtures into memory as arrays * - * @var array + * @return void */ - private $phpUnsecureFunctions = [ - 'unserialize', - 'serialize', - 'eval', - 'md5', - 'srand', - 'mt_srand' - ]; + public static function setUpBeforeClass() + { + self::loadData(self::$phpUnsecureFunctions, 'unsecure_php_functions*.php'); + self::loadData(self::$jsUnsecureFunctions, 'unsecure_js_functions*.php'); + } /** - * JS unsecure functions to detect + * Loads and merges data from fixtures * - * @var array + * @param array $data + * @param string $filePattern + * @return void */ - private $jsUnsecureFunctions = []; + private static function loadData(array &$data, $filePattern) + { + foreach (glob(__DIR__ . '/_files/security/' . $filePattern) as $file) { + $data = array_merge_recursive($data, self::readList($file)); + } + $componentRegistrar = new ComponentRegistrar(); + foreach ($data as $key => $value) { + $excludes = $value['exclude']; + $excludePaths = []; + foreach ($excludes as $exclude) { + if ('setup' == $exclude['type']) { + $excludePaths[] = BP . '/setup/' . $exclude['path']; + } else { + $excludePaths[] = $componentRegistrar->getPath($exclude['type'], $exclude['name']) + . '/' . $exclude['path']; + } + } + $data[$key]['exclude'] = $excludePaths; + } + } + + /** + * Isolate including a file into a method to reduce scope + * + * @param string $file + * @return array + */ + private static function readList($file) + { + return include $file; + } /** * Detect unsecure functions usage for changed files in whitelist with the exception of blacklist @@ -48,46 +93,69 @@ class UnsecureFunctionsUsageTest extends \PHPUnit_Framework_TestCase public function testUnsecureFunctionsUsage() { $invoker = new \Magento\Framework\App\Utility\AggregateInvoker($this); + $functionDetector = new FunctionDetector(); $invoker( - function ($fileName) { - $result = ''; - $errorMessage = 'The following functions are non secure and should be avoided: ' - . implode(', ', $this->phpUnsecureFunctions) - . ' for PHP'; - if (!empty($this->jsUnsecureFunctions)) { - $errorMessage .= ', and ' - . implode(', ', $this->jsUnsecureFunctions) - . ' for JavaScript'; - } - $errorMessage .= ".\n"; - $regexp = $this->getRegexpByFileExtension(pathinfo($fileName, PATHINFO_EXTENSION)); - if ($regexp) { - $matches = preg_grep( - $regexp, - file($fileName) - ); - if (!empty($matches)) { - foreach (array_keys($matches) as $line) { - $result .= $fileName . ':' . ($line + 1) . "\n"; - } - } - $this->assertEmpty($result, $errorMessage . $result); + function ($fileFullPath) use ($functionDetector) { + $functions = $this->getFunctions($fileFullPath); + $lines = $functionDetector->detect($fileFullPath, array_keys($functions)); + + $message = ''; + if (!empty($lines)) { + $message = $this->composeMessage($fileFullPath, $lines, $functions); } + $this->assertEmpty( + $lines, + $message + ); }, - $this->unsecureFunctionsUsageDataProvider() + $this->getFilesToVerify() ); } /** - * Data provider for test + * Compose message + * + * @param string $fileFullPath + * @param array $lines + * @param array $functionRules + * @return string + */ + private function composeMessage($fileFullPath, $lines, $functionRules) + { + $result = ''; + foreach ($lines as $lineNumber => $detectedFunctions) { + $detectedFunctionRules = array_intersect_key($functionRules, array_flip($detectedFunctions)); + $replacementString = ''; + foreach ($detectedFunctionRules as $function => $functionRule) { + $replacement = $functionRule['replacement']; + if (is_array($replacement)) { + $replacement = array_unique($replacement); + $replacement = count($replacement) > 1 ? + "[\n\t\t\t" . implode("\n\t\t\t", $replacement) . "\n\t\t]" : + $replacement[0]; + } + $replacement = empty($replacement) ? 'No suggested replacement at this time' : $replacement; + $replacementString .= "\t\t'$function' => '$replacement'\n"; + } + $result .= sprintf( + "Functions '%s' are not secure in %s. \n\tSuggested replacement:\n%s", + implode(', ', $detectedFunctions), + $fileFullPath . ':' . $lineNumber, + $replacementString + ); + } + return $result; + } + + /** + * Get files to be verified * * @return array */ - public function unsecureFunctionsUsageDataProvider() + private function getFilesToVerify() { $fileExtensions = $this->fileExtensions; $directoriesToScan = Files::init()->readLists(__DIR__ . '/_files/security/whitelist.txt'); - $blackListFiles = include __DIR__ . '/_files/security/blacklist.php'; $filesToVerify = []; foreach (glob(__DIR__ . '/../_files/changed_files*') as $listFile) { @@ -104,7 +172,7 @@ class UnsecureFunctionsUsageTest extends \PHPUnit_Framework_TestCase ); $filesToVerify = array_filter( $filesToVerify, - function ($path) use ($directoriesToScan, $fileExtensions, $blackListFiles) { + function ($path) use ($directoriesToScan, $fileExtensions) { if (!file_exists($path[0])) { return false; } @@ -113,11 +181,9 @@ class UnsecureFunctionsUsageTest extends \PHPUnit_Framework_TestCase $directory = realpath($directory); if (strpos($path, $directory) === 0) { if (preg_match($fileExtensions, $path)) { - foreach ($blackListFiles as $blackListFile) { - $blackListFile = preg_quote($blackListFile, '#'); - if (preg_match('#' . $blackListFile . '#', $path)) { - return false; - } + // skip unit tests + if (preg_match('#' . preg_quote('Test/Unit', '#') . '#', $path)) { + return false; } return true; } @@ -130,35 +196,27 @@ class UnsecureFunctionsUsageTest extends \PHPUnit_Framework_TestCase } /** - * Get regular expression by file extension + * Get functions for the given file * - * @param string $fileExtension - * @return string|bool + * @param string $fileFullPath + * @return array */ - private function getRegexpByFileExtension($fileExtension) + private function getFunctions($fileFullPath) { - $regexp = false; + $fileExtension = pathinfo($fileFullPath, PATHINFO_EXTENSION); + $functions = []; if ($fileExtension == 'php') { - $regexp = $this->prepareRegexp($this->phpUnsecureFunctions); + $functions = self::$phpUnsecureFunctions; } elseif ($fileExtension == 'js') { - $regexp = $this->prepareRegexp($this->jsUnsecureFunctions); + $functions = self::$jsUnsecureFunctions; } elseif ($fileExtension == 'phtml') { - $regexp = $this->prepareRegexp($this->phpUnsecureFunctions + $this->jsUnsecureFunctions); + $functions = array_merge_recursive(self::$phpUnsecureFunctions, self::$jsUnsecureFunctions); } - return $regexp; - } - - /** - * Prepare regular expression for unsecure function names - * - * @param array $functions - * @return string - */ - private function prepareRegexp(array $functions) - { - if (empty($functions)) { - return ''; + foreach ($functions as $function => $functionRules) { + if (in_array($fileFullPath, $functionRules['exclude'])) { + unset($functions[$function]); + } } - return '/(?<!function |[^\s])\b(' . join('|', $functions) . ')\s*\(/i'; + return $functions; } } 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/dev/tests/static/testsuite/Magento/Test/Legacy/_files/restricted_classes.php b/dev/tests/static/testsuite/Magento/Test/Legacy/_files/restricted_classes.php index a950b2d7e9ed243356da176f8eef1095ef4fb210..683449d4e5e34b919ef476d93c26fe01d122b0a8 100644 --- a/dev/tests/static/testsuite/Magento/Test/Legacy/_files/restricted_classes.php +++ b/dev/tests/static/testsuite/Magento/Test/Legacy/_files/restricted_classes.php @@ -1,27 +1,103 @@ <?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + /** * Classes that are restricted to use directly. * A <replacement> will be suggested to be used instead. * Use <whitelist> to specify files and directories that are allowed to use restricted classes. * * Format: array(<class_name>, <replacement>[, array(<whitelist>)]]) - * - * Copyright © 2016 Magento. All rights reserved. - * See COPYING.txt for license details. */ return [ 'Zend_Db_Select' => [ 'replacement' => '\Magento\Framework\DB\Select', 'exclude' => [ - ['type' => 'library', 'name' => 'magento/framework', 'path' => 'DB/Select.php'], - ['type' => 'library', 'name' => 'magento/framework', 'path' => 'DB/Adapter/Pdo/Mysql.php'], - ['type' => 'library', 'name' => 'magento/framework', 'path' => 'Model/ResourceModel/Iterator.php'], + [ + 'type' => 'library', + 'name' => 'magento/framework', + 'path' => 'DB/Select.php' + ], + [ + 'type' => 'library', + 'name' => 'magento/framework', + 'path' => 'DB/Adapter/Pdo/Mysql.php' + ], + [ + 'type' => 'library', + 'name' => 'magento/framework', + 'path' => 'Model/ResourceModel/Iterator.php' + ], ] ], 'Zend_Db_Adapter_Pdo_Mysql' => [ 'replacement' => '\Magento\Framework\DB\Adapter\Pdo\Mysql', 'exclude' => [ - ['type' => 'library', 'name' => 'magento/framework', 'path' => 'DB/Adapter/Pdo/Mysql.php'], + [ + 'type' => 'library', + 'name' => 'magento/framework', + 'path' => 'DB/Adapter/Pdo/Mysql.php' + ], ] ], + 'Magento\Framework\Serialize\Serializer\Serialize' => [ + 'replacement' => 'Magento\Framework\Serialize\SerializerInterface', + 'exclude' => [ + [ + 'type' => 'library', + 'name' => 'magento/framework', + 'path' => 'DB/Adapter/Pdo/Mysql.php' + ], + [ + 'type' => 'library', + 'name' => 'magento/framework', + 'path' => 'App/ObjectManager/ConfigLoader/Compiled.php' + ], + [ + 'type' => 'library', + 'name' => 'magento/framework', + 'path' => 'App/Config/ScopePool.php'], + [ + 'type' => 'library', + 'name' => 'magento/framework', + 'path' => 'App/ObjectManager/ConfigCache.php' + ], + [ + 'type' => 'library', + 'name' => 'magento/framework', + 'path' => 'App/ObjectManager/ConfigLoader.php' + ], + [ + 'type' => 'library', + 'name' => 'magento/framework', + 'path' => 'ObjectManager/Config/Compiled.php' + ], + [ + 'type' => 'library', + 'name' => 'magento/framework', + 'path' => 'Interception/Config/Config.php' + ], + [ + 'type' => 'library', + 'name' => 'magento/framework', + 'path' => 'Interception/PluginList/PluginList.php' + ], + [ + 'type' => 'library', + 'name' => 'magento/framework', + 'path' => 'App/Router/ActionList.php' + ], + [ + 'type' => 'library', + 'name' => 'magento/framework', + 'path' => 'Serialize/Test/Unit/Serializer/SerializeTest.php' + ], + [ + 'type' => 'setup', + 'path' => 'src/Magento/Setup/Module/Di/Compiler/Config/Writer/Filesystem.php' + ], + ] + ] ]; diff --git a/dev/tests/static/testsuite/Magento/Test/Legacy/_files/security/blacklist.php b/dev/tests/static/testsuite/Magento/Test/Legacy/_files/security/blacklist.php deleted file mode 100644 index 42b8e68e784111b96d43049ae27dc5ebc963ad40..0000000000000000000000000000000000000000 --- a/dev/tests/static/testsuite/Magento/Test/Legacy/_files/security/blacklist.php +++ /dev/null @@ -1,10 +0,0 @@ -<?php -/** - * Copyright © 2016 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -return [ - 'Test/Unit', - 'lib/internal/Magento/Framework/DB/Adapter/Pdo/Mysql.php', - 'lib/internal/Magento/Framework/Serialize/Serializer/Serialize.php', -]; diff --git a/dev/tests/static/testsuite/Magento/Test/Legacy/_files/security/unsecure_php_functions.php b/dev/tests/static/testsuite/Magento/Test/Legacy/_files/security/unsecure_php_functions.php new file mode 100644 index 0000000000000000000000000000000000000000..eb51d1bbba3bd98ec7ef2d5fd26754aea8fc221a --- /dev/null +++ b/dev/tests/static/testsuite/Magento/Test/Legacy/_files/security/unsecure_php_functions.php @@ -0,0 +1,52 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +/** + * Functions that are not secure to use. + * A <replacement> will be suggested to be used instead. + * Use <exclude> to specify files and directories that are allowed to use function. + * + * Format: [ + * <class_name> => [ + * 'replacement' => <replacement>, + * 'exclude' => [ + * <exclude>, + * <exclude>, + * ] + * ] + */ +return [ + 'unserialize' => [ + 'replacement' => '\Magento\Framework\Serialize\SerializerInterface::unserialize', + 'exclude' => [ + ['type' => 'library', 'name' => 'magento/framework', 'path' => 'DB/Adapter/Pdo/Mysql.php'], + ['type' => 'library', 'name' => 'magento/framework', 'path' => 'Serialize/Serializer/Serialize.php'], + ] + ], + 'serialize' => [ + 'replacement' => '\Magento\Framework\Serialize\SerializerInterface::serialize', + 'exclude' => [ + ['type' => 'library', 'name' => 'magento/framework', 'path' => 'DB/Adapter/Pdo/Mysql.php'], + ['type' => 'library', 'name' => 'magento/framework', 'path' => 'Serialize/Serializer/Serialize.php'], + ] + ], + 'eval' => [ + 'replacement' => '', + 'exclude' => [] + ], + 'md5' => [ + 'replacement' => '', + 'exclude' => [] + ], + 'srand' => [ + 'replacement' => '', + 'exclude' => [] + ], + 'mt_srand' => [ + 'replacement' => '', + 'exclude' => [] + ], +]; diff --git a/lib/internal/Magento/Framework/Api/ExtensionAttribute/Config.php b/lib/internal/Magento/Framework/Api/ExtensionAttribute/Config.php index 303e4a57926662733398a7703afea0c548da2f03..1dcfe02e56b3ed22f780216bb0728a8a0ee6466e 100644 --- a/lib/internal/Magento/Framework/Api/ExtensionAttribute/Config.php +++ b/lib/internal/Magento/Framework/Api/ExtensionAttribute/Config.php @@ -7,24 +7,32 @@ namespace Magento\Framework\Api\ExtensionAttribute; use Magento\Framework\Config\CacheInterface; use Magento\Framework\Api\ExtensionAttribute\Config\Reader; +use Magento\Framework\Serialize\SerializerInterface; /** * Extension attributes config */ class Config extends \Magento\Framework\Config\Data { + /** + * Cache identifier + */ const CACHE_ID = 'extension_attributes_config'; /** - * Initialize reader and cache. + * Constructor * * @param Reader $reader * @param CacheInterface $cache + * @param string $cacheId|null + * @param SerializerInterface|null $serializer */ public function __construct( Reader $reader, - CacheInterface $cache + CacheInterface $cache, + $cacheId = self::CACHE_ID, + SerializerInterface $serializer = null ) { - parent::__construct($reader, $cache, self::CACHE_ID); + parent::__construct($reader, $cache, $cacheId, $serializer); } } diff --git a/lib/internal/Magento/Framework/Api/Search/SearchResult.php b/lib/internal/Magento/Framework/Api/Search/SearchResult.php index f637ef27d7b2cb4889e509aac154997ff1454aa9..f4ece5c84dde049468b76b357ecb09e2e86c2230 100644 --- a/lib/internal/Magento/Framework/Api/Search/SearchResult.php +++ b/lib/internal/Magento/Framework/Api/Search/SearchResult.php @@ -85,4 +85,18 @@ class SearchResult extends AbstractSimpleObject implements SearchResultInterface { return $this->setData(self::TOTAL_COUNT, $totalCount); } + + /** + * Retrieve ids of all items + * + * @return array + */ + public function getAllIds() + { + $ids = []; + foreach ($this->getItems() as $item) { + $ids[] = $item->getId(); + } + return $ids; + } } diff --git a/lib/internal/Magento/Framework/Api/Search/SearchResultInterface.php b/lib/internal/Magento/Framework/Api/Search/SearchResultInterface.php index ffa4c0fe43cf2422efbefc5a2c1605ec78281711..d44a8be3fb0ecff9a5031d07d66a50785c31c9d0 100644 --- a/lib/internal/Magento/Framework/Api/Search/SearchResultInterface.php +++ b/lib/internal/Magento/Framework/Api/Search/SearchResultInterface.php @@ -7,6 +7,11 @@ namespace Magento\Framework\Api\Search; use Magento\Framework\Api\SearchResultsInterface; +/** + * Interface SearchResultInterface + * + * @api + */ interface SearchResultInterface extends SearchResultsInterface { /**#@+ @@ -48,4 +53,11 @@ interface SearchResultInterface extends SearchResultsInterface * @return \Magento\Framework\Api\Search\SearchCriteriaInterface */ public function getSearchCriteria(); + + /** + * Retrieve all ids from list + * + * @return int[] + */ + public function getAllIds(); } diff --git a/lib/internal/Magento/Framework/Api/Test/Unit/Search/SearchResultTest.php b/lib/internal/Magento/Framework/Api/Test/Unit/Search/SearchResultTest.php new file mode 100644 index 0000000000000000000000000000000000000000..5d289291996906e4b60b0940da8fafd893a720fc --- /dev/null +++ b/lib/internal/Magento/Framework/Api/Test/Unit/Search/SearchResultTest.php @@ -0,0 +1,72 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Framework\Api\Test\Unit\Search; + +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; +use Magento\Framework\Api\Search\SearchResult; +use Magento\Framework\Api\Search\DocumentInterface; + +class SearchResultTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var SearchResult + */ + private $search; + + /** + * @var DocumentInterface[] + */ + private $items; + + /** + * @var ObjectManager + */ + private $objectManager; + + /** + * Set up + */ + protected function setUp() + { + $document1 = $this->getMock(DocumentInterface::class); + $document2 = $this->getMock(DocumentInterface::class); + + $this->items = [ $document1, $document2]; + $document1->expects($this->any()) + ->method('getId') + ->willReturn(1); + $document2->expects($this->any()) + ->method('getId') + ->willReturn(2); + + $data = [ + 'items' => $this->items + ]; + $this->objectManager = new ObjectManager($this); + $this->search = $this->objectManager->getObject( + SearchResult::class, + [ + 'data' => $data + ] + ); + } + + /** + * Test getAllIds + */ + public function testGetAllIds() + { + $this->assertEquals([1, 2], $this->search->getAllIds()); + } + + /** + * Test getItems + */ + public function testGetItems() + { + $this->assertEquals($this->items, $this->search->getItems()); + } +} diff --git a/lib/internal/Magento/Framework/App/Cache/TypeList.php b/lib/internal/Magento/Framework/App/Cache/TypeList.php index 1fae9652810c8528870c5157948a4aa4809dcb0f..38516b7174d6f143b066752394b8f469a87e3bd5 100644 --- a/lib/internal/Magento/Framework/App/Cache/TypeList.php +++ b/lib/internal/Magento/Framework/App/Cache/TypeList.php @@ -5,6 +5,9 @@ */ namespace Magento\Framework\App\Cache; +use Magento\Framework\App\ObjectManager; +use Magento\Framework\Serialize\SerializerInterface; + class TypeList implements TypeListInterface { const INVALIDATED_TYPES = 'core_cache_invalidate'; @@ -29,22 +32,30 @@ class TypeList implements TypeListInterface */ protected $_cache; + /** + * @var SerializerInterface + */ + private $serializer; + /** * @param \Magento\Framework\Cache\ConfigInterface $config * @param StateInterface $cacheState * @param InstanceFactory $factory * @param \Magento\Framework\App\CacheInterface $cache + * @param SerializerInterface $serializer */ public function __construct( \Magento\Framework\Cache\ConfigInterface $config, StateInterface $cacheState, InstanceFactory $factory, - \Magento\Framework\App\CacheInterface $cache + \Magento\Framework\App\CacheInterface $cache, + SerializerInterface $serializer = null ) { $this->_config = $config; $this->_factory = $factory; $this->_cacheState = $cacheState; $this->_cache = $cache; + $this->serializer = $serializer ?: ObjectManager::getInstance()->get(SerializerInterface::class); } /** @@ -72,7 +83,7 @@ class TypeList implements TypeListInterface { $types = $this->_cache->load(self::INVALIDATED_TYPES); if ($types) { - $types = unserialize($types); + $types = $this->serializer->unserialize($types); } else { $types = []; } @@ -87,7 +98,7 @@ class TypeList implements TypeListInterface */ protected function _saveInvalidatedTypes($types) { - $this->_cache->save(serialize($types), self::INVALIDATED_TYPES); + $this->_cache->save($this->serializer->serialize($types), self::INVALIDATED_TYPES); } /** 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/CommentInterface.php b/lib/internal/Magento/Framework/App/Config/CommentInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..902d63668f368912208ed38c9d19ebb985af8b31 --- /dev/null +++ b/lib/internal/Magento/Framework/App/Config/CommentInterface.php @@ -0,0 +1,21 @@ +<?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 CommentInterface + */ +interface CommentInterface +{ + /** + * Retrieve comment for configuration data. + * + * @return string + */ + public function get(); +} 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/Initial.php b/lib/internal/Magento/Framework/App/Config/Initial.php index 0704fb855939625d2fd7c756e7abf1a213391efb..5669041ee98d232682ca8c2102290e71c0059433 100644 --- a/lib/internal/Magento/Framework/App/Config/Initial.php +++ b/lib/internal/Magento/Framework/App/Config/Initial.php @@ -8,6 +8,7 @@ namespace Magento\Framework\App\Config; use Magento\Framework\App\Config\ScopeConfigInterface; +use Magento\Framework\Serialize\SerializerInterface; class Initial { @@ -31,19 +32,30 @@ class Initial protected $_metadata = []; /** - * @param \Magento\Framework\App\Config\Initial\Reader $reader + * @var SerializerInterface + */ + private $serializer; + + /** + * Initial constructor + * + * @param Initial\Reader $reader * @param \Magento\Framework\App\Cache\Type\Config $cache + * @param SerializerInterface|null $serializer */ public function __construct( \Magento\Framework\App\Config\Initial\Reader $reader, - \Magento\Framework\App\Cache\Type\Config $cache + \Magento\Framework\App\Cache\Type\Config $cache, + SerializerInterface $serializer = null ) { + $this->serializer = $serializer ?: \Magento\Framework\App\ObjectManager::getInstance() + ->get(SerializerInterface::class); $data = $cache->load(self::CACHE_ID); if (!$data) { $data = $reader->read(); - $cache->save(serialize($data), self::CACHE_ID); + $cache->save($this->serializer->serialize($data), self::CACHE_ID); } else { - $data = unserialize($data); + $data = $this->serializer->unserialize($data); } $this->_data = $data['data']; $this->_metadata = $data['metadata']; 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/PreProcessorComposite.php b/lib/internal/Magento/Framework/App/Config/PreProcessorComposite.php new file mode 100644 index 0000000000000000000000000000000000000000..10c355d290dfc43f818fa3799ad8b46807d7e6cd --- /dev/null +++ b/lib/internal/Magento/Framework/App/Config/PreProcessorComposite.php @@ -0,0 +1,40 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Framework\App\Config; + +use Magento\Framework\App\Config\Spi\PreProcessorInterface; + +/** + * Class PreProcessorComposite + */ +class PreProcessorComposite implements PreProcessorInterface +{ + /** + * @var PreProcessorInterface[] + */ + private $processors = []; + + /** + * @param PreProcessorInterface[] $processors + */ + public function __construct(array $processors = []) + { + $this->processors = $processors; + } + + /** + * @inheritdoc + */ + public function process(array $config) + { + /** @var PreProcessorInterface $processor */ + 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/Config/Spi/PreProcessorInterface.php b/lib/internal/Magento/Framework/App/Config/Spi/PreProcessorInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..1be0783d7f7deb9ec393a40eff2e2d0df3197281 --- /dev/null +++ b/lib/internal/Magento/Framework/App/Config/Spi/PreProcessorInterface.php @@ -0,0 +1,20 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Framework\App\Config\Spi; + +/** + * Allows to use custom callbacks and functions before applying fallback + */ +interface PreProcessorInterface +{ + /** + * Pre-processing of config + * + * @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..d5a224d1b50b221d0afcf7c6127325d702c5217d 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,47 @@ 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]; + if (is_array($fileBuffer)) { + $result = array_replace_recursive($result, $fileBuffer); + } + } + } + } + + if ($fileDriver->isExists($path . '/' . $pathConfig)) { + $fileBuffer = include $path . '/' . $pathConfig; + $result = array_replace_recursive($result, $fileBuffer); + } + + if ($fileDriver->isExists($path . '/' . $pathConfig)) { + $configResult = include $path . '/' . $pathConfig; + if (is_array($configResult)) { + $result = array_replace_recursive($result, $configResult); + } + } + + return $result; } /** diff --git a/lib/internal/Magento/Framework/App/DeploymentConfig/Writer.php b/lib/internal/Magento/Framework/App/DeploymentConfig/Writer.php index ac1e5f6ecf897c4769af5b3dbe97cfde4a9e9ee8..2d8e7a14aaf55519d33376f1ee09f80b9b46cec6 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,19 @@ class Writer * * @param array $data * @param bool $override + * @param string $pool + * @param array $comments * @return void + * @throws FileSystemException */ - public function saveConfig(array $data, $override = false) + public function saveConfig(array $data, $override = false, $pool = null, array $comments = []) { - $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 { @@ -111,9 +113,10 @@ class Writer } } - $contents = $this->formatter->format($config); + $contents = $this->formatter->format($config, $comments); 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/DeploymentConfig/Writer/FormatterInterface.php b/lib/internal/Magento/Framework/App/DeploymentConfig/Writer/FormatterInterface.php index 24e31074501f3aae16a12bed0473ccfd43d45ac0..640bcb61d2031abd4d671e6f02de0636b252b16d 100644 --- a/lib/internal/Magento/Framework/App/DeploymentConfig/Writer/FormatterInterface.php +++ b/lib/internal/Magento/Framework/App/DeploymentConfig/Writer/FormatterInterface.php @@ -12,7 +12,8 @@ interface FormatterInterface * Format deployment configuration * * @param array $data + * @param array $comments * @return string */ - public function format($data); + public function format($data, array $comments = []); } diff --git a/lib/internal/Magento/Framework/App/DeploymentConfig/Writer/PhpFormatter.php b/lib/internal/Magento/Framework/App/DeploymentConfig/Writer/PhpFormatter.php index 1ab99358cef1adacff5dc2dabc1ea884885e5d95..91bd906e3ca4d83438188e3131ba5e9537af939c 100644 --- a/lib/internal/Magento/Framework/App/DeploymentConfig/Writer/PhpFormatter.php +++ b/lib/internal/Magento/Framework/App/DeploymentConfig/Writer/PhpFormatter.php @@ -12,10 +12,26 @@ namespace Magento\Framework\App\DeploymentConfig\Writer; class PhpFormatter implements FormatterInterface { /** + * Format deployment configuration. + * If $comments is present, each item will be added + * as comment to the corresponding section + * * {@inheritdoc} */ - public function format($data) + public function format($data, array $comments = []) { + if (!empty($comments) && is_array($data)) { + $elements = []; + foreach ($data as $key => $value) { + $comment = ' '; + if (!empty($comments[$key])) { + $comment = " /**\n * " . str_replace("\n", "\n * ", var_export($comments[$key], true)) . "\n */\n"; + } + $space = is_array($value) ? " \n" : ' '; + $elements[] = $comment . var_export($key, true) . ' =>' . $space . var_export($value, true); + } + return "<?php\nreturn array (\n" . implode(",\n", str_replace("\n", "\n ", $elements)) . "\n);\n"; + } return "<?php\nreturn " . var_export($data, true) . ";\n"; } } 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/ObjectManager/ConfigCache.php b/lib/internal/Magento/Framework/App/ObjectManager/ConfigCache.php index 7e8711d027bb730327f080170f6b5d4557ed9630..4e685e3472ef8305095c150088b77efc94964244 100644 --- a/lib/internal/Magento/Framework/App/ObjectManager/ConfigCache.php +++ b/lib/internal/Magento/Framework/App/ObjectManager/ConfigCache.php @@ -7,6 +7,9 @@ */ namespace Magento\Framework\App\ObjectManager; +use Magento\Framework\Serialize\SerializerInterface; +use Magento\Framework\Serialize\Serializer\Serialize; + class ConfigCache implements \Magento\Framework\ObjectManager\ConfigCacheInterface { /** @@ -21,6 +24,11 @@ class ConfigCache implements \Magento\Framework\ObjectManager\ConfigCacheInterfa */ protected $_prefix = 'diConfig'; + /** + * @var SerializerInterface + */ + private $serializer; + /** * @param \Magento\Framework\Cache\FrontendInterface $cacheFrontend */ @@ -37,7 +45,7 @@ class ConfigCache implements \Magento\Framework\ObjectManager\ConfigCacheInterfa */ public function get($key) { - return unserialize($this->_cacheFrontend->load($this->_prefix . $key)); + return $this->getSerializer()->unserialize($this->_cacheFrontend->load($this->_prefix . $key)); } /** @@ -49,6 +57,20 @@ class ConfigCache implements \Magento\Framework\ObjectManager\ConfigCacheInterfa */ public function save(array $config, $key) { - $this->_cacheFrontend->save(serialize($config), $this->_prefix . $key); + $this->_cacheFrontend->save($this->getSerializer()->serialize($config), $this->_prefix . $key); + } + + /** + * Get serializer + * + * @return SerializerInterface + * @deprecated + */ + private function getSerializer() + { + if (null === $this->serializer) { + $this->serializer = \Magento\Framework\App\ObjectManager::getInstance()->get(Serialize::class); + } + return $this->serializer; } } diff --git a/lib/internal/Magento/Framework/App/ObjectManager/ConfigLoader.php b/lib/internal/Magento/Framework/App/ObjectManager/ConfigLoader.php index 2190ff6cdb37fa5a17bc618dc4b8b2f396a787ad..2770443b6d7e28bc1565c6a79372402f5e196fee 100644 --- a/lib/internal/Magento/Framework/App/ObjectManager/ConfigLoader.php +++ b/lib/internal/Magento/Framework/App/ObjectManager/ConfigLoader.php @@ -7,6 +7,8 @@ */ namespace Magento\Framework\App\ObjectManager; +use Magento\Framework\Serialize\SerializerInterface; +use Magento\Framework\Serialize\Serializer\Serialize; use Magento\Framework\ObjectManager\ConfigLoaderInterface; class ConfigLoader implements ConfigLoaderInterface @@ -32,6 +34,11 @@ class ConfigLoader implements ConfigLoaderInterface */ protected $_cache; + /** + * @var SerializerInterface + */ + private $serializer; + /** * @param \Magento\Framework\Config\CacheInterface $cache * @param \Magento\Framework\ObjectManager\Config\Reader\DomFactory $readerFactory @@ -67,11 +74,25 @@ class ConfigLoader implements ConfigLoaderInterface if (!$data) { $data = $this->_getReader()->read($area); - $this->_cache->save(serialize($data), $cacheId); + $this->_cache->save($this->getSerializer()->serialize($data), $cacheId); } else { - $data = unserialize($data); + $data = $this->getSerializer()->unserialize($data); } return $data; } + + /** + * Get serializer + * + * @return SerializerInterface + * @deprecated + */ + private function getSerializer() + { + if (null === $this->serializer) { + $this->serializer = \Magento\Framework\App\ObjectManager::getInstance()->get(Serialize::class); + } + return $this->serializer; + } } diff --git a/lib/internal/Magento/Framework/App/ObjectManager/ConfigLoader/Compiled.php b/lib/internal/Magento/Framework/App/ObjectManager/ConfigLoader/Compiled.php index 844d3f038aefec4e5e13e80741d5f49477eea627..669c9f4121ac0612faf6ac34317e180b6011eddb 100644 --- a/lib/internal/Magento/Framework/App/ObjectManager/ConfigLoader/Compiled.php +++ b/lib/internal/Magento/Framework/App/ObjectManager/ConfigLoader/Compiled.php @@ -6,7 +6,10 @@ */ namespace Magento\Framework\App\ObjectManager\ConfigLoader; +use Magento\Framework\App\Filesystem\DirectoryList; use Magento\Framework\ObjectManager\ConfigLoaderInterface; +use Magento\Framework\Serialize\SerializerInterface; +use Magento\Framework\Serialize\Serializer\Serialize; class Compiled implements ConfigLoaderInterface { @@ -17,6 +20,11 @@ class Compiled implements ConfigLoaderInterface */ private $configCache = []; + /** + * @var SerializerInterface + */ + private $serializer; + /** * {inheritdoc} */ @@ -25,18 +33,33 @@ class Compiled implements ConfigLoaderInterface if (isset($this->configCache[$area])) { return $this->configCache[$area]; } - $this->configCache[$area] = \unserialize(\file_get_contents(self::getFilePath($area))); + $this->configCache[$area] = $this->getSerializer()->unserialize(\file_get_contents(self::getFilePath($area))); return $this->configCache[$area]; } /** - * Returns path to cached configuration + * Returns path to compiled configuration * * @param string $area * @return string */ public static function getFilePath($area) { - return BP . '/var/di/' . $area . '.ser'; + $diPath = DirectoryList::getDefaultConfig()[DirectoryList::DI][DirectoryList::PATH]; + return BP . '/' . $diPath . '/' . $area . '.ser'; + } + + /** + * Get serializer + * + * @return SerializerInterface + * @deprecated + */ + private function getSerializer() + { + if (null === $this->serializer) { + $this->serializer = new Serialize(); + } + return $this->serializer; } } diff --git a/lib/internal/Magento/Framework/App/ObjectManagerFactory.php b/lib/internal/Magento/Framework/App/ObjectManagerFactory.php index 3a007841532cc84258b7a1a4d5d03aff927b4161..530c7c43599dfcdc8749491716f0239079d16243 100644 --- a/lib/internal/Magento/Framework/App/ObjectManagerFactory.php +++ b/lib/internal/Magento/Framework/App/ObjectManagerFactory.php @@ -1,7 +1,5 @@ <?php /** - * Initialize application object manager. - * * Copyright © 2016 Magento. All rights reserved. * See COPYING.txt for license details. */ @@ -10,22 +8,15 @@ namespace Magento\Framework\App; use Magento\Framework\App\Filesystem\DirectoryList; use Magento\Framework\Filesystem\DriverPool; use Magento\Framework\Interception\ObjectManager\ConfigInterface; -use Magento\Framework\ObjectManager\Definition\Compiled\Serialized; use Magento\Framework\App\ObjectManager\Environment; use Magento\Framework\Config\File\ConfigFilePool; use Magento\Framework\Code\GeneratedFiles; /** * @SuppressWarnings(PHPMD.CouplingBetweenObjects) - * Class ObjectManagerFactory */ class ObjectManagerFactory { - /** - * Path to definitions format in deployment configuration - */ - const CONFIG_PATH_DEFINITION_FORMAT = 'definition/format'; - /** * Initialization parameter for a custom deployment configuration file */ @@ -117,18 +108,16 @@ class ObjectManagerFactory $arguments = array_merge($deploymentConfig->get(), $arguments); $definitionFactory = new \Magento\Framework\ObjectManager\DefinitionFactory( $this->driverPool->getDriver(DriverPool::FILE), - $this->directoryList->getPath(DirectoryList::DI), - $this->directoryList->getPath(DirectoryList::GENERATION), - $deploymentConfig->get(self::CONFIG_PATH_DEFINITION_FORMAT, Serialized::MODE_NAME) + $this->directoryList->getPath(DirectoryList::GENERATION) ); - $definitions = $definitionFactory->createClassDefinition($deploymentConfig->get('definitions')); + $definitions = $definitionFactory->createClassDefinition(); $relations = $definitionFactory->createRelations(); /** @var EnvironmentFactory $envFactory */ $envFactory = new $this->envFactoryClassName($relations, $definitions); /** @var EnvironmentInterface $env */ - $env = $envFactory->createEnvironment(); + $env = $envFactory->createEnvironment(); /** @var ConfigInterface $diConfig */ $diConfig = $env->getDiConfig(); @@ -298,6 +287,8 @@ class ObjectManagerFactory * @param \Magento\Framework\ObjectManager\Config\Config $diConfig * @param \Magento\Framework\ObjectManager\DefinitionInterface $definitions * @return \Magento\Framework\Interception\PluginList\PluginList + * @deprecated + * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ protected function _createPluginList( \Magento\Framework\ObjectManagerInterface $objectManager, @@ -312,8 +303,7 @@ class ObjectManagerFactory 'relations' => $relations, 'definitions' => $definitionFactory->createPluginDefinition(), 'omConfig' => $diConfig, - 'classDefinitions' => $definitions instanceof - \Magento\Framework\ObjectManager\Definition\Compiled ? $definitions : null + 'classDefinitions' => null ] ); } 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..e967bb1b007b9d495e3eaed6bfb399ce247ecdba 100644 --- a/lib/internal/Magento/Framework/App/ResourceConnection/Config.php +++ b/lib/internal/Magento/Framework/App/ResourceConnection/Config.php @@ -1,14 +1,16 @@ <?php /** - * Resource configuration. Uses application configuration to retrieve resource connection information. - * * Copyright © 2016 Magento. All rights reserved. * See COPYING.txt for license details. */ namespace Magento\Framework\App\ResourceConnection; use Magento\Framework\Config\ConfigOptionsListConstants; +use Magento\Framework\Serialize\SerializerInterface; +/** + * Resource configuration, uses application configuration to retrieve resource connection information + */ class Config extends \Magento\Framework\Config\Data\Scoped implements ConfigInterface { /** @@ -19,11 +21,24 @@ class Config extends \Magento\Framework\Config\Data\Scoped implements ConfigInte protected $_connectionNames = []; /** + * @var \Magento\Framework\App\DeploymentConfig + */ + private $deploymentConfig; + + /** + * @var bool + */ + private $initialized = false; + + /** + * Constructor + * * @param Config\Reader $reader * @param \Magento\Framework\Config\ScopeInterface $configScope * @param \Magento\Framework\Config\CacheInterface $cache * @param \Magento\Framework\App\DeploymentConfig $deploymentConfig - * @param string $cacheId + * @param string|null $cacheId + * @param SerializerInterface|null $serializer * @throws \InvalidArgumentException */ public function __construct( @@ -31,17 +46,11 @@ class Config extends \Magento\Framework\Config\Data\Scoped implements ConfigInte \Magento\Framework\Config\ScopeInterface $configScope, \Magento\Framework\Config\CacheInterface $cache, \Magento\Framework\App\DeploymentConfig $deploymentConfig, - $cacheId = 'resourcesCache' + $cacheId = 'resourcesCache', + SerializerInterface $serializer = null ) { - 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']; - } + parent::__construct($reader, $configScope, $cache, $cacheId, $serializer); + $this->deploymentConfig = $deploymentConfig; } /** @@ -52,6 +61,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 +90,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/Route/Config.php b/lib/internal/Magento/Framework/App/Route/Config.php index 70968c84d77fcf7de3951b182fd7cde2a12e365d..60412e7fa888b2969067ab7e73725b5f39d301a9 100644 --- a/lib/internal/Magento/Framework/App/Route/Config.php +++ b/lib/internal/Magento/Framework/App/Route/Config.php @@ -7,6 +7,8 @@ */ namespace Magento\Framework\App\Route; +use Magento\Framework\Serialize\SerializerInterface; + class Config implements ConfigInterface { /** @@ -39,6 +41,11 @@ class Config implements ConfigInterface */ protected $_routes; + /** + * @var SerializerInterface + */ + private $serializer; + /** * @param Config\Reader $reader * @param \Magento\Framework\Config\CacheInterface $cache @@ -73,7 +80,7 @@ class Config implements ConfigInterface return $this->_routes[$scope]; } $cacheId = $scope . '::' . $this->_cacheId; - $cachedRoutes = unserialize($this->_cache->load($cacheId)); + $cachedRoutes = $this->getSerializer()->unserialize($this->_cache->load($cacheId)); if (is_array($cachedRoutes)) { $this->_routes[$scope] = $cachedRoutes; return $cachedRoutes; @@ -81,7 +88,8 @@ class Config implements ConfigInterface $routers = $this->_reader->read($scope); $routes = $routers[$this->_areaList->getDefaultRouter($scope)]['routes']; - $this->_cache->save(serialize($routes), $cacheId); + $routesData = $this->getSerializer()->serialize($routes); + $this->_cache->save($routesData, $cacheId); $this->_routes[$scope] = $routes; return $routes; } @@ -133,4 +141,19 @@ class Config implements ConfigInterface return array_unique($modules); } + + /** + * Get serializer + * + * @return \Magento\Framework\Serialize\SerializerInterface + * @deprecated + */ + private function getSerializer() + { + if ($this->serializer === null) { + $this->serializer = \Magento\Framework\App\ObjectManager::getInstance() + ->get(SerializerInterface::class); + } + return $this->serializer; + } } diff --git a/lib/internal/Magento/Framework/App/Router/ActionList.php b/lib/internal/Magento/Framework/App/Router/ActionList.php index 11ee22a5f375ebd5f08e6cb7d606c5a4787074db..ec46154b2553ac2bc7f1d6e288a04f63602d25f7 100644 --- a/lib/internal/Magento/Framework/App/Router/ActionList.php +++ b/lib/internal/Magento/Framework/App/Router/ActionList.php @@ -6,6 +6,8 @@ */ namespace Magento\Framework\App\Router; +use Magento\Framework\Serialize\SerializerInterface; +use Magento\Framework\Serialize\Serializer\Serialize; use Magento\Framework\Module\Dir\Reader as ModuleReader; class ActionList @@ -36,27 +38,42 @@ class ActionList ]; /** + * @var SerializerInterface + */ + private $serializer; + + /** + * @var string + */ + private $actionInterface; + + /** + * ActionList constructor + * * @param \Magento\Framework\Config\CacheInterface $cache * @param ModuleReader $moduleReader * @param string $actionInterface * @param string $cacheKey * @param array $reservedWords + * @param SerializerInterface|null $serializer */ public function __construct( \Magento\Framework\Config\CacheInterface $cache, ModuleReader $moduleReader, $actionInterface = \Magento\Framework\App\ActionInterface::class, $cacheKey = 'app_action_list', - $reservedWords = [] + $reservedWords = [], + SerializerInterface $serializer = null ) { $this->reservedWords = array_merge($reservedWords, $this->reservedWords); $this->actionInterface = $actionInterface; + $this->serializer = $serializer ?: \Magento\Framework\App\ObjectManager::getInstance()->get(Serialize::class); $data = $cache->load($cacheKey); if (!$data) { $this->actions = $moduleReader->getActionFiles(); - $cache->save(serialize($this->actions), $cacheKey); + $cache->save($this->serializer->serialize($this->actions), $cacheKey); } else { - $this->actions = unserialize($data); + $this->actions = $this->serializer->unserialize($data); } } diff --git a/lib/internal/Magento/Framework/App/Test/Unit/Cache/TypeListTest.php b/lib/internal/Magento/Framework/App/Test/Unit/Cache/TypeListTest.php index a6074f6c457402054cae24c5ac05a499ef21e8fe..d185219becefed1935960b78467c98316c8bbcc3 100644 --- a/lib/internal/Magento/Framework/App/Test/Unit/Cache/TypeListTest.php +++ b/lib/internal/Magento/Framework/App/Test/Unit/Cache/TypeListTest.php @@ -7,6 +7,7 @@ namespace Magento\Framework\App\Test\Unit\Cache; use \Magento\Framework\App\Cache\TypeList; +use Magento\Framework\Serialize\SerializerInterface; /** * Test class for \Magento\Framework\App\Cache\TypeList @@ -48,6 +49,11 @@ class TypeListTest extends \PHPUnit_Framework_TestCase */ const CACHE_TYPE = \Magento\Framework\Cache\FrontendInterface::class; + /** + * @var SerializerInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $serializerMock; + protected function setUp() { $this->_typesArray = [ @@ -85,6 +91,7 @@ class TypeListTest extends \PHPUnit_Framework_TestCase '', false ); + $this->serializerMock = $this->getMock(SerializerInterface::class); $objectHelper = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); $this->_typeList = $objectHelper->getObject( @@ -93,7 +100,8 @@ class TypeListTest extends \PHPUnit_Framework_TestCase 'config' => $this->_config, 'cacheState' => $cacheState, 'factory' => $factory, - 'cache' => $this->_cache + 'cache' => $this->_cache, + 'serializer' => $this->serializerMock, ] ); } @@ -118,8 +126,12 @@ class TypeListTest extends \PHPUnit_Framework_TestCase { $expectation = [self::TYPE_KEY => $this->_getPreparedType()]; $this->_cache->expects($this->once())->method('load')->with(TypeList::INVALIDATED_TYPES)->will( - $this->returnValue(serialize($this->_typesArray)) + $this->returnValue('serializedData') ); + $this->serializerMock->expects($this->once()) + ->method('unserialize') + ->with('serializedData') + ->willReturn($this->_typesArray); $this->assertEquals($expectation, $this->_typeList->getInvalidated()); } @@ -132,8 +144,12 @@ class TypeListTest extends \PHPUnit_Framework_TestCase $expectedInvalidated = [ self::TYPE_KEY => 1, ]; + $this->serializerMock->expects($this->once()) + ->method('serialize') + ->with($expectedInvalidated) + ->willReturn('serializedData'); $this->_cache->expects($this->once())->method('save')->with( - serialize($expectedInvalidated), + 'serializedData', TypeList::INVALIDATED_TYPES ); $this->_typeList->invalidate(self::TYPE_KEY); @@ -147,8 +163,12 @@ class TypeListTest extends \PHPUnit_Framework_TestCase $expectedInvalidated = [ self::TYPE_KEY => 1, ]; + $this->serializerMock->expects($this->once()) + ->method('serialize') + ->with($expectedInvalidated) + ->willReturn('serializedData'); $this->_cache->expects($this->once())->method('save')->with( - serialize($expectedInvalidated), + 'serializedData', TypeList::INVALIDATED_TYPES ); $this->_typeList->invalidate([self::TYPE_KEY]); @@ -156,15 +176,23 @@ class TypeListTest extends \PHPUnit_Framework_TestCase public function testCleanType() { + $this->serializerMock->expects($this->once()) + ->method('unserialize') + ->with('serializedData') + ->willReturn($this->_typesArray); $this->_cache->expects($this->once())->method('load')->with(TypeList::INVALIDATED_TYPES)->will( - $this->returnValue(serialize($this->_typesArray)) + $this->returnValue('serializedData') ); $this->_config->expects($this->once())->method('getType')->with(self::TYPE_KEY)->will( $this->returnValue(['instance' => self::CACHE_TYPE]) ); unset($this->_typesArray[self::TYPE_KEY]); + $this->serializerMock->expects($this->once()) + ->method('serialize') + ->with($this->_typesArray) + ->willReturn('serializedData'); $this->_cache->expects($this->once())->method('save')->with( - serialize($this->_typesArray), + 'serializedData', TypeList::INVALIDATED_TYPES ); $this->_typeList->cleanType(self::TYPE_KEY); 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/InitialTest.php b/lib/internal/Magento/Framework/App/Test/Unit/Config/InitialTest.php index ce85753bedab5463799390149386a36ed6143803..941a670b1b44c8848371788826dcc3953a4fa8a1 100644 --- a/lib/internal/Magento/Framework/App/Test/Unit/Config/InitialTest.php +++ b/lib/internal/Magento/Framework/App/Test/Unit/Config/InitialTest.php @@ -7,59 +7,68 @@ namespace Magento\Framework\App\Test\Unit\Config; class InitialTest extends \PHPUnit_Framework_TestCase { + /** + * @var \Magento\Framework\TestFramework\Unit\Helper\ObjectManager + */ + private $objectManager; + /** * @var \Magento\Framework\App\Config\Initial */ - protected $_model; + private $config; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\App\Cache\Type\Config|\PHPUnit_Framework_MockObject_MockObject */ - protected $_initialReaderMock; + private $cacheMock; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var array */ - protected $_configCacheMock; + private $data = [ + 'data' => [ + 'default' => ['key' => 'default_value'], + 'stores' => ['default' => ['key' => 'store_value']], + 'websites' => ['default' => ['key' => 'website_value']], + ], + 'metadata' => ['metadata'], + ]; protected function setUp() { - $this->_initialReaderMock = - $this->getMock(\Magento\Framework\App\Config\Initial\Reader::class, [], [], '', false); - $this->_configCacheMock = - $this->getMock(\Magento\Framework\App\Cache\Type\Config::class, [], [], '', false); - $serializedData = serialize( + $this->objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); + $this->cacheMock = $this->getMock( + \Magento\Framework\App\Cache\Type\Config::class, + [], + [], + '', + false + ); + $this->cacheMock->expects($this->any()) + ->method('load') + ->with('initial_config') + ->willReturn(json_encode($this->data)); + $serializerMock = $this->getMock(\Magento\Framework\Serialize\SerializerInterface::class); + $serializerMock->method('unserialize') + ->willReturn($this->data); + + $this->config = $this->objectManager->getObject( + \Magento\Framework\App\Config\Initial::class, [ - 'data' => [ - 'default' => ['key' => 'default_value'], - 'stores' => ['default' => ['key' => 'store_value']], - 'websites' => ['default' => ['key' => 'website_value']], - ], - 'metadata' => ['metadata'], + 'cache' => $this->cacheMock, + 'serializer' => $serializerMock, ] ); - $this->_configCacheMock->expects( - $this->any() - )->method( - 'load' - )->with( - 'initial_config' - )->will( - $this->returnValue($serializedData) - ); - - $this->_model = new \Magento\Framework\App\Config\Initial($this->_initialReaderMock, $this->_configCacheMock); } /** - * @dataProvider getDataDataProvider - * * @param string $scope - * @param array $expectedResult + * @param array $expected + * @dataProvider getDataDataProvider */ - public function testGetData($scope, $expectedResult) + public function testGetData($scope, $expected) { - $this->assertEquals($expectedResult, $this->_model->getData($scope)); + $this->assertEquals($expected, $this->config->getData($scope)); } public function getDataDataProvider() @@ -73,7 +82,6 @@ class InitialTest extends \PHPUnit_Framework_TestCase public function testGetMetadata() { - $expectedResult = ['metadata']; - $this->assertEquals($expectedResult, $this->_model->getMetadata()); + $this->assertEquals(['metadata'], $this->config->getMetadata()); } } 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/PreProcessorCompositeTest.php b/lib/internal/Magento/Framework/App/Test/Unit/Config/PreProcessorCompositeTest.php new file mode 100644 index 0000000000000000000000000000000000000000..291bef1266134f7956919a2c831af4a7fd4715e2 --- /dev/null +++ b/lib/internal/Magento/Framework/App/Test/Unit/Config/PreProcessorCompositeTest.php @@ -0,0 +1,40 @@ +<?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\PreProcessorComposite; +use Magento\Framework\App\Config\Spi\PreProcessorInterface; + +class PreProcessorCompositeTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var PreProcessorComposite + */ + private $model; + + /** + * @var PreProcessorInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $preProcessorMock; + + protected function setUp() + { + $this->preProcessorMock = $this->getMockBuilder(PreProcessorInterface::class) + ->getMockForAbstractClass(); + + $this->model = new PreProcessorComposite([$this->preProcessorMock]); + } + + public function testProcess() + { + $this->preProcessorMock->expects($this->once()) + ->method('process') + ->with(['test' => 'data']) + ->willReturn(['test' => 'data2']); + + $this->assertSame(['test' => 'data2'], $this->model->process(['test' => '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/Writer/PhpFormatterTest.php b/lib/internal/Magento/Framework/App/Test/Unit/DeploymentConfig/Writer/PhpFormatterTest.php index a9b5bc04a12768f8de76e5cdc514e226fb4af05b..2ab8b209272f1cc882c14fb1a2dd9a15c22605f4 100644 --- a/lib/internal/Magento/Framework/App/Test/Unit/DeploymentConfig/Writer/PhpFormatterTest.php +++ b/lib/internal/Magento/Framework/App/Test/Unit/DeploymentConfig/Writer/PhpFormatterTest.php @@ -10,10 +10,128 @@ use \Magento\Framework\App\DeploymentConfig\Writer\PhpFormatter; class PhpFormatterTest extends \PHPUnit_Framework_TestCase { - public function testFormat() + /** + * @dataProvider formatWithCommentDataProvider + * @param string|array $data + * @param array $comments + * @param string $expectedResult + */ + public function testFormat($data, $comments, $expectedResult) { $formatter = new PhpFormatter(); - $data = 'test'; - $this->assertEquals("<?php\nreturn 'test';\n", $formatter->format($data)); + $this->assertEquals($expectedResult, $formatter->format($data, $comments)); + } + + /** + * @SuppressWarnings(PHPMD.ExcessiveMethodLength) + */ + public function formatWithCommentDataProvider() + { + $array = [ + 'ns1' => [ + 's1' => [ + 's11', + 's12' + ], + 's2' => [ + 's21', + 's22' + ], + ], + 'ns2' => [ + 's1' => [ + 's11' + ], + ], + 'ns3' => 'just text', + 'ns4' => 'just text' + ]; + $comments1 = ['ns2' => 'comment for namespace 2']; + $comments2 = [ + 'ns1' => 'comment for namespace 1', + 'ns2' => "comment for namespace 2.\nNext comment for namespace 2", + 'ns3' => 'comment for namespace 3', + 'ns4' => 'comment for namespace 4', + 'ns5' => 'comment for unexisted namespace 5', + ]; + $expectedResult1 = <<<TEXT +<?php +return array ( + 'ns1' => + array ( + 's1' => + array ( + 0 => 's11', + 1 => 's12', + ), + 's2' => + array ( + 0 => 's21', + 1 => 's22', + ), + ), + /** + * 'comment for namespace 2' + */ + 'ns2' => + array ( + 's1' => + array ( + 0 => 's11', + ), + ), + 'ns3' => 'just text', + 'ns4' => 'just text' +); + +TEXT; + $expectedResult2 = <<<TEXT +<?php +return array ( + /** + * 'comment for namespace 1' + */ + 'ns1' => + array ( + 's1' => + array ( + 0 => 's11', + 1 => 's12', + ), + 's2' => + array ( + 0 => 's21', + 1 => 's22', + ), + ), + /** + * 'comment for namespace 2. + * Next comment for namespace 2' + */ + 'ns2' => + array ( + 's1' => + array ( + 0 => 's11', + ), + ), + /** + * 'comment for namespace 3' + */ + 'ns3' => 'just text', + /** + * 'comment for namespace 4' + */ + 'ns4' => 'just text' +); + +TEXT; + return [ + ['string', [], "<?php\nreturn 'string';\n"], + ['string', ['comment'], "<?php\nreturn 'string';\n"], + [$array, [], "<?php\nreturn " . var_export($array, true) . ";\n"], + [$array, $comments1, $expectedResult1], + [$array, $comments2, $expectedResult2], + ]; } } 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/ObjectManager/ConfigCacheTest.php b/lib/internal/Magento/Framework/App/Test/Unit/ObjectManager/ConfigCacheTest.php index 336e958403f9198e916af3ef3fc6a3dd10af84c3..7f05857f7cc816c9e5b0be56ae3ff520ac38efa4 100644 --- a/lib/internal/Magento/Framework/App/Test/Unit/ObjectManager/ConfigCacheTest.php +++ b/lib/internal/Magento/Framework/App/Test/Unit/ObjectManager/ConfigCacheTest.php @@ -5,49 +5,86 @@ */ namespace Magento\Framework\App\Test\Unit\ObjectManager; +use Magento\Framework\Serialize\SerializerInterface; + class ConfigCacheTest extends \PHPUnit_Framework_TestCase { /** * @var \Magento\Framework\App\ObjectManager\ConfigCache */ - protected $_configCache; + private $configCache; + + /** + * @var \Magento\Framework\App\ObjectManager\ConfigCache|\PHPUnit_Framework_MockObject_MockObject + */ + private $cacheFrontendMock; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\Serialize\SerializerInterface|\PHPUnit_Framework_MockObject_MockObject */ - protected $_cacheFrontendMock; + private $serializerMock; protected function setUp() { - $this->_cacheFrontendMock = $this->getMock(\Magento\Framework\Cache\FrontendInterface::class); - $this->_configCache = new \Magento\Framework\App\ObjectManager\ConfigCache($this->_cacheFrontendMock); + $objectManagerHelper = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); + $this->cacheFrontendMock = $this->getMock(\Magento\Framework\Cache\FrontendInterface::class); + $this->configCache = $objectManagerHelper->getObject( + \Magento\Framework\App\ObjectManager\ConfigCache::class, + ['cacheFrontend' => $this->cacheFrontendMock] + ); + + $this->serializerMock = $this->getMock(SerializerInterface::class); + $objectManagerHelper->setBackwardCompatibleProperty( + $this->configCache, + 'serializer', + $this->serializerMock + ); } protected function tearDown() { - unset($this->_configCache); + unset($this->configCache); } - public function testGet() + /** + * @dataProvider getDataProvider + */ + public function testGet($loadData, $expectedResult) { $key = 'key'; - $this->_cacheFrontendMock->expects( + $this->cacheFrontendMock->expects( $this->once() )->method( 'load' )->with( 'diConfig' . $key )->will( - $this->returnValue(false) + $this->returnValue($loadData) ); - $this->assertEquals(false, $this->_configCache->get($key)); + $this->serializerMock->expects($this->once()) + ->method('unserialize') + ->with($loadData) + ->willReturn($expectedResult); + $this->assertEquals($expectedResult, $this->configCache->get($key)); + } + + public function getDataProvider() + { + return [ + [false, false], + ['serialized data', ['some data']], + ]; } public function testSave() { $key = 'key'; $config = ['config']; - $this->_cacheFrontendMock->expects($this->once())->method('save')->with(serialize($config), 'diConfig' . $key); - $this->_configCache->save($config, $key); + $serializedData = 'serialized data'; + $this->serializerMock->expects($this->once()) + ->method('serialize') + ->willReturn($serializedData); + $this->cacheFrontendMock->expects($this->once())->method('save')->with($serializedData, 'diConfig' . $key); + $this->configCache->save($config, $key); } } diff --git a/lib/internal/Magento/Framework/App/Test/Unit/ObjectManager/ConfigLoaderTest.php b/lib/internal/Magento/Framework/App/Test/Unit/ObjectManager/ConfigLoaderTest.php index 5a0b4ae96f26cf7eeebe59e0df60d6a981fb4b08..90dba092f054e04370604d061e1eb6b5088300d2 100644 --- a/lib/internal/Magento/Framework/App/Test/Unit/ObjectManager/ConfigLoaderTest.php +++ b/lib/internal/Magento/Framework/App/Test/Unit/ObjectManager/ConfigLoaderTest.php @@ -8,31 +8,38 @@ namespace Magento\Framework\App\Test\Unit\ObjectManager; +use Magento\Framework\Serialize\SerializerInterface; + class ConfigLoaderTest extends \PHPUnit_Framework_TestCase { /** * @var \Magento\Framework\App\ObjectManager\ConfigLoader */ - protected $_model; + private $object; + + /** + * @var \Magento\Framework\ObjectManager\Config\Reader\DomFactory|\PHPUnit_Framework_MockObject_MockObject + */ + private $readerFactoryMock; /** - * @var \Magento\Framework\ObjectManager\Config\Reader\DomFactory + * @var \Magento\Framework\ObjectManager\Config\Reader\Dom|\PHPUnit_Framework_MockObject_MockObject */ - protected $_readerFactoryMock; + private $readerMock; /** - * @var \Magento\Framework\ObjectManager\Config\Reader\Dom + * @var \Magento\Framework\App\Cache\Type\Config|\PHPUnit_Framework_MockObject_MockObject */ - protected $_readerMock; + private $cacheMock; /** - * @var \Magento\Framework\App\Cache\Type\Config + * @var \Magento\Framework\Serialize\SerializerInterface|\PHPUnit_Framework_MockObject_MockObject */ - protected $_cacheMock; + private $serializerMock; protected function setUp() { - $this->_readerMock = $this->getMock( + $this->readerMock = $this->getMock( \Magento\Framework\ObjectManager\Config\Reader\Dom::class, [], [], @@ -40,7 +47,7 @@ class ConfigLoaderTest extends \PHPUnit_Framework_TestCase false ); - $this->_readerFactoryMock = $this->getMock( + $this->readerFactoryMock = $this->getMock( \Magento\Framework\ObjectManager\Config\Reader\DomFactory::class, ['create'], [], @@ -48,17 +55,29 @@ class ConfigLoaderTest extends \PHPUnit_Framework_TestCase false ); - $this->_readerFactoryMock->expects( + $this->readerFactoryMock->expects( $this->any() )->method( 'create' )->will( - $this->returnValue($this->_readerMock) + $this->returnValue($this->readerMock) ); - $this->_cacheMock = $this->getMock(\Magento\Framework\App\Cache\Type\Config::class, [], [], '', false); - $this->_model = new \Magento\Framework\App\ObjectManager\ConfigLoader( - $this->_cacheMock, $this->_readerFactoryMock + $this->cacheMock = $this->getMock(\Magento\Framework\App\Cache\Type\Config::class, [], [], '', false); + $objectManagerHelper = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); + + $this->object = $objectManagerHelper->getObject( + \Magento\Framework\App\ObjectManager\ConfigLoader::class, + [ + 'cache' => $this->cacheMock, + 'readerFactory' => $this->readerFactoryMock, + ] + ); + $this->serializerMock = $this->getMock(SerializerInterface::class); + $objectManagerHelper->setBackwardCompatibleProperty( + $this->object, + 'serializer', + $this->serializerMock ); } @@ -66,23 +85,28 @@ class ConfigLoaderTest extends \PHPUnit_Framework_TestCase * @param $area * @dataProvider loadDataProvider */ - public function testLoad($area) + public function testLoadNotCached($area) { $configData = ['some' => 'config', 'data' => 'value']; + $serializedData = 'serialized data'; - $this->_cacheMock->expects( - $this->once() - )->method( - 'load' - )->with( - $area . '::DiConfig' - )->will( - $this->returnValue(false) - ); + $this->cacheMock->expects($this->once()) + ->method('load') + ->with($area . '::DiConfig') + ->will($this->returnValue(false)); + + $this->cacheMock->expects($this->once()) + ->method('save') + ->with($serializedData); + $this->readerMock->expects($this->once())->method('read')->with($area)->will($this->returnValue($configData)); - $this->_readerMock->expects($this->once())->method('read')->with($area)->will($this->returnValue($configData)); + $this->serializerMock->expects($this->once()) + ->method('serialize') + ->willReturn($serializedData); - $this->assertEquals($configData, $this->_model->load($area)); + $this->serializerMock->expects($this->never())->method('unserialize'); + + $this->assertEquals($configData, $this->object->load($area)); } /** @@ -98,4 +122,23 @@ class ConfigLoaderTest extends \PHPUnit_Framework_TestCase 'any area files' => ['any'] ]; } + + public function testLoadCached() + { + $configData = ['some' => 'config', 'data' => 'value']; + $serializedData = 'serialized data'; + + $this->cacheMock->expects($this->once()) + ->method('load') + ->willReturn($serializedData); + $this->cacheMock->expects($this->never()) + ->method('save'); + $this->readerMock->expects($this->never())->method('read'); + $this->serializerMock->expects($this->once()) + ->method('unserialize') + ->with($serializedData) + ->willReturn($configData); + $this->serializerMock->expects($this->never())->method('serialize'); + $this->assertEquals($configData, $this->object->load('testArea')); + } } 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..4b6944146e5ed4bb9d59ce458ea9b901403cbf69 100644 --- a/lib/internal/Magento/Framework/App/Test/Unit/ResourceConnection/ConfigTest.php +++ b/lib/internal/Magento/Framework/App/Test/Unit/ResourceConnection/ConfigTest.php @@ -5,47 +5,60 @@ */ 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; + private $config; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\Config\ScopeInterface|\PHPUnit_Framework_MockObject_MockObject */ - protected $_scopeMock; + private $scopeMock; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\Config\CacheInterface|\PHPUnit_Framework_MockObject_MockObject */ - protected $_cacheMock; + private $cacheMock; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\App\ResourceConnection\Config\Reader|\PHPUnit_Framework_MockObject_MockObject */ - protected $_readerMock; + private $readerMock; /** - * @var array + * @var \Magento\Framework\Serialize\SerializerInterface|\PHPUnit_Framework_MockObject_MockObject */ - protected $_resourcesConfig; + private $serializerMock; /** * @var array */ - protected $_initialResources; + private $resourcesConfig; + + /** + * @var \Magento\Framework\App\DeploymentConfig|\PHPUnit_Framework_MockObject_MockObject + */ + private $deploymentConfig; protected function setUp() { - $this->_scopeMock = $this->getMock(\Magento\Framework\Config\ScopeInterface::class); - $this->_cacheMock = $this->getMock(\Magento\Framework\Config\CacheInterface::class); - - $this->_readerMock = - $this->getMock(\Magento\Framework\App\ResourceConnection\Config\Reader::class, [], [], '', false); + $this->scopeMock = $this->getMock(\Magento\Framework\Config\ScopeInterface::class); + $this->cacheMock = $this->getMock(\Magento\Framework\Config\CacheInterface::class); + + $this->readerMock = $this->getMock( + \Magento\Framework\App\ResourceConnection\Config\Reader::class, + [], + [], + '', + false + ); + $this->serializerMock = $this->getMock(\Magento\Framework\Serialize\SerializerInterface::class); - $this->_resourcesConfig = [ + $this->resourcesConfig = [ 'mainResourceName' => ['name' => 'mainResourceName', 'extends' => 'anotherResourceName'], 'otherResourceName' => ['name' => 'otherResourceName', 'connection' => 'otherConnectionName'], 'anotherResourceName' => ['name' => 'anotherResourceName', 'connection' => 'anotherConnection'], @@ -53,61 +66,61 @@ class ConfigTest extends \PHPUnit_Framework_TestCase 'extendedResourceName' => ['name' => 'extendedResourceName', 'extends' => 'validResource'], ]; - $this->_initialResources = [ - 'validResource' => ['connection' => 'validConnectionName'], - ]; - - $this->_cacheMock->expects( - $this->any() - )->method( - 'load' - )->will( - $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->_model = new \Magento\Framework\App\ResourceConnection\Config( - $this->_readerMock, - $this->_scopeMock, - $this->_cacheMock, - $deploymentConfig, - 'cacheId' + $serializedData = 'serialized data'; + $this->cacheMock->expects($this->any()) + ->method('load') + ->willReturn($serializedData); + $this->serializerMock->method('unserialize') + ->with($serializedData) + ->willReturn($this->resourcesConfig); + + $this->deploymentConfig = $this->getMock(\Magento\Framework\App\DeploymentConfig::class, [], [], '', false); + $this->config = new \Magento\Framework\App\ResourceConnection\Config( + $this->readerMock, + $this->scopeMock, + $this->cacheMock, + $this->deploymentConfig, + 'cacheId', + $this->serializerMock ); } /** - * @dataProvider getConnectionNameDataProvider * @param string $resourceName * @param string $connectionName + * @dataProvider getConnectionNameDataProvider */ public function testGetConnectionName($resourceName, $connectionName) { - $this->assertEquals($connectionName, $this->_model->getConnectionName($resourceName)); + $this->deploymentConfig->expects($this->once()) + ->method('getConfigData') + ->with(ConfigOptionsListConstants::KEY_RESOURCE) + ->willReturn([ + 'validResource' => ['connection' => 'validConnectionName'], + ]); + $this->assertEquals($connectionName, $this->config->getConnectionName($resourceName)); } /** * @expectedException \InvalidArgumentException */ - public function testExceptionConstructor() + public function testGetConnectionNameWithException() { - $deploymentConfig = $this->getMock(\Magento\Framework\App\DeploymentConfig::class, [], [], '', false); - $deploymentConfig->expects($this->once()) + $deploymentConfigMock = $this->getMock(\Magento\Framework\App\DeploymentConfig::class, [], [], '', false); + $deploymentConfigMock->expects($this->once()) ->method('getConfigData') - ->with('resource') + ->with(ConfigOptionsListConstants::KEY_RESOURCE) ->willReturn(['validResource' => ['somekey' => 'validConnectionName']]); - new \Magento\Framework\App\ResourceConnection\Config( - $this->_readerMock, - $this->_scopeMock, - $this->_cacheMock, - $deploymentConfig, - 'cacheId' + $config = new \Magento\Framework\App\ResourceConnection\Config( + $this->readerMock, + $this->scopeMock, + $this->cacheMock, + $deploymentConfigMock, + 'cacheId', + $this->serializerMock ); + $config->getConnectionName('default'); } /** diff --git a/lib/internal/Magento/Framework/App/Test/Unit/Route/ConfigTest.php b/lib/internal/Magento/Framework/App/Test/Unit/Route/ConfigTest.php index 949ed3f9953c91782361e30e5240748c2646f0ea..fe6f8d05114c58cc0585bc44908faf3fa2a2b666 100644 --- a/lib/internal/Magento/Framework/App/Test/Unit/Route/ConfigTest.php +++ b/lib/internal/Magento/Framework/App/Test/Unit/Route/ConfigTest.php @@ -13,7 +13,7 @@ class ConfigTest extends \PHPUnit_Framework_TestCase protected $_config; /** - * @var Cache_Mock_Wrapper + * @var \Magento\Framework\App\Route\Config\Reader|\PHPUnit_Framework_MockObject_MockObject */ protected $_readerMock; @@ -32,88 +32,76 @@ class ConfigTest extends \PHPUnit_Framework_TestCase */ protected $_areaList; + /** + * @var \Magento\Framework\Serialize\SerializerInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $serializerMock; + protected function setUp() { $this->_readerMock = $this->getMock(\Magento\Framework\App\Route\Config\Reader::class, [], [], '', false); $this->_cacheMock = $this->getMock(\Magento\Framework\Config\CacheInterface::class); $this->_configScopeMock = $this->getMock(\Magento\Framework\Config\ScopeInterface::class); $this->_areaList = $this->getMock(\Magento\Framework\App\AreaList::class, [], [], '', false); - $this->_configScopeMock->expects( - $this->any() - )->method( - 'getCurrentScope' - )->will( - $this->returnValue('areaCode') - ); - $this->_config = new \Magento\Framework\App\Route\Config( - $this->_readerMock, - $this->_cacheMock, - $this->_configScopeMock, - $this->_areaList + $this->_configScopeMock->expects($this->any()) + ->method('getCurrentScope') + ->willReturn('areaCode'); + $objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); + $this->_config = $objectManager->getObject( + \Magento\Framework\App\Route\Config::class, + [ + 'reader' => $this->_readerMock, + 'cache' => $this->_cacheMock, + 'configScope' => $this->_configScopeMock, + 'areaList' => $this->_areaList + ] ); + $this->serializerMock = $this->getMock(\Magento\Framework\Serialize\SerializerInterface::class); + $objectManager->setBackwardCompatibleProperty($this->_config, 'serializer', $this->serializerMock); } public function testGetRouteFrontNameIfCacheIfRouterIdNotExist() { - $this->_cacheMock->expects( - $this->once() - )->method( - 'load' - )->with( - 'areaCode::RoutesConfig' - )->will( - $this->returnValue(serialize(['expected'])) - ); + $this->_cacheMock->expects($this->once()) + ->method('load') + ->with('areaCode::RoutesConfig') + ->willReturn('["expected"]'); $this->assertEquals('routerCode', $this->_config->getRouteFrontName('routerCode')); } public function testGetRouteByFrontName() { - $this->_cacheMock->expects( - $this->once() - )->method( - 'load' - )->with( - 'areaCode::RoutesConfig' - )->will( - $this->returnValue(serialize(['routerCode' => ['frontName' => 'routerName']])) - ); - - $this->assertEquals('routerCode', $this->_config->getRouteByFrontName('routerName')); - - // check internal caching in $this->_routes array + $data = ['routerCode' => ['frontName' => 'routerName']]; + $this->_cacheMock->expects($this->once()) + ->method('load') + ->with('areaCode::RoutesConfig') + ->willReturn('serializedData'); + $this->serializerMock->expects($this->once()) + ->method('unserialize') + ->with('serializedData') + ->willReturn($data); $this->assertEquals('routerCode', $this->_config->getRouteByFrontName('routerName')); } public function testGetRouteByFrontNameNoRoutes() { - $this->_cacheMock->expects( - $this->once() - )->method( - 'load' - )->with( - 'areaCode::RoutesConfig' - )->will( - $this->returnValue(serialize([])) - ); - - $this->assertFalse($this->_config->getRouteByFrontName('routerName')); - - // check caching in $this->_routes array + $this->_cacheMock->expects($this->once()) + ->method('load') + ->with('areaCode::RoutesConfig') + ->willReturn('serializedData'); + $this->serializerMock->expects($this->once()) + ->method('unserialize') + ->with('serializedData') + ->willReturn([]); $this->assertFalse($this->_config->getRouteByFrontName('routerName')); } public function testGetRouteByFrontNameNoCache() { - $this->_cacheMock->expects( - $this->once() - )->method( - 'load' - )->with( - 'scope::RoutesConfig' - )->will( - $this->returnValue(serialize(false)) - ); + $this->_cacheMock->expects($this->once()) + ->method('load') + ->with('scope::RoutesConfig') + ->willReturn('false'); $routes = [ 'routerCode' => [ @@ -127,6 +115,8 @@ class ConfigTest extends \PHPUnit_Framework_TestCase ], ]; + $serializedData = json_encode($routes); + $this->_readerMock->expects( $this->once() )->method( @@ -147,34 +137,29 @@ class ConfigTest extends \PHPUnit_Framework_TestCase $this->returnValue('default_router') ); - $this->_cacheMock->expects( - $this->once() - )->method( - 'save' - )->with( - serialize($routes), - 'scope::RoutesConfig' - ); + $this->serializerMock->expects($this->once()) + ->method('serialize') + ->willReturn($serializedData); - $this->assertEquals('routerCode', $this->_config->getRouteByFrontName('routerName', 'scope')); + $this->_cacheMock->expects($this->once()) + ->method('save') + ->with($serializedData, 'scope::RoutesConfig'); - // check caching in $this->_routes array $this->assertEquals('routerCode', $this->_config->getRouteByFrontName('routerName', 'scope')); } public function testGetModulesByFrontName() { - $this->_cacheMock->expects( - $this->once() - )->method( - 'load' - )->with( - 'areaCode::RoutesConfig' - )->will( - $this->returnValue( - serialize(['routerCode' => ['frontName' => 'routerName', 'modules' => ['Module1']]]) - ) - ); + $data = ['routerCode' => ['frontName' => 'routerName', 'modules' => ['Module1']]]; + + $this->_cacheMock->expects($this->once()) + ->method('load') + ->with('areaCode::RoutesConfig') + ->willReturn('serializedData'); + $this->serializerMock->expects($this->once()) + ->method('unserialize') + ->with('serializedData') + ->willReturn($data); $this->assertEquals(['Module1'], $this->_config->getModulesByFrontName('routerName')); } } diff --git a/lib/internal/Magento/Framework/App/Test/Unit/Router/ActionListTest.php b/lib/internal/Magento/Framework/App/Test/Unit/Router/ActionListTest.php index c24c31e282c62255b3970e01c0994cdb52866dd8..bef703e99a33e1888faf418fdf29e806bfa15003 100644 --- a/lib/internal/Magento/Framework/App/Test/Unit/Router/ActionListTest.php +++ b/lib/internal/Magento/Framework/App/Test/Unit/Router/ActionListTest.php @@ -1,7 +1,5 @@ <?php /** - * RouterList model test class - * * Copyright © 2016 Magento. All rights reserved. * See COPYING.txt for license details. */ @@ -12,69 +10,76 @@ class ActionListTest extends \PHPUnit_Framework_TestCase /** * @var \Magento\Framework\TestFramework\Unit\Helper\ObjectManager */ - protected $objectManager; + private $objectManager; /** - * @var \Magento\Framework\Config\CacheInterface | \PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\Config\CacheInterface|\PHPUnit_Framework_MockObject_MockObject */ - protected $cacheMock; + private $cacheMock; /** - * @var \Magento\Framework\Module\Dir\Reader | \PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\Module\Dir\Reader|\PHPUnit_Framework_MockObject_MockObject */ - protected $moduleReaderMock; + private $readerMock; /** * @var \Magento\Framework\App\Router\ActionList */ - protected $actionList; + private $actionList; + + /** + * @var \Magento\Framework\Serialize\SerializerInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $serializerMock; protected function setUp() { $this->objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); - $this->cacheMock = $this->getMockBuilder(\Magento\Framework\Config\CacheInterface::class) - ->disableOriginalConstructor() - ->getMock(); - $this->moduleReaderMock = $this->getMockBuilder(\Magento\Framework\Module\Dir\Reader::class) - ->disableOriginalConstructor() - ->getMock(); + $this->cacheMock = $this->getMock( + \Magento\Framework\Config\CacheInterface::class, + [], + [], + '', + false + ); + $this->readerMock = $this->getMock( + \Magento\Framework\Module\Dir\Reader::class, + [], + [], + '', + false + ); + $this->serializerMock = $this->getMock(\Magento\Framework\Serialize\SerializerInterface::class); } - public function testConstructorCachedData() + public function testConstructActionsCached() { $this->cacheMock->expects($this->once()) ->method('load') - ->will($this->returnValue(serialize('data'))); + ->willReturn('"data"'); + $this->serializerMock->expects($this->once()) + ->method('unserialize'); $this->cacheMock->expects($this->never()) ->method('save'); - $this->moduleReaderMock->expects($this->never()) + $this->readerMock->expects($this->never()) ->method('getActionFiles'); - $this->actionList = $this->objectManager->getObject( - \Magento\Framework\App\Router\ActionList::class, - [ - 'cache' => $this->cacheMock, - 'moduleReader' => $this->moduleReaderMock, - ] - ); + $this->createActionListInstance(); } - public function testConstructorNoCachedData() + public function testConstructActionsNoCached() { $this->cacheMock->expects($this->once()) ->method('load') - ->will($this->returnValue(false)); + ->willReturn(false); + $this->serializerMock->expects($this->once()) + ->method('serialize'); $this->cacheMock->expects($this->once()) ->method('save'); - $this->moduleReaderMock->expects($this->once()) + $this->readerMock->expects($this->once()) ->method('getActionFiles') - ->will($this->returnValue('data')); - $this->actionList = $this->objectManager->getObject( - \Magento\Framework\App\Router\ActionList::class, - [ - 'cache' => $this->cacheMock, - 'moduleReader' => $this->moduleReaderMock, - ] - ); + ->willReturn('data') + ; + $this->createActionListInstance(); } /** @@ -88,22 +93,15 @@ class ActionListTest extends \PHPUnit_Framework_TestCase */ public function testGet($module, $area, $namespace, $action, $data, $expected) { - $this->cacheMock->expects($this->once()) ->method('load') ->will($this->returnValue(false)); $this->cacheMock->expects($this->once()) ->method('save'); - $this->moduleReaderMock->expects($this->once()) + $this->readerMock->expects($this->once()) ->method('getActionFiles') - ->will($this->returnValue($data)); - $this->actionList = $this->objectManager->getObject( - \Magento\Framework\App\Router\ActionList::class, - [ - 'cache' => $this->cacheMock, - 'moduleReader' => $this->moduleReaderMock, - ] - ); + ->willReturn($data); + $this->createActionListInstance(); $this->assertEquals($expected, $this->actionList->get($module, $area, $namespace, $action)); } @@ -168,4 +166,16 @@ class ActionListTest extends \PHPUnit_Framework_TestCase ], ]; } + + private function createActionListInstance() + { + $this->actionList = $this->objectManager->getObject( + \Magento\Framework\App\Router\ActionList::class, + [ + 'cache' => $this->cacheMock, + 'moduleReader' => $this->readerMock, + 'serializer' => $this->serializerMock, + ] + ); + } } diff --git a/lib/internal/Magento/Framework/Cache/Config/Data.php b/lib/internal/Magento/Framework/Cache/Config/Data.php index a1f203d9aa7bb6c8ef19567f76bfe11ab893f1ce..5909fff105e2bbfda587f1715e81955bb5aa0ca7 100644 --- a/lib/internal/Magento/Framework/Cache/Config/Data.php +++ b/lib/internal/Magento/Framework/Cache/Config/Data.php @@ -1,12 +1,15 @@ <?php /** - * Cache configuration data container. Provides cache configuration data based on current config scope - * * Copyright © 2016 Magento. All rights reserved. * See COPYING.txt for license details. */ namespace Magento\Framework\Cache\Config; +use Magento\Framework\Serialize\SerializerInterface; + +/** + * Provides cached configuration data based on current config scope + */ class Data extends \Magento\Framework\Config\Data\Scoped { /** @@ -17,17 +20,21 @@ class Data extends \Magento\Framework\Config\Data\Scoped protected $_scopePriorityScheme = ['global']; /** + * Constructor + * * @param \Magento\Framework\Cache\Config\Reader $reader * @param \Magento\Framework\Config\ScopeInterface $configScope * @param \Magento\Framework\Config\CacheInterface $cache * @param string $cacheId + * @param SerializerInterface|null $serializer */ public function __construct( \Magento\Framework\Cache\Config\Reader $reader, \Magento\Framework\Config\ScopeInterface $configScope, \Magento\Framework\Config\CacheInterface $cache, - $cacheId + $cacheId, + SerializerInterface $serializer = null ) { - parent::__construct($reader, $configScope, $cache, $cacheId); + parent::__construct($reader, $configScope, $cache, $cacheId, $serializer); } } 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/Communication/Config/Data.php b/lib/internal/Magento/Framework/Communication/Config/Data.php index e073c7c5471c2adb122c006c21371143c22eff8b..29667100b68603e9a8ff02e7f4486dfa4c55566c 100644 --- a/lib/internal/Magento/Framework/Communication/Config/Data.php +++ b/lib/internal/Magento/Framework/Communication/Config/Data.php @@ -5,23 +5,27 @@ */ namespace Magento\Framework\Communication\Config; +use Magento\Framework\Serialize\SerializerInterface; + /** - * Communication config data. + * Provides communication configuration */ class Data extends \Magento\Framework\Config\Data { /** - * Initialize dependencies. + * Constructor * * @param \Magento\Framework\Communication\Config\CompositeReader $reader * @param \Magento\Framework\Config\CacheInterface $cache - * @param string $cacheId + * @param string|null $cacheId + * @param SerializerInterface|null $serializer */ public function __construct( \Magento\Framework\Communication\Config\CompositeReader $reader, \Magento\Framework\Config\CacheInterface $cache, - $cacheId = 'communication_config_cache' + $cacheId = 'communication_config_cache', + SerializerInterface $serializer = null ) { - parent::__construct($reader, $cache, $cacheId); + parent::__construct($reader, $cache, $cacheId, $serializer); } } diff --git a/lib/internal/Magento/Framework/Config/ConfigOptionsListConstants.php b/lib/internal/Magento/Framework/Config/ConfigOptionsListConstants.php index b6363520dc085c75ec44a1700094e328af1fb973..304174ac52d3792054221c27d53624f34ed2ca7e 100644 --- a/lib/internal/Magento/Framework/Config/ConfigOptionsListConstants.php +++ b/lib/internal/Magento/Framework/Config/ConfigOptionsListConstants.php @@ -37,7 +37,6 @@ class ConfigOptionsListConstants */ const INPUT_KEY_ENCRYPTION_KEY = 'key'; const INPUT_KEY_SESSION_SAVE = 'session-save'; - const INPUT_KEY_DEFINITION_FORMAT = 'definition-format'; const INPUT_KEY_DB_HOST = 'db-host'; const INPUT_KEY_DB_NAME = 'db-name'; const INPUT_KEY_DB_USER = 'db-user'; @@ -51,6 +50,9 @@ class ConfigOptionsListConstants const INPUT_KEY_CACHE_HOSTS = 'http-cache-hosts'; /**#@-*/ + /** @deprecated */ + const INPUT_KEY_DEFINITION_FORMAT = 'definition-format'; + /**#@+ * Values for session-save */ 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/Data.php b/lib/internal/Magento/Framework/Config/Data.php index ed5ed3ad9f2e20ff4046bbd09a3ab3714311eaa9..1169abafccd8f2d868d2d56c821a67a761368f38 100644 --- a/lib/internal/Magento/Framework/Config/Data.php +++ b/lib/internal/Magento/Framework/Config/Data.php @@ -1,26 +1,29 @@ <?php /** - * Config data. Represents loaded and cached configuration data. Should be used to gain access to different types - * * Copyright © 2016 Magento. All rights reserved. * See COPYING.txt for license details. */ namespace Magento\Framework\Config; +use Magento\Framework\Serialize\SerializerInterface; +use Magento\Framework\App\ObjectManager; + /** + * Represents loaded and cached configuration data, should be used to gain access to different types + * * @SuppressWarnings(PHPMD.NumberOfChildren) */ class Data implements \Magento\Framework\Config\DataInterface { /** - * Configuration reader model + * Configuration reader * * @var ReaderInterface */ protected $_reader; /** - * Configuration cache model + * Configuration cache * * @var CacheInterface */ @@ -62,26 +65,35 @@ class Data implements \Magento\Framework\Config\DataInterface */ private $cacheId; + /** + * @var SerializerInterface + */ + private $serializer; + /** * Constructor * * @param ReaderInterface $reader * @param CacheInterface $cache * @param string $cacheId + * @param SerializerInterface|null $serializer */ public function __construct( ReaderInterface $reader, CacheInterface $cache, - $cacheId + $cacheId, + SerializerInterface $serializer = null ) { $this->reader = $reader; $this->cache = $cache; $this->cacheId = $cacheId; + $this->serializer = $serializer ?: ObjectManager::getInstance()->get(SerializerInterface::class); $this->initData(); } /** * Initialise data for configuration + * * @return void */ protected function initData() @@ -89,10 +101,11 @@ class Data implements \Magento\Framework\Config\DataInterface $data = $this->cache->load($this->cacheId); if (false === $data) { $data = $this->reader->read(); - $this->cache->save(serialize($data), $this->cacheId, $this->cacheTags); + $this->cache->save($this->serializer->serialize($data), $this->cacheId, $this->cacheTags); } else { - $data = unserialize($data); + $data = $this->serializer->unserialize($data); } + $this->merge($data); } @@ -133,6 +146,7 @@ class Data implements \Magento\Framework\Config\DataInterface /** * Clear cache data + * * @return void */ public function reset() diff --git a/lib/internal/Magento/Framework/Config/Data/Scoped.php b/lib/internal/Magento/Framework/Config/Data/Scoped.php index 36b265ac9e6f47584917433e50c54e83999948db..f9c151e867b89726ccea1f46ed269931efee51da 100644 --- a/lib/internal/Magento/Framework/Config/Data/Scoped.php +++ b/lib/internal/Magento/Framework/Config/Data/Scoped.php @@ -5,6 +5,12 @@ */ namespace Magento\Framework\Config\Data; +use Magento\Framework\Serialize\SerializerInterface; +use Magento\Framework\App\ObjectManager; + +/** + * Provides scoped configuration + */ class Scoped extends \Magento\Framework\Config\Data { /** @@ -49,6 +55,11 @@ class Scoped extends \Magento\Framework\Config\Data */ protected $_loadedScopes = []; + /** + * @var SerializerInterface + */ + private $serializer; + /** * Constructor * @@ -56,17 +67,20 @@ class Scoped extends \Magento\Framework\Config\Data * @param \Magento\Framework\Config\ScopeInterface $configScope * @param \Magento\Framework\Config\CacheInterface $cache * @param string $cacheId + * @param SerializerInterface|null $serializer */ public function __construct( \Magento\Framework\Config\ReaderInterface $reader, \Magento\Framework\Config\ScopeInterface $configScope, \Magento\Framework\Config\CacheInterface $cache, - $cacheId + $cacheId, + SerializerInterface $serializer = null ) { $this->_reader = $reader; $this->_configScope = $configScope; $this->_cache = $cache; $this->_cacheId = $cacheId; + $this->serializer = $serializer ?: ObjectManager::getInstance()->get(SerializerInterface::class); } /** @@ -98,11 +112,14 @@ class Scoped extends \Magento\Framework\Config\Data if (false == isset($this->_loadedScopes[$scopeCode])) { if ($scopeCode !== 'primary' && ($data = $this->_cache->load($scopeCode . '::' . $this->_cacheId)) ) { - $data = unserialize($data); + $data = $this->serializer->unserialize($data); } else { $data = $this->_reader->read($scopeCode); if ($scopeCode !== 'primary') { - $this->_cache->save(serialize($data), $scopeCode . '::' . $this->_cacheId); + $this->_cache->save( + $this->serializer->serialize($data), + $scopeCode . '::' . $this->_cacheId + ); } } $this->merge($data); 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/Data/ScopedTest.php b/lib/internal/Magento/Framework/Config/Test/Unit/Data/ScopedTest.php index 496da72ceef9b45d06a498aae8bc732a08de43ae..607977b99bb42a9fcdd0162a5443186343ef06f3 100644 --- a/lib/internal/Magento/Framework/Config/Test/Unit/Data/ScopedTest.php +++ b/lib/internal/Magento/Framework/Config/Test/Unit/Data/ScopedTest.php @@ -7,6 +7,11 @@ namespace Magento\Framework\Config\Test\Unit\Data; class ScopedTest extends \PHPUnit_Framework_TestCase { + /** + * @var \Magento\Framework\TestFramework\Unit\Helper\ObjectManager + */ + private $objectManager; + /** * @var \Magento\Framework\Config\Data\Scoped */ @@ -27,17 +32,28 @@ class ScopedTest extends \PHPUnit_Framework_TestCase */ protected $_cacheMock; + /** + * @var \Magento\Framework\Serialize\SerializerInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $serializerMock; + protected function setUp() { + $this->objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); $this->_readerMock = $this->getMock(\Magento\Framework\Config\ReaderInterface::class); $this->_configScopeMock = $this->getMock(\Magento\Framework\Config\ScopeInterface::class); $this->_cacheMock = $this->getMock(\Magento\Framework\Config\CacheInterface::class); + $this->serializerMock = $this->getMock(\Magento\Framework\Serialize\SerializerInterface::class); - $this->_model = new \Magento\Framework\Config\Data\Scoped( - $this->_readerMock, - $this->_configScopeMock, - $this->_cacheMock, - 'tag' + $this->_model = $this->objectManager->getObject( + \Magento\Framework\Config\Data\Scoped::class, + [ + 'reader' => $this->_readerMock, + 'configScope' => $this->_configScopeMock, + 'cache' => $this->_cacheMock, + 'cacheId' => 'tag', + 'serializer' => $this->serializerMock + ] ); } @@ -47,7 +63,7 @@ class ScopedTest extends \PHPUnit_Framework_TestCase * @param string $default * @dataProvider getConfigByPathDataProvider */ - public function testgetConfigByPath($path, $expectedValue, $default) + public function testGetConfigByPath($path, $expectedValue, $default) { $testData = [ 'key_1' => [ @@ -55,7 +71,12 @@ class ScopedTest extends \PHPUnit_Framework_TestCase 'key_1.2' => ['some' => 'arrayValue'], ], ]; - $this->_cacheMock->expects($this->any())->method('load')->will($this->returnValue(serialize([]))); + $this->_cacheMock->expects($this->once()) + ->method('load') + ->willReturn(false); + $this->_readerMock->expects($this->once()) + ->method('read') + ->willReturn([]); $this->_model->merge($testData); $this->assertEquals($expectedValue, $this->_model->get($path, $default)); } @@ -77,6 +98,7 @@ class ScopedTest extends \PHPUnit_Framework_TestCase public function testGetScopeSwitchingWithNonCachedData() { $testValue = ['some' => 'testValue']; + $serializedData = 'serialized data'; /** change current area */ $this->_configScopeMock->expects( @@ -109,8 +131,15 @@ class ScopedTest extends \PHPUnit_Framework_TestCase $this->returnValue($testValue) ); + $this->serializerMock->expects($this->once()) + ->method('serialize') + ->with($testValue) + ->willReturn($serializedData); + /** test cache saving */ - $this->_cacheMock->expects($this->once())->method('save')->with(serialize($testValue), 'adminhtml::tag'); + $this->_cacheMock->expects($this->once()) + ->method('save') + ->with($serializedData, 'adminhtml::tag'); /** test config value existence */ $this->assertEquals('testValue', $this->_model->get('some')); @@ -122,6 +151,7 @@ class ScopedTest extends \PHPUnit_Framework_TestCase public function testGetScopeSwitchingWithCachedData() { $testValue = ['some' => 'testValue']; + $serializedData = 'serialized data'; /** change current area */ $this->_configScopeMock->expects( @@ -132,16 +162,16 @@ class ScopedTest extends \PHPUnit_Framework_TestCase $this->returnValue('adminhtml') ); + $this->serializerMock->expects($this->once()) + ->method('unserialize') + ->with($serializedData) + ->willReturn($testValue); + /** set cache data */ - $this->_cacheMock->expects( - $this->once() - )->method( - 'load' - )->with( - 'adminhtml::tag' - )->will( - $this->returnValue(serialize($testValue)) - ); + $this->_cacheMock->expects($this->once()) + ->method('load') + ->with('adminhtml::tag') + ->willReturn($serializedData); /** test preventing of getting data from reader */ $this->_readerMock->expects($this->never())->method('read'); diff --git a/lib/internal/Magento/Framework/Config/Test/Unit/DataTest.php b/lib/internal/Magento/Framework/Config/Test/Unit/DataTest.php index 5c58310e096bbd27b1ba5448e7a5da92c86da250..c37d2108191b429b4d4fa7289b5464570aad5ad9 100644 --- a/lib/internal/Magento/Framework/Config/Test/Unit/DataTest.php +++ b/lib/internal/Magento/Framework/Config/Test/Unit/DataTest.php @@ -10,33 +10,46 @@ namespace Magento\Framework\Config\Test\Unit; class DataTest extends \PHPUnit_Framework_TestCase { - /** @var \Magento\Framework\Config\ReaderInterface|\PHPUnit_Framework_MockObject_MockObject */ - protected $reader; - /** @var \Magento\Framework\Config\CacheInterface|\PHPUnit_Framework_MockObject_MockObject */ - protected $cache; - /** @var \Magento\Framework\TestFramework\Unit\Helper\ObjectManager */ - protected $objectManagerHelper; + /** + * @var \Magento\Framework\Config\ReaderInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $readerMock; + + /** + * @var \Magento\Framework\Config\CacheInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $cacheMock; + + /** + * @var \Magento\Framework\Serialize\SerializerInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $serializerMock; protected function setUp() { - $this->reader = $this->getMockBuilder(\Magento\Framework\Config\ReaderInterface::class) - ->disableOriginalConstructor() - ->getMock(); - $this->cache = $this->getMockBuilder(\Magento\Framework\Config\CacheInterface::class) - ->disableOriginalConstructor() - ->getMock(); - $this->objectManagerHelper = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); + $this->readerMock = $this->getMock(\Magento\Framework\Config\ReaderInterface::class); + $this->cacheMock = $this->getMock(\Magento\Framework\Config\CacheInterface::class); + $this->serializerMock = $this->getMock(\Magento\Framework\Serialize\SerializerInterface::class); } - public function testGet() + public function testGetConfigNotCached() { $data = ['a' => 'b']; - $cacheid = 'test'; - $this->cache->expects($this->once())->method('load')->will($this->returnValue(false)); - $this->reader->expects($this->once())->method('read')->will($this->returnValue($data)); - + $cacheId = 'test'; + $this->cacheMock->expects($this->once()) + ->method('load') + ->willReturn(false); + $this->readerMock->expects($this->once()) + ->method('read') + ->willReturn($data); + $this->serializerMock->expects($this->once()) + ->method('serialize') + ->with($data); $config = new \Magento\Framework\Config\Data( - $this->reader, $this->cache, $cacheid + $this->readerMock, + $this->cacheMock, + $cacheId, + $this->serializerMock ); $this->assertEquals($data, $config->get()); $this->assertEquals('b', $config->get('a')); @@ -44,18 +57,50 @@ class DataTest extends \PHPUnit_Framework_TestCase $this->assertEquals(33, $config->get('a/b', 33)); } - public function testReset() + public function testGetConfigCached() { - $cacheid = 'test'; - $this->cache->expects($this->once())->method('load')->will($this->returnValue(serialize([]))); - $this->cache->expects($this->once())->method('remove')->with($cacheid); - + $data = ['a' => 'b']; + $serializedData = '{"a":"b"}'; + $cacheId = 'test'; + $this->cacheMock->expects($this->once()) + ->method('load') + ->willReturn($serializedData); + $this->readerMock->expects($this->never()) + ->method('read'); + $this->serializerMock->expects($this->once()) + ->method('unserialize') + ->with($serializedData) + ->willReturn($data); $config = new \Magento\Framework\Config\Data( - $this->reader, - $this->cache, - $cacheid + $this->readerMock, + $this->cacheMock, + $cacheId, + $this->serializerMock ); + $this->assertEquals($data, $config->get()); + $this->assertEquals('b', $config->get('a')); + } + public function testReset() + { + $serializedData = ''; + $cacheId = 'test'; + $this->cacheMock->expects($this->once()) + ->method('load') + ->willReturn($serializedData); + $this->serializerMock->expects($this->once()) + ->method('unserialize') + ->with($serializedData) + ->willReturn([]); + $this->cacheMock->expects($this->once()) + ->method('remove') + ->with($cacheId); + $config = new \Magento\Framework\Config\Data( + $this->readerMock, + $this->cacheMock, + $cacheId, + $this->serializerMock + ); $config->reset(); } } 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/lib/internal/Magento/Framework/Crontab/CrontabManager.php b/lib/internal/Magento/Framework/Crontab/CrontabManager.php new file mode 100644 index 0000000000000000000000000000000000000000..2b597b8eb638fb21af887ab7b47490f5533fafae --- /dev/null +++ b/lib/internal/Magento/Framework/Crontab/CrontabManager.php @@ -0,0 +1,199 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Framework\Crontab; + +use Magento\Framework\ShellInterface; +use Magento\Framework\Phrase; +use Magento\Framework\Exception\LocalizedException; +use Magento\Framework\Filesystem; +use Magento\Framework\App\Filesystem\DirectoryList; + +/** + * Manager works with cron tasks + */ +class CrontabManager implements CrontabManagerInterface +{ + /** + * @var ShellInterface + */ + private $shell; + + /** + * @var Filesystem + */ + private $filesystem; + + /** + * @param ShellInterface $shell + * @param Filesystem $filesystem + */ + public function __construct( + ShellInterface $shell, + Filesystem $filesystem + ) { + $this->shell = $shell; + $this->filesystem = $filesystem; + } + + /** + * {@inheritdoc} + */ + public function getTasks() + { + $this->checkSupportedOs(); + $content = $this->getCrontabContent(); + $pattern = '!(' . self::TASKS_BLOCK_START . ')(.*?)(' . self::TASKS_BLOCK_END . ')!s'; + + if (preg_match($pattern, $content, $matches)) { + $tasks = trim($matches[2], PHP_EOL); + $tasks = explode(PHP_EOL, $tasks); + return $tasks; + } + + return []; + } + + /** + * {@inheritdoc} + */ + public function saveTasks(array $tasks) + { + $this->checkSupportedOs(); + $baseDir = $this->filesystem->getDirectoryRead(DirectoryList::ROOT)->getAbsolutePath(); + $logDir = $this->filesystem->getDirectoryRead(DirectoryList::LOG)->getAbsolutePath(); + + if (!$tasks) { + throw new LocalizedException(new Phrase('List of tasks is empty')); + } + + foreach ($tasks as $key => $task) { + if (empty($task['expression'])) { + $tasks[$key]['expression'] = '* * * * *'; + } + + if (empty($task['command'])) { + throw new LocalizedException(new Phrase('Command should not be empty')); + } + + $tasks[$key]['command'] = str_replace( + ['{magentoRoot}', '{magentoLog}'], + [$baseDir, $logDir], + $task['command'] + ); + } + + $content = $this->getCrontabContent(); + $content = $this->cleanMagentoSection($content); + $content = $this->generateSection($content, $tasks); + + $this->save($content); + } + + /** + * {@inheritdoc} + * @throws LocalizedException + */ + public function removeTasks() + { + $this->checkSupportedOs(); + $content = $this->getCrontabContent(); + $content = $this->cleanMagentoSection($content); + $this->save($content); + } + + /** + * Generate Magento Tasks Section + * + * @param string $content + * @param array $tasks + * @return string + */ + private function generateSection($content, $tasks = []) + { + if ($tasks) { + $content .= self::TASKS_BLOCK_START . PHP_EOL; + foreach ($tasks as $task) { + $content .= $task['expression'] . ' ' . PHP_BINARY . ' '. $task['command'] . PHP_EOL; + } + $content .= self::TASKS_BLOCK_END . PHP_EOL; + } + + return $content; + } + + /** + * Clean Magento Tasks Section in crontab content + * + * @param string $content + * @return string + */ + private function cleanMagentoSection($content) + { + $content = preg_replace( + '!' . preg_quote(self::TASKS_BLOCK_START) . '.*?' . preg_quote(self::TASKS_BLOCK_END . PHP_EOL) . '!s', + '', + $content + ); + + return $content; + } + + /** + * Get crontab content without Magento Tasks Section + * + * In case of some exceptions the empty content is returned + * + * @return string + */ + private function getCrontabContent() + { + try { + $content = (string)$this->shell->execute('crontab -l'); + } catch (LocalizedException $e) { + return ''; + } + + return $content; + } + + /** + * Save crontab + * + * @param string $content + * @return void + * @throws LocalizedException + */ + private function save($content) + { + $content = str_replace('%', '%%', $content); + + try { + $this->shell->execute('echo "' . $content . '" | crontab -'); + } catch (LocalizedException $e) { + throw new LocalizedException( + new Phrase('Error during saving of crontab: %1', [$e->getPrevious()->getMessage()]), + $e + ); + } + } + + /** + * Check that OS is supported + * + * If OS is not supported then no possibility to work with crontab + * + * @return void + * @throws LocalizedException + */ + private function checkSupportedOs() + { + if (stripos(PHP_OS, 'WIN') === 0) { + throw new LocalizedException( + new Phrase('Your operation system is not supported to work with this command') + ); + } + } +} diff --git a/lib/internal/Magento/Framework/Crontab/CrontabManagerInterface.php b/lib/internal/Magento/Framework/Crontab/CrontabManagerInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..c00ab41d8b873a46dc27abbb1af37a23b7e7fd86 --- /dev/null +++ b/lib/internal/Magento/Framework/Crontab/CrontabManagerInterface.php @@ -0,0 +1,43 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Framework\Crontab; + +use Magento\Framework\Exception\LocalizedException; + +interface CrontabManagerInterface +{ + /**#@+ + * Constants for wrapping Magento section in crontab + */ + const TASKS_BLOCK_START = '#~ MAGENTO START'; + const TASKS_BLOCK_END = '#~ MAGENTO END'; + /**#@-*/ + + /** + * Get list of Magento Tasks + * + * @return array + * @throws LocalizedException + */ + public function getTasks(); + + /** + * Save Magento Tasks to crontab + * + * @param array $tasks + * @return void + * @throws LocalizedException + */ + public function saveTasks(array $tasks); + + /** + * Remove Magento Tasks form crontab + * + * @return void + * @throws LocalizedException + */ + public function removeTasks(); +} diff --git a/lib/internal/Magento/Framework/Crontab/README.md b/lib/internal/Magento/Framework/Crontab/README.md new file mode 100644 index 0000000000000000000000000000000000000000..bfbf194715dc8f9f359137ecb79be5a1adbd5c5e --- /dev/null +++ b/lib/internal/Magento/Framework/Crontab/README.md @@ -0,0 +1,12 @@ +Library for working with crontab + +The library has the next interfaces: +* CrontabManagerInterface +* TasksProviderInterface + +*CrontabManagerInterface* provides working with crontab: +* *getTasks* - get list of Magento cron tasks from crontab +* *saveTasks* - save Magento cron tasks to crontab +* *removeTasks* - remove Magento cron tasks from crontab + +*TasksProviderInterface* has only one method *getTasks*. This interface provides transportation the list of tasks from DI \ No newline at end of file diff --git a/lib/internal/Magento/Framework/Crontab/TasksProvider.php b/lib/internal/Magento/Framework/Crontab/TasksProvider.php new file mode 100644 index 0000000000000000000000000000000000000000..94524fd2bbd19b4395a8ba36daaa0f43c2b6c648 --- /dev/null +++ b/lib/internal/Magento/Framework/Crontab/TasksProvider.php @@ -0,0 +1,33 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Framework\Crontab; + +/** + * TasksProvider collects list of tasks + */ +class TasksProvider implements TasksProviderInterface +{ + /** + * @var array + */ + private $tasks = []; + + /** + * @param array $tasks + */ + public function __construct(array $tasks = []) + { + $this->tasks = $tasks; + } + + /** + * {@inheritdoc} + */ + public function getTasks() + { + return $this->tasks; + } +} diff --git a/lib/internal/Magento/Framework/Crontab/TasksProviderInterface.php b/lib/internal/Magento/Framework/Crontab/TasksProviderInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..bb02c30797be4cbf015c5858ac1c88825bde54a7 --- /dev/null +++ b/lib/internal/Magento/Framework/Crontab/TasksProviderInterface.php @@ -0,0 +1,16 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Framework\Crontab; + +interface TasksProviderInterface +{ + /** + * Get list of tasks + * + * @return array + */ + public function getTasks(); +} diff --git a/lib/internal/Magento/Framework/Crontab/Test/Unit/CrontabManagerTest.php b/lib/internal/Magento/Framework/Crontab/Test/Unit/CrontabManagerTest.php new file mode 100644 index 0000000000000000000000000000000000000000..7cafd386c629a4b48350d5ca4937b58fd49da4b6 --- /dev/null +++ b/lib/internal/Magento/Framework/Crontab/Test/Unit/CrontabManagerTest.php @@ -0,0 +1,333 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Framework\Crontab\Test\Unit; + +use Magento\Framework\Crontab\CrontabManager; +use Magento\Framework\Crontab\CrontabManagerInterface; +use Magento\Framework\ShellInterface; +use Magento\Framework\Phrase; +use Magento\Framework\Exception\LocalizedException; +use Magento\Framework\Filesystem; +use Magento\Framework\App\Filesystem\DirectoryList; +use Magento\Framework\Filesystem\Directory\ReadInterface; +use Magento\Framework\Filesystem\DriverPool; + +class CrontabManagerTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var ShellInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $shellMock; + + /** + * @var Filesystem|\PHPUnit_Framework_MockObject_MockObject + */ + private $filesystemMock; + + /** + * @var CrontabManager + */ + private $crontabManager; + + /** + * @return void + */ + protected function setUp() + { + $this->shellMock = $this->getMockBuilder(ShellInterface::class) + ->getMockForAbstractClass(); + $this->filesystemMock = $this->getMockBuilder(Filesystem::class) + ->disableOriginalClone() + ->disableOriginalConstructor() + ->getMock(); + + $this->crontabManager = new CrontabManager($this->shellMock, $this->filesystemMock); + } + + /** + * @return void + */ + public function testGetTasksNoCrontab() + { + $exception = new \Exception('crontab: no crontab for user'); + $localizedException = new LocalizedException(new Phrase('Some error'), $exception); + + $this->shellMock->expects($this->once()) + ->method('execute') + ->with('crontab -l', []) + ->willThrowException($localizedException); + + $this->assertEquals([], $this->crontabManager->getTasks()); + } + + /** + * @param string $content + * @param array $tasks + * @return void + * @dataProvider getTasksDataProvider + */ + public function testGetTasks($content, $tasks) + { + $this->shellMock->expects($this->once()) + ->method('execute') + ->with('crontab -l', []) + ->willReturn($content); + + $this->assertEquals($tasks, $this->crontabManager->getTasks()); + } + + /** + * @return array + */ + public function getTasksDataProvider() + { + return [ + [ + 'content' => '* * * * * /bin/php /var/www/cron.php' . PHP_EOL + . CrontabManagerInterface::TASKS_BLOCK_START . PHP_EOL + . '* * * * * /bin/php /var/www/magento/bin/magento cron:run' . PHP_EOL + . CrontabManagerInterface::TASKS_BLOCK_END . PHP_EOL, + 'tasks' => ['* * * * * /bin/php /var/www/magento/bin/magento cron:run'], + ], + [ + 'content' => '* * * * * /bin/php /var/www/cron.php' . PHP_EOL + . CrontabManagerInterface::TASKS_BLOCK_START . PHP_EOL + . '* * * * * /bin/php /var/www/magento/bin/magento cron:run' . PHP_EOL + . '* * * * * /bin/php /var/www/magento/bin/magento setup:cron:run' . PHP_EOL + . CrontabManagerInterface::TASKS_BLOCK_END . PHP_EOL, + 'tasks' => [ + '* * * * * /bin/php /var/www/magento/bin/magento cron:run', + '* * * * * /bin/php /var/www/magento/bin/magento setup:cron:run', + ], + ], + [ + 'content' => '* * * * * /bin/php /var/www/cron.php' . PHP_EOL, + 'tasks' => [], + ], + [ + 'content' => '', + 'tasks' => [], + ], + ]; + } + + /** + * @return void + * @expectedException \Magento\Framework\Exception\LocalizedException + * @expectedExceptionMessage Shell error + */ + public function testRemoveTasksWithException() + { + $exception = new \Exception('Shell error'); + $localizedException = new LocalizedException(new Phrase('Some error'), $exception); + + $this->shellMock->expects($this->at(0)) + ->method('execute') + ->with('crontab -l', []) + ->willReturn(''); + + $this->shellMock->expects($this->at(1)) + ->method('execute') + ->with('echo "" | crontab -', []) + ->willThrowException($localizedException); + + $this->crontabManager->removeTasks(); + } + + /** + * @param string $contentBefore + * @param string $contentAfter + * @return void + * @dataProvider removeTasksDataProvider + */ + public function testRemoveTasks($contentBefore, $contentAfter) + { + $this->shellMock->expects($this->at(0)) + ->method('execute') + ->with('crontab -l', []) + ->willReturn($contentBefore); + + $this->shellMock->expects($this->at(1)) + ->method('execute') + ->with('echo "' . $contentAfter . '" | crontab -', []); + + $this->crontabManager->removeTasks(); + } + + /** + * @return array + */ + public function removeTasksDataProvider() + { + return [ + [ + 'contentBefore' => '* * * * * /bin/php /var/www/cron.php' . PHP_EOL + . CrontabManagerInterface::TASKS_BLOCK_START . PHP_EOL + . '* * * * * /bin/php /var/www/magento/bin/magento cron:run' . PHP_EOL + . CrontabManagerInterface::TASKS_BLOCK_END . PHP_EOL, + 'contentAfter' => '* * * * * /bin/php /var/www/cron.php' . PHP_EOL + ], + [ + 'contentBefore' => '* * * * * /bin/php /var/www/cron.php' . PHP_EOL + . CrontabManagerInterface::TASKS_BLOCK_START . PHP_EOL + . '* * * * * /bin/php /var/www/magento/bin/magento cron:run' . PHP_EOL + . '* * * * * /bin/php /var/www/magento/bin/magento setup:cron:run' . PHP_EOL + . CrontabManagerInterface::TASKS_BLOCK_END . PHP_EOL, + 'contentAfter' => '* * * * * /bin/php /var/www/cron.php' . PHP_EOL + ], + [ + 'contentBefore' => '* * * * * /bin/php /var/www/cron.php' . PHP_EOL, + 'contentAfter' => '* * * * * /bin/php /var/www/cron.php' . PHP_EOL + ], + [ + 'contentBefore' => '', + 'contentAfter' => '' + ], + ]; + } + + /** + * @return void + * @expectedException \Magento\Framework\Exception\LocalizedException + * @expectedExceptionMessage List of tasks is empty + */ + public function testSaveTasksWithEmptyTasksList() + { + $baseDirMock = $this->getMockBuilder(ReadInterface::class) + ->getMockForAbstractClass(); + $baseDirMock->expects($this->once()) + ->method('getAbsolutePath') + ->willReturn('/var/www/magento2/'); + $logDirMock = $this->getMockBuilder(ReadInterface::class) + ->getMockForAbstractClass(); + $logDirMock->expects($this->once()) + ->method('getAbsolutePath') + ->willReturn('/var/www/magento2/var/log/'); + + $this->filesystemMock->expects($this->any()) + ->method('getDirectoryRead') + ->willReturnMap([ + [DirectoryList::ROOT, DriverPool::FILE, $baseDirMock], + [DirectoryList::LOG, DriverPool::FILE, $logDirMock], + ]); + + $this->crontabManager->saveTasks([]); + } + + /** + * @return void + * @expectedException \Magento\Framework\Exception\LocalizedException + * @expectedExceptionMessage Command should not be empty + */ + public function testSaveTasksWithoutCommand() + { + $baseDirMock = $this->getMockBuilder(ReadInterface::class) + ->getMockForAbstractClass(); + $baseDirMock->expects($this->once()) + ->method('getAbsolutePath') + ->willReturn('/var/www/magento2/'); + $logDirMock = $this->getMockBuilder(ReadInterface::class) + ->getMockForAbstractClass(); + $logDirMock->expects($this->once()) + ->method('getAbsolutePath') + ->willReturn('/var/www/magento2/var/log/'); + + $this->filesystemMock->expects($this->any()) + ->method('getDirectoryRead') + ->willReturnMap([ + [DirectoryList::ROOT, DriverPool::FILE, $baseDirMock], + [DirectoryList::LOG, DriverPool::FILE, $logDirMock], + ]); + + $this->crontabManager->saveTasks([ + 'myCron' => ['expression' => '* * * * *'] + ]); + } + + /** + * @param array $tasks + * @param string $content + * @param string $contentToSave + * @return void + * @dataProvider saveTasksDataProvider + */ + public function testSaveTasks($tasks, $content, $contentToSave) + { + $baseDirMock = $this->getMockBuilder(ReadInterface::class) + ->getMockForAbstractClass(); + $baseDirMock->expects($this->once()) + ->method('getAbsolutePath') + ->willReturn('/var/www/magento2/'); + $logDirMock = $this->getMockBuilder(ReadInterface::class) + ->getMockForAbstractClass(); + $logDirMock->expects($this->once()) + ->method('getAbsolutePath') + ->willReturn('/var/www/magento2/var/log/'); + + $this->filesystemMock->expects($this->any()) + ->method('getDirectoryRead') + ->willReturnMap([ + [DirectoryList::ROOT, DriverPool::FILE, $baseDirMock], + [DirectoryList::LOG, DriverPool::FILE, $logDirMock], + ]); + + $this->shellMock->expects($this->at(0)) + ->method('execute') + ->with('crontab -l', []) + ->willReturn($content); + + $this->shellMock->expects($this->at(1)) + ->method('execute') + ->with('echo "' . $contentToSave . '" | crontab -', []); + + $this->crontabManager->saveTasks($tasks); + } + + /** + * @return array + */ + public function saveTasksDataProvider() + { + $content = '* * * * * /bin/php /var/www/cron.php' . PHP_EOL + . CrontabManagerInterface::TASKS_BLOCK_START . PHP_EOL + . '* * * * * /bin/php /var/www/magento/bin/magento cron:run' . PHP_EOL + . CrontabManagerInterface::TASKS_BLOCK_END . PHP_EOL; + + return [ + [ + 'tasks' => [ + ['expression' => '* * * * *', 'command' => 'run.php'] + ], + 'content' => $content, + 'contentToSave' => '* * * * * /bin/php /var/www/cron.php' . PHP_EOL + . CrontabManagerInterface::TASKS_BLOCK_START . PHP_EOL + . '* * * * * ' . PHP_BINARY . ' run.php' . PHP_EOL + . CrontabManagerInterface::TASKS_BLOCK_END . PHP_EOL, + ], + [ + 'tasks' => [ + ['expression' => '1 2 3 4 5', 'command' => 'run.php'] + ], + 'content' => $content, + 'contentToSave' => '* * * * * /bin/php /var/www/cron.php' . PHP_EOL + . CrontabManagerInterface::TASKS_BLOCK_START . PHP_EOL + . '1 2 3 4 5 ' . PHP_BINARY . ' run.php' . PHP_EOL + . CrontabManagerInterface::TASKS_BLOCK_END . PHP_EOL, + ], + [ + 'tasks' => [ + ['command' => '{magentoRoot}run.php >> {magentoLog}cron.log'] + ], + 'content' => $content, + 'contentToSave' => '* * * * * /bin/php /var/www/cron.php' . PHP_EOL + . CrontabManagerInterface::TASKS_BLOCK_START . PHP_EOL + . '* * * * * ' . PHP_BINARY . ' /var/www/magento2/run.php >>' + . ' /var/www/magento2/var/log/cron.log' . PHP_EOL + . CrontabManagerInterface::TASKS_BLOCK_END . PHP_EOL, + ], + ]; + } +} diff --git a/lib/internal/Magento/Framework/Crontab/Test/Unit/TasksProviderTest.php b/lib/internal/Magento/Framework/Crontab/Test/Unit/TasksProviderTest.php new file mode 100644 index 0000000000000000000000000000000000000000..80be47cda5ef4973ad1999968dd636da0bd1757a --- /dev/null +++ b/lib/internal/Magento/Framework/Crontab/Test/Unit/TasksProviderTest.php @@ -0,0 +1,34 @@ +<?php + +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Framework\Crontab\Test\Unit; + +use Magento\Framework\Crontab\TasksProvider; + +class TasksProviderTest extends \PHPUnit_Framework_TestCase +{ + /** + * @return void + */ + public function testTasksProviderEmpty() + { + /** @var $tasksProvider $tasksProvider */ + $tasksProvider = new TasksProvider(); + $this->assertSame([], $tasksProvider->getTasks()); + } + + public function testTasksProvider() + { + $tasks = [ + 'magentoCron' => ['expressin' => '* * * * *', 'command' => 'bin/magento cron:run'], + 'magentoSetup' => ['command' => 'bin/magento setup:cron:run'], + ]; + + /** @var $tasksProvider $tasksProvider */ + $tasksProvider = new TasksProvider($tasks); + $this->assertSame($tasks, $tasksProvider->getTasks()); + } +} diff --git a/lib/internal/Magento/Framework/Data/CollectionDataSourceInterface.php b/lib/internal/Magento/Framework/Data/CollectionDataSourceInterface.php index eeff60c1f61c887ef87439b680e8d73fbf6791f2..4bdf29fd1c8fc167af98cc79fd1d20c9696c7b50 100644 --- a/lib/internal/Magento/Framework/Data/CollectionDataSourceInterface.php +++ b/lib/internal/Magento/Framework/Data/CollectionDataSourceInterface.php @@ -5,9 +5,11 @@ */ namespace Magento\Framework\Data; +use Magento\Framework\View\Element\Block\ArgumentInterface; + /** * Interface CollectionDataSourceInterface */ -interface CollectionDataSourceInterface +interface CollectionDataSourceInterface extends ArgumentInterface { } diff --git a/lib/internal/Magento/Framework/DataObject/Copy/Config/Data.php b/lib/internal/Magento/Framework/DataObject/Copy/Config/Data.php index 61802637750c691e433bab4736272d6a29e8b984..5f2a1518d485a9d7201df0c19cb0f99487c68a0c 100644 --- a/lib/internal/Magento/Framework/DataObject/Copy/Config/Data.php +++ b/lib/internal/Magento/Framework/DataObject/Copy/Config/Data.php @@ -1,12 +1,13 @@ <?php /** - * Fieldset configuration data container. Provides fieldset configuration data. - * * Copyright © 2016 Magento. All rights reserved. * See COPYING.txt for license details. */ namespace Magento\Framework\DataObject\Copy\Config; +/** + * Provides DataObject copier configuration + */ class Data extends \Magento\Framework\Config\Data { } diff --git a/lib/internal/Magento/Framework/Event/Config/Data.php b/lib/internal/Magento/Framework/Event/Config/Data.php index 7bd082e5d465bc1299af865c42a24e0c504640b0..4b69e597934978d1ea4715159ff2125c0d4684c0 100644 --- a/lib/internal/Magento/Framework/Event/Config/Data.php +++ b/lib/internal/Magento/Framework/Event/Config/Data.php @@ -1,12 +1,15 @@ <?php /** - * Event configuration data container - * * Copyright © 2016 Magento. All rights reserved. * See COPYING.txt for license details. */ namespace Magento\Framework\Event\Config; +use Magento\Framework\Serialize\SerializerInterface; + +/** + * Provides event configuration + */ class Data extends \Magento\Framework\Config\Data\Scoped { /** @@ -17,17 +20,21 @@ class Data extends \Magento\Framework\Config\Data\Scoped protected $_scopePriorityScheme = ['global']; /** + * Constructor + * * @param \Magento\Framework\Event\Config\Reader $reader * @param \Magento\Framework\Config\ScopeInterface $configScope * @param \Magento\Framework\Config\CacheInterface $cache - * @param string $cacheId + * @param string|null $cacheId + * @param SerializerInterface|null $serializer */ public function __construct( \Magento\Framework\Event\Config\Reader $reader, \Magento\Framework\Config\ScopeInterface $configScope, \Magento\Framework\Config\CacheInterface $cache, - $cacheId = 'event_config_cache' + $cacheId = 'event_config_cache', + SerializerInterface $serializer = null ) { - parent::__construct($reader, $configScope, $cache, $cacheId); + parent::__construct($reader, $configScope, $cache, $cacheId, $serializer); } } diff --git a/lib/internal/Magento/Framework/File/Mime.php b/lib/internal/Magento/Framework/File/Mime.php index c8fe56eaa9e68ee9e61c9bcec7cf038b29fbff34..d698f9cced06ff7b3761ebfd226fa4cfca3b39f2 100644 --- a/lib/internal/Magento/Framework/File/Mime.php +++ b/lib/internal/Magento/Framework/File/Mime.php @@ -71,7 +71,7 @@ class Mime throw new \InvalidArgumentException("File '$file' doesn't exist"); } - $extension = pathinfo($file, PATHINFO_EXTENSION); + $extension = strtolower(pathinfo($file, PATHINFO_EXTENSION)); if (isset($this->mimeTypes[$extension])) { $result = $this->mimeTypes[$extension]; } diff --git a/lib/internal/Magento/Framework/File/Test/Unit/MimeTest.php b/lib/internal/Magento/Framework/File/Test/Unit/MimeTest.php index 7c2a1d71279c440953ba8bea4ef101412a53f5e6..90b970b7f8d8a1471c3f36fe5466838b11c49c97 100644 --- a/lib/internal/Magento/Framework/File/Test/Unit/MimeTest.php +++ b/lib/internal/Magento/Framework/File/Test/Unit/MimeTest.php @@ -47,6 +47,7 @@ class MimeTest extends \PHPUnit_Framework_TestCase return [ 'javascript' => [__DIR__ . '/_files/javascript.js', 'application/javascript'], 'weird extension' => [__DIR__ . '/_files/file.weird', 'application/octet-stream'], + 'weird uppercase extension' => [__DIR__ . '/_files/UPPERCASE.WEIRD', 'application/octet-stream'], ]; } } diff --git a/lib/internal/Magento/Framework/File/Test/Unit/_files/UPPERCASE.WEIRD b/lib/internal/Magento/Framework/File/Test/Unit/_files/UPPERCASE.WEIRD new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/lib/internal/Magento/Framework/HTTP/Adapter/Curl.php b/lib/internal/Magento/Framework/HTTP/Adapter/Curl.php index 181783c7b2115d8a216c681077e116e98344d15c..e2ea747218f60485e644ba6c3ba9b65da68409ab 100644 --- a/lib/internal/Magento/Framework/HTTP/Adapter/Curl.php +++ b/lib/internal/Magento/Framework/HTTP/Adapter/Curl.php @@ -27,7 +27,7 @@ class Curl implements \Zend_Http_Client_Adapter_Interface | CURLPROTO_FTPS ), 'verifypeer' => true, - 'verifyhost' => 2, + 'verifyhost' => 2 ]; /** @@ -53,6 +53,7 @@ class Curl implements \Zend_Http_Client_Adapter_Interface 'protocols' => CURLOPT_PROTOCOLS, 'verifypeer' => CURLOPT_SSL_VERIFYPEER, 'verifyhost' => CURLOPT_SSL_VERIFYHOST, + 'sslversion' => CURLOPT_SSLVERSION, ]; /** diff --git a/lib/internal/Magento/Framework/HTTP/Client/Curl.php b/lib/internal/Magento/Framework/HTTP/Client/Curl.php index 67525f62f6336cf7de844e866a153be223dc0b5c..c1d1299a1bd3fd578d1a40c2f173682dc079f004 100644 --- a/lib/internal/Magento/Framework/HTTP/Client/Curl.php +++ b/lib/internal/Magento/Framework/HTTP/Client/Curl.php @@ -9,6 +9,7 @@ namespace Magento\Framework\HTTP\Client; * Class to work with HTTP protocol using curl library * * @author Magento Core Team <core@magentocommerce.com> + * @SuppressWarnings(PHPMD.ExcessiveClassComplexity) */ class Curl implements \Magento\Framework\HTTP\ClientInterface { @@ -16,7 +17,7 @@ class Curl implements \Magento\Framework\HTTP\ClientInterface * Max supported protocol by curl CURL_SSLVERSION_TLSv1_2 * @var int */ - private static $sslVersion = 6; + private $sslVersion; /** * Hostname @@ -86,7 +87,7 @@ class Curl implements \Magento\Framework\HTTP\ClientInterface /** * Curl - * @var object + * @var resource */ protected $_ch; @@ -117,10 +118,11 @@ class Curl implements \Magento\Framework\HTTP\ClientInterface } /** - * Constructor + * @param int|null $sslVersion */ - public function __construct() + public function __construct($sslVersion = null) { + $this->sslVersion = $sslVersion; } /** @@ -377,10 +379,11 @@ class Curl implements \Magento\Framework\HTTP\ClientInterface $this->curlOption(CURLOPT_PORT, $this->_port); } - //$this->curlOption(CURLOPT_HEADER, 1); $this->curlOption(CURLOPT_RETURNTRANSFER, 1); $this->curlOption(CURLOPT_HEADERFUNCTION, [$this, 'parseHeaders']); - $this->curlOption(CURLOPT_SSLVERSION, self::$sslVersion); + if ($this->sslVersion !== null) { + $this->curlOption(CURLOPT_SSLVERSION, $this->sslVersion); + } if (count($this->_curlUserOptions)) { foreach ($this->_curlUserOptions as $k => $v) { @@ -415,6 +418,7 @@ class Curl implements \Magento\Framework\HTTP\ClientInterface * @param resource $ch curl handle, not needed * @param string $data * @return int + * @throws \Exception * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ protected function parseHeaders($ch, $data) @@ -422,11 +426,10 @@ class Curl implements \Magento\Framework\HTTP\ClientInterface if ($this->_headerCount == 0) { $line = explode(" ", trim($data), 3); if (count($line) != 3) { - return $this->doError("Invalid response line returned from server: " . $data); + $this->doError("Invalid response line returned from server: " . $data); } $this->_responseStatus = intval($line[1]); } else { - //var_dump($data); $name = $value = ''; $out = explode(": ", trim($data), 2); if (count($out) == 2) { diff --git a/lib/internal/Magento/Framework/Indexer/Config/Converter.php b/lib/internal/Magento/Framework/Indexer/Config/Converter.php index b8b17b185a1f2630842d6fe6e01b6a9de2a52107..0112b4d9a4de301a312e3e66bd146d8f477cd349 100644 --- a/lib/internal/Magento/Framework/Indexer/Config/Converter.php +++ b/lib/internal/Magento/Framework/Indexer/Config/Converter.php @@ -72,10 +72,10 @@ class Converter implements ConverterInterface $data['fieldsets'] = isset($data['fieldsets']) ? $data['fieldsets'] : []; switch ($childNode->nodeName) { case 'title': - $data['title'] = $this->getTranslatedNodeValue($childNode); + $data['title'] = $childNode->nodeValue; break; case 'description': - $data['description'] = $this->getTranslatedNodeValue($childNode); + $data['description'] = $childNode->nodeValue; break; case 'saveHandler': $data['saveHandler'] = $this->getAttributeValue($childNode, 'class'); @@ -207,6 +207,7 @@ class Converter implements ConverterInterface * * @param \DOMNode $node * @return string + * @deprecated */ protected function getTranslatedNodeValue(\DOMNode $node) { diff --git a/lib/internal/Magento/Framework/Interception/Config/Config.php b/lib/internal/Magento/Framework/Interception/Config/Config.php index 9812e505cc397226f689b7cbfe354cbf6a5ce608..0b30b2619c069751430de447b7731568bacc847d 100644 --- a/lib/internal/Magento/Framework/Interception/Config/Config.php +++ b/lib/internal/Magento/Framework/Interception/Config/Config.php @@ -7,6 +7,9 @@ */ namespace Magento\Framework\Interception\Config; +use Magento\Framework\Serialize\SerializerInterface; +use Magento\Framework\Serialize\Serializer\Serialize; + class Config implements \Magento\Framework\Interception\ConfigInterface { /** @@ -71,6 +74,13 @@ class Config implements \Magento\Framework\Interception\ConfigInterface protected $_scopeList; /** + * @var SerializerInterface + */ + private $serializer; + + /** + * Config constructor + * * @param \Magento\Framework\Config\ReaderInterface $reader * @param \Magento\Framework\Config\ScopeListInterface $scopeList * @param \Magento\Framework\Cache\FrontendInterface $cache @@ -78,6 +88,7 @@ class Config implements \Magento\Framework\Interception\ConfigInterface * @param \Magento\Framework\Interception\ObjectManager\ConfigInterface $omConfig * @param \Magento\Framework\ObjectManager\DefinitionInterface $classDefinitions * @param string $cacheId + * @param SerializerInterface|null $serializer */ public function __construct( \Magento\Framework\Config\ReaderInterface $reader, @@ -86,7 +97,8 @@ class Config implements \Magento\Framework\Interception\ConfigInterface \Magento\Framework\ObjectManager\RelationsInterface $relations, \Magento\Framework\Interception\ObjectManager\ConfigInterface $omConfig, \Magento\Framework\ObjectManager\DefinitionInterface $classDefinitions, - $cacheId = 'interception' + $cacheId = 'interception', + SerializerInterface $serializer = null ) { $this->_omConfig = $omConfig; $this->_relations = $relations; @@ -95,10 +107,11 @@ class Config implements \Magento\Framework\Interception\ConfigInterface $this->_cacheId = $cacheId; $this->_reader = $reader; $this->_scopeList = $scopeList; - + $this->serializer = $serializer ?: \Magento\Framework\App\ObjectManager::getInstance() + ->get(Serialize::class); $intercepted = $this->_cache->load($this->_cacheId); if ($intercepted !== false) { - $this->_intercepted = unserialize($intercepted); + $this->_intercepted = $this->serializer->unserialize($intercepted); } else { $this->initialize($this->_classDefinitions->getClasses()); } @@ -129,7 +142,7 @@ class Config implements \Magento\Framework\Interception\ConfigInterface foreach ($classDefinitions as $class) { $this->hasPlugins($class); } - $this->_cache->save(serialize($this->_intercepted), $this->_cacheId); + $this->_cache->save($this->serializer->serialize($this->_intercepted), $this->_cacheId); } /** diff --git a/lib/internal/Magento/Framework/Interception/Definition/Compiled.php b/lib/internal/Magento/Framework/Interception/Definition/Compiled.php deleted file mode 100644 index 6fbe9c99dce8637e8c31b9ce493b5b79c45e62c0..0000000000000000000000000000000000000000 --- a/lib/internal/Magento/Framework/Interception/Definition/Compiled.php +++ /dev/null @@ -1,39 +0,0 @@ -<?php -/** - * Compiled method plugin definitions. Must be used in production for maximum performance - * - * Copyright © 2016 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Framework\Interception\Definition; - -use Magento\Framework\Interception\DefinitionInterface; - -class Compiled implements DefinitionInterface -{ - /** - * List of plugin definitions - * - * @var array - */ - protected $_definitions = []; - - /** - * @param array $definitions - */ - public function __construct(array $definitions) - { - $this->_definitions = $definitions; - } - - /** - * Retrieve list of methods - * - * @param string $type - * @return string[] - */ - public function getMethodList($type) - { - return $this->_definitions[$type]; - } -} diff --git a/lib/internal/Magento/Framework/Interception/PluginList/PluginList.php b/lib/internal/Magento/Framework/Interception/PluginList/PluginList.php index bae8f7c118c08b298bdc17b86db65181af075c3a..a84e23dc75548d059ea1007ab83a3d7728eeca40 100644 --- a/lib/internal/Magento/Framework/Interception/PluginList/PluginList.php +++ b/lib/internal/Magento/Framework/Interception/PluginList/PluginList.php @@ -1,7 +1,5 @@ <?php /** - * Plugin configuration storage. Provides list of plugins configured for type. - * * Copyright © 2016 Magento. All rights reserved. * See COPYING.txt for license details. */ @@ -17,8 +15,12 @@ use Magento\Framework\Interception\ObjectManager\ConfigInterface; use Magento\Framework\ObjectManager\RelationsInterface; use Magento\Framework\ObjectManager\DefinitionInterface as ClassDefinitions; use Magento\Framework\ObjectManagerInterface; +use Magento\Framework\Serialize\SerializerInterface; +use Magento\Framework\Serialize\Serializer\Serialize; /** + * Plugin config, provides list of plugins for a type + * * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class PluginList extends Scoped implements InterceptionPluginList @@ -81,6 +83,13 @@ class PluginList extends Scoped implements InterceptionPluginList private $logger; /** + * @var SerializerInterface + */ + private $serializer; + + /** + * Constructor + * * @param ReaderInterface $reader * @param ScopeInterface $configScope * @param CacheInterface $cache @@ -90,7 +99,8 @@ class PluginList extends Scoped implements InterceptionPluginList * @param ObjectManagerInterface $objectManager * @param ClassDefinitions $classDefinitions * @param array $scopePriorityScheme - * @param string $cacheId + * @param string|null $cacheId + * @param SerializerInterface|null $serializer * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( @@ -103,9 +113,11 @@ class PluginList extends Scoped implements InterceptionPluginList ObjectManagerInterface $objectManager, ClassDefinitions $classDefinitions, array $scopePriorityScheme = ['global'], - $cacheId = 'plugins' + $cacheId = 'plugins', + SerializerInterface $serializer = null ) { - parent::__construct($reader, $configScope, $cache, $cacheId); + $this->serializer = $serializer ?: $objectManager->get(Serialize::class); + parent::__construct($reader, $configScope, $cache, $cacheId, $this->serializer); $this->_omConfig = $omConfig; $this->_relations = $relations; $this->_definitions = $definitions; @@ -275,7 +287,7 @@ class PluginList extends Scoped implements InterceptionPluginList $cacheId = implode('|', $this->_scopePriorityScheme) . "|" . $this->_cacheId; $data = $this->_cache->load($cacheId); if ($data) { - list($this->_data, $this->_inherited, $this->_processed) = unserialize($data); + list($this->_data, $this->_inherited, $this->_processed) = $this->serializer->unserialize($data); foreach ($this->_scopePriorityScheme as $scopeCode) { $this->_loadedScopes[$scopeCode] = true; } @@ -307,7 +319,10 @@ class PluginList extends Scoped implements InterceptionPluginList foreach ($this->getClassDefinitions() as $class) { $this->_inheritPlugins($class); } - $this->_cache->save(serialize([$this->_data, $this->_inherited, $this->_processed]), $cacheId); + $this->_cache->save( + $this->serializer->serialize([$this->_data, $this->_inherited, $this->_processed]), + $cacheId + ); } $this->_pluginInstances = []; } @@ -371,10 +386,10 @@ class PluginList extends Scoped implements InterceptionPluginList } /** - * Returns logger instance + * Get logger * - * @deprecated * @return \Psr\Log\LoggerInterface + * @deprecated */ private function getLogger() { diff --git a/lib/internal/Magento/Framework/Interception/Test/Unit/Config/ConfigTest.php b/lib/internal/Magento/Framework/Interception/Test/Unit/Config/ConfigTest.php index 992ed838b7c522af706668ae6f8443edfea8ef8c..7d15d1029bda65837aacc94111132fdc1c34e829 100644 --- a/lib/internal/Magento/Framework/Interception/Test/Unit/Config/ConfigTest.php +++ b/lib/internal/Magento/Framework/Interception/Test/Unit/Config/ConfigTest.php @@ -6,6 +6,8 @@ // @codingStandardsIgnoreFile namespace Magento\Framework\Interception\Test\Unit\Config; +use Magento\Framework\Serialize\SerializerInterface; + require_once __DIR__ . '/../Custom/Module/Model/Item.php'; require_once __DIR__ . '/../Custom/Module/Model/Item/Enhanced.php'; require_once __DIR__ . '/../Custom/Module/Model/ItemContainer.php'; @@ -22,32 +24,38 @@ class ConfigTest extends \PHPUnit_Framework_TestCase /** * @var \PHPUnit_Framework_MockObject_MockObject */ - protected $configScopeMock; + private $configScopeMock; /** * @var \PHPUnit_Framework_MockObject_MockObject */ - protected $readerMock; + private $readerMock; /** * @var \PHPUnit_Framework_MockObject_MockObject */ - protected $cacheMock; + private $cacheMock; /** * @var \PHPUnit_Framework_MockObject_MockObject */ - protected $omConfigMock; + private $omConfigMock; /** * @var \PHPUnit_Framework_MockObject_MockObject */ - protected $definitionMock; + private $definitionMock; /** * @var \PHPUnit_Framework_MockObject_MockObject */ - protected $relationsMock; + private $relationsMock; + + /** @var SerializerInterface|\PHPUnit_Framework_MockObject_MockObject */ + private $serializerMock; + + /** @var \Magento\Framework\TestFramework\Unit\Helper\ObjectManager */ + private $objectManagerHelper; protected function setUp() { @@ -67,6 +75,8 @@ class ConfigTest extends \PHPUnit_Framework_TestCase $this->relationsMock = $this->getMockForAbstractClass( \Magento\Framework\ObjectManager\RelationsInterface::class ); + $this->serializerMock = $this->getMock(SerializerInterface::class); + $this->objectManagerHelper = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); } /** @@ -131,14 +141,22 @@ class ConfigTest extends \PHPUnit_Framework_TestCase $this->relationsMock->expects($this->any())->method('has')->will($this->returnValue($expectedResult)); $this->relationsMock->expects($this->any())->method('getParents')->will($this->returnValue($entityParents)); - $model = new \Magento\Framework\Interception\Config\Config( - $this->readerMock, - $this->configScopeMock, - $this->cacheMock, - $this->relationsMock, - $this->omConfigMock, - $this->definitionMock, - 'interception' + $this->serializerMock->expects($this->once()) + ->method('serialize'); + + $this->serializerMock->expects($this->never())->method('unserialize'); + + $model = $this->objectManagerHelper->getObject( + \Magento\Framework\Interception\Config\Config::class, + [ + 'reader' => $this->readerMock, + 'scopeList' => $this->configScopeMock, + 'cache' => $this->cacheMock, + 'relations' => $this->relationsMock, + 'omConfig' => $this->omConfigMock, + 'classDefinitions' => $this->definitionMock, + 'serializer' => $this->serializerMock, + ] ); $this->assertEquals($expectedResult, $model->hasPlugins($type)); @@ -163,18 +181,32 @@ class ConfigTest extends \PHPUnit_Framework_TestCase ]; $this->readerMock->expects($this->never())->method('read'); $this->cacheMock->expects($this->never())->method('save'); + $serializedValue = 'serializedData'; $this->cacheMock->expects($this->any()) ->method('load') ->with($cacheId) - ->will($this->returnValue(serialize($interceptionData))); - $model = new \Magento\Framework\Interception\Config\Config( - $this->readerMock, - $this->configScopeMock, - $this->cacheMock, - new \Magento\Framework\ObjectManager\Relations\Runtime(), - $this->omConfigMock, - $this->definitionMock, - $cacheId + ->will($this->returnValue($serializedValue)); + + $this->serializerMock->expects($this->never())->method('serialize'); + $this->serializerMock->expects($this->once()) + ->method('unserialize') + ->with($serializedValue) + ->willReturn($interceptionData); + + $model = $this->objectManagerHelper->getObject( + \Magento\Framework\Interception\Config\Config::class, + [ + 'reader' => $this->readerMock, + 'scopeList' => $this->configScopeMock, + 'cache' => $this->cacheMock, + 'relations' => $this->objectManagerHelper->getObject( + \Magento\Framework\ObjectManager\Relations\Runtime::class + ), + 'omConfig' => $this->omConfigMock, + 'classDefinitions' => $this->definitionMock, + 'cacheId' => $cacheId, + 'serializer' => $this->serializerMock, + ] ); $this->assertEquals($expectedResult, $model->hasPlugins($type)); diff --git a/lib/internal/Magento/Framework/Interception/Test/Unit/Definition/CompiledTest.php b/lib/internal/Magento/Framework/Interception/Test/Unit/Definition/CompiledTest.php deleted file mode 100644 index a64cd96b62966023daf9d910c58b6a1f526925c6..0000000000000000000000000000000000000000 --- a/lib/internal/Magento/Framework/Interception/Test/Unit/Definition/CompiledTest.php +++ /dev/null @@ -1,24 +0,0 @@ -<?php -/** - * Copyright © 2016 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Framework\Interception\Test\Unit\Definition; - -class CompiledTest extends \PHPUnit_Framework_TestCase -{ - /** - * @var array - */ - protected $_definitions = ['type' => 'definitions']; - - /** - * @covers \Magento\Framework\Interception\Definition\Compiled::getMethodList - * @covers \Magento\Framework\Interception\Definition\Compiled::__construct - */ - public function testGetMethodList() - { - $model = new \Magento\Framework\Interception\Definition\Compiled($this->_definitions); - $this->assertEquals('definitions', $model->getMethodList('type')); - } -} diff --git a/lib/internal/Magento/Framework/Interception/Test/Unit/PluginList/PluginListTest.php b/lib/internal/Magento/Framework/Interception/Test/Unit/PluginList/PluginListTest.php index ac1e510f28b226a9c6386a35ca31192b7900cdc4..11e8dabf6d924cb4c566746514af503091b85935 100644 --- a/lib/internal/Magento/Framework/Interception/Test/Unit/PluginList/PluginListTest.php +++ b/lib/internal/Magento/Framework/Interception/Test/Unit/PluginList/PluginListTest.php @@ -5,6 +5,9 @@ */ namespace Magento\Framework\Interception\Test\Unit\PluginList; +use Magento\Framework\Serialize\SerializerInterface; +use Magento\Framework\ObjectManagerInterface; + require_once __DIR__ . '/../Custom/Module/Model/Item.php'; require_once __DIR__ . '/../Custom/Module/Model/Item/Enhanced.php'; require_once __DIR__ . '/../Custom/Module/Model/ItemContainer.php'; @@ -23,22 +26,32 @@ class PluginListTest extends \PHPUnit_Framework_TestCase /** * @var \Magento\Framework\Interception\PluginList\PluginList */ - protected $_model; + private $object; + + /** + * @var \Magento\Framework\Config\ScopeInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $configScopeMock; + + /** + * @var \Magento\Framework\Config\CacheInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $cacheMock; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var \Psr\Log\LoggerInterface|\PHPUnit_Framework_MockObject_MockObject */ - protected $_configScopeMock; + private $loggerMock; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var SerializerInterface|\PHPUnit_Framework_MockObject_MockObject */ - protected $_objectManagerMock; + private $serializerMock; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var ObjectManagerInterface||\PHPUnit_Framework_MockObject_MockObject */ - protected $_cacheMock; + private $objectManagerMock; protected function setUp() { @@ -46,10 +59,10 @@ class PluginListTest extends \PHPUnit_Framework_TestCase $readerMock = $this->getMock(\Magento\Framework\ObjectManager\Config\Reader\Dom::class, [], [], '', false); $readerMock->expects($this->any())->method('read')->will($this->returnValueMap($readerMap)); - $this->_configScopeMock = $this->getMock(\Magento\Framework\Config\ScopeInterface::class); - $this->_cacheMock = $this->getMock(\Magento\Framework\Config\CacheInterface::class); + $this->configScopeMock = $this->getMock(\Magento\Framework\Config\ScopeInterface::class); + $this->cacheMock = $this->getMock(\Magento\Framework\Config\CacheInterface::class); // turn cache off - $this->_cacheMock->expects($this->any()) + $this->cacheMock->expects($this->any()) ->method('get') ->will($this->returnValue(false)); @@ -59,62 +72,76 @@ class PluginListTest extends \PHPUnit_Framework_TestCase $omConfigMock->expects($this->any())->method('getOriginalInstanceType')->will($this->returnArgument(0)); - $this->_objectManagerMock = $this->getMock(\Magento\Framework\ObjectManagerInterface::class); + $this->objectManagerMock = $this->getMock(ObjectManagerInterface::class); + $this->objectManagerMock->expects($this->any()) + ->method('get') + ->willReturnArgument(0); + $this->serializerMock = $this->getMock(SerializerInterface::class); $definitions = new \Magento\Framework\ObjectManager\Definition\Runtime(); - $this->_model = new \Magento\Framework\Interception\PluginList\PluginList( - $readerMock, - $this->_configScopeMock, - $this->_cacheMock, - new \Magento\Framework\ObjectManager\Relations\Runtime(), - $omConfigMock, - new \Magento\Framework\Interception\Definition\Runtime(), - $this->_objectManagerMock, - $definitions, - ['global'], - 'interception' + $objectManagerHelper = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); + $this->object = $objectManagerHelper->getObject( + \Magento\Framework\Interception\PluginList\PluginList::class, + [ + 'reader' => $readerMock, + 'configScope' => $this->configScopeMock, + 'cache' => $this->cacheMock, + 'relations' => new \Magento\Framework\ObjectManager\Relations\Runtime(), + 'omConfig' => $omConfigMock, + 'definitions' => new \Magento\Framework\Interception\Definition\Runtime(), + 'objectManager' => $this->objectManagerMock, + 'classDefinitions' => $definitions, + 'scopePriorityScheme' => ['global'], + 'cacheId' => 'interception', + 'serializer' => $this->serializerMock + ] + ); + + $this->loggerMock = $this->getMock(\Psr\Log\LoggerInterface::class); + $objectManagerHelper->setBackwardCompatibleProperty( + $this->object, + 'logger', + $this->loggerMock ); } public function testGetPlugin() { - $this->_objectManagerMock->expects($this->any())->method('get')->will($this->returnArgument(0)); - $this->_configScopeMock->expects($this->any())->method('getCurrentScope')->will($this->returnValue('backend')); - $this->_model->getNext(\Magento\Framework\Interception\Test\Unit\Custom\Module\Model\Item::class, 'getName'); - $this->_model->getNext( + $this->configScopeMock->expects($this->any())->method('getCurrentScope')->will($this->returnValue('backend')); + $this->object->getNext(\Magento\Framework\Interception\Test\Unit\Custom\Module\Model\Item::class, 'getName'); + $this->object->getNext( \Magento\Framework\Interception\Test\Unit\Custom\Module\Model\ItemContainer::class, 'getName' ); - $this->_model->getNext( + $this->object->getNext( \Magento\Framework\Interception\Test\Unit\Custom\Module\Model\StartingBackslash::class, 'getName' ); - $this->assertEquals( \Magento\Framework\Interception\Test\Unit\Custom\Module\Model\ItemPlugin\Simple::class, - $this->_model->getPlugin( + $this->object->getPlugin( \Magento\Framework\Interception\Test\Unit\Custom\Module\Model\Item::class, 'simple_plugin' ) ); $this->assertEquals( \Magento\Framework\Interception\Test\Unit\Custom\Module\Model\ItemPlugin\Advanced::class, - $this->_model->getPlugin( + $this->object->getPlugin( \Magento\Framework\Interception\Test\Unit\Custom\Module\Model\Item::class, 'advanced_plugin' ) ); $this->assertEquals( \Magento\Framework\Interception\Test\Unit\Custom\Module\Model\ItemContainerPlugin\Simple::class, - $this->_model->getPlugin( + $this->object->getPlugin( \Magento\Framework\Interception\Test\Unit\Custom\Module\Model\ItemContainer::class, 'simple_plugin' ) ); $this->assertEquals( \Magento\Framework\Interception\Test\Unit\Custom\Module\Model\StartingBackslash\Plugin::class, - $this->_model->getPlugin( + $this->object->getPlugin( \Magento\Framework\Interception\Test\Unit\Custom\Module\Model\StartingBackslash::class, 'simple_plugin' ) @@ -131,15 +158,14 @@ class PluginListTest extends \PHPUnit_Framework_TestCase */ public function testGetPlugins($expectedResult, $type, $method, $scopeCode, $code = '__self') { - $this->_objectManagerMock->expects($this->any())->method('get')->will($this->returnArgument(0)); - $this->_configScopeMock->expects( + $this->configScopeMock->expects( $this->any() )->method( 'getCurrentScope' )->will( $this->returnValue($scopeCode) ); - $this->assertEquals($expectedResult, $this->_model->getNext($type, $method, $code)); + $this->assertEquals($expectedResult, $this->object->getNext($type, $method, $code)); } /** @@ -207,12 +233,26 @@ class PluginListTest extends \PHPUnit_Framework_TestCase */ public function testInheritPluginsWithNonExistingClass() { - $this->_objectManagerMock->expects($this->any())->method('get')->will($this->returnArgument(0)); - $this->_configScopeMock->expects($this->any()) + $this->configScopeMock->expects($this->any()) ->method('getCurrentScope') ->will($this->returnValue('frontend')); - $this->_model->getNext('SomeType', 'someMethod'); + $this->object->getNext('SomeType', 'someMethod'); + } + + public function testLoadScopedDataNotCached() + { + $this->configScopeMock->expects($this->exactly(3)) + ->method('getCurrentScope') + ->will($this->returnValue('scope')); + $this->serializerMock->expects($this->once()) + ->method('serialize'); + $this->serializerMock->expects($this->never()) + ->method('unserialize'); + $this->cacheMock->expects($this->once()) + ->method('save'); + + $this->assertEquals(null, $this->object->getNext('Type', 'method')); } /** @@ -221,19 +261,14 @@ class PluginListTest extends \PHPUnit_Framework_TestCase */ public function testInheritPluginsWithNotExistingPlugin() { - $loggerMock = $this->getMock(\Psr\Log\LoggerInterface::class); - $this->_objectManagerMock->expects($this->once()) - ->method('get') - ->with(\Psr\Log\LoggerInterface::class) - ->willReturn($loggerMock); - $loggerMock->expects($this->once()) + $this->loggerMock->expects($this->once()) ->method('info') ->with("Reference to undeclared plugin with name 'simple_plugin'."); - $this->_configScopeMock->expects($this->any()) + $this->configScopeMock->expects($this->any()) ->method('getCurrentScope') ->will($this->returnValue('frontend')); - $this->assertNull($this->_model->getNext('typeWithoutInstance', 'someMethod')); + $this->assertNull($this->object->getNext('typeWithoutInstance', 'someMethod')); } /** @@ -242,19 +277,24 @@ class PluginListTest extends \PHPUnit_Framework_TestCase */ public function testLoadScopedDataCached() { - $this->_objectManagerMock->expects($this->any())->method('get')->will($this->returnArgument(0)); - $this->_configScopeMock->expects($this->once()) + $this->configScopeMock->expects($this->once()) ->method('getCurrentScope') ->will($this->returnValue('scope')); $data = [['key'], ['key'], ['key']]; + $serializedData = 'serialized data'; - $this->_cacheMock->expects($this->once()) + $this->serializerMock->expects($this->never()) + ->method('serialize'); + $this->serializerMock->expects($this->once()) + ->method('unserialize') + ->willReturn($data); + $this->cacheMock->expects($this->once()) ->method('load') ->with('global|scope|interception') - ->will($this->returnValue(serialize($data))); + ->willReturn($serializedData); - $this->assertEquals(null, $this->_model->getNext('Type', 'method')); + $this->assertEquals(null, $this->object->getNext('Type', 'method')); } /** @@ -263,23 +303,23 @@ class PluginListTest extends \PHPUnit_Framework_TestCase */ public function testLoadScopeDataWithEmptyData() { - $this->_objectManagerMock->expects($this->any()) + $this->objectManagerMock->expects($this->any()) ->method('get') ->will($this->returnArgument(0)); - $this->_configScopeMock->expects($this->any()) + $this->configScopeMock->expects($this->any()) ->method('getCurrentScope') ->will($this->returnValue('emptyscope')); $this->assertEquals( [4 => ['simple_plugin']], - $this->_model->getNext( + $this->object->getNext( \Magento\Framework\Interception\Test\Unit\Custom\Module\Model\Item::class, 'getName' ) ); $this->assertEquals( \Magento\Framework\Interception\Test\Unit\Custom\Module\Model\ItemPlugin\Simple::class, - $this->_model->getPlugin( + $this->object->getPlugin( \Magento\Framework\Interception\Test\Unit\Custom\Module\Model\Item::class, 'simple_plugin' ) diff --git a/lib/internal/Magento/Framework/Mview/Config/Data.php b/lib/internal/Magento/Framework/Mview/Config/Data.php index d2e4ee91bea2d8c6ad5712476d3af9910b818cd1..fed3021a161ee6280f7d3f0e01e7b5e15329d88a 100644 --- a/lib/internal/Magento/Framework/Mview/Config/Data.php +++ b/lib/internal/Magento/Framework/Mview/Config/Data.php @@ -5,6 +5,11 @@ */ namespace Magento\Framework\Mview\Config; +use Magento\Framework\Serialize\SerializerInterface; + +/** + * Provides materialized view configuration + */ class Data extends \Magento\Framework\Config\Data { /** @@ -13,22 +18,26 @@ class Data extends \Magento\Framework\Config\Data protected $stateCollection; /** - * @param \Magento\Framework\Mview\Config\Reader $reader + * Constructor + * + * @param Reader $reader * @param \Magento\Framework\Config\CacheInterface $cache * @param \Magento\Framework\Mview\View\State\CollectionInterface $stateCollection - * @param string $cacheId + * @param string|null $cacheId + * @param SerializerInterface|null $serializer */ public function __construct( \Magento\Framework\Mview\Config\Reader $reader, \Magento\Framework\Config\CacheInterface $cache, \Magento\Framework\Mview\View\State\CollectionInterface $stateCollection, - $cacheId = 'mview_config' + $cacheId = 'mview_config', + SerializerInterface $serializer = null ) { $this->stateCollection = $stateCollection; $isCacheExists = $cache->test($cacheId); - parent::__construct($reader, $cache, $cacheId); + parent::__construct($reader, $cache, $cacheId, $serializer); if (!$isCacheExists) { $this->deleteNonexistentStates(); diff --git a/lib/internal/Magento/Framework/Mview/Test/Unit/Config/DataTest.php b/lib/internal/Magento/Framework/Mview/Test/Unit/Config/DataTest.php index 244b1b1e1382dd962560dffdec638e16dc7d71a0..777c099d9b83844c9448f172ae07106f66a5ca13 100644 --- a/lib/internal/Magento/Framework/Mview/Test/Unit/Config/DataTest.php +++ b/lib/internal/Magento/Framework/Mview/Test/Unit/Config/DataTest.php @@ -10,32 +10,37 @@ class DataTest extends \PHPUnit_Framework_TestCase /** * @var \Magento\Framework\Mview\Config\Data */ - protected $model; + private $config; /** * @var \Magento\Framework\Mview\Config\Reader|\PHPUnit_Framework_MockObject_MockObject */ - protected $reader; + private $reader; /** * @var \Magento\Framework\Config\CacheInterface|\PHPUnit_Framework_MockObject_MockObject */ - protected $cache; + private $cache; /** * @var \Magento\Framework\Mview\View\State\CollectionInterface|\PHPUnit_Framework_MockObject_MockObject */ - protected $stateCollection; + private $stateCollection; /** * @var string */ - protected $cacheId = 'mview_config'; + private $cacheId = 'mview_config'; /** * @var string */ - protected $views = ['view1' => [], 'view3' => []]; + private $views = ['view1' => [], 'view3' => []]; + + /** + * @var \Magento\Framework\Serialize\SerializerInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $serializerMock; protected function setUp() { @@ -58,28 +63,29 @@ class DataTest extends \PHPUnit_Framework_TestCase true, ['getItems'] ); + + $this->serializerMock = $this->getMock(\Magento\Framework\Serialize\SerializerInterface::class); } public function testConstructorWithCache() { $this->cache->expects($this->once())->method('test')->with($this->cacheId)->will($this->returnValue(true)); - $this->cache->expects( - $this->once() - )->method( - 'load' - )->with( - $this->cacheId - )->will( - $this->returnValue(serialize($this->views)) - ); + $this->cache->expects($this->once()) + ->method('load') + ->with($this->cacheId); $this->stateCollection->expects($this->never())->method('getItems'); - $this->model = new \Magento\Framework\Mview\Config\Data( + $this->serializerMock->expects($this->once()) + ->method('unserialize') + ->willReturn($this->views); + + $this->config = new \Magento\Framework\Mview\Config\Data( $this->reader, $this->cache, $this->stateCollection, - $this->cacheId + $this->cacheId, + $this->serializerMock ); } @@ -114,11 +120,12 @@ class DataTest extends \PHPUnit_Framework_TestCase $this->stateCollection->expects($this->once())->method('getItems')->will($this->returnValue($states)); - $this->model = new \Magento\Framework\Mview\Config\Data( + $this->config = new \Magento\Framework\Mview\Config\Data( $this->reader, $this->cache, $this->stateCollection, - $this->cacheId + $this->cacheId, + $this->serializerMock ); } } diff --git a/lib/internal/Magento/Framework/ObjectManager/Config/Compiled.php b/lib/internal/Magento/Framework/ObjectManager/Config/Compiled.php index 779e8cf0a0e5ecf15b0fcb6da1e48b80a5bb3072..0260af34ef1089281b36e37b75906203d7780684 100644 --- a/lib/internal/Magento/Framework/ObjectManager/Config/Compiled.php +++ b/lib/internal/Magento/Framework/ObjectManager/Config/Compiled.php @@ -6,9 +6,14 @@ namespace Magento\Framework\ObjectManager\Config; use Magento\Framework\ObjectManager\ConfigInterface; +use Magento\Framework\Serialize\SerializerInterface; +use Magento\Framework\Serialize\Serializer\Serialize; use Magento\Framework\ObjectManager\ConfigCacheInterface; use Magento\Framework\ObjectManager\RelationsInterface; +/** + * Provides object manager configuration when in compiled mode + */ class Compiled implements ConfigInterface { /** @@ -27,6 +32,13 @@ class Compiled implements ConfigInterface private $preferences; /** + * @var SerializerInterface + */ + private $serializer; + + /** + * Constructor + * * @param array $data */ public function __construct($data) @@ -72,7 +84,7 @@ class Compiled implements ConfigInterface { if (isset($this->arguments[$type])) { if (is_string($this->arguments[$type])) { - $this->arguments[$type] = unserialize($this->arguments[$type]); + $this->arguments[$type] = $this->getSerializer()->unserialize($this->arguments[$type]); } return $this->arguments[$type]; } else { @@ -159,4 +171,19 @@ class Compiled implements ConfigInterface { return $this->preferences; } + + /** + * Get serializer + * + * @return SerializerInterface + * @deprecated + */ + private function getSerializer() + { + if (null === $this->serializer) { + $this->serializer = \Magento\Framework\App\ObjectManager::getInstance() + ->get(Serialize::class); + } + return $this->serializer; + } } diff --git a/lib/internal/Magento/Framework/ObjectManager/Config/Config.php b/lib/internal/Magento/Framework/ObjectManager/Config/Config.php index 5dc02e6ba7d97cc0a1123572c7577ae767d369af..7ad196cdd34b4d90b1179ad8559b63ea8b1fa684 100644 --- a/lib/internal/Magento/Framework/ObjectManager/Config/Config.php +++ b/lib/internal/Magento/Framework/ObjectManager/Config/Config.php @@ -5,6 +5,7 @@ */ namespace Magento\Framework\ObjectManager\Config; +use Magento\Framework\Serialize\SerializerInterface; use Magento\Framework\ObjectManager\ConfigCacheInterface; use Magento\Framework\ObjectManager\DefinitionInterface; use Magento\Framework\ObjectManager\RelationsInterface; @@ -74,6 +75,11 @@ class Config implements \Magento\Framework\ObjectManager\ConfigInterface */ protected $_mergedArguments; + /** + * @var \Magento\Framework\Serialize\SerializerInterface + */ + private $serializer; + /** * @param RelationsInterface $relations * @param DefinitionInterface $definitions @@ -267,10 +273,12 @@ class Config implements \Magento\Framework\ObjectManager\ConfigInterface if ($this->_cache) { if (!$this->_currentCacheKey) { $this->_currentCacheKey = md5( - serialize([$this->_arguments, $this->_nonShared, $this->_preferences, $this->_virtualTypes]) + $this->getSerializer()->serialize( + [$this->_arguments, $this->_nonShared, $this->_preferences, $this->_virtualTypes] + ) ); } - $key = md5($this->_currentCacheKey . serialize($configuration)); + $key = md5($this->_currentCacheKey . $this->getSerializer()->serialize($configuration)); $cached = $this->_cache->get($key); if ($cached) { list( @@ -323,4 +331,19 @@ class Config implements \Magento\Framework\ObjectManager\ConfigInterface { return $this->_preferences; } + + /** + * Get serializer + * + * @return \Magento\Framework\Serialize\SerializerInterface + * @deprecated + */ + private function getSerializer() + { + if ($this->serializer === null) { + $this->serializer = \Magento\Framework\App\ObjectManager::getInstance() + ->get(SerializerInterface::class); + } + return $this->serializer; + } } diff --git a/lib/internal/Magento/Framework/ObjectManager/Definition/Compiled.php b/lib/internal/Magento/Framework/ObjectManager/Definition/Compiled.php deleted file mode 100644 index 2cb3b21211f23af76ab75ad6875b4cc6396f4a50..0000000000000000000000000000000000000000 --- a/lib/internal/Magento/Framework/ObjectManager/Definition/Compiled.php +++ /dev/null @@ -1,85 +0,0 @@ -<?php -/** - * Copyright © 2016 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Framework\ObjectManager\Definition; - -/** - * Compiled class definitions. Should be used for maximum performance in production. - */ -abstract class Compiled implements \Magento\Framework\ObjectManager\DefinitionInterface -{ - /** - * Class definitions - * - * @var array - */ - protected $_definitions; - - /** - * @var \Magento\Framework\Code\Reader\ClassReaderInterface - */ - protected $reader ; - - /** - * @param array $definitions - * @param \Magento\Framework\Code\Reader\ClassReaderInterface $reader - */ - public function __construct(array $definitions, \Magento\Framework\Code\Reader\ClassReaderInterface $reader = null) - { - list($this->_signatures, $this->_definitions) = $definitions; - $this->reader = $reader ?: new \Magento\Framework\Code\Reader\ClassReader(); - } - - /** - * Unpack signature - * - * @param string $signature - * @return mixed - */ - abstract protected function _unpack($signature); - - /** - * Get list of method parameters - * - * Retrieve an ordered list of constructor parameters. - * Each value is an array with following entries: - * - * array( - * 0, // string: Parameter name - * 1, // string|null: Parameter type - * 2, // bool: whether this param is required - * 3, // mixed: default value - * ); - * - * @param string $className - * @return array|null - */ - public function getParameters($className) - { - // if the definition isn't found in the list gathered from the compiled file then using reflection to find it - if (!array_key_exists($className, $this->_definitions)) { - return $this->reader->getConstructor($className); - } - - $definition = $this->_definitions[$className]; - if ($definition !== null) { - if (is_string($this->_signatures[$definition])) { - $this->_signatures[$definition] = $this->_unpack($this->_signatures[$definition]); - } - return $this->_signatures[$definition]; - } - return null; - } - - /** - * Retrieve list of all classes covered with definitions - * - * @return array - */ - public function getClasses() - { - return array_keys($this->_definitions); - } -} diff --git a/lib/internal/Magento/Framework/ObjectManager/Definition/Compiled/Binary.php b/lib/internal/Magento/Framework/ObjectManager/Definition/Compiled/Binary.php deleted file mode 100644 index bba816e072e6b78072c0c1297dcc70935c42a1e9..0000000000000000000000000000000000000000 --- a/lib/internal/Magento/Framework/ObjectManager/Definition/Compiled/Binary.php +++ /dev/null @@ -1,27 +0,0 @@ -<?php -/** - * Igbinary serialized definition reader - * - * Copyright © 2016 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Framework\ObjectManager\Definition\Compiled; - -class Binary extends \Magento\Framework\ObjectManager\Definition\Compiled -{ - /** - * Mode name - */ - const MODE_NAME = 'igbinary'; - - /** - * Unpack signature - * - * @param string $signature - * @return mixed - */ - protected function _unpack($signature) - { - return igbinary_unserialize($signature); - } -} diff --git a/lib/internal/Magento/Framework/ObjectManager/Definition/Compiled/Serialized.php b/lib/internal/Magento/Framework/ObjectManager/Definition/Compiled/Serialized.php deleted file mode 100644 index a799725c390991676c4162384f69b4e4e8135933..0000000000000000000000000000000000000000 --- a/lib/internal/Magento/Framework/ObjectManager/Definition/Compiled/Serialized.php +++ /dev/null @@ -1,27 +0,0 @@ -<?php -/** - * Serialized definition reader - * - * Copyright © 2016 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Framework\ObjectManager\Definition\Compiled; - -class Serialized extends \Magento\Framework\ObjectManager\Definition\Compiled -{ - /** - * Mode name - */ - const MODE_NAME = 'serialized'; - - /** - * Unpack signature - * - * @param string $signature - * @return mixed - */ - protected function _unpack($signature) - { - return unserialize($signature); - } -} diff --git a/lib/internal/Magento/Framework/ObjectManager/DefinitionFactory.php b/lib/internal/Magento/Framework/ObjectManager/DefinitionFactory.php index 40959aa19669425dbcc0eec15df5cb1bafae6738..29431b570bc6416e2f180ab86efb37be292be893 100644 --- a/lib/internal/Magento/Framework/ObjectManager/DefinitionFactory.php +++ b/lib/internal/Magento/Framework/ObjectManager/DefinitionFactory.php @@ -1,41 +1,22 @@ <?php /** - * Object manager definition factory - * * Copyright © 2016 Magento. All rights reserved. * See COPYING.txt for license details. - * */ - -// @codingStandardsIgnoreFile - namespace Magento\Framework\ObjectManager; -use Magento\Framework\Api\Code\Generator\Mapper as MapperGenerator; -use Magento\Framework\Api\Code\Generator\SearchResults; use Magento\Framework\Filesystem\DriverInterface; use Magento\Framework\Interception\Code\Generator as InterceptionGenerator; -use Magento\Framework\ObjectManager\Code\Generator; -use Magento\Framework\ObjectManager\Code\Generator\Converter as ConverterGenerator; -use Magento\Framework\ObjectManager\Definition\Compiled\Binary; -use Magento\Framework\ObjectManager\Definition\Compiled\Serialized; use Magento\Framework\ObjectManager\Definition\Runtime; use Magento\Framework\ObjectManager\Profiler\Code\Generator as ProfilerGenerator; -use Magento\Framework\Api\Code\Generator\ExtensionAttributesGenerator; -use Magento\Framework\Api\Code\Generator\ExtensionAttributesInterfaceGenerator; +use Magento\Framework\Serialize\SerializerInterface; +use Magento\Framework\Code\Generator\Autoloader; /** * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class DefinitionFactory { - /** - * Directory containing compiled class metadata - * - * @var string - */ - protected $_definitionDir; - /** * Class generation dir * @@ -43,13 +24,6 @@ class DefinitionFactory */ protected $_generationDir; - /** - * Format of definitions - * - * @var string - */ - protected $_definitionFormat; - /** * Filesystem Driver * @@ -57,16 +31,6 @@ class DefinitionFactory */ protected $_filesystemDriver; - /** - * List of definition models - * - * @var array - */ - protected static $definitionClasses = [ - Binary::MODE_NAME => \Magento\Framework\ObjectManager\Definition\Compiled\Binary::class, - Serialized::MODE_NAME => \Magento\Framework\ObjectManager\Definition\Compiled\Serialized::class, - ]; - /** * @var \Magento\Framework\Code\Generator */ @@ -74,39 +38,26 @@ class DefinitionFactory /** * @param DriverInterface $filesystemDriver - * @param string $definitionDir * @param string $generationDir - * @param string $definitionFormat */ - public function __construct(DriverInterface $filesystemDriver, $definitionDir, $generationDir, $definitionFormat) - { + public function __construct( + DriverInterface $filesystemDriver, + $generationDir + ) { $this->_filesystemDriver = $filesystemDriver; - $this->_definitionDir = $definitionDir; $this->_generationDir = $generationDir; - $this->_definitionFormat = $definitionFormat; } /** * Create class definitions * - * @param mixed $definitions - * @return Runtime + * @return DefinitionInterface */ - public function createClassDefinition($definitions = false) + public function createClassDefinition() { - if ($definitions) { - if (is_string($definitions)) { - $definitions = $this->_unpack($definitions); - } - $definitionModel = self::$definitionClasses[$this->_definitionFormat]; - $result = new $definitionModel($definitions); - } else { - $autoloader = new \Magento\Framework\Code\Generator\Autoloader($this->getCodeGenerator()); - spl_autoload_register([$autoloader, 'load']); - - $result = new Runtime(); - } - return $result; + $autoloader = new Autoloader($this->getCodeGenerator()); + spl_autoload_register([$autoloader, 'load']); + return new Runtime(); } /** @@ -116,14 +67,7 @@ class DefinitionFactory */ public function createPluginDefinition() { - $path = $this->_definitionDir . '/plugins.ser'; - if ($this->_filesystemDriver->isReadable($path)) { - return new \Magento\Framework\Interception\Definition\Compiled( - $this->_unpack($this->_filesystemDriver->fileGetContents($path)) - ); - } else { - return new \Magento\Framework\Interception\Definition\Runtime(); - } + return new \Magento\Framework\Interception\Definition\Runtime(); } /** @@ -133,36 +77,7 @@ class DefinitionFactory */ public function createRelations() { - $path = $this->_definitionDir . '/' . 'relations.ser'; - if ($this->_filesystemDriver->isReadable($path)) { - return new \Magento\Framework\ObjectManager\Relations\Compiled( - $this->_unpack($this->_filesystemDriver->fileGetContents($path)) - ); - } else { - return new \Magento\Framework\ObjectManager\Relations\Runtime(); - } - } - - /** - * Gets supported definition formats - * - * @return array - */ - public static function getSupportedFormats() - { - return array_keys(self::$definitionClasses); - } - - /** - * Un-compress definitions - * - * @param string $definitions - * @return mixed - */ - protected function _unpack($definitions) - { - $extractor = $this->_definitionFormat == Binary::MODE_NAME ? 'igbinary_unserialize' : 'unserialize'; - return $extractor($definitions); + return new \Magento\Framework\ObjectManager\Relations\Runtime(); } /** diff --git a/lib/internal/Magento/Framework/ObjectManager/Relations/Compiled.php b/lib/internal/Magento/Framework/ObjectManager/Relations/Compiled.php deleted file mode 100644 index 71455dbf9acd49e7e7c6d93699934a89ede5827a..0000000000000000000000000000000000000000 --- a/lib/internal/Magento/Framework/ObjectManager/Relations/Compiled.php +++ /dev/null @@ -1,55 +0,0 @@ -<?php -/** - * List of parent classes with their parents and interfaces - * - * Copyright © 2016 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Framework\ObjectManager\Relations; - -class Compiled implements \Magento\Framework\ObjectManager\RelationsInterface -{ - /** - * List of class relations - * - * @var array - */ - protected $_relations; - - /** - * Default relation list - * - * @var array - */ - protected $_default = []; - - /** - * @param array $relations - */ - public function __construct(array $relations) - { - $this->_relations = $relations; - } - - /** - * Check whether requested type is available for read - * - * @param string $type - * @return bool - */ - public function has($type) - { - return isset($this->_relations[$type]); - } - - /** - * Retrieve parents for class - * - * @param string $type - * @return array - */ - public function getParents($type) - { - return $this->_relations[$type]; - } -} diff --git a/lib/internal/Magento/Framework/ObjectManager/Test/Unit/Config/CompiledTest.php b/lib/internal/Magento/Framework/ObjectManager/Test/Unit/Config/CompiledTest.php index 1fcf3176540db6279e3fec6754fb3a7a22b3cc59..489dc9d814e1183432e174601b9a650bd0690eea 100644 --- a/lib/internal/Magento/Framework/ObjectManager/Test/Unit/Config/CompiledTest.php +++ b/lib/internal/Magento/Framework/ObjectManager/Test/Unit/Config/CompiledTest.php @@ -5,87 +5,93 @@ */ namespace Magento\Framework\ObjectManager\Test\Unit\Config; -use Magento\Framework\ObjectManager\Config\Compiled as CompiledConfig; -use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper; +use Magento\Framework\ObjectManager\Config\Compiled; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManager; +use Magento\Framework\Serialize\SerializerInterface; class CompiledTest extends \PHPUnit_Framework_TestCase { /** - * @var ObjectManagerHelper + * @var ObjectManager */ - private $objectManagerHelper; - - protected function setUp() - { - $this->objectManagerHelper = new ObjectManagerHelper($this); - } + private $objectManager; /** - * @param array $initialData - * @param array $configuration - * @param array $expectedArguments - * @param array $expectedVirtualTypes - * @param array $expectedPreferences - * - * @dataProvider extendDataProvider + * @var SerializerInterface|\PHPUnit_Framework_MockObject_MockObject */ - public function testExtend( - array $initialData, - array $configuration, - array $expectedArguments, - array $expectedVirtualTypes, - array $expectedPreferences - ) { - /** @var CompiledConfig $compiledConfig */ - $compiledConfig = $this->objectManagerHelper->getObject(CompiledConfig::class, ['data' => $initialData]); - $compiledConfig->extend($configuration); + private $serializerMock; - foreach ($expectedArguments as $type => $arguments) { - $this->assertEquals($arguments, $compiledConfig->getArguments($type)); - } - - $this->assertEquals($expectedVirtualTypes, $compiledConfig->getVirtualTypes()); - $this->assertEquals($expectedPreferences, $compiledConfig->getPreferences()); + protected function setUp() + { + $this->objectManager = new ObjectManager($this); + $this->serializerMock = $this->getMock(SerializerInterface::class); } - /** - * @return array - */ - public function extendDataProvider() + public function testExtend() { - return [ - [ - 'initialData' => [ - 'arguments' => [ - 'type1' => serialize(['argument1_1' => 'argumentValue1_1', 'argument1_2' => 'argumentValue1_2']) - ], - 'instanceTypes' => [ - 'instanceType1' => 'instanceTypeValue1', 'instanceType2' => 'instanceTypeValue2' - ], - 'preferences' => ['preference1' => 'preferenceValue1', 'preference2' => 'preferenceValue2'] - ], - 'configuration' => [ - 'arguments' => [ - 'type1' => serialize(['argument1_1' => 'newArgumentValue1_1']), - 'type2' => serialize(['argument2_1' => 'newArgumentValue2_1']) - ], - 'instanceTypes' => [ - 'instanceType2' => 'newInstanceTypeValue2', 'instanceType3' => 'newInstanceTypeValue3' - ], - 'preferences' => ['preference1' => 'newPreferenceValue1'] - ], - 'expectedArguments' => [ - 'type1' => ['argument1_1' => 'newArgumentValue1_1'], - 'type2' => ['argument2_1' => 'newArgumentValue2_1'] - ], - 'expectedVirtualTypes' => [ - 'instanceType1' => 'instanceTypeValue1', 'instanceType2' => 'newInstanceTypeValue2', - 'instanceType3' => 'newInstanceTypeValue3' - ], - 'expectedPreferences' => [ - 'preference1' => 'newPreferenceValue1', 'preference2' => 'preferenceValue2' - ] + $initialData = [ + 'arguments' => [ + 'type1' => 'initial serialized configuration for type1' + ], + 'instanceTypes' => [ + 'instanceType1' => 'instanceTypeValue1', + 'instanceType2' => 'instanceTypeValue2' + ], + 'preferences' => [ + 'preference1' => 'preferenceValue1', + 'preference2' => 'preferenceValue2' + ] + ]; + $configuration = [ + 'arguments' => [ + 'type1' => 'serialized configuration for type1', + 'type2' => 'serialized configuration for type2' + ], + 'instanceTypes' => [ + 'instanceType2' => 'newInstanceTypeValue2', + 'instanceType3' => 'newInstanceTypeValue3' + ], + 'preferences' => [ + 'preference1' => 'newPreferenceValue1' ] ]; + $expectedArguments = [ + 'type1' => [ + 'argument1_1' => 'newArgumentValue1_1' + ], + 'type2' => [ + 'argument2_1' => 'newArgumentValue2_1' + ] + ]; + $expectedVirtualTypes = [ + 'instanceType1' => 'instanceTypeValue1', + 'instanceType2' => 'newInstanceTypeValue2', + 'instanceType3' => 'newInstanceTypeValue3' + ]; + $expectedPreferences = [ + 'preference1' => 'newPreferenceValue1', + 'preference2' => 'preferenceValue2' + ]; + $this->serializerMock->expects($this->at(0)) + ->method('unserialize') + ->with($configuration['arguments']['type1']) + ->willReturn($expectedArguments['type1']); + $this->serializerMock->expects($this->at(1)) + ->method('unserialize') + ->with($configuration['arguments']['type2']) + ->willReturn($expectedArguments['type2']); + $compiled = $this->objectManager->getObject( + Compiled::class, + [ + 'data' => $initialData, + 'serializer' => $this->serializerMock + ] + ); + $compiled->extend($configuration); + foreach ($expectedArguments as $type => $arguments) { + $this->assertEquals($arguments, $compiled->getArguments($type)); + } + $this->assertEquals($expectedVirtualTypes, $compiled->getVirtualTypes()); + $this->assertEquals($expectedPreferences, $compiled->getPreferences()); } } diff --git a/lib/internal/Magento/Framework/ObjectManager/Test/Unit/Config/ConfigTest.php b/lib/internal/Magento/Framework/ObjectManager/Test/Unit/Config/ConfigTest.php index 844d5fa94a62728e7f1bbbce850affd764214021..4cc51652fdb74454fde50182a3062b53b5616dc5 100644 --- a/lib/internal/Magento/Framework/ObjectManager/Test/Unit/Config/ConfigTest.php +++ b/lib/internal/Magento/Framework/ObjectManager/Test/Unit/Config/ConfigTest.php @@ -5,10 +5,19 @@ */ namespace Magento\Framework\ObjectManager\Test\Unit\Config; +use Magento\Framework\Serialize\SerializerInterface; use \Magento\Framework\ObjectManager\Config\Config; class ConfigTest extends \PHPUnit_Framework_TestCase { + /** @var \Magento\Framework\TestFramework\Unit\Helper\ObjectManager */ + private $objectManagerHelper; + + protected function setUp() + { + $this->objectManagerHelper = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); + } + public function testGetArgumentsEmpty() { $config = new Config(); @@ -42,6 +51,14 @@ class ConfigTest extends \PHPUnit_Framework_TestCase $cache->expects($this->once())->method('get')->will($this->returnValue(false)); $config = new Config(null, $definitions); + $serializerMock = $this->getMock(SerializerInterface::class); + $serializerMock->expects($this->exactly(2)) + ->method('serialize'); + $this->objectManagerHelper->setBackwardCompatibleProperty( + $config, + 'serializer', + $serializerMock + ); $config->setCache($cache); $this->_assertFooTypeArguments($config); diff --git a/lib/internal/Magento/Framework/ObjectManager/Test/Unit/Definition/Compiled/BinaryTest.php b/lib/internal/Magento/Framework/ObjectManager/Test/Unit/Definition/Compiled/BinaryTest.php deleted file mode 100644 index 80cf73a44e7ac694a58646bb902690d9d00ab012..0000000000000000000000000000000000000000 --- a/lib/internal/Magento/Framework/ObjectManager/Test/Unit/Definition/Compiled/BinaryTest.php +++ /dev/null @@ -1,21 +0,0 @@ -<?php -/** - * Copyright © 2016 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Framework\ObjectManager\Test\Unit\Definition\Compiled; - -class BinaryTest extends \PHPUnit_Framework_TestCase -{ - public function testGetParametersWithUnpacking() - { - if (!function_exists('igbinary_serialize')) { - $this->markTestSkipped('This test requires igbinary PHP extension'); - } - $checkString = 'packed code'; - $signatures = ['wonderfulClass' => igbinary_serialize($checkString)]; - $definitions = ['wonderful' => 'wonderfulClass']; - $model = new \Magento\Framework\ObjectManager\Definition\Compiled\Binary([$signatures, $definitions]); - $this->assertEquals($checkString, $model->getParameters('wonderful')); - } -} diff --git a/lib/internal/Magento/Framework/ObjectManager/Test/Unit/Definition/Compiled/SerializedTest.php b/lib/internal/Magento/Framework/ObjectManager/Test/Unit/Definition/Compiled/SerializedTest.php deleted file mode 100644 index 9454377c3b7207dbfc355f022e1faedb75b61a52..0000000000000000000000000000000000000000 --- a/lib/internal/Magento/Framework/ObjectManager/Test/Unit/Definition/Compiled/SerializedTest.php +++ /dev/null @@ -1,35 +0,0 @@ -<?php -/** - * Copyright © 2016 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Framework\ObjectManager\Test\Unit\Definition\Compiled; - -class SerializedTest extends \PHPUnit_Framework_TestCase -{ - public function testGetParametersWithoutDefinition() - { - $signatures = []; - $definitions = ['wonderful' => null]; - $model = new \Magento\Framework\ObjectManager\Definition\Compiled\Serialized([$signatures, $definitions]); - $this->assertEquals(null, $model->getParameters('wonderful')); - } - - public function testGetParametersWithSignatureObject() - { - $wonderfulSignature = new \stdClass(); - $signatures = ['wonderfulClass' => $wonderfulSignature]; - $definitions = ['wonderful' => 'wonderfulClass']; - $model = new \Magento\Framework\ObjectManager\Definition\Compiled\Serialized([$signatures, $definitions]); - $this->assertEquals($wonderfulSignature, $model->getParameters('wonderful')); - } - - public function testGetParametersWithUnpacking() - { - $checkString = 'code to pack'; - $signatures = ['wonderfulClass' => serialize($checkString)]; - $definitions = ['wonderful' => 'wonderfulClass']; - $model = new \Magento\Framework\ObjectManager\Definition\Compiled\Serialized([$signatures, $definitions]); - $this->assertEquals($checkString, $model->getParameters('wonderful')); - } -} diff --git a/lib/internal/Magento/Framework/ObjectManager/Test/Unit/Definition/CompiledStub.php b/lib/internal/Magento/Framework/ObjectManager/Test/Unit/Definition/CompiledStub.php deleted file mode 100644 index 16b8436a0c41aa7bf6506d34e61b58827032d5c1..0000000000000000000000000000000000000000 --- a/lib/internal/Magento/Framework/ObjectManager/Test/Unit/Definition/CompiledStub.php +++ /dev/null @@ -1,25 +0,0 @@ -<?php -/** - * Copyright © 2016 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Framework\ObjectManager\Test\Unit\Definition; - -use \Magento\Framework\ObjectManager\Definition\Compiled; - -/** - * Stub class for abstract Magento\Framework\ObjectManager\DefinitionInterface - */ -class CompiledStub extends Compiled -{ - /** - * Unpack signature - * - * @param string $signature - * @return mixed - */ - protected function _unpack($signature) - { - return unserialize($signature); - } -} diff --git a/lib/internal/Magento/Framework/ObjectManager/Test/Unit/Definition/CompiledTest.php b/lib/internal/Magento/Framework/ObjectManager/Test/Unit/Definition/CompiledTest.php deleted file mode 100644 index 0e7c79e8571d2686f561df97ed6832d93768d2fa..0000000000000000000000000000000000000000 --- a/lib/internal/Magento/Framework/ObjectManager/Test/Unit/Definition/CompiledTest.php +++ /dev/null @@ -1,37 +0,0 @@ -<?php -/** - * Copyright © 2016 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Framework\ObjectManager\Test\Unit\Definition; - -use \Magento\Framework\ObjectManager\Definition\Compiled; - -class CompiledTest extends \PHPUnit_Framework_TestCase -{ - public function testGetParametersWithUndefinedDefinition() - { - $objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); - $undefinedDefinitionSignature = new \stdClass(); - $className = 'undefinedDefinition'; - $readerMock = $this->getMock( - \Magento\Framework\Code\Reader\ClassReader::class, - ['getConstructor'], - [], - '', - false - ); - $readerMock->expects($this->once()) - ->method('getConstructor') - ->with($className) - ->willReturn($undefinedDefinitionSignature); - $model = $objectManager->getObject( - \Magento\Framework\ObjectManager\Test\Unit\Definition\CompiledStub::class, - [ - 'definitions' => [[], []], - 'reader' => $readerMock - ] - ); - $this->assertEquals($undefinedDefinitionSignature, $model->getParameters($className)); - } -} diff --git a/lib/internal/Magento/Framework/ObjectManager/Test/Unit/DefinitionFactoryTest.php b/lib/internal/Magento/Framework/ObjectManager/Test/Unit/DefinitionFactoryTest.php index 468e01ce80aba618d1b7447b3ca2a720c52cbe85..8c587cec4351ce1156f4043af8d16e7d827895d4 100644 --- a/lib/internal/Magento/Framework/ObjectManager/Test/Unit/DefinitionFactoryTest.php +++ b/lib/internal/Magento/Framework/ObjectManager/Test/Unit/DefinitionFactoryTest.php @@ -3,119 +3,56 @@ * Copyright © 2016 Magento. All rights reserved. * See COPYING.txt for license details. */ - namespace Magento\Framework\ObjectManager\Test\Unit; -use Magento\Framework\ObjectManager\Definition\Compiled\Serialized; +use Magento\Framework\Filesystem\Driver\File; +use Magento\Framework\ObjectManager\DefinitionFactory; +use Magento\Framework\ObjectManager\DefinitionInterface; +use Magento\Framework\Interception\DefinitionInterface as InterceptionDefinitionInterface; +use Magento\Framework\ObjectManager\RelationsInterface; class DefinitionFactoryTest extends \PHPUnit_Framework_TestCase { /** - * @var \Magento\Framework\Filesystem\DriverInterface | \PHPUnit_Framework_MockObject_MockObject - */ - protected $filesystemDriverMock; - - /** - * @var \Magento\Framework\ObjectManager\DefinitionFactory + * @var File|\PHPUnit_Framework_MockObject_MockObject */ - protected $model; + private $filesystemDriverMock; /** - * @var string + * @var DefinitionFactory */ - protected $sampleContent; + private $definitionFactory; protected function setUp() { - $this->sampleContent = serialize([1, 2, 3]); - $this->filesystemDriverMock = $this->getMock( - \Magento\Framework\Filesystem\Driver\File::class, - [], - [], - '', - false - ); - $this->model = new \Magento\Framework\ObjectManager\DefinitionFactory( + $this->filesystemDriverMock = $this->getMock(File::class); + $this->definitionFactory = new DefinitionFactory( $this->filesystemDriverMock, - 'DefinitionDir', - 'GenerationDir', - Serialized::MODE_NAME + 'generation dir' ); } - public function testCreateClassDefinitionFromString() + public function testCreateClassDefinition() { $this->assertInstanceOf( - \Magento\Framework\ObjectManager\Definition\Compiled\Serialized::class, - $this->model->createClassDefinition($this->sampleContent) + DefinitionInterface::class, + $this->definitionFactory->createClassDefinition() ); } - /** - * @param string $path - * @param string $callMethod - * @param string $expectedClass - * @dataProvider createPluginsAndRelationsReadableDataProvider - */ - public function testCreatePluginsAndRelationsReadable($path, $callMethod, $expectedClass) - { - $this->filesystemDriverMock->expects($this->once())->method('isReadable') - ->with($path) - ->will($this->returnValue(true)); - $this->filesystemDriverMock->expects($this->once())->method('fileGetContents') - ->with($path) - ->will($this->returnValue($this->sampleContent)); - $this->assertInstanceOf($expectedClass, $this->model->$callMethod()); - } - - public function createPluginsAndRelationsReadableDataProvider() - { - return [ - 'relations' => [ - 'DefinitionDir/relations.ser', - 'createRelations', \Magento\Framework\ObjectManager\Relations\Compiled::class, - ], - 'plugins' => [ - 'DefinitionDir/plugins.ser', - 'createPluginDefinition', \Magento\Framework\Interception\Definition\Compiled::class, - ], - ]; - } - - /** - * @param string $path - * @param string $callMethod - * @param string $expectedClass - * @dataProvider createPluginsAndRelationsNotReadableDataProvider - */ - public function testCreatePluginsAndRelationsNotReadable($path, $callMethod, $expectedClass) + public function testCreatePluginDefinition() { - $this->filesystemDriverMock->expects($this->once())->method('isReadable') - ->with($path) - ->will($this->returnValue(false)); - $this->assertInstanceOf($expectedClass, $this->model->$callMethod()); - } - - public function createPluginsAndRelationsNotReadableDataProvider() - { - return [ - 'relations' => [ - 'DefinitionDir/relations.ser', - 'createRelations', \Magento\Framework\ObjectManager\Relations\Runtime::class, - ], - 'plugins' => [ - 'DefinitionDir/plugins.ser', - 'createPluginDefinition', \Magento\Framework\Interception\Definition\Runtime::class, - ], - ]; + $this->assertInstanceOf( + InterceptionDefinitionInterface::class, + $this->definitionFactory->createPluginDefinition() + ); } - public function testGetSupportedFormats() + public function testCreateRelations() { - $actual = \Magento\Framework\ObjectManager\DefinitionFactory::getSupportedFormats(); - $this->assertInternalType('array', $actual); - foreach ($actual as $className) { - $this->assertInternalType('string', $className); - } + $this->assertInstanceOf( + RelationsInterface::class, + $this->definitionFactory->createRelations() + ); } } diff --git a/lib/internal/Magento/Framework/ObjectManager/Test/Unit/Relations/CompiledTest.php b/lib/internal/Magento/Framework/ObjectManager/Test/Unit/Relations/CompiledTest.php deleted file mode 100644 index 336a798df100e156895ea5cd20768650909b2722..0000000000000000000000000000000000000000 --- a/lib/internal/Magento/Framework/ObjectManager/Test/Unit/Relations/CompiledTest.php +++ /dev/null @@ -1,27 +0,0 @@ -<?php -/** - * Copyright © 2016 Magento. All rights reserved. - * See COPYING.txt for license details. - */ - -namespace Magento\Framework\ObjectManager\Test\Unit\Relations; - -class CompiledTest extends \PHPUnit_Framework_TestCase -{ - public function testHas() - { - $relations = ['amazing' => 'yes']; - - $model = new \Magento\Framework\ObjectManager\Relations\Compiled($relations); - $this->assertEquals(true, $model->has('amazing')); - $this->assertEquals(false, $model->has('fuzzy')); - } - - public function testGetParents() - { - $relations = ['amazing' => 'parents']; - - $model = new \Magento\Framework\ObjectManager\Relations\Compiled($relations); - $this->assertEquals('parents', $model->getParents('amazing')); - } -} diff --git a/lib/internal/Magento/Framework/Reflection/MethodsMap.php b/lib/internal/Magento/Framework/Reflection/MethodsMap.php index f7f402ae4b8a00c905e65678105f8461922d8571..c7a9183a78ee5e903355b06507402744349f83fc 100644 --- a/lib/internal/Magento/Framework/Reflection/MethodsMap.php +++ b/lib/internal/Magento/Framework/Reflection/MethodsMap.php @@ -6,6 +6,7 @@ namespace Magento\Framework\Reflection; +use Magento\Framework\Serialize\SerializerInterface; use Zend\Code\Reflection\ClassReflection; use Zend\Code\Reflection\MethodReflection; use Zend\Code\Reflection\ParameterReflection; @@ -45,6 +46,11 @@ class MethodsMap */ private $fieldNamer; + /** + * @var \Magento\Framework\Serialize\SerializerInterface + */ + private $serializer; + /** * @param \Magento\Framework\Cache\FrontendInterface $cache * @param TypeProcessor $typeProcessor @@ -95,11 +101,11 @@ class MethodsMap if (!isset($this->serviceInterfaceMethodsMap[$key])) { $methodMap = $this->cache->load($key); if ($methodMap) { - $this->serviceInterfaceMethodsMap[$key] = unserialize($methodMap); + $this->serviceInterfaceMethodsMap[$key] = $this->getSerializer()->unserialize($methodMap); } else { $methodMap = $this->getMethodMapViaReflection($interfaceName); $this->serviceInterfaceMethodsMap[$key] = $methodMap; - $this->cache->save(serialize($this->serviceInterfaceMethodsMap[$key]), $key); + $this->cache->save($this->getSerializer()->serialize($this->serviceInterfaceMethodsMap[$key]), $key); } } return $this->serviceInterfaceMethodsMap[$key]; @@ -117,7 +123,7 @@ class MethodsMap $cacheId = self::SERVICE_METHOD_PARAMS_CACHE_PREFIX . hash('md5', $serviceClassName . $serviceMethodName); $params = $this->cache->load($cacheId); if ($params !== false) { - return unserialize($params); + return $this->getSerializer()->unserialize($params); } $serviceClass = new ClassReflection($serviceClassName); /** @var MethodReflection $serviceMethod */ @@ -133,7 +139,7 @@ class MethodsMap self::METHOD_META_DEFAULT_VALUE => $isDefaultValueAvailable ? $paramReflection->getDefaultValue() : null ]; } - $this->cache->save(serialize($params), $cacheId, [ReflectionCache::CACHE_TAG]); + $this->cache->save($this->getSerializer()->serialize($params), $cacheId, [ReflectionCache::CACHE_TAG]); return $params; } @@ -217,4 +223,19 @@ class MethodsMap $methods = $this->getMethodsMap($type); return $methods[$methodName]['isRequired']; } + + /** + * Get serializer + * + * @return \Magento\Framework\Serialize\SerializerInterface + * @deprecated + */ + private function getSerializer() + { + if ($this->serializer === null) { + $this->serializer = \Magento\Framework\App\ObjectManager::getInstance() + ->get(SerializerInterface::class); + } + return $this->serializer; + } } diff --git a/lib/internal/Magento/Framework/Reflection/Test/Unit/MethodsMapTest.php b/lib/internal/Magento/Framework/Reflection/Test/Unit/MethodsMapTest.php index 6f4dc37b8faff83791030ddbdee16e80a1fdfb02..67a372c4d33ca754d7d35e9005730c55a55e4a19 100644 --- a/lib/internal/Magento/Framework/Reflection/Test/Unit/MethodsMapTest.php +++ b/lib/internal/Magento/Framework/Reflection/Test/Unit/MethodsMapTest.php @@ -6,9 +6,9 @@ namespace Magento\Framework\Reflection\Test\Unit; +use Magento\Framework\Serialize\SerializerInterface; use Magento\Framework\Reflection\MethodsMap; use Magento\Framework\Reflection\TypeProcessor; -use Magento\Framework\Reflection\FieldNamer; /** * MethodsMap test @@ -18,7 +18,10 @@ class MethodsMapTest extends \PHPUnit_Framework_TestCase /** * @var MethodsMap */ - private $model; + private $object; + + /** @var SerializerInterface|\PHPUnit_Framework_MockObject_MockObject */ + private $serializerMock; /** * Set up helper. @@ -39,7 +42,7 @@ class MethodsMapTest extends \PHPUnit_Framework_TestCase ->getMockForAbstractClass(); $fieldNamerMock = $this->getMockBuilder(\Magento\Framework\Reflection\FieldNamer::class) ->getMockForAbstractClass(); - $this->model = $objectManager->getObject( + $this->object = $objectManager->getObject( \Magento\Framework\Reflection\MethodsMap::class, [ 'cache' => $cacheMock, @@ -48,27 +51,33 @@ class MethodsMapTest extends \PHPUnit_Framework_TestCase 'fieldNamer' => $fieldNamerMock, ] ); + $this->serializerMock = $this->getMock(SerializerInterface::class); + $objectManager->setBackwardCompatibleProperty( + $this->object, + 'serializer', + $this->serializerMock + ); } public function testGetMethodReturnType() { $this->assertEquals( 'string', - $this->model->getMethodReturnType( + $this->object->getMethodReturnType( \Magento\Framework\Reflection\FieldNamer::class, 'getFieldNameForMethodName' ) ); $this->assertEquals( 'mixed', - $this->model->getMethodReturnType( + $this->object->getMethodReturnType( \Magento\Framework\Reflection\TypeCaster::class, 'castValueToType' ) ); $this->assertEquals( 'array', - $this->model->getMethodReturnType( + $this->object->getMethodReturnType( \Magento\Framework\Reflection\MethodsMap::class, 'getMethodsMap' ) @@ -77,42 +86,46 @@ class MethodsMapTest extends \PHPUnit_Framework_TestCase public function testGetMethodsMap() { - $methodsMap = $this->model->getMethodsMap(\Magento\Framework\Reflection\MethodsMap::class); - $this->assertEquals( - [ - 'getMethodReturnType' => [ - 'type' => 'string', - 'isRequired' => true, - 'description' => null, - 'parameterCount' => 2, - ], - 'getMethodsMap' => [ - 'type' => 'array', - 'isRequired' => true, - 'description' => "<pre> Service methods' reflection data stored in cache as 'methodName' => " - . "'returnType' ex. [ 'create' => '\Magento\Customer\Api\Data\Customer', 'validatePassword' " - . "=> 'boolean' ] </pre>", - 'parameterCount' => 1, - ], - 'getMethodParams' => [ - 'type' => 'array', - 'isRequired' => true, - 'description' => null, - 'parameterCount' => 2 - ], - 'isMethodValidForDataField' => [ - 'type' => 'bool', - 'isRequired' => true, - 'description' => null, - 'parameterCount' => 2, - ], - 'isMethodReturnValueRequired' => [ - 'type' => 'bool', - 'isRequired' => true, - 'description' => null, - 'parameterCount' => 2, - ], + $data = [ + 'getMethodReturnType' => [ + 'type' => 'string', + 'isRequired' => true, + 'description' => null, + 'parameterCount' => 2, + ], + 'getMethodsMap' => [ + 'type' => 'array', + 'isRequired' => true, + 'description' => "<pre> Service methods' reflection data stored in cache as 'methodName' => " + . "'returnType' ex. [ 'create' => '\Magento\Customer\Api\Data\Customer', 'validatePassword' " + . "=> 'boolean' ] </pre>", + 'parameterCount' => 1, ], + 'getMethodParams' => [ + 'type' => 'array', + 'isRequired' => true, + 'description' => null, + 'parameterCount' => 2 + ], + 'isMethodValidForDataField' => [ + 'type' => 'bool', + 'isRequired' => true, + 'description' => null, + 'parameterCount' => 2, + ], + 'isMethodReturnValueRequired' => [ + 'type' => 'bool', + 'isRequired' => true, + 'description' => null, + 'parameterCount' => 2, + ], + ]; + $this->serializerMock->expects($this->once()) + ->method('serialize') + ->with($data); + $methodsMap = $this->object->getMethodsMap(\Magento\Framework\Reflection\MethodsMap::class); + $this->assertEquals( + $data, $methodsMap ); } @@ -125,7 +138,7 @@ class MethodsMapTest extends \PHPUnit_Framework_TestCase */ public function testIsMethodValidForDataField($type, $methodName, $expectedResult) { - $this->assertEquals($this->model->isMethodValidForDataField($type, $methodName), $expectedResult); + $this->assertEquals($this->object->isMethodValidForDataField($type, $methodName), $expectedResult); } /** @@ -157,7 +170,7 @@ class MethodsMapTest extends \PHPUnit_Framework_TestCase */ public function testIsMethodReturnValueRequired($type, $methodName, $expectedResult) { - $this->assertEquals($this->model->isMethodValidForDataField($type, $methodName), $expectedResult); + $this->assertEquals($this->object->isMethodValidForDataField($type, $methodName), $expectedResult); } /** diff --git a/lib/internal/Magento/Framework/Search/Request/Config.php b/lib/internal/Magento/Framework/Search/Request/Config.php index b348f214dd4c2f1496224651854a2aad16264186..80a963af39b41e0ca6327383dcff1c50132510d0 100644 --- a/lib/internal/Magento/Framework/Search/Request/Config.php +++ b/lib/internal/Magento/Framework/Search/Request/Config.php @@ -5,21 +5,32 @@ */ namespace Magento\Framework\Search\Request; +use Magento\Framework\Serialize\SerializerInterface; + +/** + * Provides search request configuration + */ class Config extends \Magento\Framework\Config\Data { - /** Cache ID for Search Request*/ + /** + * Cache identifier + */ const CACHE_ID = 'request_declaration'; /** + * Constructor + * * @param \Magento\Framework\Search\Request\Config\FilesystemReader $reader * @param \Magento\Framework\Config\CacheInterface $cache - * @param string $cacheId + * @param string|null $cacheId + * @param SerializerInterface|null $serializer */ public function __construct( \Magento\Framework\Search\Request\Config\FilesystemReader $reader, \Magento\Framework\Config\CacheInterface $cache, - $cacheId = self::CACHE_ID + $cacheId = self::CACHE_ID, + SerializerInterface $serializer = null ) { - parent::__construct($reader, $cache, $cacheId); + parent::__construct($reader, $cache, $cacheId, $serializer); } } diff --git a/lib/internal/Magento/Framework/Test/Unit/TranslateTest.php b/lib/internal/Magento/Framework/Test/Unit/TranslateTest.php index 8d1692dd9cdc147bc76d0fa425cba4436e31ef5e..a8199768a365f5b638124b428ae6338ea9864cd3 100644 --- a/lib/internal/Magento/Framework/Test/Unit/TranslateTest.php +++ b/lib/internal/Magento/Framework/Test/Unit/TranslateTest.php @@ -5,6 +5,7 @@ */ namespace Magento\Framework\Test\Unit; +use Magento\Framework\Serialize\SerializerInterface; use \Magento\Framework\Translate; /** @@ -59,6 +60,7 @@ class TranslateTest extends \PHPUnit_Framework_TestCase protected function setUp() { + $objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); $this->viewDesign = $this->getMock(\Magento\Framework\View\DesignInterface::class, [], [], '', false); $this->cache = $this->getMock(\Magento\Framework\Cache\FrontendInterface::class, [], [], '', false); $this->viewFileSystem = $this->getMock(\Magento\Framework\View\FileSystem::class, [], [], '', false); @@ -104,6 +106,21 @@ class TranslateTest extends \PHPUnit_Framework_TestCase $this->csvParser, $this->packDictionary ); + + $serializerMock = $this->getMock(SerializerInterface::class); + $serializerMock->method('serialize') + ->willReturnCallback(function ($data) { + return json_encode($data); + }); + $serializerMock->method('unserialize') + ->willReturnCallback(function ($string) { + return json_decode($string, true); + }); + $objectManager->setBackwardCompatibleProperty( + $this->translate, + 'serializer', + $serializerMock + ); } /** @@ -119,7 +136,7 @@ class TranslateTest extends \PHPUnit_Framework_TestCase $this->cache->expects($this->exactly($forceReload ? 0 : 1)) ->method('load') - ->will($this->returnValue(serialize($cachedData))); + ->will($this->returnValue(json_encode($cachedData))); if (!$forceReload && $cachedData !== false) { $this->translate->loadData($area, $forceReload); @@ -222,7 +239,7 @@ class TranslateTest extends \PHPUnit_Framework_TestCase { $this->cache->expects($this->once()) ->method('load') - ->will($this->returnValue(serialize($data))); + ->will($this->returnValue(json_encode($data))); $this->expectsSetConfig('themeId'); $this->translate->loadData('frontend'); $this->assertEquals($result, $this->translate->getData()); diff --git a/lib/internal/Magento/Framework/Translate.php b/lib/internal/Magento/Framework/Translate.php index 36f693270f42f6f8e4ceda68e13cb45bde426c42..c5571ab0b8edb282ba164e5ec36f9a3b9e2c9f96 100644 --- a/lib/internal/Magento/Framework/Translate.php +++ b/lib/internal/Magento/Framework/Translate.php @@ -108,6 +108,11 @@ class Translate implements \Magento\Framework\TranslateInterface */ protected $packDictionary; + /** + * @var \Magento\Framework\Serialize\SerializerInterface + */ + private $serializer; + /** * @param \Magento\Framework\View\DesignInterface $viewDesign * @param \Magento\Framework\Cache\FrontendInterface $cache @@ -474,7 +479,7 @@ class Translate implements \Magento\Framework\TranslateInterface { $data = $this->_cache->load($this->getCacheId()); if ($data) { - $data = unserialize($data); + $data = $this->getSerializer()->unserialize($data); } return $data; } @@ -486,7 +491,22 @@ class Translate implements \Magento\Framework\TranslateInterface */ protected function _saveCache() { - $this->_cache->save(serialize($this->getData()), $this->getCacheId(true), [], false); + $this->_cache->save($this->getSerializer()->serialize($this->getData()), $this->getCacheId(true), [], false); return $this; } + + /** + * Get serializer + * + * @return \Magento\Framework\Serialize\SerializerInterface + * @deprecated + */ + private function getSerializer() + { + if ($this->serializer === null) { + $this->serializer = \Magento\Framework\App\ObjectManager::getInstance() + ->get(Serialize\SerializerInterface::class); + } + return $this->serializer; + } } diff --git a/lib/internal/Magento/Framework/Unserialize/README.md b/lib/internal/Magento/Framework/Unserialize/README.md index 971bd6980abb136c2246e4618a8776be8bdaa16d..2dbf7436aa60fbc23b378102418ef4dbc8634e85 100644 --- a/lib/internal/Magento/Framework/Unserialize/README.md +++ b/lib/internal/Magento/Framework/Unserialize/README.md @@ -1,2 +1 @@ -Library provides custom unserialize method. Method checks if serialized string contains serialized object and do not -unserialize it. If string doesn't contain serialized object, method calls native PHP function unserialize. \ No newline at end of file +This library is deprecated, please use Magento\Framework\Serialize\SerializerInterface instead. \ No newline at end of file diff --git a/lib/internal/Magento/Framework/Unserialize/Unserialize.php b/lib/internal/Magento/Framework/Unserialize/Unserialize.php index 9d4785915a6dd6b8e3a03b7108fecb21b3b4712a..cfd3e81ca6b0942c879f24994feeb391e3e4cf0b 100644 --- a/lib/internal/Magento/Framework/Unserialize/Unserialize.php +++ b/lib/internal/Magento/Framework/Unserialize/Unserialize.php @@ -6,6 +6,9 @@ namespace Magento\Framework\Unserialize; +/** + * @deprecated + */ class Unserialize { /** diff --git a/lib/internal/Magento/Framework/Validator/Factory.php b/lib/internal/Magento/Framework/Validator/Factory.php index d2e3837d131382becdf07413b373a944bea75f4e..76633f48dfe0b96fcbe473aa579817339173685e 100644 --- a/lib/internal/Magento/Framework/Validator/Factory.php +++ b/lib/internal/Magento/Framework/Validator/Factory.php @@ -1,20 +1,20 @@ <?php /** - * Magento validator config factory - * * Copyright © 2016 Magento. All rights reserved. * See COPYING.txt for license details. */ - -// @codingStandardsIgnoreFile - namespace Magento\Framework\Validator; use Magento\Framework\Cache\FrontendInterface; +/** + * @codingStandardsIgnoreFile + */ class Factory { - /** cache key */ + /** + * Cache key + */ const CACHE_KEY = __CLASS__; /** @@ -44,6 +44,16 @@ class Factory */ private $cache; + /** + * @var \Magento\Framework\Serialize\SerializerInterface + */ + private $serializer; + + /** + * @var \Magento\Framework\Config\FileIteratorFactory + */ + private $fileIteratorFactory; + /** * Initialize dependencies * @@ -70,9 +80,10 @@ class Factory $this->_configFiles = $this->cache->load(self::CACHE_KEY); if (!$this->_configFiles) { $this->_configFiles = $this->moduleReader->getConfigurationFiles('validation.xml'); - $this->cache->save(serialize($this->_configFiles), self::CACHE_KEY); + $this->cache->save($this->getSerializer()->serialize($this->_configFiles->toArray()), self::CACHE_KEY); } else { - $this->_configFiles = unserialize($this->_configFiles); + $filesArray = $this->getSerializer()->unserialize($this->_configFiles); + $this->_configFiles = $this->getFileIteratorFactory()->create(array_keys($filesArray)); } } } @@ -109,7 +120,7 @@ class Factory { $this->_initializeConfigList(); $this->_initializeDefaultTranslator(); - return $this->_objectManager->create( + return $this->_objectManager->create( \Magento\Framework\Validator\Config::class, ['configFiles' => $this->_configFiles]); } @@ -140,4 +151,33 @@ class Factory $this->_initializeDefaultTranslator(); return $this->getValidatorConfig()->createValidator($entityName, $groupName, $builderConfig); } + + /** + * Get serializer + * + * @return \Magento\Framework\Serialize\SerializerInterface + * @deprecated + */ + private function getSerializer() + { + if ($this->serializer === null) { + $this->serializer = $this->_objectManager->get(\Magento\Framework\Serialize\SerializerInterface::class); + } + return $this->serializer; + } + + /** + * Get file iterator factory + * + * @return \Magento\Framework\Config\FileIteratorFactory + * @deprecated + */ + private function getFileIteratorFactory() + { + if ($this->fileIteratorFactory === null) { + $this->fileIteratorFactory = $this->_objectManager + ->get(\Magento\Framework\Config\FileIteratorFactory::class); + } + return $this->fileIteratorFactory; + } } diff --git a/lib/internal/Magento/Framework/Validator/Test/Unit/FactoryTest.php b/lib/internal/Magento/Framework/Validator/Test/Unit/FactoryTest.php index bb829010795e85957dce379405fa4111300dbb36..4c4ef93bc15be7102347c06917e8806eb7aefd5d 100644 --- a/lib/internal/Magento/Framework/Validator/Test/Unit/FactoryTest.php +++ b/lib/internal/Magento/Framework/Validator/Test/Unit/FactoryTest.php @@ -1,98 +1,139 @@ <?php /** - * Unit test for \Magento\Framework\Validator\Factory - * * Copyright © 2016 Magento. All rights reserved. * See COPYING.txt for license details. */ namespace Magento\Framework\Validator\Test\Unit; +/** + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ class FactoryTest extends \PHPUnit_Framework_TestCase { /** - * @var \Magento\Framework\ObjectManagerInterface + * @var \Magento\Framework\ObjectManagerInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $objectManagerMock; + + /** + * @var \Magento\Framework\Module\Dir\Reader|\PHPUnit_Framework_MockObject_MockObject + */ + private $readerMock; + + /** + * @var \Magento\Framework\Validator\Config|\PHPUnit_Framework_MockObject_MockObject + */ + private $validatorConfigMock; + + /** + * @var \Magento\Framework\Cache\FrontendInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $cacheMock; + + /** + * @var \Magento\Framework\Serialize\SerializerInterface|\PHPUnit_Framework_MockObject_MockObject */ - protected $_objectManager; + private $serializerMock; /** - * @var \Magento\Framework\Module\Dir\Reader + * @var \Magento\Framework\Config\FileIteratorFactory|\PHPUnit_Framework_MockObject_MockObject */ - protected $_config; + private $fileIteratorFactoryMock; /** - * @var \Magento\Framework\TranslateInterface + * @var \Magento\Framework\Config\FileIterator|\PHPUnit_Framework_MockObject_MockObject */ - protected $_translateAdapter; + private $fileIteratorMock; /** - * @var \Magento\Framework\Validator\Config + * @var \Magento\Framework\Translate\AdapterInterface */ - protected $_validatorConfig; + private $defaultTranslator; - private $cache; + /** + * @var \Magento\Framework\Validator\Factory + */ + private $factory; /** - * @var \Magento\Framework\Translate\AdapterInterface|null + * @var string */ - protected $_defaultTranslator = null; + private $jsonString = '["\/tmp\/moduleOne\/etc\/validation.xml"]'; /** - * Save default translator + * @var array */ + private $data = ['/tmp/moduleOne/etc/validation.xml']; + protected function setUp() { - $this->_defaultTranslator = \Magento\Framework\Validator\AbstractValidator::getDefaultTranslator(); - $this->_objectManager = $this->getMock(\Magento\Framework\ObjectManagerInterface::class); - $this->_validatorConfig = $this->getMockBuilder( - \Magento\Framework\Validator\Config::class - )->setMethods( - ['createValidatorBuilder', 'createValidator'] - )->disableOriginalConstructor()->getMock(); - - $this->_objectManager->expects( - $this->at(0) - )->method( - 'create' - )->with( - \Magento\Framework\Translate\Adapter::class - )->will( - $this->returnValue(new \Magento\Framework\Translate\Adapter()) - ); + $this->defaultTranslator = \Magento\Framework\Validator\AbstractValidator::getDefaultTranslator(); - $this->_objectManager->expects( - $this->at(1) - )->method( - 'create' - )->with( + $this->objectManagerMock = $this->getMock(\Magento\Framework\ObjectManagerInterface::class); + $this->validatorConfigMock = $this->getMock( \Magento\Framework\Validator\Config::class, - ['configFiles' => ['/tmp/moduleOne/etc/validation.xml']] - )->will( - $this->returnValue($this->_validatorConfig) + ['createValidatorBuilder', 'createValidator'], + [], + '', + false ); - - // Config mock - $this->_config = $this->getMockBuilder( - \Magento\Framework\Module\Dir\Reader::class - )->setMethods( - ['getConfigurationFiles'] - )->disableOriginalConstructor()->getMock(); - $this->_config->expects( - $this->once() - )->method( - 'getConfigurationFiles' - )->with( - 'validation.xml' - )->will( - $this->returnValue(['/tmp/moduleOne/etc/validation.xml']) + $translateAdapterMock = $this->getMock(\Magento\Framework\Translate\Adapter::class, [], [], '', false); + $this->objectManagerMock->expects($this->at(0)) + ->method('create') + ->with(\Magento\Framework\Translate\Adapter::class) + ->willReturn($translateAdapterMock); + $this->fileIteratorMock = $this->getMock( + \Magento\Framework\Config\FileIterator::class, + [], + [], + '', + false + ); + $this->objectManagerMock->expects($this->at(1)) + ->method('create') + ->with( + \Magento\Framework\Validator\Config::class, + ['configFiles' => $this->fileIteratorMock] + ) + ->willReturn($this->validatorConfigMock); + $this->readerMock = $this->getMock( + \Magento\Framework\Module\Dir\Reader::class, + ['getConfigurationFiles'], + [], + '', + false ); + $this->cacheMock = $this->getMock(\Magento\Framework\Cache\FrontendInterface::class); - // Translate adapter mock - $this->_translateAdapter = $this->getMockBuilder( - \Magento\Framework\TranslateInterface::class - )->disableOriginalConstructor()->getMock(); + $objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); + + $this->factory = $objectManager->getObject( + \Magento\Framework\Validator\Factory::class, + [ + 'objectManager' => $this->objectManagerMock, + 'moduleReader' => $this->readerMock, + 'cache' => $this->cacheMock + ] + ); - $this->cache = $this->getMockBuilder(\Magento\Framework\Cache\FrontendInterface::class) - ->getMockForAbstractClass(); + $this->serializerMock = $this->getMock(\Magento\Framework\Serialize\SerializerInterface::class); + $this->fileIteratorFactoryMock = $this->getMock( + \Magento\Framework\Config\FileIteratorFactory::class, + [], + [], + '', + false + ); + $objectManager->setBackwardCompatibleProperty( + $this->factory, + 'serializer', + $this->serializerMock + ); + $objectManager->setBackwardCompatibleProperty( + $this->factory, + 'fileIteratorFactory', + $this->fileIteratorFactoryMock + ); } /** @@ -100,87 +141,103 @@ class FactoryTest extends \PHPUnit_Framework_TestCase */ protected function tearDown() { - \Magento\Framework\Validator\AbstractValidator::setDefaultTranslator($this->_defaultTranslator); - unset($this->_defaultTranslator); + \Magento\Framework\Validator\AbstractValidator::setDefaultTranslator($this->defaultTranslator); + unset($this->defaultTranslator); } - /** - * Test getValidatorConfig created correct validator config. Check that validator translator was initialized. - */ public function testGetValidatorConfig() { - $factory = new \Magento\Framework\Validator\Factory( - $this->_objectManager, - $this->_config, - $this->cache - ); - $actualConfig = $factory->getValidatorConfig(); + $this->readerMock->method('getConfigurationFiles') + ->with('validation.xml') + ->willReturn($this->fileIteratorMock); + $this->fileIteratorMock->method('toArray') + ->willReturn($this->data); + $actualConfig = $this->factory->getValidatorConfig(); $this->assertInstanceOf( \Magento\Framework\Validator\Config::class, $actualConfig, 'Object of incorrect type was created' ); - - // Check that validator translator was correctly instantiated - $validatorTranslator = \Magento\Framework\Validator\AbstractValidator::getDefaultTranslator(); $this->assertInstanceOf( \Magento\Framework\Translate\Adapter::class, - $validatorTranslator, + \Magento\Framework\Validator\AbstractValidator::getDefaultTranslator(), 'Default validator translate adapter was not set correctly' ); } - /** - * Test createValidatorBuilder call - */ + public function testGetValidatorConfigCacheNotExist() + { + $this->cacheMock->expects($this->once()) + ->method('load') + ->willReturn(false); + $this->readerMock->expects($this->once()) + ->method('getConfigurationFiles') + ->willReturn($this->fileIteratorMock); + $this->fileIteratorMock->method('toArray') + ->willReturn($this->data); + $this->cacheMock->expects($this->once()) + ->method('save') + ->with($this->jsonString); + $this->serializerMock->expects($this->once()) + ->method('serialize') + ->with($this->data) + ->willReturn($this->jsonString); + $this->factory->getValidatorConfig(); + $this->factory->getValidatorConfig(); + } + + public function testGetValidatorConfigCacheExist() + { + $this->cacheMock->expects($this->once()) + ->method('load') + ->willReturn($this->jsonString); + $this->readerMock->expects($this->never()) + ->method('getConfigurationFiles'); + $this->cacheMock->expects($this->never()) + ->method('save'); + $this->serializerMock->expects($this->once()) + ->method('unserialize') + ->with($this->jsonString) + ->willReturn($this->data); + $this->fileIteratorFactoryMock->method('create') + ->willReturn($this->fileIteratorMock); + $this->factory->getValidatorConfig(); + $this->factory->getValidatorConfig(); + } + public function testCreateValidatorBuilder() { - $objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); - $this->_validatorConfig->expects( - $this->once() - )->method( - 'createValidatorBuilder' - )->with( - 'test', - 'class', - [] - )->will( - $this->returnValue( - $objectManager->getObject(\Magento\Framework\Validator\Builder::class, ['constraints' => []]) - ) - ); - $factory = new \Magento\Framework\Validator\Factory( - $this->_objectManager, - $this->_config, - $this->cache - ); + $this->readerMock->method('getConfigurationFiles') + ->with('validation.xml') + ->willReturn($this->fileIteratorMock); + $this->fileIteratorMock->method('toArray') + ->willReturn($this->data); + $builderMock = $this->getMock(\Magento\Framework\Validator\Builder::class, [], [], '', false); + $this->validatorConfigMock->expects($this->once()) + ->method('createValidatorBuilder') + ->with('test', 'class', []) + ->willReturn($builderMock); $this->assertInstanceOf( \Magento\Framework\Validator\Builder::class, - $factory->createValidatorBuilder('test', 'class', []) + $this->factory->createValidatorBuilder('test', 'class', []) ); } - /** - * Test createValidatorBuilder call - */ public function testCreateValidator() { - $this->_validatorConfig->expects( - $this->once() - )->method( - 'createValidator' - )->with( - 'test', - 'class', - [] - )->will( - $this->returnValue(new \Magento\Framework\Validator()) - ); - $factory = new \Magento\Framework\Validator\Factory( - $this->_objectManager, - $this->_config, - $this->cache + $this->readerMock->method('getConfigurationFiles') + ->with('validation.xml') + ->willReturn($this->fileIteratorMock); + $this->fileIteratorMock->method('toArray') + ->willReturn($this->data); + $validatorMock = $this->getMock(\Magento\Framework\Validator::class, [], [], '', false); + $this->validatorConfigMock->expects($this->once()) + ->method('createValidator') + ->with('test', 'class', []) + ->willReturn($validatorMock); + $this->assertInstanceOf( + \Magento\Framework\Validator::class, + $this->factory->createValidator('test', 'class', []) ); - $this->assertInstanceOf(\Magento\Framework\Validator::class, $factory->createValidator('test', 'class', [])); } } diff --git a/lib/internal/Magento/Framework/View/Asset/MergeStrategy/Checksum.php b/lib/internal/Magento/Framework/View/Asset/MergeStrategy/Checksum.php index bfdd516de7e366a3df4773776abec8e118b3916f..44b5bb65c49d36f690490e130f68c3868f162ce6 100644 --- a/lib/internal/Magento/Framework/View/Asset/MergeStrategy/Checksum.php +++ b/lib/internal/Magento/Framework/View/Asset/MergeStrategy/Checksum.php @@ -6,6 +6,8 @@ namespace Magento\Framework\View\Asset\MergeStrategy; use Magento\Framework\App\Filesystem\DirectoryList; +use Magento\Framework\App\ObjectManager; +use Magento\Framework\View\Asset\Source; /** * Skip merging if all of the files that need to be merged were not modified @@ -25,6 +27,11 @@ class Checksum implements \Magento\Framework\View\Asset\MergeStrategyInterface */ protected $filesystem; + /** + * @var Source + */ + private $assetSource; + /** * @param \Magento\Framework\View\Asset\MergeStrategyInterface $strategy * @param \Magento\Framework\Filesystem $filesystem @@ -37,17 +44,31 @@ class Checksum implements \Magento\Framework\View\Asset\MergeStrategyInterface $this->filesystem = $filesystem; } + /** + * @deprecated + * @return Source + */ + private function getAssetSource() + { + if (!$this->assetSource) { + $this->assetSource = ObjectManager::getInstance()->get(Source::class); + } + return $this->assetSource; + } + /** * {@inheritdoc} */ public function merge(array $assetsToMerge, \Magento\Framework\View\Asset\LocalInterface $resultAsset) { - $sourceDir = $this->filesystem->getDirectoryRead(DirectoryList::ROOT); + $rootDir = $this->filesystem->getDirectoryRead(DirectoryList::ROOT); $mTime = null; /** @var \Magento\Framework\View\Asset\MergeableInterface $asset */ foreach ($assetsToMerge as $asset) { - $mTime .= $sourceDir->stat($sourceDir->getRelativePath($asset->getSourceFile()))['mtime']; + $sourceFile = $this->getAssetSource()->findSource($asset); + $mTime .= $rootDir->stat($rootDir->getRelativePath($sourceFile))['mtime']; } + if (null === $mTime) { return; // nothing to merge } diff --git a/lib/internal/Magento/Framework/View/Element/Block/ArgumentInterface.php b/lib/internal/Magento/Framework/View/Element/Block/ArgumentInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..123a75946ba775c0e1565e7689201fde8f8c9f0b --- /dev/null +++ b/lib/internal/Magento/Framework/View/Element/Block/ArgumentInterface.php @@ -0,0 +1,14 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Framework\View\Element\Block; + +/** + * Block argument interface. + * All objects that are injected to block arguments should implement this interface. + */ +interface ArgumentInterface +{ +} diff --git a/lib/internal/Magento/Framework/View/Element/UiComponent/Config/Provider/Component/Definition.php b/lib/internal/Magento/Framework/View/Element/UiComponent/Config/Provider/Component/Definition.php index 1980da578c248cb8ccc8cc95e2e41c6097b0c45c..3778839894adbb93edc2d65dc4e1cdf088212d04 100644 --- a/lib/internal/Magento/Framework/View/Element/UiComponent/Config/Provider/Component/Definition.php +++ b/lib/internal/Magento/Framework/View/Element/UiComponent/Config/Provider/Component/Definition.php @@ -39,6 +39,11 @@ class Definition */ protected $componentData; + /** + * @var \Magento\Framework\Serialize\SerializerInterface + */ + private $serializer; + /** * Constructor * @@ -56,9 +61,9 @@ class Definition $cachedData = $this->cache->load(static::CACHE_ID); if ($cachedData === false) { $data = $uiReader->read(); - $this->cache->save(serialize($data), static::CACHE_ID); + $this->cache->save($this->getSerializer()->serialize($data), static::CACHE_ID); } else { - $data = unserialize($cachedData); + $data = $this->getSerializer()->unserialize($cachedData); } $this->prepareComponentData($data); } @@ -109,4 +114,19 @@ class Definition $this->setComponentData($name, reset($data)); } } + + /** + * Get serializer + * + * @return \Magento\Framework\Serialize\SerializerInterface + * @deprecated + */ + private function getSerializer() + { + if ($this->serializer === null) { + $this->serializer = \Magento\Framework\App\ObjectManager::getInstance() + ->get(\Magento\Framework\Serialize\SerializerInterface::class); + } + return $this->serializer; + } } diff --git a/lib/internal/Magento/Framework/View/Element/UiComponent/Config/Provider/Template.php b/lib/internal/Magento/Framework/View/Element/UiComponent/Config/Provider/Template.php index 79d185b2b26a700ea82734bc037f8fda4c082d1c..f740a2e403bb8f86da3501e7d9716567b93917b2 100644 --- a/lib/internal/Magento/Framework/View/Element/UiComponent/Config/Provider/Template.php +++ b/lib/internal/Magento/Framework/View/Element/UiComponent/Config/Provider/Template.php @@ -5,9 +5,6 @@ */ namespace Magento\Framework\View\Element\UiComponent\Config\Provider; -use Magento\Framework\Config\CacheInterface; -use Magento\Framework\View\Element\UiComponent\Config\ReaderFactory; -use Magento\Framework\View\Element\UiComponent\Config\DomMergerInterface; use Magento\Framework\View\Element\UiComponent\Config\FileCollector\AggregatedFileCollector; use Magento\Framework\View\Element\UiComponent\Config\FileCollector\AggregatedFileCollectorFactory; @@ -32,19 +29,19 @@ class Template protected $aggregatedFileCollector; /** - * @var DomMergerInterface + * @var \Magento\Framework\View\Element\UiComponent\Config\DomMergerInterface */ protected $domMerger; /** - * @var CacheInterface + * @var \Magento\Framework\Config\CacheInterface */ protected $cache; /** * Factory for UI config reader * - * @var ReaderFactory + * @var \Magento\Framework\View\Element\UiComponent\Config\ReaderFactory */ protected $readerFactory; @@ -58,20 +55,25 @@ class Template */ protected $cachedTemplates = []; + /** + * @var \Magento\Framework\Serialize\SerializerInterface + */ + private $serializer; + /** * Constructor * * @param AggregatedFileCollector $aggregatedFileCollector - * @param DomMergerInterface $domMerger - * @param CacheInterface $cache - * @param ReaderFactory $readerFactory + * @param \Magento\Framework\View\Element\UiComponent\Config\DomMergerInterface $domMerger + * @param \Magento\Framework\Config\CacheInterface $cache + * @param \Magento\Framework\View\Element\UiComponent\Config\ReaderFactory $readerFactory * @param AggregatedFileCollectorFactory $aggregatedFileCollectorFactory */ public function __construct( AggregatedFileCollector $aggregatedFileCollector, - DomMergerInterface $domMerger, - CacheInterface $cache, - ReaderFactory $readerFactory, + \Magento\Framework\View\Element\UiComponent\Config\DomMergerInterface $domMerger, + \Magento\Framework\Config\CacheInterface $cache, + \Magento\Framework\View\Element\UiComponent\Config\ReaderFactory $readerFactory, AggregatedFileCollectorFactory $aggregatedFileCollectorFactory ) { $this->aggregatedFileCollector = $aggregatedFileCollector; @@ -81,7 +83,9 @@ class Template $this->aggregatedFileCollectorFactory = $aggregatedFileCollectorFactory; $cachedTemplates = $this->cache->load(static::CACHE_ID); - $this->cachedTemplates = $cachedTemplates === false ? [] : unserialize($cachedTemplates); + $this->cachedTemplates = $cachedTemplates === false ? [] : $this->getSerializer()->unserialize( + $cachedTemplates + ); } /** @@ -104,8 +108,23 @@ class Template 'domMerger' => $this->domMerger ] )->getContent(); - $this->cache->save(serialize($this->cachedTemplates), static::CACHE_ID); + $this->cache->save($this->getSerializer()->serialize($this->cachedTemplates), static::CACHE_ID); return $this->cachedTemplates[$hash]; } + + /** + * Get serializer + * + * @return \Magento\Framework\Serialize\SerializerInterface + * @deprecated + */ + private function getSerializer() + { + if ($this->serializer === null) { + $this->serializer = \Magento\Framework\App\ObjectManager::getInstance() + ->get(\Magento\Framework\Serialize\SerializerInterface::class); + } + return $this->serializer; + } } diff --git a/lib/internal/Magento/Framework/View/Test/Unit/Asset/MergeStrategy/ChecksumTest.php b/lib/internal/Magento/Framework/View/Test/Unit/Asset/MergeStrategy/ChecksumTest.php index 9c7859116c4cbcc3da0947e6a39e5f1295dc4a8b..b20420640ebe42b31472299b2879f2f13f6abbe1 100644 --- a/lib/internal/Magento/Framework/View/Test/Unit/Asset/MergeStrategy/ChecksumTest.php +++ b/lib/internal/Magento/Framework/View/Test/Unit/Asset/MergeStrategy/ChecksumTest.php @@ -8,6 +8,7 @@ namespace Magento\Framework\View\Test\Unit\Asset\MergeStrategy; use \Magento\Framework\View\Asset\MergeStrategy\Checksum; use Magento\Framework\App\Filesystem\DirectoryList; +use Magento\Framework\View\Asset\Source; class ChecksumTest extends \PHPUnit_Framework_TestCase { @@ -31,6 +32,11 @@ class ChecksumTest extends \PHPUnit_Framework_TestCase */ private $resultAsset; + /** + * @var Source|\PHPUnit_Framework_MockObject_MockObject + */ + private $assetSource; + /** * @var \Magento\Framework\View\Asset\MergeStrategy\Checksum */ @@ -53,6 +59,15 @@ class ChecksumTest extends \PHPUnit_Framework_TestCase ->with(DirectoryList::STATIC_VIEW) ->will($this->returnValue($this->targetDir)); $this->checksum = new Checksum($this->mergerMock, $filesystem); + $this->assetSource = $this->getMockBuilder(Source::class) + ->disableOriginalConstructor() + ->getMock(); + + $reflection = new \ReflectionClass(Checksum::class); + $reflectionProperty = $reflection->getProperty('assetSource'); + $reflectionProperty->setAccessible(true); + $reflectionProperty->setValue($this->checksum, $this->assetSource); + $this->resultAsset = $this->getMock(\Magento\Framework\View\Asset\File::class, [], [], '', false); } @@ -114,9 +129,17 @@ class ChecksumTest extends \PHPUnit_Framework_TestCase private function getAssetsToMerge() { $one = $this->getMock(\Magento\Framework\View\Asset\File::class, [], [], '', false); - $one->expects($this->once())->method('getSourceFile')->will($this->returnValue('/dir/file/one.txt')); $two = $this->getMock(\Magento\Framework\View\Asset\File::class, [], [], '', false); - $two->expects($this->once())->method('getSourceFile')->will($this->returnValue('/dir/file/two.txt')); + $one->expects($this->never()) + ->method('getSourceFile'); + $two->expects($this->never()) + ->method('getSourceFile'); + + $this->assetSource->expects($this->exactly(2)) + ->method('findSource') + ->withConsecutive([$one], [$two]) + ->willReturnOnConsecutiveCalls('/dir/file/one.txt', '/dir/file/two.txt'); + $this->sourceDir->expects($this->exactly(2)) ->method('getRelativePath') ->will($this->onConsecutiveCalls('file/one.txt', 'file/two.txt')); diff --git a/lib/internal/Magento/Framework/View/Test/Unit/Layout/Argument/Interpreter/ObjectTest.php b/lib/internal/Magento/Framework/View/Test/Unit/Layout/Argument/Interpreter/ObjectTest.php index a8f2374cc0ce11efd32b7c6e0419db5c3a799086..8de579730b154035d02b38fbdb8d07ef3315d194 100644 --- a/lib/internal/Magento/Framework/View/Test/Unit/Layout/Argument/Interpreter/ObjectTest.php +++ b/lib/internal/Magento/Framework/View/Test/Unit/Layout/Argument/Interpreter/ObjectTest.php @@ -34,16 +34,11 @@ class ObjectTest extends \PHPUnit_Framework_TestCase public function testEvaluate() { - $input = ['value' => self::EXPECTED_CLASS]; - $this->_objectManager->expects( - $this->once() - )->method( - 'create' - )->with( - self::EXPECTED_CLASS - )->will( - $this->returnValue($this) - ); + $input = ['name' => 'dataSource', 'value' => self::EXPECTED_CLASS]; + $this->_objectManager->expects($this->once()) + ->method('create') + ->with(self::EXPECTED_CLASS) + ->willReturn($this); $actual = $this->_model->evaluate($input); $this->assertSame($this, $actual); @@ -56,17 +51,18 @@ class ObjectTest extends \PHPUnit_Framework_TestCase { $this->setExpectedException($expectedException, $expectedExceptionMessage); $self = $this; - $this->_objectManager->expects($this->any())->method('create')->will( - $this->returnCallback( - function ($className) use ($self) { - return $self->getMock($className); - } - ) + $this->_objectManager->expects($this->any())->method('create')->willReturnCallback( + function ($className) use ($self) { + return $self->getMock($className); + } ); $this->_model->evaluate($input); } + /** + * @return array + */ public function evaluateWrongClassDataProvider() { return [ diff --git a/lib/internal/Magento/Framework/Webapi/Test/Unit/ServiceInputProcessorTest.php b/lib/internal/Magento/Framework/Webapi/Test/Unit/ServiceInputProcessorTest.php index 0ebb6d9be4f3dfb55cfa6650e7714519fd96748f..658755d38a4e86ea8ffcc4e8333e30e4f6507658 100644 --- a/lib/internal/Magento/Framework/Webapi/Test/Unit/ServiceInputProcessorTest.php +++ b/lib/internal/Magento/Framework/Webapi/Test/Unit/ServiceInputProcessorTest.php @@ -8,6 +8,7 @@ namespace Magento\Framework\Webapi\Test\Unit; +use Magento\Framework\Serialize\SerializerInterface; use Magento\Framework\Webapi\ServiceInputProcessor; use Magento\Framework\Webapi\Test\Unit\ServiceInputProcessor\WebapiBuilderFactory; use Magento\Framework\Webapi\Test\Unit\ServiceInputProcessor\AssociativeArray; @@ -97,6 +98,16 @@ class ServiceInputProcessorTest extends \PHPUnit_Framework_TestCase 'fieldNamer' => $this->fieldNamer ] ); + $serializerMock = $this->getMock(SerializerInterface::class); + $serializerMock->method('serialize') + ->willReturn('serializedData'); + $serializerMock->method('unserialize') + ->willReturn('unserializedData'); + $objectManager->setBackwardCompatibleProperty( + $this->methodsMap, + 'serializer', + $serializerMock + ); $this->serviceInputProcessor = $objectManager->getObject( \Magento\Framework\Webapi\ServiceInputProcessor::class, @@ -111,10 +122,11 @@ class ServiceInputProcessorTest extends \PHPUnit_Framework_TestCase /** @var \Magento\Framework\Reflection\NameFinder $nameFinder */ $nameFinder = $objectManager->getObject(\Magento\Framework\Reflection\NameFinder::class); - $serviceInputProcessorReflection = new \ReflectionClass(get_class($this->serviceInputProcessor)); - $typeResolverReflection = $serviceInputProcessorReflection->getProperty('nameFinder'); - $typeResolverReflection->setAccessible(true); - $typeResolverReflection->setValue($this->serviceInputProcessor, $nameFinder); + $objectManager->setBackwardCompatibleProperty( + $this->serviceInputProcessor, + 'nameFinder', + $nameFinder + ); } public function testSimpleProperties() diff --git a/lib/web/css/source/components/_modals.less b/lib/web/css/source/components/_modals.less index daf325efd3a0276e7ad7e7318e75451b8474cb78..ea866d4775ac23728d62bf2782be416d314cc06d 100644 --- a/lib/web/css/source/components/_modals.less +++ b/lib/web/css/source/components/_modals.less @@ -189,6 +189,8 @@ // If applied, switching outer popup scroll to inner &._inner-scroll { overflow-y: visible; + + .ie11 &, .ie10 &, .ie9 & { overflow-y: auto; @@ -196,6 +198,8 @@ .modal-inner-wrap { max-height: 90%; + + .ie11 &, .ie10 &, .ie9 & { max-height: none; diff --git a/lib/web/mage/adminhtml/wysiwyg/tiny_mce/setup.js b/lib/web/mage/adminhtml/wysiwyg/tiny_mce/setup.js index 2c4ab52b896cb8fd8bf01974d7f39cfc8f11e4f4..057f492509192292022cf7290f6d18dc872c62b1 100755 --- a/lib/web/mage/adminhtml/wysiwyg/tiny_mce/setup.js +++ b/lib/web/mage/adminhtml/wysiwyg/tiny_mce/setup.js @@ -329,8 +329,9 @@ define([ encodeDirectives: function(content) { // collect all HTML tags with attributes that contain directives - return content.gsub(/<([a-z0-9\-\_]+.+?)([a-z0-9\-\_]+=".*?\{\{.+?\}\}.*?".+?)>/i, function(match) { + return content.gsub(/<([a-z0-9\-\_]+.+?)([a-z0-9\-\_]+=".*?\{\{.+?\}\}.*?".*?)>/i, function(match) { var attributesString = match[2]; + // process tag attributes string attributesString = attributesString.gsub(/([a-z0-9\-\_]+)="(.*?)(\{\{.+?\}\})(.*?)"/i, function(m) { return m[1] + '="' + m[2] + this.makeDirectiveUrl(Base64.mageEncode(m[3])) + m[4] + '"'; diff --git a/lib/web/mage/calendar.js b/lib/web/mage/calendar.js index 984274575aa3ab0af08faee6bf1f653f73782adb..5893b95f4bd38b21e17628353489c37af758848e 100644 --- a/lib/web/mage/calendar.js +++ b/lib/web/mage/calendar.js @@ -552,7 +552,7 @@ //Set date/time according to timezone offset $(el).datepicker('setTimezoneDate') // To ensure that user can re-select date field without clicking outside it first. - .blur(); + .blur().trigger('change'); }; return { diff --git a/lib/web/mage/utils/misc.js b/lib/web/mage/utils/misc.js index c6440b8929395419053ab53961f5fcc231ab7eee..29fed485f290c86f92099fc6cba68734711980d2 100644 --- a/lib/web/mage/utils/misc.js +++ b/lib/web/mage/utils/misc.js @@ -207,6 +207,22 @@ define([ } return formData; + }, + + /** + * Converts PHP IntlFormatter format to moment format. + * + * @param {String} format - PHP format + * @returns {String} - moment compatible formatting + */ + convertToMomentFormat: function (format) { + var newFormat; + + newFormat = format.replace(/yy|y/gi, 'YYYY'); // replace the year + newFormat = newFormat.replace(/dd|d/g, 'DD'); // replace the date + newFormat = newFormat.replace(/mm|m/gi, 'MM'); //replace the month + + return newFormat; } }; }); diff --git a/setup/performance-toolkit/benchmark.jmx b/setup/performance-toolkit/benchmark.jmx index c2ef9ebbea04d2250962ac7fe70d5ecc5435996f..576b8afc0bef99f098863feb97f093cf2c23ef42 100644 --- a/setup/performance-toolkit/benchmark.jmx +++ b/setup/performance-toolkit/benchmark.jmx @@ -3918,7 +3918,7 @@ vars.put("loadType", "Guest");</stringProp> </GaussianRandomTimer> <hashTree/> - <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Checkout Estimate Shipping Methods ${__property(activeAdminThread)}(${testLabel})" enabled="true"> + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Checkout Estimate Shipping Methods${__property(activeAdminThread)}(${testLabel})" enabled="true"> <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> <collectionProp name="Arguments.arguments"> @@ -3983,7 +3983,7 @@ vars.put("loadType", "Guest");</stringProp> </GaussianRandomTimer> <hashTree/> - <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Checkout Billing/Shipping Information ${__property(activeAdminThread)}(${testLabel})" enabled="true"> + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Checkout Billing/Shipping Information${__property(activeAdminThread)}(${testLabel})" enabled="true"> <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> <collectionProp name="Arguments.arguments"> @@ -4048,7 +4048,7 @@ vars.put("loadType", "Guest");</stringProp> </GaussianRandomTimer> <hashTree/> - <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Checkout Payment Info/Place Order ${__property(activeAdminThread)}(${testLabel})" enabled="true"> + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Checkout Payment Info/Place Order${__property(activeAdminThread)}(${testLabel})" enabled="true"> <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> <collectionProp name="Arguments.arguments"> @@ -5264,7 +5264,7 @@ vars.put("loadType", "Customer");</stringProp> </GaussianRandomTimer> <hashTree/> - <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Checkout Estimate Shipping Methods ${__property(activeAdminThread)}(${testLabel})" enabled="true"> + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Checkout Estimate Shipping Methods${__property(activeAdminThread)}(${testLabel})" enabled="true"> <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> <collectionProp name="Arguments.arguments"> 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/Command/DiCompileMultiTenantCommand.php b/setup/src/Magento/Setup/Console/Command/DiCompileMultiTenantCommand.php deleted file mode 100644 index ac6a43189d7abe247be6ac87b91b60b3967314ed..0000000000000000000000000000000000000000 --- a/setup/src/Magento/Setup/Console/Command/DiCompileMultiTenantCommand.php +++ /dev/null @@ -1,493 +0,0 @@ -<?php -/** - * Copyright © 2016 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Setup\Console\Command; - -use Magento\Framework\Filesystem\DriverInterface; -use Magento\Setup\Model\ObjectManagerProvider; -use Magento\Framework\App\ObjectManager; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Input\InputOption; -use Magento\Framework\Api\Code\Generator\Mapper; -use Magento\Framework\Api\Code\Generator\SearchResults; -use Magento\Framework\Autoload\AutoloaderRegistry; -use Magento\Framework\Component\ComponentRegistrar; -use Magento\Framework\Interception\Code\Generator\Interceptor; -use Magento\Framework\ObjectManager\Code\Generator\Converter; -use Magento\Framework\ObjectManager\Code\Generator\Factory; -use Magento\Framework\ObjectManager\Code\Generator\Proxy; -use Magento\Framework\ObjectManager\Code\Generator\Repository; -use Magento\Framework\ObjectManager\Code\Generator\Persistor; -use Magento\Framework\Api\Code\Generator\ExtensionAttributesGenerator; -use Magento\Framework\Api\Code\Generator\ExtensionAttributesInterfaceGenerator; -use Magento\Setup\Module\Di\Code\Scanner; -use Magento\Setup\Module\Di\Compiler\Log\Log; -use Magento\Setup\Module\Di\Compiler\Log\Writer; -use Magento\Setup\Module\Di\Definition\Compressor; -use Magento\Setup\Module\Di\Definition\Serializer\Igbinary; -use Magento\Setup\Module\Di\Definition\Serializer\Standard; -use \Magento\Framework\App\Filesystem\DirectoryList; -use Magento\Framework\Code\Generator as CodeGenerator; - -/** - * Command to generate all non-existing proxies and factories, and pre-compile class definitions, - * inheritance information and plugin definitions - * - * @SuppressWarnings(PHPMD.CouplingBetweenObjects) - */ -class DiCompileMultiTenantCommand extends AbstractSetupCommand -{ - /**#@+ - * Names of input options - */ - const INPUT_KEY_SERIALIZER = 'serializer'; - const INPUT_KEY_EXTRA_CLASSES_FILE = 'extra-classes-file'; - const INPUT_KEY_GENERATION = 'generation'; - const INPUT_KEY_DI= 'di'; - const INPUT_KEY_EXCLUDE_PATTERN= 'exclude-pattern'; - /**#@- */ - - /**#@+ - * Possible values for serializer - */ - const SERIALIZER_VALUE_SERIALIZE = 'serialize'; - const SERIALIZER_VALUE_IGBINARY = 'igbinary'; - /**#@- */ - - /** Command name */ - const NAME = 'setup:di:compile-multi-tenant'; - - /** - * Object Manager - * - * @var ObjectManager - */ - private $objectManager; - - /** - * Filesystem Directory List - * - * @var DirectoryList - */ - private $directoryList; - - /** - * - * @var array - */ - private $entities; - - /** - * - * @var array - */ - private $files = []; - - /** - * - * @var CodeGenerator - */ - private $generator; - - /** - * - * @var Log - */ - private $log; - - /** - * @var ComponentRegistrar - */ - private $componentRegistrar; - - /** - * Constructor - * - * @param ObjectManagerProvider $objectManagerProvider - * @param DirectoryList $directoryList - * @param ComponentRegistrar $componentRegistrar - */ - public function __construct( - ObjectManagerProvider $objectManagerProvider, - DirectoryList $directoryList, - ComponentRegistrar $componentRegistrar - ) { - $this->objectManager = $objectManagerProvider->get(); - $this->directoryList = $directoryList; - $this->componentRegistrar = $componentRegistrar; - parent::__construct(); - } - - /** - * {@inheritdoc} - */ - protected function configure() - { - $options = [ - new InputOption( - self::INPUT_KEY_SERIALIZER, - null, - InputOption::VALUE_REQUIRED, - 'Serializer function that should be used (' . self::SERIALIZER_VALUE_SERIALIZE . '|' - . self::SERIALIZER_VALUE_IGBINARY . ') default: ' . self::SERIALIZER_VALUE_SERIALIZE - ), - new InputOption( - self::INPUT_KEY_EXTRA_CLASSES_FILE, - null, - InputOption::VALUE_REQUIRED, - 'Path to file with extra proxies and factories to generate' - ), - new InputOption( - self::INPUT_KEY_GENERATION, - null, - InputOption::VALUE_REQUIRED, - 'Absolute path to generated classes, <magento_root>/var/generation by default' - ), - new InputOption( - self::INPUT_KEY_DI, - null, - InputOption::VALUE_REQUIRED, - 'Absolute path to DI definitions directory, <magento_root>/var/di by default' - ), - new InputOption( - self::INPUT_KEY_EXCLUDE_PATTERN, - null, - InputOption::VALUE_REQUIRED, - 'Allows to exclude Paths from compilation (default is #[\\\\/]m1[\\\\/]#i)' - ), - ]; - $this->setName(self::NAME) - ->setDescription( - 'Generates all non-existing proxies and factories, and pre-compile class definitions, ' - . 'inheritance information and plugin definitions' - ) - ->setDefinition($options); - parent::configure(); - } - - /** - * Get module directories exclude patterns - * - * @return array - */ - private function getModuleExcludePatterns() - { - $modulesExcludePatterns = []; - foreach ($this->componentRegistrar->getPaths(ComponentRegistrar::MODULE) as $modulePath) { - $modulesExcludePatterns[] = "#^" . $modulePath . "/Test#"; - } - return $modulesExcludePatterns; - } - - /** - * Get library directories exclude patterns - * - * @return array - */ - private function getLibraryExcludePatterns() - { - $libraryExcludePatterns = []; - foreach ($this->componentRegistrar->getPaths(ComponentRegistrar::LIBRARY) as $libraryPath) { - $libraryExcludePatterns[] = "#^" . $libraryPath . "/([\\w]+/)?Test#"; - } - return $libraryExcludePatterns; - } - - /** - * {@inheritdoc} - */ - protected function execute(InputInterface $input, OutputInterface $output) - { - $errors = $this->validate($input); - if ($errors) { - $output->writeln($errors); - return; - } - - $generationDir = $input->getOption(self::INPUT_KEY_GENERATION) ? $input->getOption(self::INPUT_KEY_GENERATION) - : $this->directoryList->getPath(DirectoryList::GENERATION); - $modulesExcludePatterns = $this->getModuleExcludePatterns(); - $testExcludePatterns = [ - "#^" . $this->directoryList->getPath(DirectoryList::SETUP) . "/[\\w]+/[\\w]+/Test#", - "#^" . $this->directoryList->getRoot() . "/dev/tools/Magento/Tools/[\\w]+/Test#" - ]; - $librariesExcludePatterns = $this->getLibraryExcludePatterns(); - $testExcludePatterns = array_merge($testExcludePatterns, $modulesExcludePatterns, $librariesExcludePatterns); - $fileExcludePatterns = $input->getOption('exclude-pattern') ? - [$input->getOption(self::INPUT_KEY_EXCLUDE_PATTERN)] : ['#[\\\\/]M1[\\\\/]#i']; - $fileExcludePatterns = array_merge($fileExcludePatterns, $testExcludePatterns); - /** @var Writer\Console logWriter Writer model for success messages */ - $logWriter = new Writer\Console($output); - $this->log = new Log($logWriter, $logWriter); - AutoloaderRegistry::getAutoloader()->addPsr4('Magento\\', $generationDir . '/Magento/'); - // 1 Code generation - $this->generateCode($generationDir, $fileExcludePatterns, $input); - // 2. Compilation - $this->compileCode($generationDir, $fileExcludePatterns, $input); - //Reporter - $this->log->report(); - if (!$this->log->hasError()) { - $output->writeln( - '<info>On *nix systems, verify the Magento application has permissions to modify files ' - . 'created by the compiler in the "var" directory. For instance, if you run the Magento application ' - . 'using Apache, the owner of the files in the "var" directory should be the Apache user (example ' - . 'command: "chown -R www-data:www-data <MAGENTO_ROOT>/var" where MAGENTO_ROOT is the Magento ' - . 'root directory).</info>' - ); - } - } - - /** - * Generate Code - * - * @param string $generationDir - * @param array $fileExcludePatterns - * @param InputInterface $input - * @return void - * @SuppressWarnings(PHPMD.CyclomaticComplexity) - * @SuppressWarnings(PHPMD.NPathComplexity) - */ - public function generateCode($generationDir, $fileExcludePatterns, $input) - { - // 1.1 Code scan - $filePatterns = ['php' => '/.*\.php$/', 'di' => '/\/etc\/([a-zA-Z_]*\/di|di)\.xml$/']; - $directoryScanner = new Scanner\DirectoryScanner(); - foreach ($this->componentRegistrar->getPaths(ComponentRegistrar::MODULE) as $codeScanDir) { - $this->files = array_merge_recursive( - $this->files, - $directoryScanner->scan($codeScanDir, $filePatterns, $fileExcludePatterns) - ); - } - $this->files['di'][] = $this->directoryList->getPath( - \Magento\Framework\App\Filesystem\DirectoryList::CONFIG - ) . '/di.xml'; - $this->files['additional'] = [$input->getOption(self::INPUT_KEY_EXTRA_CLASSES_FILE)]; - $repositoryScanner = new Scanner\RepositoryScanner(); - $repositories = $repositoryScanner->collectEntities($this->files['di']); - $scanner = new Scanner\CompositeScanner(); - $scanner->addChild(new Scanner\PhpScanner($this->log), 'php'); - $scanner->addChild(new Scanner\XmlScanner($this->log), 'di'); - $scanner->addChild(new Scanner\ArrayScanner(), 'additional'); - $this->entities = $scanner->collectEntities($this->files); - $interceptorScanner = new Scanner\XmlInterceptorScanner(); - $this->entities['interceptors'] = $interceptorScanner->collectEntities($this->files['di']); - // 1.2 Generation of Factory and Additional Classes - $generatorIo = $this->objectManager->create( - \Magento\Framework\Code\Generator\Io::class, - ['generationDirectory' => $generationDir] - ); - $this->generator = $this->objectManager->create( - \Magento\Framework\Code\Generator::class, - ['ioObject' => $generatorIo] - ); - /** Initialize object manager for code generation based on configs */ - $this->generator->setObjectManager($this->objectManager); - $generatorAutoloader = new \Magento\Framework\Code\Generator\Autoloader($this->generator); - spl_autoload_register([$generatorAutoloader, 'load']); - - foreach ($repositories as $entityName) { - switch ($this->generator->generateClass($entityName)) { - case CodeGenerator::GENERATION_SUCCESS: - $this->log->add(Log::GENERATION_SUCCESS, $entityName); - break; - case CodeGenerator::GENERATION_ERROR: - $this->log->add(Log::GENERATION_ERROR, $entityName); - break; - case CodeGenerator::GENERATION_SKIP: - default: - //no log - break; - } - } - foreach (['php', 'additional'] as $type) { - sort($this->entities[$type]); - foreach ($this->entities[$type] as $entityName) { - switch ($this->generator->generateClass($entityName)) { - case CodeGenerator::GENERATION_SUCCESS: - $this->log->add(Log::GENERATION_SUCCESS, $entityName); - break; - case CodeGenerator::GENERATION_ERROR: - $this->log->add(Log::GENERATION_ERROR, $entityName); - break; - case CodeGenerator::GENERATION_SKIP: - default: - //no log - break; - } - } - } - } - - /** - * Compile Code - * - * @param string $generationDir - * @param array $fileExcludePatterns - * @param InputInterface $input - * @return void - * @SuppressWarnings(PHPMD.CyclomaticComplexity) - * @SuppressWarnings(PHPMD.NPathComplexity) - */ - private function compileCode($generationDir, $fileExcludePatterns, $input) - { - $diDir = $input->getOption(self::INPUT_KEY_DI) ? $input->getOption(self::INPUT_KEY_DI) : - $this->directoryList->getPath(DirectoryList::DI); - $relationsFile = $diDir . '/relations.ser'; - $pluginDefFile = $diDir . '/plugins.ser'; - $compilationDirs = [ - $this->directoryList->getPath(DirectoryList::SETUP) . '/Magento/Setup/Module', - $this->directoryList->getRoot() . '/dev/tools/Magento/Tools', - ]; - $compilationDirs = array_merge( - $compilationDirs, - $this->componentRegistrar->getPaths(ComponentRegistrar::MODULE), - $this->componentRegistrar->getPaths(ComponentRegistrar::LIBRARY) - ); - $serializer = $input->getOption(self::INPUT_KEY_SERIALIZER) == Igbinary::NAME ? new Igbinary() : new Standard(); - // 2.1 Code scan - $validator = new \Magento\Framework\Code\Validator(); - $validator->add(new \Magento\Framework\Code\Validator\ConstructorIntegrity()); - $validator->add(new \Magento\Framework\Code\Validator\ContextAggregation()); - $classesScanner = new \Magento\Setup\Module\Di\Code\Reader\ClassesScanner(); - $classesScanner->addExcludePatterns($fileExcludePatterns); - $directoryInstancesNamesList = new \Magento\Setup\Module\Di\Code\Reader\Decorator\Directory( - $this->log, - new \Magento\Framework\Code\Reader\ClassReader(), - $classesScanner, - $validator, - $generationDir - ); - foreach ($compilationDirs as $path) { - if (is_readable($path)) { - $directoryInstancesNamesList->getList($path); - } - } - $inheritanceScanner = new Scanner\InheritanceInterceptorScanner( - new \Magento\Framework\ObjectManager\InterceptableValidator() - ); - $this->entities['interceptors'] = $inheritanceScanner->collectEntities( - get_declared_classes(), - $this->entities['interceptors'] - ); - // 2.1.1 Generation of Proxy and Interceptor Classes - foreach (['interceptors', 'di'] as $type) { - foreach ($this->entities[$type] as $entityName) { - switch ($this->generator->generateClass($entityName)) { - case CodeGenerator::GENERATION_SUCCESS: - $this->log->add(Log::GENERATION_SUCCESS, $entityName); - break; - case CodeGenerator::GENERATION_ERROR: - $this->log->add(Log::GENERATION_ERROR, $entityName); - break; - case CodeGenerator::GENERATION_SKIP: - default: - //no log - break; - } - } - } - //2.1.2 Compile relations for Proxy/Interceptor classes - $directoryInstancesNamesList->getList($generationDir); - $relations = $directoryInstancesNamesList->getRelations(); - // 2.2 Compression - $relationsFileDir = dirname($relationsFile); - if (!file_exists($relationsFileDir)) { - mkdir($relationsFileDir, 0777, true); - } - $relations = array_filter($relations); - file_put_contents($relationsFile, $serializer->serialize($relations)); - // 3. Plugin Definition Compilation - $pluginScanner = new Scanner\CompositeScanner(); - $pluginScanner->addChild(new Scanner\PluginScanner(), 'di'); - $pluginDefinitions = []; - $pluginList = $pluginScanner->collectEntities($this->files); - $pluginDefinitionList = new \Magento\Framework\Interception\Definition\Runtime(); - foreach ($pluginList as $type => $entityList) { - foreach ($entityList as $entity) { - $pluginDefinitions[ltrim($entity, '\\')] = $pluginDefinitionList->getMethodList($entity); - } - } - $outputContent = $serializer->serialize($pluginDefinitions); - $pluginDefFileDir = dirname($pluginDefFile); - if (!file_exists($pluginDefFileDir)) { - mkdir($pluginDefFileDir, 0777, true); - } - file_put_contents($pluginDefFile, $outputContent); - } - - /** - * Check if all option values provided by the user are valid - * - * @param InputInterface $input - * @return string[] - * @SuppressWarnings(PHPMD.CyclomaticComplexity) - */ - private function validate(InputInterface $input) - { - $errors = []; - $options = $input->getOptions(); - foreach ($options as $key => $value) { - if (!$value) { - continue; - } - switch ($key) { - case self::INPUT_KEY_SERIALIZER: - if (($value !== self::SERIALIZER_VALUE_SERIALIZE) && ($value !== self::SERIALIZER_VALUE_IGBINARY)) { - $errors[] = '<error>Invalid value for command option \'' . self::INPUT_KEY_SERIALIZER - . '\'. Possible values (' . self::SERIALIZER_VALUE_SERIALIZE . '|' - . self::SERIALIZER_VALUE_IGBINARY . ').</error>'; - } - break; - case self::INPUT_KEY_EXTRA_CLASSES_FILE: - if (!file_exists($value)) { - $errors[] = '<error>Path does not exist for the value of command option \'' - . self::INPUT_KEY_EXTRA_CLASSES_FILE . '\'.</error>'; - } - break; - case self::INPUT_KEY_GENERATION: - $errorMsg = $this->validateOutputPath($value, self::INPUT_KEY_GENERATION); - if ($errorMsg !== '') { - $errors[] = $errorMsg; - } - break; - case self::INPUT_KEY_DI: - $errorMsg = $this->validateOutputPath($value, self::INPUT_KEY_DI); - if ($errorMsg !== '') { - $errors[] = $errorMsg; - } - break; - case self::INPUT_KEY_EXCLUDE_PATTERN: - if (@preg_match($value, null) === false) { - $errors[] = '<error>Invalid pattern for command option \'' . self::INPUT_KEY_EXCLUDE_PATTERN - . '\'.</error>'; - } - break; - } - } - return $errors; - } - - /** - * Validate output path based on type - * - * @param string $value - * @param string $type - * @return string - */ - private function validateOutputPath($value, $type) - { - $errorMsg = ''; - if (!file_exists($value)) { - $errorMsg = '<error>Path does not exist for the value of command option \'' . $type . '\'.</error>'; - } - if (file_exists($value) && !is_writeable($value)) { - $errorMsg .= '<error>Non-writable directory is provided by the value of command option \'' - . $type . '\'.</error>'; - - } - return $errorMsg; - } -} 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/setup/src/Magento/Setup/Fixtures/AttributeSetsFixture.php b/setup/src/Magento/Setup/Fixtures/AttributeSetsFixture.php index 5617eca9a0e7e24694c151d508ed09a4cd547999..1bdffb253ae1f06f24647cf7efbc85d0801286f9 100644 --- a/setup/src/Magento/Setup/Fixtures/AttributeSetsFixture.php +++ b/setup/src/Magento/Setup/Fixtures/AttributeSetsFixture.php @@ -16,12 +16,27 @@ class AttributeSetsFixture extends Fixture */ protected $priority = 25; + /** + * Cache for attribute IDs. + * + * @var array + */ + private $attributeIdsCache = []; + + /** + * Quantity of unique attributes to generate. Zero means infinity. + * + * @var int + */ + protected $uniqueAttributesQuantity = 0; + /** * {@inheritdoc} */ public function execute() { - $attributeSets = $this->fixtureModel->getValue('attribute_sets', null); + $this->populateUniqueAttributesQuantity(); + $attributeSets = $this->getAttributeSetsFixtureValue(); if ($attributeSets === null) { return; } @@ -71,37 +86,81 @@ class AttributeSetsFixture extends Fixture $attributesData = array_key_exists(0, $attributeSetData['attributes']['attribute']) ? $attributeSetData['attributes']['attribute'] : [$attributeSetData['attributes']['attribute']]; foreach ($attributesData as $attributeData) { - //Create Attribute - /** @var \Magento\Catalog\Api\Data\ProductAttributeInterfaceFactory $attributeFactory */ - $attributeFactory = $this->fixtureModel->getObjectManager()->create( - \Magento\Catalog\Api\Data\ProductAttributeInterfaceFactory::class - ); - - $optionsData = array_key_exists(0, $attributeData['options']['option']) - ? $attributeData['options']['option'] : [$attributeData['options']['option']]; - $options = []; - foreach ($optionsData as $optionData) { - /** @var \Magento\Eav\Api\Data\AttributeOptionInterfaceFactory $optionFactory */ - $optionFactory = $this->fixtureModel->getObjectManager()->create( - \Magento\Eav\Api\Data\AttributeOptionInterfaceFactory::class + if ($this->uniqueAttributesQuantity === 0 + || (count($this->attributeIdsCache) < $this->uniqueAttributesQuantity)) { + //Create Attribute + /** @var \Magento\Catalog\Api\Data\ProductAttributeInterfaceFactory $attributeFactory */ + $attributeFactory = $this->fixtureModel->getObjectManager()->create( + \Magento\Catalog\Api\Data\ProductAttributeInterfaceFactory::class ); - $option = $optionFactory->create(['data' => $optionData]); - $options[] = $option; - } - $attribute = $attributeFactory->create(['data' => $attributeData]); - $attribute->setOptions($options); + $optionsData = array_key_exists(0, $attributeData['options']['option']) + ? $attributeData['options']['option'] : [$attributeData['options']['option']]; + $options = []; + foreach ($optionsData as $optionData) { + /** @var \Magento\Eav\Api\Data\AttributeOptionInterfaceFactory $optionFactory */ + $optionFactory = $this->fixtureModel->getObjectManager()->create( + \Magento\Eav\Api\Data\AttributeOptionInterfaceFactory::class + ); + $option = $optionFactory->create(['data' => $optionData]); + $options[] = $option; + } - $result = $attributeRepository->save($attribute); - $attributeId = $result->getAttributeId(); + $attribute = $attributeFactory->create(['data' => $attributeData]); + $attribute->setOptions($options); + $result = $attributeRepository->save($attribute); + $attributeId = $result->getAttributeId(); + $this->fillAttributeIdsCache($attributeId); + } else { + $attributeId = $this->getAttributeIdFromCache(); + } //Associate Attribute to Attribute Set $sortOrder = 3; + $attributeManagement->assign($attributeSetId, $attributeGroupId, $attributeId, $sortOrder); } } } + /** + * Get attribute ID from cache. + * + * @return int + */ + private function getAttributeIdFromCache() + { + $attributeId = next($this->attributeIdsCache); + if ($attributeId === false) { + $attributeId = reset($this->attributeIdsCache); + } + + return $attributeId; + } + + /** + * Fill attribute IDs cache. + * + * @param int $attributeId + * @return void + */ + private function fillAttributeIdsCache($attributeId) + { + if ($this->uniqueAttributesQuantity !== 0) { + $this->attributeIdsCache[] = $attributeId; + } + } + + /** + * Populate quantity of unique attributes to generate. + * + * @return void + */ + protected function populateUniqueAttributesQuantity() + { + $this->uniqueAttributesQuantity = $this->fixtureModel->getValue('unique_attributes_quantity', 0); + } + /** * {@inheritdoc} */ @@ -119,4 +178,14 @@ class AttributeSetsFixture extends Fixture 'attribute_sets' => 'Attribute Sets' ]; } + + /** + * Get attribute sets fixture value. + * + * @return array|null + */ + protected function getAttributeSetsFixtureValue() + { + return $this->fixtureModel->getValue('attribute_sets', null); + } } diff --git a/setup/src/Magento/Setup/Fixtures/ConfigurableProductsFixture.php b/setup/src/Magento/Setup/Fixtures/ConfigurableProductsFixture.php index 2340de71cf78363ed00fd9248577e7479b6dc012..9e84578281c5d65b8a84b384aab699b266c7286b 100644 --- a/setup/src/Magento/Setup/Fixtures/ConfigurableProductsFixture.php +++ b/setup/src/Magento/Setup/Fixtures/ConfigurableProductsFixture.php @@ -25,6 +25,13 @@ class ConfigurableProductsFixture extends SimpleProductsFixture */ protected $searchConfig; + /** + * Variations count. + * + * @var int + */ + protected $variationsCount; + //@codingStandardsIgnoreStart /** * Get CSV template headers @@ -169,7 +176,7 @@ class ConfigurableProductsFixture extends SimpleProductsFixture ) { return [ - 'sku' => 'Configurable Product %s' . $suffix, + 'sku' => $this->getConfigurableProductSkuPattern() . $suffix, 'store_view_code' => '', 'attribute_set_code' => $attributeSetClosure, 'additional_attributes' => $additionalAttributesClosure, @@ -225,8 +232,8 @@ class ConfigurableProductsFixture extends SimpleProductsFixture 'updated_at' => '2013-10-25 15:12:39', 'upsell_tgtr_position_behavior' => '', 'upsell_tgtr_position_limit' => '', - 'url_key' => "configurable-product-%s{$suffix}", - 'url_path' => "configurable-product-%s{$suffix}", + 'url_key' => $this->getUrlKeyPrefix() . "{$suffix}", + 'url_path' => $this->getUrlKeyPrefix() . "{$suffix}", 'visibility' => 'Catalog, Search', 'weight' => '', 'qty' => 333, @@ -305,7 +312,7 @@ class ConfigurableProductsFixture extends SimpleProductsFixture $data = []; for ($i = 1; $i <= $optionsNumber; $i++) { $productData = [ - 'sku' => "Configurable Product %s-option {$i}{$suffix}", + 'sku' => $this->getConfigurableOptionSkuPattern() . "{$i}{$suffix}", 'store_view_code' => '', 'attribute_set_code' => $attributeSetClosure, 'additional_attributes' => $additionalAttributesClosure, @@ -361,8 +368,8 @@ class ConfigurableProductsFixture extends SimpleProductsFixture 'updated_at' => '2013-10-25 15:12:32', 'upsell_tgtr_position_behavior' => '', 'upsell_tgtr_position_limit' => '', - 'url_key' => "simple-of-configurable-product-{$suffix}-%s-option-{$i}", - 'url_path' => "simple-of-configurable-product-{$suffix}-%s-option-{$i}", + 'url_key' => $this->getOptionUrlKeyPrefix() . "-{$suffix}-%s-option-{$i}", + 'url_path' => $this->getOptionUrlKeyPrefix() . "-{$suffix}-%s-option-{$i}", 'variations' => '', 'variations_1382710717' => '', 'variations_1382710773' => '', @@ -431,7 +438,7 @@ class ConfigurableProductsFixture extends SimpleProductsFixture */ public function execute() { - $configurableProductsCount = $this->fixtureModel->getValue('configurable_products', 0); + $configurableProductsCount = $this->getConfigurableProductsValue(); if (!$configurableProductsCount) { return; } @@ -440,170 +447,147 @@ class ConfigurableProductsFixture extends SimpleProductsFixture $maxAmountOfWordsShortDescription = $this->getSearchConfigValue('max_amount_of_words_short_description'); $minAmountOfWordsDescription = $this->getSearchConfigValue('min_amount_of_words_description'); $minAmountOfWordsShortDescription = $this->getSearchConfigValue('min_amount_of_words_short_description'); + $configurableProductsWithAttributes = []; - $attributes = $this->getAttributes(); - $searchTerms = $this->getSearchTerms(); - $this->fixtureModel->resetObjectManager(); - $result = $this->getCategoriesAndWebsites(); - $variationCount = $this->fixtureModel->getValue('configurable_products_variation', 3); - $result = array_values($result); - $dataGenerator = new DataGenerator(realpath(__DIR__ . '/' . 'dictionary.csv')); - - $productWebsiteClosure = function ($index) use ($result) { - return $result[$index % count($result)][0]; - }; - $productCategoryClosure = function ($index) use ($result) { - return $result[$index % count($result)][2] . '/' . $result[$index % count($result)][1]; - }; - $shortDescriptionClosure = function ($index) - use ( - $searchTerms, - $simpleProductsCount, - $configurableProductsCount, - $dataGenerator, - $maxAmountOfWordsShortDescription, - $minAmountOfWordsShortDescription - ) - { - $count = $searchTerms === null - ? 0 - : round( - $searchTerms[$index % count($searchTerms)]['count'] * ( - $configurableProductsCount / ($simpleProductsCount + $configurableProductsCount) - ) - ); - mt_srand($index); - return $dataGenerator->generate( - $minAmountOfWordsShortDescription, - $maxAmountOfWordsShortDescription, - 'shortDescription-' . $index - ) . ($index <= ($count * count($searchTerms)) ? ' ' - . $searchTerms[$index % count($searchTerms)]['term'] : ''); - }; - $descriptionClosure = function ($index) - use ( - $searchTerms, - $simpleProductsCount, - $configurableProductsCount, - $dataGenerator, - $maxAmountOfWordsDescription, - $minAmountOfWordsDescription - ) - { - $count = $searchTerms === null - ? 0 - : round( - $searchTerms[$index % count($searchTerms)]['count'] * ( - $configurableProductsCount / ($simpleProductsCount + $configurableProductsCount) - ) - ); - mt_srand($index); - return $dataGenerator->generate( - $minAmountOfWordsDescription, - $maxAmountOfWordsDescription, - 'description-' . $index - ) . ($index <= ($count * count($searchTerms)) - ? ' ' . $searchTerms[$index % count($searchTerms)]['term'] : ''); - }; - $priceClosure = function($index) { - mt_srand($index); - switch (mt_rand(0,3)) { - case 0: return 9.99; - case 1: return 5; - case 2: return 1; - case 3: return mt_rand(1,10000)/10; - } - }; - $attributeSetClosure = function($index) use ($attributes, $result) { - mt_srand($index); - $attributeSet = (count(array_keys($attributes)) > (($index - 1) % count($result)) - ? array_keys($attributes)[mt_rand(0, count(array_keys($attributes)) - 1)] : 'Default'); - return $attributeSet; - }; - $variationClosure = function($index, $variationIndex) use ($attributes, $result, $variationCount) { - mt_srand($index); - $attributeSetCode = (count(array_keys($attributes)) > (($index - 1) % count($result)) - ? array_keys($attributes)[mt_rand(0, count(array_keys($attributes)) - 1)] : 'Default'); - $skus = []; - for ($i=1; $i <= $variationCount; $i++) { - $skus[] = 'sku=Configurable Product ' . $index . '-option ' . $i; - } - $values = []; - if ($attributeSetCode == 'Default') { - for ($i=1; $i <= $variationCount; $i++) { - $values[] = 'configurable_variation=option ' . $i; - } + if ($this->getAdditionalConfigurableProductsVariations() === null) { + $configurableProductsWithAttributes[$configurableProductsCount] + = $this->getConfigurableProductsVariationsValue(); + } else { + if (strpos($this->getAdditionalConfigurableProductsVariations(), ',')) { + $variations = explode(',', $this->getAdditionalConfigurableProductsVariations()); } else { - for ($i=$variationCount; $i > 0; $i--) { - $attributeValues = ''; - foreach ($attributes[$attributeSetCode] as $attribute) { - $attributeValues = $attributeValues . $attribute['name'] . "=" . - $attribute['values'][($variationIndex - $i) % count($attribute['values'])] . ","; - } - $values [] = $attributeValues; - } + $variations = [$this->getAdditionalConfigurableProductsVariations()]; } - $variations = []; - for ($i=0; $i < $variationCount; $i++) { - $variations[] = trim(implode(",",[$skus[$i],$values[$i]]), ","); + + foreach ($variations as $variation) { + $value = explode(':', $variation); + $configurableProductsWithAttributes[$value[0]] = $value[1]; } - return implode("|",$variations); - }; - $additionalAttributesClosure = function($index, $variationIndex) use ($attributes, $result) { - $attributeValues = ''; - mt_srand($index); - $attributeSetCode = (count(array_keys($attributes)) > (($index - 1) % count($result)) - ? array_keys($attributes)[mt_rand(0, count(array_keys($attributes)) - 1)] : 'Default'); - if ($attributeSetCode !== 'Default' ) { - foreach ($attributes[$attributeSetCode] as $attribute) { - $attributeValues = $attributeValues . $attribute['name'] . "=" . - $attribute['values'][$variationIndex % count($attribute['values'])] . ","; + } + + foreach ($configurableProductsWithAttributes as $productsCount => $variationsCount) { + $this->variationsCount = $variationsCount; + $configurableProductsCount = $productsCount; + $attributes = $this->getAttributes(); + $searchTerms = $this->getSearchTerms(); + $this->fixtureModel->resetObjectManager(); + $result = $this->getCategoriesAndWebsites(); + $result = array_values($result); + $dataGenerator = new DataGenerator(realpath(__DIR__ . '/' . 'dictionary.csv')); + + $productWebsiteClosure = function ($index) use ($result) { + return $result[$index % count($result)][0]; + }; + $productCategoryClosure = function ($index) use ($result) { + return $result[$index % count($result)][2] . '/' . $result[$index % count($result)][1]; + }; + $shortDescriptionClosure = function ($index) + use ( + $searchTerms, + $simpleProductsCount, + $configurableProductsCount, + $dataGenerator, + $maxAmountOfWordsShortDescription, + $minAmountOfWordsShortDescription + ) { + $count = $searchTerms === null + ? 0 + : round( + $searchTerms[$index % count($searchTerms)]['count'] * ( + $configurableProductsCount / ($simpleProductsCount + $configurableProductsCount) + ) + ); + mt_srand($index); + return $dataGenerator->generate( + $minAmountOfWordsShortDescription, + $maxAmountOfWordsShortDescription, + 'shortDescription-' . $index + ) . ($index <= ($count * count($searchTerms)) ? ' ' + . $searchTerms[$index % count($searchTerms)]['term'] : ''); + }; + $descriptionClosure = function ($index) + use ( + $searchTerms, + $simpleProductsCount, + $configurableProductsCount, + $dataGenerator, + $maxAmountOfWordsDescription, + $minAmountOfWordsDescription + ) { + $count = $searchTerms === null + ? 0 + : round( + $searchTerms[$index % count($searchTerms)]['count'] * ( + $configurableProductsCount / ($simpleProductsCount + $configurableProductsCount) + ) + ); + mt_srand($index); + return $dataGenerator->generate( + $minAmountOfWordsDescription, + $maxAmountOfWordsDescription, + 'description-' . $index + ) . ($index <= ($count * count($searchTerms)) + ? ' ' . $searchTerms[$index % count($searchTerms)]['term'] : ''); + }; + $priceClosure = function ($index) { + mt_srand($index); + switch (mt_rand(0, 3)) { + case 0: + return 9.99; + case 1: + return 5; + case 2: + return 1; + case 3: + return mt_rand(1, 10000) / 10; } - } - return trim($attributeValues, ","); - }; - /** - * Create configurable products - */ - $pattern = new Pattern(); - $pattern->setHeaders($this->getHeaders()); - $pattern->setRowsSet( - $this->getRows( - $productCategoryClosure, - $productWebsiteClosure, - $shortDescriptionClosure, - $descriptionClosure, - $priceClosure, - $attributeSetClosure, - $additionalAttributesClosure, - $variationClosure, - $variationCount - ) - ); + }; + $attributeSetClosure = $this->getAttributeSetClosure($attributes, $result); + $variationClosure = $this->getVariationsClosure($attributes, $result, $variationsCount); + $additionalAttributesClosure = $this->getAdditionalAttributesClosure($attributes, $result); + /** + * Create configurable products + */ + $pattern = new Pattern(); + $pattern->setHeaders($this->getHeaders()); + $pattern->setRowsSet( + $this->getRows( + $productCategoryClosure, + $productWebsiteClosure, + $shortDescriptionClosure, + $descriptionClosure, + $priceClosure, + $attributeSetClosure, + $additionalAttributesClosure, + $variationClosure, + $variationsCount + ) + ); - /** @var \Magento\ImportExport\Model\Import $import */ - $import = $this->fixtureModel->getObjectManager()->create( - \Magento\ImportExport\Model\Import::class, - [ - 'data' => [ - 'entity' => 'catalog_product', - 'behavior' => 'append', - 'validation_strategy' => 'validation-stop-on-errors', - ], - ] - ); + /** @var \Magento\ImportExport\Model\Import $import */ + $import = $this->fixtureModel->getObjectManager()->create( + \Magento\ImportExport\Model\Import::class, + [ + 'data' => [ + 'entity' => 'catalog_product', + 'behavior' => 'append', + 'validation_strategy' => 'validation-stop-on-errors', + ], + ] + ); - $source = $this->fixtureModel->getObjectManager()->create( - Generator::class, - ['rowPattern' => $pattern, 'count' => $configurableProductsCount] - ); - // it is not obvious, but the validateSource() will actually save import queue data to DB - if (!$import->validateSource($source)) { - throw new \Exception($import->getFormatedLogTrace()); - } - // this converts import queue into actual entities - if (!$import->importSource()) { - throw new \Exception($import->getFormatedLogTrace()); + $source = $this->fixtureModel->getObjectManager()->create( + Generator::class, + ['rowPattern' => $pattern, 'count' => $configurableProductsCount] + ); + // it is not obvious, but the validateSource() will actually save import queue data to DB + if (!$import->validateSource($source)) { + throw new \Exception($import->getFormatedLogTrace()); + } + // this converts import queue into actual entities + if (!$import->importSource()) { + throw new \Exception($import->getFormatedLogTrace()); + } } } // @codingStandardsIgnoreEnd @@ -674,4 +658,166 @@ class ConfigurableProductsFixture extends SimpleProductsFixture } return $result; } + + /** + * Get configurable products value. + * + * @return int + */ + protected function getConfigurableProductsValue() + { + return $this->fixtureModel->getValue('configurable_products', 0); + } + + /** + * Get configurable products variations value. + * + * @return int + */ + protected function getConfigurableProductsVariationsValue() + { + return $this->fixtureModel->getValue('configurable_products_variation', 3); + } + + /** + * Get attribute set closure + * + * @param array $attributes + * @param array $result + * @return \Closure + */ + protected function getAttributeSetClosure(array $attributes, array $result) + { + return function ($index) use ($attributes, $result) { + mt_srand($index); + $attributeSet = (count(array_keys($attributes)) > (($index - 1) % count($result)) + ? array_keys($attributes)[mt_rand(0, count(array_keys($attributes)) - 1)] : 'Default'); + return $attributeSet; + }; + } + + /** + * Get additional attributes closure. + * + * @param array $attributes + * @param array $result + * @return \Closure + */ + protected function getAdditionalAttributesClosure(array $attributes, array $result) + { + return function ($index, $variationIndex) use ($attributes, $result) { + $attributeValues = ''; + mt_srand($index); + $attributeSetCode = (count(array_keys($attributes)) > (($index - 1) % count($result)) + ? array_keys($attributes)[mt_rand(0, count(array_keys($attributes)) - 1)] : 'Default'); + if ($attributeSetCode !== 'Default') { + foreach ($attributes[$attributeSetCode] as $attribute) { + $attributeValues = $attributeValues . $attribute['name'] . "=" . + $attribute['values'][$variationIndex % count($attribute['values'])] . ","; + } + } + return trim($attributeValues, ","); + }; + } + + /** + * Get variations closure. + * + * @param array $attributes + * @param array $result + * @param int $variationCount + * @return \Closure + */ + protected function getVariationsClosure(array $attributes, array $result, $variationCount) + { + return function ($index, $variationIndex) use ($attributes, $result, $variationCount) { + mt_srand($index); + $attributeSetCode = (count(array_keys($attributes)) > (($index - 1) % count($result)) + ? array_keys($attributes)[mt_rand(0, count(array_keys($attributes)) - 1)] : 'Default'); + $skus = []; + for ($i = 1; $i <= $variationCount; $i++) { + $skus[] = 'sku=' . sprintf($this->getConfigurableOptionSkuPattern(), $index) . $i; + } + $values = []; + if ($attributeSetCode == 'Default') { + for ($i = 1; $i <= $variationCount; $i++) { + $values[] = 'configurable_variation=option ' . $i; + } + } else { + for ($i = $variationCount; $i > 0; $i--) { + $attributeValues = ''; + foreach ($attributes[$attributeSetCode] as $attribute) { + $attributeValues = $attributeValues . $attribute['name'] . "=" . + $attribute['values'][($variationIndex - $i) % count($attribute['values'])] . ","; + } + $values [] = $attributeValues; + } + } + $variations = []; + for ($i = 0; $i < $variationCount; $i++) { + $variations[] = trim(implode(",", [$skus[$i], $values[$i]]), ","); + } + return implode("|", $variations); + }; + } + + /** + * Get configurable product sku pattern. + * + * @return string + */ + private function getConfigurableProductSkuPattern() + { + return 'Configurable Product ' . $this->getConfigurableProductPrefix() . ' %s'; + } + + /** + * Get configurable option sku pattern. + * + * @return string + */ + protected function getConfigurableOptionSkuPattern() + { + return 'Configurable Product ' . $this->getConfigurableProductPrefix() . '%s-option'; + } + + /** + * Get url key prefix. + * + * @return string + */ + private function getUrlKeyPrefix() + { + return 'configurable-product' . $this->getConfigurableProductPrefix() . '-%s'; + } + + /** + * Get option url key prefix. + * + * @return string + */ + private function getOptionUrlKeyPrefix() + { + return 'simple-of-configurable-product' . $this->getConfigurableProductPrefix(); + } + + /** + * Get additional configurations for configurable products. + * + * @return string|null + */ + private function getAdditionalConfigurableProductsVariations() + { + return $this->fixtureModel->getValue('configurable_products_variations', null); + } + + /** + * Get configurable product prefix. + * + * @return string + */ + protected function getConfigurableProductPrefix() + { + return ''; + } } diff --git a/setup/src/Magento/Setup/Fixtures/SimpleProductsFixture.php b/setup/src/Magento/Setup/Fixtures/SimpleProductsFixture.php index fbb28d35269b177762410e8da7560612dd64db9c..43270676cb94f0a16729d7c16dab4913247f105c 100644 --- a/setup/src/Magento/Setup/Fixtures/SimpleProductsFixture.php +++ b/setup/src/Magento/Setup/Fixtures/SimpleProductsFixture.php @@ -235,7 +235,7 @@ class SimpleProductsFixture extends Fixture */ protected function getAttributes() { - $attributeSets = $this->fixtureModel->getValue('attribute_sets', null); + $attributeSets = $this->getAttributeSets(); $attributes = []; if ($attributeSets !== null && array_key_exists('attribute_set', $attributeSets)) { @@ -337,4 +337,14 @@ class SimpleProductsFixture extends Fixture } return $searchTerms; } + + /** + * Get attribute sets. + * + * @return array|null + */ + private function getAttributeSets() + { + return $this->fixtureModel->getValue('attribute_sets', null); + } } diff --git a/setup/src/Magento/Setup/Model/ConfigGenerator.php b/setup/src/Magento/Setup/Model/ConfigGenerator.php index 140f5a739889c829efe34689c044310a4d7d62a3..ce86ce4dd471f01876fbc3ba87d6697b5156eea7 100644 --- a/setup/src/Magento/Setup/Model/ConfigGenerator.php +++ b/setup/src/Magento/Setup/Model/ConfigGenerator.php @@ -116,19 +116,12 @@ class ConfigGenerator * * @param array $data * @return ConfigData + * @deprecated + * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ public function createDefinitionsConfig(array $data) { - $configData = new ConfigData(ConfigFilePool::APP_ENV); - - if (!empty($data[ConfigOptionsListConstants::INPUT_KEY_DEFINITION_FORMAT])) { - $configData->set( - ObjectManagerFactory::CONFIG_PATH_DEFINITION_FORMAT, - $data[ConfigOptionsListConstants::INPUT_KEY_DEFINITION_FORMAT] - ); - } - - return $configData; + return null; } /** diff --git a/setup/src/Magento/Setup/Model/ConfigOptionsList.php b/setup/src/Magento/Setup/Model/ConfigOptionsList.php index 4e8374aabb4e6b647aca8c34ca67041ca3532c54..0c1419a73cb8ebdb805dde29cc3412203dab7b07 100644 --- a/setup/src/Magento/Setup/Model/ConfigOptionsList.php +++ b/setup/src/Magento/Setup/Model/ConfigOptionsList.php @@ -72,13 +72,6 @@ class ConfigOptionsList implements ConfigOptionsListInterface 'Session save handler', ConfigOptionsListConstants::SESSION_SAVE_FILES ), - new SelectConfigOption( - ConfigOptionsListConstants::INPUT_KEY_DEFINITION_FORMAT, - SelectConfigOption::FRONTEND_WIZARD_SELECT, - DefinitionFactory::getSupportedFormats(), - ObjectManagerFactory::CONFIG_PATH_DEFINITION_FORMAT, - 'Type of definitions used by Object Manager' - ), new TextConfigOption( ConfigOptionsListConstants::INPUT_KEY_DB_HOST, TextConfigOption::FRONTEND_WIZARD_TEXT, diff --git a/setup/src/Magento/Setup/Module/Di/Code/Generator/PluginList.php b/setup/src/Magento/Setup/Module/Di/Code/Generator/PluginList.php index 703cbced8e33a637b5548eae93539d4e1f7b4ab8..851bfa8c36313852a8d7c876f4abe195a7b2ffdf 100644 --- a/setup/src/Magento/Setup/Module/Di/Code/Generator/PluginList.php +++ b/setup/src/Magento/Setup/Module/Di/Code/Generator/PluginList.php @@ -1,14 +1,15 @@ <?php /** - * * Copyright © 2016 Magento. All rights reserved. * See COPYING.txt for license details. */ - namespace Magento\Setup\Module\Di\Code\Generator; use Magento\Framework\Interception; +/** + * Provides plugin list configuration + */ class PluginList extends Interception\PluginList\PluginList { /** diff --git a/setup/src/Magento/Setup/Module/Di/Compiler/Config/Writer/Filesystem.php b/setup/src/Magento/Setup/Module/Di/Compiler/Config/Writer/Filesystem.php index daf8425802ac535dd6255085d55c9637b62c5656..342b26a22e32ba941429d0e1dc9299af08472f49 100644 --- a/setup/src/Magento/Setup/Module/Di/Compiler/Config/Writer/Filesystem.php +++ b/setup/src/Magento/Setup/Module/Di/Compiler/Config/Writer/Filesystem.php @@ -8,8 +8,9 @@ namespace Magento\Setup\Module\Di\Compiler\Config\Writer; use Magento\Framework\App\Filesystem\DirectoryList; -use Magento\Framework\Filesystem\DriverInterface; use Magento\Setup\Module\Di\Compiler\Config\WriterInterface; +use Magento\Framework\Serialize\SerializerInterface; +use Magento\Framework\Serialize\Serializer\Serialize; class Filesystem implements WriterInterface { @@ -18,6 +19,11 @@ class Filesystem implements WriterInterface */ private $directoryList; + /** + * @var SerializerInterface + */ + private $serializer; + /** * Constructor * @@ -39,8 +45,10 @@ class Filesystem implements WriterInterface { $this->initialize(); - $serialized = serialize($config); - file_put_contents($this->directoryList->getPath(DirectoryList::DI) . '/' . $key . '.ser', $serialized); + file_put_contents( + $this->directoryList->getPath(DirectoryList::DI) . '/' . $key . '.ser', + $this->getSerializer()->serialize($config) + ); } /** @@ -54,4 +62,19 @@ class Filesystem implements WriterInterface mkdir($this->directoryList->getPath(DirectoryList::DI)); } } + + /** + * Get serializer + * + * @return SerializerInterface + * @deprecated + */ + private function getSerializer() + { + if (null === $this->serializer) { + $this->serializer = \Magento\Framework\App\ObjectManager::getInstance() + ->get(Serialize::class); + } + return $this->serializer; + } } diff --git a/setup/src/Magento/Setup/Module/I18n/Dictionary/Writer/Csv.php b/setup/src/Magento/Setup/Module/I18n/Dictionary/Writer/Csv.php index d28c3161903a2e6e762988709a01e0af3c1029f5..10490b6565534001a451ffc2d997ae120a420adf 100644 --- a/setup/src/Magento/Setup/Module/I18n/Dictionary/Writer/Csv.php +++ b/setup/src/Magento/Setup/Module/I18n/Dictionary/Writer/Csv.php @@ -54,9 +54,19 @@ class Csv implements WriterInterface * Close file handler * * @return void + * + * @deprecated */ public function __destructor() { fclose($this->_fileHandler); } + + /** + * Destructor for closing file handler + */ + public function __destruct() + { + fclose($this->_fileHandler); + } } 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 diff --git a/setup/src/Magento/Setup/Test/Unit/Fixtures/AttributeSetsFixtureTest.php b/setup/src/Magento/Setup/Test/Unit/Fixtures/AttributeSetsFixtureTest.php index 674f444fbde10666b75aa5dadfef3719e3177152..2192f4e84e26e7d39e5fa09b2e5ee752eb659b10 100644 --- a/setup/src/Magento/Setup/Test/Unit/Fixtures/AttributeSetsFixtureTest.php +++ b/setup/src/Magento/Setup/Test/Unit/Fixtures/AttributeSetsFixtureTest.php @@ -202,7 +202,7 @@ class AttributeSetsFixtureTest extends \PHPUnit_Framework_TestCase ->willReturn($optionFactoryMock); $this->fixtureModelMock - ->expects($this->once()) + ->expects($this->any()) ->method('getValue') ->willReturn($attributeSets); @@ -267,7 +267,7 @@ class AttributeSetsFixtureTest extends \PHPUnit_Framework_TestCase ->method('getObjectManager') ->will($this->returnValue($objectManagerMock)); $this->fixtureModelMock - ->expects($this->once()) + ->expects($this->any()) ->method('getValue') ->willReturn(null); diff --git a/setup/src/Magento/Setup/Test/Unit/Model/ConfigOptionsListTest.php b/setup/src/Magento/Setup/Test/Unit/Model/ConfigOptionsListTest.php index 1e37d351d8f039014ae35a9fdfbe3aaa725375fe..eaab4d28d7620ebdc31c97b9a938afdb59957f55 100644 --- a/setup/src/Magento/Setup/Test/Unit/Model/ConfigOptionsListTest.php +++ b/setup/src/Magento/Setup/Test/Unit/Model/ConfigOptionsListTest.php @@ -48,32 +48,30 @@ class ConfigOptionsListTest extends \PHPUnit_Framework_TestCase $this->assertSame('Encryption key', $options[0]->getDescription()); $this->assertInstanceOf(\Magento\Framework\Setup\Option\SelectConfigOption::class, $options[1]); $this->assertSame('Session save handler', $options[1]->getDescription()); - $this->assertInstanceOf(\Magento\Framework\Setup\Option\SelectConfigOption::class, $options[2]); - $this->assertSame('Type of definitions used by Object Manager', $options[2]->getDescription()); + $this->assertInstanceOf(\Magento\Framework\Setup\Option\TextConfigOption::class, $options[2]); + $this->assertSame('Database server host', $options[2]->getDescription()); $this->assertInstanceOf(\Magento\Framework\Setup\Option\TextConfigOption::class, $options[3]); - $this->assertSame('Database server host', $options[3]->getDescription()); + $this->assertSame('Database name', $options[3]->getDescription()); $this->assertInstanceOf(\Magento\Framework\Setup\Option\TextConfigOption::class, $options[4]); - $this->assertSame('Database name', $options[4]->getDescription()); + $this->assertSame('Database server username', $options[4]->getDescription()); $this->assertInstanceOf(\Magento\Framework\Setup\Option\TextConfigOption::class, $options[5]); - $this->assertSame('Database server username', $options[5]->getDescription()); + $this->assertSame('Database server engine', $options[5]->getDescription()); $this->assertInstanceOf(\Magento\Framework\Setup\Option\TextConfigOption::class, $options[6]); - $this->assertSame('Database server engine', $options[6]->getDescription()); + $this->assertSame('Database server password', $options[6]->getDescription()); $this->assertInstanceOf(\Magento\Framework\Setup\Option\TextConfigOption::class, $options[7]); - $this->assertSame('Database server password', $options[7]->getDescription()); + $this->assertSame('Database table prefix', $options[7]->getDescription()); $this->assertInstanceOf(\Magento\Framework\Setup\Option\TextConfigOption::class, $options[8]); - $this->assertSame('Database table prefix', $options[8]->getDescription()); + $this->assertSame('Database type', $options[8]->getDescription()); $this->assertInstanceOf(\Magento\Framework\Setup\Option\TextConfigOption::class, $options[9]); - $this->assertSame('Database type', $options[9]->getDescription()); - $this->assertInstanceOf(\Magento\Framework\Setup\Option\TextConfigOption::class, $options[10]); - $this->assertSame('Database initial set of commands', $options[10]->getDescription()); - $this->assertInstanceOf(\Magento\Framework\Setup\Option\FlagConfigOption::class, $options[11]); + $this->assertSame('Database initial set of commands', $options[9]->getDescription()); + $this->assertInstanceOf(\Magento\Framework\Setup\Option\FlagConfigOption::class, $options[10]); $this->assertSame( 'If specified, then db connection validation will be skipped', - $options[11]->getDescription() + $options[10]->getDescription() ); - $this->assertInstanceOf(\Magento\Framework\Setup\Option\TextConfigOption::class, $options[12]); - $this->assertSame('http Cache hosts', $options[12]->getDescription()); - $this->assertEquals(13, count($options)); + $this->assertInstanceOf(\Magento\Framework\Setup\Option\TextConfigOption::class, $options[11]); + $this->assertSame('http Cache hosts', $options[11]->getDescription()); + $this->assertEquals(12, count($options)); } public function testCreateOptions() diff --git a/setup/src/Magento/Setup/Test/Unit/Module/ConfigGeneratorTest.php b/setup/src/Magento/Setup/Test/Unit/Module/ConfigGeneratorTest.php index caca5509d1e14ee4500803d05275d543692393f1..238bf7ea3db9f2f48be1414aaa2f7ad9783ce78c 100644 --- a/setup/src/Magento/Setup/Test/Unit/Module/ConfigGeneratorTest.php +++ b/setup/src/Magento/Setup/Test/Unit/Module/ConfigGeneratorTest.php @@ -66,14 +66,6 @@ class ConfigGeneratorTest extends \PHPUnit_Framework_TestCase $this->assertEquals([], $returnValue->getData()); } - public function testCreateDefinitionsConfig() - { - $testData = [ConfigOptionsListConstants::INPUT_KEY_DEFINITION_FORMAT => 'test-format']; - $returnValue = $this->configGeneratorObject->createDefinitionsConfig($testData); - $this->assertEquals(ConfigFilePool::APP_ENV, $returnValue->getFileKey()); - $this->assertEquals(['definition' => ['format' => 'test-format']], $returnValue->getData()); - } - public function testCreateDbConfig() { $testData = [